diff --git a/.gitattributes b/.gitattributes
index 7d07d70cc8d5dcee3cda2a04cf5384dc12953437..72ed017bd809a25b080d1660f176ff21de71b551 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1 +1,2 @@
 * text=lf
+*.bat eol=crlf
diff --git a/.gitignore b/.gitignore
index 31d9ca3d1cc4f1fb472863f46a698bd10d006c79..f0494927dc628598fe6dd3d4967249e8c30ef6ec 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,3 +10,4 @@ composer.phar
 import/solrmarc.log
 /solr
 node_modules
+public/swagger-ui
diff --git a/.travis.yml b/.travis.yml
index cbbbd1f96d82c7c270fa059ecb7895acc943d64b..1baa7a4fd129f325615fc66f791dbd9306b7171d 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,21 +1,23 @@
 sudo: false
 language: php
 php:
-  - 5.4
-  - 5.5
   - 5.6
   - 7.0
+  - 7.1
 
 env:
   - VUFIND_HOME=$PWD VUFIND_LOCAL_DIR=$PWD/local
 
 before_script:
-  - pear install pear/Http_Request2
-  - pear channel-discover pear.phing.info
-  - pear install phing/phing
   - phpenv config-rm xdebug.ini
   - phpenv rehash
+  - composer install
   - npm install -g eslint@"<3.0.0"
 
+cache:
+  directories:
+    - downloads
+    - $HOME/.composer/cache
+
 script:
-  - phing composer phpunitfast phpcs-console php-cs-fixer-dryrun eslint
+  - vendor/bin/phing phpunitfast phpcs-console php-cs-fixer-dryrun eslint
diff --git a/Gruntfile.js b/Gruntfile.js
index ee5380f8e0f41163db1c67e4a1006261b37b90b0..54942d19d6ce87f30ca915c589f41d7772fb1921 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -28,25 +28,31 @@ module.exports = function(grunt) {
   }
 
   var fontAwesomePath = '"../../bootstrap3/css/fonts"';
+  var lessFileSettings = [{
+    expand: true,
+    src: "themes/*/less/compiled.less",
+    rename: function (dest, src) {
+      return src.replace('/less/', '/css/').replace('.less', '.css');
+    }
+  }];
 
   grunt.initConfig({
     // LESS compilation
     less: {
       compile: {
+        files: lessFileSettings,
         options: {
           paths: getLoadPaths,
           compress: true,
           modifyVars: {
             'fa-font-path': fontAwesomePath
           }
-        },
-        files: [{
-          expand: true,
-          src: "themes/*/less/compiled.less",
-          rename: function (dest, src) {
-            return src.replace('/less/', '/css/').replace('.less', '.css');
-          }
-        }]
+        }
+      }
+    },
+    // Less with maps
+    lessdev: {
+      less: {
       }
     },
     // SASS compilation
@@ -74,6 +80,13 @@ module.exports = function(grunt) {
             src: ['*.less'],
             ext: '.scss',
             dest: 'themes/bootprint3/scss'
+          },
+          {
+            expand: true,
+            cwd: 'themes/sandal/less',
+            src: ['*.less'],
+            ext: '.scss',
+            dest: 'themes/sandal/scss'
           }
         ],
         options: {
@@ -85,6 +98,13 @@ module.exports = function(grunt) {
               },
               order: 3
             },
+            { // Remove unquote
+              pattern: /(\s+)unquote\("([^"]+)"\)/gi,
+              replacement: function mixinCommas(match, space, $1) {
+                return space + $1;
+              },
+              order: 3
+            },
             { // Inline &:extends converted
               pattern: /&:extend\(([^\)]+)\)/gi,
               replacement: '@extend $1',
@@ -132,12 +152,34 @@ module.exports = function(grunt) {
         files: 'themes/*/less/**/*.less',
         tasks: ['less']
       },
+      lessdev: {
+        files: 'themes/*/less/**/*.less',
+        tasks: ['lessdev']
+      },
       scss: {
         files: 'themes/*/scss/**/*.scss',
         tasks: ['scss']
       }
     }
   });
+
+  grunt.registerMultiTask('lessdev', function lessWithMaps() {
+    grunt.config.set('less', {
+      dev: {
+        files: lessFileSettings,
+        options: {
+          paths: getLoadPaths,
+          sourceMap: true,
+          sourceMapFileInline: true,
+          modifyVars: {
+            'fa-font-path': fontAwesomePath
+          }
+        }
+      }
+    });
+    grunt.task.run('less');
+  });
+
   grunt.registerMultiTask('scss', function sassScan() {
     var sassConfig = {},
       path = require('path'),
diff --git a/README.md b/README.md
index 8a418ab30b65f1c09475d577ae0627d8ac3d109f..aded15750c4b3827af94af6fa2b6c82409e8679b 100644
--- a/README.md
+++ b/README.md
@@ -9,7 +9,15 @@ records.  To learn more, visit https://vufind.org.
 
 Installation
 ------------
-See online documentation at https://vufind.org/wiki/installation
+See our [online installation documentation](https://vufind.org/wiki/installation) for step-by-step instructions for installing from packaged releases to popular platforms.
+
+VuFind's [packaged releases](http://vufind-org.github.io/vufind/downloads.html) have all dependencies included. If you are installing directly from a Git checkout, you will need to load these dependencies manually using the [Composer](https://getcomposer.org) tool by running `composer install` from the VuFind home directory.
+
+
+Documentation and Support
+-------------------------
+The VuFind community maintains a detailed [wiki](http://vufind.org/wiki) containing information on using and customizing the software. The VuFind website also lists [sources of community and commercial support](http://vufind-org.github.io/vufind/support.html).
+
 
 Contributing
 ------------
diff --git a/build.xml b/build.xml
index c55115c867d98454bb966987bba879f7f1faf562..21fbfbb913aa2e51f7c423aa6e8f37bd13bb2f98 100644
--- a/build.xml
+++ b/build.xml
@@ -25,16 +25,19 @@
   <property name="selenium_browser" value="firefox" />
   <property name="snooze_multiplier" value="1" /><!-- can be used to slow down tests (selenium only) -->
   <property name="solr_startup_sleep" value="0" />
+  <property name="solr_version" value="6.4.2" />
   <property name="php-cs-fixers" value="no_blank_lines_before_namespaces,function_call_space,trailing_spaces,unused_use,lowercase_keywords,encoding,parenthesis,php_closing_tag,visibility,duplicate_semicolon,extra_empty_lines,no_blank_lines_after_class_opening,no_empty_lines_after_phpdocs,operators_spaces,spaces_before_semicolon,ternary_spaces,concat_with_spaces,short_array_syntax,phpdoc_no_access,remove_leading_slash_use,eof_ending" />
 
 
-  <property name="version" value="3.1.3" />
+  <property name="version" value="4.0.1" />
 
   <!-- We only need the -p switch if the password is non-blank -->
   <if><not><equals arg1="${mysqlrootpass}" arg2="" /></not><then>
     <property name="mysqlpwswitch" value="-p" />
   </then></if>
 
+  <includepath classpath="${srcdir}/vendor/phpdocumentor" />
+
   <!-- Main Target -->
   <target name="main" description="main target">
     <phingcall target="startup" />
@@ -137,6 +140,64 @@
     <exec dir="${srcdir}/module/VuFind/tests" command="VUFIND_MINK_DRIVER=${mink_driver} VUFIND_SELENIUM_BROWSER=${selenium_browser} VUFIND_SNOOZE_MULTIPLIER=${snooze_multiplier} VUFIND_LOCAL_DIR=${srcdir}/local VUFIND_URL=${vufindurl} ${srcdir}/vendor/bin/phpunit -dzend.enable_gc=0 ${phpunit_extra_params}" passthru="true" checkreturn="true" />
   </target>
 
+  <target name="installsolr" description="Install Solr">
+    <!-- load previously installed version from marker file, if present -->
+    <if>
+      <available file="${srcdir}/solr/vendor/.installedVersion" />
+      <then>
+        <loadfile property="existing_solr_version" file="${srcdir}/solr/vendor/.installedVersion" />
+      </then>
+    </if>
+    <!-- only attempt to install Solr if the desired version is not already there -->
+    <if>
+      <not><equals arg1="${existing_solr_version}" arg2="${solr_version}" /></not>
+      <then>
+        <!-- make sure we don't run out of memory during installation: -->
+        <php expression="ini_set('memory_limit', '1G');" />
+
+        <!-- download from Apache if not already present in the downloads cache -->
+        <if>
+          <not><available file="${srcdir}/downloads/solr-${solr_version}.tgz" /></not>
+           <then>
+            <mkdir dir="${srcdir}/downloads" />
+            <httpget url="http://archive.apache.org/dist/lucene/solr/${solr_version}/solr-${solr_version}.tgz" dir="${srcdir}/downloads" />
+          </then>
+        </if>
+        <!-- unpack the archive into solr/vendor -->
+        <untar file="${srcdir}/downloads/solr-${solr_version}.tgz" todir="${srcdir}/solr" />
+        <delete dir="${srcdir}/solr/vendor" includeemptydirs="true" failonerror="false" />
+        <move file="${srcdir}/solr/solr-${solr_version}" tofile="${srcdir}/solr/vendor" />
+        <!-- make scripts executable -->
+        <chmod mode="0755">
+          <fileset dir="${srcdir}/solr/vendor/bin">
+            <include name="**/**" />
+            <exclude name="**/*.cmd" />
+          </fileset>
+        </chmod>
+        <!-- update the marker file with the installed version -->
+        <echo file="${srcdir}/solr/vendor/.installedVersion" message="${solr_version}" />
+      </then>
+    </if>
+  </target>
+
+  <target name="installswaggerui">
+    <delete dir="${srcdir}/public/swagger-ui" includeemptydirs="true" failonerror="false" />
+    <copy todir="${srcdir}/public/swagger-ui">
+      <fileset dir="${srcdir}/vendor/swagger-api/swagger-ui/dist" defaultexcludes="false" />
+    </copy>
+    <reflexive>
+      <fileset dir="${srcdir}/public/swagger-ui">
+        <include pattern="index.html" />
+      </fileset>
+      <filterchain>
+        <replaceregexp>
+          <regexp pattern="defaultModelRendering: 'schema'" replace="defaultModelRendering: 'model'" />
+          <regexp pattern="url = &quot;.*&quot;" replace="url = &quot;../api/v1?swagger&quot;" />
+        </replaceregexp>
+      </filterchain>
+    </reflexive>
+  </target>
+
   <target name="composer" description="Install dependencies with Composer">
     <httpget url="https://getcomposer.org/composer.phar" sslVerifyPeer="false" dir="${srcdir}" />
     <echo message="Installing dependencies..." />
@@ -159,7 +220,7 @@
     <if>
       <istrue value="${seleniumjar}" />
       <then>
-        <exec command="xvfb-run --server-args=&quot;-screen 0 1024x768x24&quot; java -jar ${seleniumjar} > /dev/null &amp;" />
+        <exec command="xvfb-run --server-args=&quot;-screen 0 1024x768x24&quot; java -jar ${seleniumjar}" passthru="true" spawn="true" checkreturn="true" />
       </then>
     </if>
 
@@ -187,7 +248,7 @@
         <exec command="PGPASSWORD=${vufinddbpass} psql -U ${vufinddbuser} -f ${srcdir}/module/VuFind/sql/pgsql.sql ${vufinddb}" checkreturn="true" />
 
         <!-- configure VuFind -->
-        <exec command="sed -e &quot;s!mysql://root@localhost/vufind!pgsql://${vufinddbuser}:${vufinddbpass}@${pgsqlhost}/${vufinddb}!&quot; ${srcdir}/config/vufind/config.ini &gt; ${srcdir}/local/config/vufind/config.ini.tmp" />
+        <property name="db_connection_string" value="pgsql://${vufinddbuser}:${vufinddbpass}@${pgsqlhost}/${vufinddb}" />
       </then>
       <else>
         <!-- build database -->
@@ -198,13 +259,19 @@
         <exec command="mysql -h ${mysqlhost} -u ${mysqlrootuser} ${mysqlpwswitch}${mysqlrootpass} -D ${vufinddb} &lt; ${srcdir}/module/VuFind/sql/mysql.sql" checkreturn="true" />
 
         <!-- configure VuFind -->
-        <exec command="sed -e &quot;s!mysql://root@localhost/vufind!mysql://${vufinddbuser}:${vufinddbpass}@${mysqlhost}/${vufinddb}!&quot; ${srcdir}/config/vufind/config.ini &gt; ${srcdir}/local/config/vufind/config.ini.tmp" />
+        <property name="db_connection_string" value="mysql://${vufinddbuser}:${vufinddbpass}@${mysqlhost}/${vufinddb}" />
       </else>
     </if>
 
-    <!-- Turn on exception logging -->
-    <exec command="sed -e &quot;s!;file           = /var/log/vufind.log:alert,error,notice,debug!file = ${srcdir}/vufind-exception.log:alert-5,error-5!&quot; ${srcdir}/local/config/vufind/config.ini.tmp &gt; ${srcdir}/local/config/vufind/config.ini" />
-    <delete file="${srcdir}/local/config/vufind/config.ini.tmp" />
+    <!-- Update config.ini to activate DB connection and exception logging -->
+    <copy file="${srcdir}/config/vufind/config.ini" tofile="${srcdir}/local/config/vufind/config.ini">
+      <filterchain>
+        <replaceregexp>
+          <regexp pattern="mysql://root@localhost/vufind" replace="${db_connection_string}" />
+          <regexp pattern=";file\s+= /var/log/vufind.log:alert,error,notice,debug" replace="file = ${srcdir}/vufind-exception.log:alert-5,error-5" />
+        </replaceregexp>
+      </filterchain>
+    </copy>
     <exec command="touch ${srcdir}/vufind-exception.log" />
     <exec command="chmod a+w ${srcdir}/vufind-exception.log" />
 
@@ -283,7 +350,6 @@
     <!-- delete the configuration, sample index, logs and cache data -->
     <delete file="${srcdir}/import/solrmarc.log" failonerror="true" />
     <delete dir="${srcdir}/solr" includeemptydirs="true" failonerror="true" />
-    <delete file="${srcdir}/composer.lock" failonerror="false" />
     <delete file="${srcdir}/composer.phar" failonerror="false" />
     <delete file="${srcdir}/vufind-exception.log" failonerror="false" />
     <delete dir="${srcdir}/vendor" includeemptydirs="true" failonerror="false" />
@@ -304,9 +370,15 @@
       <property name="composer_extra_params" value="--no-dev" />
     </phingcall>
     <exec command="git archive HEAD --format=tar | tar -x -C ${builddir}/export/vufind/usr/local/vufind" />
-    <copy todir = "${builddir}/export/vufind/usr/local/vufind/vendor">
+    <copy todir="${builddir}/export/vufind/usr/local/vufind/vendor">
       <fileset dir="${srcdir}/vendor" defaultexcludes="false" />
     </copy>
+    <copy todir="${builddir}/export/vufind/usr/local/vufind/solr/vendor">
+      <fileset dir="${srcdir}/solr/vendor" defaultexcludes="false" />
+    </copy>
+    <copy todir="${builddir}/export/vufind/usr/local/vufind/public/swagger-ui">
+      <fileset dir="${srcdir}/public/swagger-ui" defaultexcludes="false" />
+    </copy>
 
     <!-- create a version-specific symlink so that tar/zip packages will have
          appropriate directory structures. -->
diff --git a/composer.json b/composer.json
index f6ea1158571f0f49aad77eefa6cd5e90c0b8e3f1..1268594bfc2995a6a4f8aa5a427ec9e3d749f5c1 100644
--- a/composer.json
+++ b/composer.json
@@ -9,36 +9,74 @@
     ],
     "license": "GPL-2.0",
     "require": {
+        "php": ">=5.6",
         "aferrandini/phpqrcode": "1.0.1",
-        "jasig/phpcas": "1.3.3",
+        "jasig/phpcas": "1.3.5",
         "cap60552/php-sip2": "1.0.0",
-        "los/losrecaptcha": "1.0.0",
         "ahand/mobileesp": "dev-master",
-        "matthiasmullie/minify": "1.3.35",
+        "matthiasmullie/minify": "1.3.45",
         "ocramius/proxy-manager": "1.0.2",
-        "oyejorge/less.php": "1.7.0.9",
-        "pear/file_marc": "1.1.2",
+        "oyejorge/less.php": "1.7.0.14",
+        "pear/file_marc": "1.1.5",
+        "pear/http_request2": "2.3.0",
         "pear/validate_ispn": "dev-master",
-        "serialssolutions/summon": "1.0.0",
-        "symfony/yaml": "2.7.6",
+        "phing/phing": "2.16.0",
+        "serialssolutions/summon": "1.1.0",
+        "symfony/yaml": "3.3.2",
+        "swagger-api/swagger-ui": "2.2.10",
         "vufind-org/vufindcode": "1.0.3",
-        "vufind-org/vufindharvest": "2.1.0",
+        "vufind-org/vufindharvest": "2.3.0",
         "vufind-org/vufindhttp": "2.1.1",
-        "yajra/laravel-pdo-via-oci8": "1.1.1",
+        "yajra/laravel-pdo-via-oci8": "1.3.1",
+        "zendframework/zend-cache": "2.7.2",
+        "zendframework/zend-captcha": "2.7.1",
         "sabre/vobject": "^3.4",
-        "zendframework/zendframework": "2.4.6",
+        "zendframework/zend-code": "2.6.3",
+        "zendframework/zend-config": "2.6.0",
+        "zendframework/zend-console": "2.6.0",
+        "zendframework/zend-crypt": "3.2.0",
+        "zendframework/zend-db": "2.8.2",
+        "zendframework/zend-dom": "2.6.0",
+        "zendframework/zend-escaper": "2.5.2",
+        "zendframework/zend-eventmanager": "3.1.0",
+        "zendframework/zend-feed": "2.8.0",
+        "zendframework/zend-http": "2.6.0",
+        "zendframework/zend-i18n": "2.7.4",
+        "zendframework/zend-loader": "2.5.1",
+        "zendframework/zend-log": "2.9.2",
+        "zendframework/zend-mail": "2.8.0",
+        "zendframework/zend-modulemanager": "2.7.2",
+        "zendframework/zend-mvc": "2.7.8",
+        "zendframework/zend-paginator": "2.7.0",
+        "zendframework/zend-serializer": "2.8.0",
+        "zendframework/zend-servicemanager": "2.7.5",
+        "zendframework/zend-session": "2.8.0",
+        "zendframework/zend-soap": "2.6.0",
+        "zendframework/zend-stdlib": "2.7.7",
+        "zendframework/zend-text": "2.6.0",
+        "zendframework/zend-validator": "2.9.1",
+        "zendframework/zend-view": "2.9.0",
         "zendframework/zendrest": "2.0.2",
-        "zendframework/zendservice-amazon": "2.0.4",
-        "zf-commons/zfc-rbac": "2.5.2"
+        "zendframework/zendservice-amazon": "2.3.0",
+        "zendframework/zendservice-recaptcha": "3.0.0",
+        "zf-commons/zfc-rbac": "2.6.3",
+        "pear/archive_tar": "^1.4"
     },
     "require-dev": {
-        "behat/mink": "1.7.0",
-        "behat/mink-selenium2-driver": "1.3.0",
+        "behat/mink": "1.7.1",
+        "behat/mink-selenium2-driver": "1.3.1",
         "friendsofphp/php-cs-fixer": "1.11.6",
-        "phploc/phploc": "2.0.6",
-        "phpmd/phpmd": "1.5.0",
-        "phpunit/phpunit": "4.8.27",
-        "sebastian/phpcpd": "2.0.0",
-        "squizlabs/php_codesniffer": "2.6.0"
+        "phpdocumentor/phpdocumentor": "2.9.0",
+        "phploc/phploc": "3.0.1",
+        "phpmd/phpmd": "2.6.0",
+        "phpunit/phpunit": "5.7.15",
+        "sebastian/phpcpd": "2.0.4",
+        "squizlabs/php_codesniffer": "2.8.1",
+        "twig/twig": "1.27"
+    },
+    "scripts": {
+        "phing-install-dependencies": "phing installsolr installswaggerui",
+        "post-install-cmd": "@phing-install-dependencies",
+        "post-update-cmd": "@phing-install-dependencies"
     }
 }
diff --git a/composer.lock b/composer.lock
new file mode 100644
index 0000000000000000000000000000000000000000..5e3c5c962ac6b04a688e11f7d373acf3bd5f6a53
--- /dev/null
+++ b/composer.lock
@@ -0,0 +1,7988 @@
+{
+    "_readme": [
+        "This file locks the dependencies of your project to a known state",
+        "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
+        "This file is @generated automatically"
+    ],
+    "content-hash": "aea8a7723ba0f3cb502ae7f1679b9578",
+    "packages": [
+        {
+            "name": "aferrandini/phpqrcode",
+            "version": "1.0.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/aferrandini/PHPQRCode.git",
+                "reference": "3c1c0454d43710ab5bbe19a51ad4cb41c22e3d46"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/aferrandini/PHPQRCode/zipball/3c1c0454d43710ab5bbe19a51ad4cb41c22e3d46",
+                "reference": "3c1c0454d43710ab5bbe19a51ad4cb41c22e3d46",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.0"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-0": {
+                    "PHPQRCode": "lib/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Ariel Ferrandini",
+                    "email": "arielferrandini@gmail.com",
+                    "homepage": "http://www.ferrandini.com/",
+                    "role": "Developer"
+                }
+            ],
+            "description": "PHPQRCode porting and changed for PHP 5.3 compatibility",
+            "homepage": "https://github.com/aferrandini/PHPQRCode",
+            "keywords": [
+                "barcode",
+                "php",
+                "qrcode"
+            ],
+            "time": "2013-07-08T09:39:08+00:00"
+        },
+        {
+            "name": "ahand/mobileesp",
+            "version": "dev-master",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/ahand/mobileesp.git",
+                "reference": "c02055dbe9baee63aab11438f4d7b5d25075d347"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/ahand/mobileesp/zipball/c02055dbe9baee63aab11438f4d7b5d25075d347",
+                "reference": "c02055dbe9baee63aab11438f4d7b5d25075d347",
+                "shasum": ""
+            },
+            "type": "library",
+            "autoload": {
+                "classmap": [
+                    "PHP"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "Apache-2.0"
+            ],
+            "authors": [
+                {
+                    "name": "Anthony Hand",
+                    "email": "anthony.hand@gmail.com",
+                    "role": "Maintainer"
+                }
+            ],
+            "description": "Since 2008, MobileESP provides web site developers an easy-to-use and lightweight API for detecting whether visitors are using a mobile device, and if so, what kind. The APIs provide simple boolean results ('true' or 'false') for identifying individual device categories (such as iPhone, BlackBerry, Android, and Windows Mobile), device capabilities (e.g., J2ME), and broad classes of devices, such as 'iPhone Tier' (iPhone/Android/Tizen) or 'Tablet Tier.' APIs are available in PHP, JavaScript, Java, C#, Ruby Python, and more.",
+            "homepage": "http://www.mobileesp.org",
+            "keywords": [
+                "Mobile-Detect",
+                "browser",
+                "detect android",
+                "detect ipad",
+                "detect iphone",
+                "detect tablet",
+                "mobile",
+                "mobile detect",
+                "mobile detector",
+                "mobile device",
+                "mobile esp",
+                "mobile redirect",
+                "mobile view managing",
+                "mobiledetect",
+                "responsive web",
+                "user agent",
+                "useragent"
+            ],
+            "time": "2017-06-06 22:20:56"
+        },
+        {
+            "name": "cap60552/php-sip2",
+            "version": "v1.0.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/cap60552/php-sip2.git",
+                "reference": "9904f94e857b7d4d4fd494f2d6634dcaf0d6e2c1"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/cap60552/php-sip2/zipball/9904f94e857b7d4d4fd494f2d6634dcaf0d6e2c1",
+                "reference": "9904f94e857b7d4d4fd494f2d6634dcaf0d6e2c1",
+                "shasum": ""
+            },
+            "type": "library",
+            "autoload": {
+                "classmap": [
+                    "/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "GPL-3.0"
+            ],
+            "authors": [
+                {
+                    "name": "John Wohlers",
+                    "email": "john@wohlershome.net",
+                    "role": "Maintainer"
+                }
+            ],
+            "description": "PHP class library to facilitate communication with Integrated Library System (ILS) servers via 3M's SIP2.",
+            "homepage": "https://github.com/cap60552/php-sip2",
+            "time": "2015-11-03T04:42:39+00:00"
+        },
+        {
+            "name": "container-interop/container-interop",
+            "version": "1.2.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/container-interop/container-interop.git",
+                "reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/container-interop/container-interop/zipball/79cbf1341c22ec75643d841642dd5d6acd83bdb8",
+                "reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8",
+                "shasum": ""
+            },
+            "require": {
+                "psr/container": "^1.0"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Interop\\Container\\": "src/Interop/Container/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "description": "Promoting the interoperability of container objects (DIC, SL, etc.)",
+            "homepage": "https://github.com/container-interop/container-interop",
+            "time": "2017-02-14T19:40:03+00:00"
+        },
+        {
+            "name": "jasig/phpcas",
+            "version": "1.3.5",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/Jasig/phpCAS.git",
+                "reference": "61c8899c8f91204e8b9135d795461e50fe5c2db0"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/Jasig/phpCAS/zipball/61c8899c8f91204e8b9135d795461e50fe5c2db0",
+                "reference": "61c8899c8f91204e8b9135d795461e50fe5c2db0",
+                "shasum": ""
+            },
+            "require": {
+                "ext-curl": "*",
+                "php": ">=5.4.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "~3.7.10"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.3.x-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "source/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "Apache-2.0"
+            ],
+            "authors": [
+                {
+                    "name": "Joachim Fritschi",
+                    "homepage": "https://wiki.jasig.org/display/~fritschi"
+                },
+                {
+                    "name": "Adam Franco",
+                    "homepage": "https://wiki.jasig.org/display/~adamfranco"
+                }
+            ],
+            "description": "Provides a simple API for authenticating users against a CAS server",
+            "homepage": "https://wiki.jasig.org/display/CASC/phpCAS",
+            "keywords": [
+                "cas",
+                "jasig"
+            ],
+            "time": "2017-04-10T19:12:45+00:00"
+        },
+        {
+            "name": "matthiasmullie/minify",
+            "version": "1.3.45",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/matthiasmullie/minify.git",
+                "reference": "09b83e9dbdc50cf6734c6a9652a54891c0651998"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/matthiasmullie/minify/zipball/09b83e9dbdc50cf6734c6a9652a54891c0651998",
+                "reference": "09b83e9dbdc50cf6734c6a9652a54891c0651998",
+                "shasum": ""
+            },
+            "require": {
+                "ext-pcre": "*",
+                "matthiasmullie/path-converter": "~1.1",
+                "php": ">=5.3.0"
+            },
+            "require-dev": {
+                "friendsofphp/php-cs-fixer": "~1.0",
+                "matthiasmullie/scrapbook": "~1.0",
+                "phpunit/phpunit": "~4.8"
+            },
+            "suggest": {
+                "psr/cache-implementation": "Cache implementation to use with Minify::cache"
+            },
+            "bin": [
+                "bin/minifycss",
+                "bin/minifyjs"
+            ],
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "MatthiasMullie\\Minify\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Matthias Mullie",
+                    "email": "minify@mullie.eu",
+                    "homepage": "http://www.mullie.eu",
+                    "role": "Developer"
+                }
+            ],
+            "description": "CSS & JS minifier",
+            "homepage": "http://www.minifier.org",
+            "keywords": [
+                "JS",
+                "css",
+                "javascript",
+                "minifier",
+                "minify"
+            ],
+            "time": "2017-06-13T15:54:31+00:00"
+        },
+        {
+            "name": "matthiasmullie/path-converter",
+            "version": "1.1.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/matthiasmullie/path-converter.git",
+                "reference": "08551ec1b156e923c242a10ab484bd4d6ead6631"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/matthiasmullie/path-converter/zipball/08551ec1b156e923c242a10ab484bd4d6ead6631",
+                "reference": "08551ec1b156e923c242a10ab484bd4d6ead6631",
+                "shasum": ""
+            },
+            "require": {
+                "ext-pcre": "*",
+                "php": ">=5.3.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "~4.8"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "MatthiasMullie\\PathConverter\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Matthias Mullie",
+                    "email": "pathconverter@mullie.eu",
+                    "homepage": "http://www.mullie.eu",
+                    "role": "Developer"
+                }
+            ],
+            "description": "Relative path converter",
+            "homepage": "http://github.com/matthiasmullie/path-converter",
+            "keywords": [
+                "converter",
+                "path",
+                "paths",
+                "relative"
+            ],
+            "time": "2017-01-26T08:54:49+00:00"
+        },
+        {
+            "name": "ocramius/proxy-manager",
+            "version": "1.0.2",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/Ocramius/ProxyManager.git",
+                "reference": "57e9272ec0e8deccf09421596e0e2252df440e11"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/Ocramius/ProxyManager/zipball/57e9272ec0e8deccf09421596e0e2252df440e11",
+                "reference": "57e9272ec0e8deccf09421596e0e2252df440e11",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.3",
+                "zendframework/zend-code": ">2.2.5,<3.0"
+            },
+            "require-dev": {
+                "ext-phar": "*",
+                "phpunit/phpunit": "~4.0",
+                "squizlabs/php_codesniffer": "1.5.*"
+            },
+            "suggest": {
+                "ocramius/generated-hydrator": "To have very fast object to array to object conversion for ghost objects",
+                "zendframework/zend-json": "To have the JsonRpc adapter (Remote Object feature)",
+                "zendframework/zend-soap": "To have the Soap adapter (Remote Object feature)",
+                "zendframework/zend-stdlib": "To use the hydrator proxy",
+                "zendframework/zend-xmlrpc": "To have the XmlRpc adapter (Remote Object feature)"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.0.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-0": {
+                    "ProxyManager\\": "src"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Marco Pivetta",
+                    "email": "ocramius@gmail.com",
+                    "homepage": "http://ocramius.github.com/"
+                }
+            ],
+            "description": "A library providing utilities to generate, instantiate and generally operate with Object Proxies",
+            "homepage": "https://github.com/Ocramius/ProxyManager",
+            "keywords": [
+                "aop",
+                "lazy loading",
+                "proxy",
+                "proxy pattern",
+                "service proxies"
+            ],
+            "time": "2015-08-09T04:28:19+00:00"
+        },
+        {
+            "name": "oyejorge/less.php",
+            "version": "v1.7.0.14",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/oyejorge/less.php.git",
+                "reference": "42925c5a01a07d67ca7e82dfc8fb31814d557bc9"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/oyejorge/less.php/zipball/42925c5a01a07d67ca7e82dfc8fb31814d557bc9",
+                "reference": "42925c5a01a07d67ca7e82dfc8fb31814d557bc9",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "~4.8.24"
+            },
+            "bin": [
+                "bin/lessc"
+            ],
+            "type": "library",
+            "autoload": {
+                "psr-0": {
+                    "Less": "lib/"
+                },
+                "classmap": [
+                    "lessc.inc.php"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "Apache-2.0"
+            ],
+            "authors": [
+                {
+                    "name": "Matt Agar",
+                    "homepage": "https://github.com/agar"
+                },
+                {
+                    "name": "Martin Jantošovič",
+                    "homepage": "https://github.com/Mordred"
+                },
+                {
+                    "name": "Josh Schmidt",
+                    "homepage": "https://github.com/oyejorge"
+                }
+            ],
+            "description": "PHP port of the Javascript version of LESS http://lesscss.org (Originally maintained by Josh Schmidt)",
+            "homepage": "http://lessphp.gpeasy.com",
+            "keywords": [
+                "css",
+                "less",
+                "less.js",
+                "lesscss",
+                "php",
+                "stylesheet"
+            ],
+            "time": "2017-03-28T22:19:25+00:00"
+        },
+        {
+            "name": "paragonie/random_compat",
+            "version": "v2.0.10",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/paragonie/random_compat.git",
+                "reference": "634bae8e911eefa89c1abfbf1b66da679ac8f54d"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/paragonie/random_compat/zipball/634bae8e911eefa89c1abfbf1b66da679ac8f54d",
+                "reference": "634bae8e911eefa89c1abfbf1b66da679ac8f54d",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.2.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "4.*|5.*"
+            },
+            "suggest": {
+                "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes."
+            },
+            "type": "library",
+            "autoload": {
+                "files": [
+                    "lib/random.php"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Paragon Initiative Enterprises",
+                    "email": "security@paragonie.com",
+                    "homepage": "https://paragonie.com"
+                }
+            ],
+            "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7",
+            "keywords": [
+                "csprng",
+                "pseudorandom",
+                "random"
+            ],
+            "time": "2017-03-13T16:27:32+00:00"
+        },
+        {
+            "name": "pear/archive_tar",
+            "version": "1.4.3",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/pear/Archive_Tar.git",
+                "reference": "43455c960da70e655c6bdf8ea2bc8cc1a6034afb"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/pear/Archive_Tar/zipball/43455c960da70e655c6bdf8ea2bc8cc1a6034afb",
+                "reference": "43455c960da70e655c6bdf8ea2bc8cc1a6034afb",
+                "shasum": ""
+            },
+            "require": {
+                "pear/pear-core-minimal": "^1.10.0alpha2",
+                "php": ">=5.2.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "*"
+            },
+            "suggest": {
+                "ext-bz2": "bz2 compression support.",
+                "ext-xz": "lzma2 compression support.",
+                "ext-zlib": "Gzip compression support."
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.4.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-0": {
+                    "Archive_Tar": ""
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "include-path": [
+                "./"
+            ],
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Vincent Blavet",
+                    "email": "vincent@phpconcept.net"
+                },
+                {
+                    "name": "Greg Beaver",
+                    "email": "greg@chiaraquartet.net"
+                },
+                {
+                    "name": "Michiel Rook",
+                    "email": "mrook@php.net"
+                }
+            ],
+            "description": "Tar file management class",
+            "homepage": "https://github.com/pear/Archive_Tar",
+            "keywords": [
+                "archive",
+                "tar"
+            ],
+            "time": "2017-06-11T17:28:11+00:00"
+        },
+        {
+            "name": "pear/console_getopt",
+            "version": "v1.4.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/pear/Console_Getopt.git",
+                "reference": "82f05cd1aa3edf34e19aa7c8ca312ce13a6a577f"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/pear/Console_Getopt/zipball/82f05cd1aa3edf34e19aa7c8ca312ce13a6a577f",
+                "reference": "82f05cd1aa3edf34e19aa7c8ca312ce13a6a577f",
+                "shasum": ""
+            },
+            "type": "library",
+            "autoload": {
+                "psr-0": {
+                    "Console": "./"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "include-path": [
+                "./"
+            ],
+            "license": [
+                "BSD-2-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Greg Beaver",
+                    "email": "cellog@php.net",
+                    "role": "Helper"
+                },
+                {
+                    "name": "Andrei Zmievski",
+                    "email": "andrei@php.net",
+                    "role": "Lead"
+                },
+                {
+                    "name": "Stig Bakken",
+                    "email": "stig@php.net",
+                    "role": "Developer"
+                }
+            ],
+            "description": "More info available on: http://pear.php.net/package/Console_Getopt",
+            "time": "2015-07-20T20:28:12+00:00"
+        },
+        {
+            "name": "pear/file_marc",
+            "version": "1.1.5",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/pear/File_MARC.git",
+                "reference": "ecf5a79661595e3804ad4c0ede984757b4fe8d8f"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/pear/File_MARC/zipball/ecf5a79661595e3804ad4c0ede984757b4fe8d8f",
+                "reference": "ecf5a79661595e3804ad4c0ede984757b4fe8d8f",
+                "shasum": ""
+            },
+            "require": {
+                "pear/pear_exception": "1.*"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "*"
+            },
+            "suggest": {
+                "pear/validate_ispn": "Install optionally via your project's composer.json"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-0": {
+                    "File": "./"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "include-path": [
+                "./"
+            ],
+            "license": [
+                "LGPL-2.1"
+            ],
+            "authors": [
+                {
+                    "name": "Dan Scott",
+                    "email": "dbs@php.net",
+                    "homepage": "https://coffeecode.net",
+                    "role": "Lead"
+                }
+            ],
+            "description": "Supports the MAchine Readable Cataloging (MARC) file format documented at http://loc.gov/marc/",
+            "time": "2017-01-23T16:49:13+00:00"
+        },
+        {
+            "name": "pear/http_request2",
+            "version": "v2.3.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/pear/HTTP_Request2.git",
+                "reference": "3599cf0fe455a4e281da464f6510bfc5c2ce54c4"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/pear/HTTP_Request2/zipball/3599cf0fe455a4e281da464f6510bfc5c2ce54c4",
+                "reference": "3599cf0fe455a4e281da464f6510bfc5c2ce54c4",
+                "shasum": ""
+            },
+            "require": {
+                "pear/net_url2": "^2.2.0",
+                "pear/pear_exception": "^1.0.0",
+                "php": ">=5.2.0"
+            },
+            "suggest": {
+                "ext-fileinfo": "Adds support for looking up mime-types using finfo.",
+                "ext-zlib": "Allows handling gzip compressed responses.",
+                "lib-curl": "Allows using cURL as a request backend.",
+                "lib-openssl": "Allows handling SSL requests when not using cURL."
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-trunk": "2.2-dev"
+                }
+            },
+            "autoload": {
+                "psr-0": {
+                    "HTTP_Request2": ""
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "include-path": [
+                "./"
+            ],
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Alexey Borzov",
+                    "email": "avb@php.net"
+                }
+            ],
+            "description": "Provides an easy way to perform HTTP requests.",
+            "homepage": "http://pear.php.net/package/HTTP_Request2",
+            "keywords": [
+                "PEAR",
+                "curl",
+                "http",
+                "request"
+            ],
+            "time": "2016-02-13T20:20:39+00:00"
+        },
+        {
+            "name": "pear/net_url2",
+            "version": "v2.2.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/pear/Net_URL2.git",
+                "reference": "43a87606daf52efe6685c92131be083143108e37"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/pear/Net_URL2/zipball/43a87606daf52efe6685c92131be083143108e37",
+                "reference": "43a87606daf52efe6685c92131be083143108e37",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.1.4"
+            },
+            "require-dev": {
+                "phpunit/phpunit": ">=3.3.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.2.x-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "Net/URL2.php"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "David Coallier",
+                    "email": "davidc@php.net"
+                },
+                {
+                    "name": "Tom Klingenberg",
+                    "email": "tkli@php.net"
+                },
+                {
+                    "name": "Christian Schmidt",
+                    "email": "chmidt@php.net"
+                }
+            ],
+            "description": "Class for parsing and handling URL. Provides parsing of URLs into their constituent parts (scheme, host, path etc.), URL generation, and resolving of relative URLs.",
+            "homepage": "https://github.com/pear/Net_URL2",
+            "keywords": [
+                "PEAR",
+                "net",
+                "networking",
+                "rfc3986",
+                "uri",
+                "url"
+            ],
+            "time": "2016-04-18T22:24:01+00:00"
+        },
+        {
+            "name": "pear/pear-core-minimal",
+            "version": "v1.10.3",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/pear/pear-core-minimal.git",
+                "reference": "070f0b600b2caca2501e2c9b7e553016e4b0d115"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/pear/pear-core-minimal/zipball/070f0b600b2caca2501e2c9b7e553016e4b0d115",
+                "reference": "070f0b600b2caca2501e2c9b7e553016e4b0d115",
+                "shasum": ""
+            },
+            "require": {
+                "pear/console_getopt": "~1.4",
+                "pear/pear_exception": "~1.0"
+            },
+            "replace": {
+                "rsky/pear-core-min": "self.version"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-0": {
+                    "": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "include-path": [
+                "src/"
+            ],
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Christian Weiske",
+                    "email": "cweiske@php.net",
+                    "role": "Lead"
+                }
+            ],
+            "description": "Minimal set of PEAR core files to be used as composer dependency",
+            "time": "2017-02-28T16:46:11+00:00"
+        },
+        {
+            "name": "pear/pear_exception",
+            "version": "v1.0.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/pear/PEAR_Exception.git",
+                "reference": "8c18719fdae000b690e3912be401c76e406dd13b"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/pear/PEAR_Exception/zipball/8c18719fdae000b690e3912be401c76e406dd13b",
+                "reference": "8c18719fdae000b690e3912be401c76e406dd13b",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=4.4.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "*"
+            },
+            "type": "class",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-0": {
+                    "PEAR": ""
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "include-path": [
+                "."
+            ],
+            "license": [
+                "BSD-2-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Helgi Thormar",
+                    "email": "dufuz@php.net"
+                },
+                {
+                    "name": "Greg Beaver",
+                    "email": "cellog@php.net"
+                }
+            ],
+            "description": "The PEAR Exception base class.",
+            "homepage": "https://github.com/pear/PEAR_Exception",
+            "keywords": [
+                "exception"
+            ],
+            "time": "2015-02-10T20:07:52+00:00"
+        },
+        {
+            "name": "pear/validate",
+            "version": "v0.8.5",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/pear/Validate.git",
+                "reference": "d055541ee2d7165329d5e5b8e91907d7fae1cff2"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/pear/Validate/zipball/d055541ee2d7165329d5e5b8e91907d7fae1cff2",
+                "reference": "d055541ee2d7165329d5e5b8e91907d7fae1cff2",
+                "shasum": ""
+            },
+            "suggest": {
+                "pear/date": "Install optionally via your project's composer.json"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-0": {
+                    "Validate": "./"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "include-path": [
+                "./"
+            ],
+            "license": [
+                "New BSD"
+            ],
+            "authors": [
+                {
+                    "name": "Pierre-Alain Joye",
+                    "email": "pierre.php@gmail.com",
+                    "role": "Lead"
+                },
+                {
+                    "name": "Thomas V.V.Cox",
+                    "email": "cox@php.net",
+                    "role": "Lead"
+                },
+                {
+                    "name": "Helgi Þormar Þorbjörnsson",
+                    "email": "dufuz@php.net",
+                    "role": "Lead"
+                },
+                {
+                    "name": "Amir Mohammad Saied",
+                    "email": "amirsaied@gmail.com",
+                    "role": "Lead"
+                },
+                {
+                    "name": "David Coallier",
+                    "email": "david@echolibre.com",
+                    "role": "Lead"
+                },
+                {
+                    "name": "bertrand Gugger",
+                    "email": "bertrand@toggg.com",
+                    "role": "Lead"
+                },
+                {
+                    "name": "Stefan Neufeind",
+                    "email": "pear.neufeind@speedpartner.de",
+                    "role": "Developer"
+                }
+            ],
+            "description": "Validate numbers, email, strings, dates, URIs and more",
+            "homepage": "http://pear.php.net/package/Validate",
+            "time": "2015-02-20T09:16:13+00:00"
+        },
+        {
+            "name": "pear/validate_ispn",
+            "version": "dev-master",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/pear/Validate_ISPN.git",
+                "reference": "9ea9312a0841b5d745742c737772aeffa6d06e96"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/pear/Validate_ISPN/zipball/9ea9312a0841b5d745742c737772aeffa6d06e96",
+                "reference": "9ea9312a0841b5d745742c737772aeffa6d06e96",
+                "shasum": ""
+            },
+            "require": {
+                "pear/validate": "*"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "*"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-0": {
+                    "Validate": "./"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "include-path": [
+                "./"
+            ],
+            "license": [
+                "BSD-2-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Helgi Þormar",
+                    "email": "dufuz@php.net",
+                    "role": "Lead"
+                },
+                {
+                    "name": "Piotr Klaban",
+                    "email": "makler@man.torun.pl",
+                    "role": "Lead"
+                }
+            ],
+            "description": "More info available on: http://pear.php.net/package/Validate_ISPN",
+            "time": "2015-04-14 04:17:31"
+        },
+        {
+            "name": "phing/phing",
+            "version": "2.16.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/phingofficial/phing.git",
+                "reference": "151a0f4d8cebf7711eccc62dde3f09bc36a00d7b"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/phingofficial/phing/zipball/151a0f4d8cebf7711eccc62dde3f09bc36a00d7b",
+                "reference": "151a0f4d8cebf7711eccc62dde3f09bc36a00d7b",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.2.0",
+                "symfony/yaml": "^3.1"
+            },
+            "require-dev": {
+                "ext-pdo_sqlite": "*",
+                "mikey179/vfsstream": "^1.6",
+                "pdepend/pdepend": "2.x",
+                "pear/archive_tar": "1.4.x",
+                "pear/http_request2": "dev-trunk",
+                "pear/net_growl": "dev-trunk",
+                "pear/pear-core-minimal": "1.10.1",
+                "pear/versioncontrol_git": "@dev",
+                "pear/versioncontrol_svn": "~0.5",
+                "phpdocumentor/phpdocumentor": "2.x",
+                "phploc/phploc": "~2.0.6",
+                "phpmd/phpmd": "~2.2",
+                "phpunit/phpunit": ">=3.7",
+                "sebastian/git": "~1.0",
+                "sebastian/phpcpd": "2.x",
+                "siad007/versioncontrol_hg": "^1.0",
+                "simpletest/simpletest": "^1.1",
+                "squizlabs/php_codesniffer": "~2.2"
+            },
+            "suggest": {
+                "pdepend/pdepend": "PHP version of JDepend",
+                "pear/archive_tar": "Tar file management class",
+                "pear/versioncontrol_git": "A library that provides OO interface to handle Git repository",
+                "pear/versioncontrol_svn": "A simple OO-style interface for Subversion, the free/open-source version control system",
+                "phpdocumentor/phpdocumentor": "Documentation Generator for PHP",
+                "phploc/phploc": "A tool for quickly measuring the size of a PHP project",
+                "phpmd/phpmd": "PHP version of PMD tool",
+                "phpunit/php-code-coverage": "Library that provides collection, processing, and rendering functionality for PHP code coverage information",
+                "phpunit/phpunit": "The PHP Unit Testing Framework",
+                "sebastian/phpcpd": "Copy/Paste Detector (CPD) for PHP code",
+                "siad007/versioncontrol_hg": "A library for interfacing with Mercurial repositories.",
+                "tedivm/jshrink": "Javascript Minifier built in PHP"
+            },
+            "bin": [
+                "bin/phing"
+            ],
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.16.x-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "classes/phing/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "include-path": [
+                "classes"
+            ],
+            "license": [
+                "LGPL-3.0"
+            ],
+            "authors": [
+                {
+                    "name": "Michiel Rook",
+                    "email": "mrook@php.net"
+                },
+                {
+                    "name": "Phing Community",
+                    "homepage": "https://www.phing.info/trac/wiki/Development/Contributors"
+                }
+            ],
+            "description": "PHing Is Not GNU make; it's a PHP project build system or build tool based on Apache Ant.",
+            "homepage": "https://www.phing.info/",
+            "keywords": [
+                "build",
+                "phing",
+                "task",
+                "tool"
+            ],
+            "time": "2016-12-22T20:16:33+00:00"
+        },
+        {
+            "name": "psr/container",
+            "version": "1.0.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/php-fig/container.git",
+                "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
+                "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Psr\\Container\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "PHP-FIG",
+                    "homepage": "http://www.php-fig.org/"
+                }
+            ],
+            "description": "Common Container Interface (PHP FIG PSR-11)",
+            "homepage": "https://github.com/php-fig/container",
+            "keywords": [
+                "PSR-11",
+                "container",
+                "container-interface",
+                "container-interop",
+                "psr"
+            ],
+            "time": "2017-02-14T16:28:37+00:00"
+        },
+        {
+            "name": "psr/http-message",
+            "version": "1.0.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/php-fig/http-message.git",
+                "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363",
+                "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Psr\\Http\\Message\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "PHP-FIG",
+                    "homepage": "http://www.php-fig.org/"
+                }
+            ],
+            "description": "Common interface for HTTP messages",
+            "homepage": "https://github.com/php-fig/http-message",
+            "keywords": [
+                "http",
+                "http-message",
+                "psr",
+                "psr-7",
+                "request",
+                "response"
+            ],
+            "time": "2016-08-06T14:39:51+00:00"
+        },
+        {
+            "name": "psr/log",
+            "version": "1.0.2",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/php-fig/log.git",
+                "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
+                "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Psr\\Log\\": "Psr/Log/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "PHP-FIG",
+                    "homepage": "http://www.php-fig.org/"
+                }
+            ],
+            "description": "Common interface for logging libraries",
+            "homepage": "https://github.com/php-fig/log",
+            "keywords": [
+                "log",
+                "psr",
+                "psr-3"
+            ],
+            "time": "2016-10-10T12:19:37+00:00"
+        },
+        {
+            "name": "serialssolutions/summon",
+            "version": "v1.1.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/summon/Summon.php.git",
+                "reference": "170beb3b0505f2047613b101213379537e651ea2"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/summon/Summon.php/zipball/170beb3b0505f2047613b101213379537e651ea2",
+                "reference": "170beb3b0505f2047613b101213379537e651ea2",
+                "shasum": ""
+            },
+            "type": "library",
+            "autoload": {
+                "psr-0": {
+                    "SerialsSolutions": ""
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "GPL-2.0"
+            ],
+            "authors": [
+                {
+                    "name": "Demian Katz",
+                    "email": "demian.katz@villanova.edu"
+                }
+            ],
+            "description": "Library for interacting with Serials Solutions' Summon API.",
+            "time": "2017-05-17T20:36:35+00:00"
+        },
+        {
+            "name": "swagger-api/swagger-ui",
+            "version": "v2.2.10",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/swagger-api/swagger-ui.git",
+                "reference": "64dc3060b3700b12e466f8d67b7d7ec3574b015f"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/swagger-api/swagger-ui/zipball/64dc3060b3700b12e466f8d67b7d7ec3574b015f",
+                "reference": "64dc3060b3700b12e466f8d67b7d7ec3574b015f",
+                "shasum": ""
+            },
+            "type": "library",
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "Apache-2.0"
+            ],
+            "authors": [
+                {
+                    "name": "Tony Tam",
+                    "email": "fehguy@gmail.com"
+                },
+                {
+                    "name": "Mohsen Azimi",
+                    "email": "me@azimi.me"
+                }
+            ],
+            "description": "Swagger UI is a dependency-free collection of HTML, JavaScript, and CSS assets that dynamically generate beautiful documentation from a Swagger-compliant API",
+            "homepage": "http://swagger.io",
+            "keywords": [
+                "api",
+                "documentation",
+                "openapi",
+                "specification",
+                "swagger",
+                "ui"
+            ],
+            "time": "2017-01-05T08:57:09+00:00"
+        },
+        {
+            "name": "symfony/yaml",
+            "version": "v3.3.2",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/yaml.git",
+                "reference": "9752a30000a8ca9f4b34b5227d15d0101b96b063"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/yaml/zipball/9752a30000a8ca9f4b34b5227d15d0101b96b063",
+                "reference": "9752a30000a8ca9f4b34b5227d15d0101b96b063",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.5.9"
+            },
+            "require-dev": {
+                "symfony/console": "~2.8|~3.0"
+            },
+            "suggest": {
+                "symfony/console": "For validating YAML files using the lint command"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "3.3-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\Component\\Yaml\\": ""
+                },
+                "exclude-from-classmap": [
+                    "/Tests/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Fabien Potencier",
+                    "email": "fabien@symfony.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Symfony Yaml Component",
+            "homepage": "https://symfony.com",
+            "time": "2017-06-02T22:05:06+00:00"
+        },
+        {
+            "name": "vufind-org/vufindcode",
+            "version": "v1.0.3",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/vufind-org/vufindcode.git",
+                "reference": "f50091c35f50865b926bac549e671347c4d4389d"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/vufind-org/vufindcode/zipball/f50091c35f50865b926bac549e671347c4d4389d",
+                "reference": "f50091c35f50865b926bac549e671347c4d4389d",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.0"
+            },
+            "require-dev": {
+                "friendsofphp/php-cs-fixer": "1.11.3",
+                "phploc/phploc": "2.0.6",
+                "phpmd/phpmd": "1.5.0",
+                "phpunit/phpunit": "4.8.4",
+                "sebastian/phpcpd": "1.4.3",
+                "squizlabs/php_codesniffer": "2.6.0"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-0": {
+                    "VuFindCode\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "GPL-2.0"
+            ],
+            "authors": [
+                {
+                    "name": "Demian Katz",
+                    "email": "demian.katz@villanova.edu"
+                }
+            ],
+            "description": "Class for representing ISBNs (a VuFind support library)",
+            "homepage": "https://vufind.org/",
+            "time": "2016-06-06T19:12:16+00:00"
+        },
+        {
+            "name": "vufind-org/vufindharvest",
+            "version": "v2.3.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/vufind-org/vufindharvest.git",
+                "reference": "c59e0a64b59873120c5cda32cbb8654629a8320e"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/vufind-org/vufindharvest/zipball/c59e0a64b59873120c5cda32cbb8654629a8320e",
+                "reference": "c59e0a64b59873120c5cda32cbb8654629a8320e",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.6",
+                "zendframework/zend-console": ">=2.2",
+                "zendframework/zend-http": ">=2.2"
+            },
+            "require-dev": {
+                "friendsofphp/php-cs-fixer": "1.11.6",
+                "phing/phing": "2.16.0",
+                "phpdocumentor/phpdocumentor": "2.9.0",
+                "phploc/phploc": "3.0.1",
+                "phpmd/phpmd": "2.6.0",
+                "phpunit/phpunit": "5.7.15",
+                "sebastian/phpcpd": "2.0.4",
+                "squizlabs/php_codesniffer": "2.8.1"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "VuFindHarvest\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "GPL-2.0"
+            ],
+            "authors": [
+                {
+                    "name": "Demian Katz",
+                    "email": "demian.katz@villanova.edu",
+                    "role": "Maintainer"
+                }
+            ],
+            "description": "VuFind Harvest Tools",
+            "homepage": "https://vufind.org/",
+            "time": "2017-04-06T18:31:39+00:00"
+        },
+        {
+            "name": "vufind-org/vufindhttp",
+            "version": "v2.1.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/vufind-org/vufindhttp.git",
+                "reference": "b1b7dcd5f2c87a199fd3d6d439898cc7ddd0d7ca"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/vufind-org/vufindhttp/zipball/b1b7dcd5f2c87a199fd3d6d439898cc7ddd0d7ca",
+                "reference": "b1b7dcd5f2c87a199fd3d6d439898cc7ddd0d7ca",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.4",
+                "zendframework/zend-http": ">=2.2"
+            },
+            "require-dev": {
+                "friendsofphp/php-cs-fixer": "1.11.3",
+                "phploc/phploc": "2.0.6",
+                "phpmd/phpmd": "1.5.0",
+                "phpunit/phpunit": "4.8.4",
+                "sebastian/phpcpd": "2.0.0",
+                "squizlabs/php_codesniffer": "2.6.0",
+                "zendframework/zend-uri": ">=2.2"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-0": {
+                    "VuFindHttp\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "GPL-2.0"
+            ],
+            "authors": [
+                {
+                    "name": "David Maus",
+                    "email": "maus@hab.de",
+                    "role": "developer"
+                },
+                {
+                    "name": "Demian Katz",
+                    "email": "demian.katz@villanova.edu",
+                    "role": "Maintainer"
+                }
+            ],
+            "description": "VuFind HTTP service library",
+            "homepage": "https://vufind.org/",
+            "time": "2016-09-23T12:51:36+00:00"
+        },
+        {
+            "name": "yajra/laravel-pdo-via-oci8",
+            "version": "v1.3.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/yajra/pdo-via-oci8.git",
+                "reference": "b3e52482af67770a0b3ea620f11ba0a1b38b4afd"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/yajra/pdo-via-oci8/zipball/b3e52482af67770a0b3ea620f11ba0a1b38b4afd",
+                "reference": "b3e52482af67770a0b3ea620f11ba0a1b38b4afd",
+                "shasum": ""
+            },
+            "require-dev": {
+                "phpunit/phpunit": "4.0.*"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Yajra\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Arjay Angeles",
+                    "email": "aqangeles@gmail.com"
+                }
+            ],
+            "description": "PDO userspace driver proxying calls to PHP OCI8 driver",
+            "time": "2017-02-02T02:51:53+00:00"
+        },
+        {
+            "name": "zendframework/zend-cache",
+            "version": "2.7.2",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/zendframework/zend-cache.git",
+                "reference": "c98331b96d3b9d9b24cf32d02660602edb34d039"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/zendframework/zend-cache/zipball/c98331b96d3b9d9b24cf32d02660602edb34d039",
+                "reference": "c98331b96d3b9d9b24cf32d02660602edb34d039",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^5.5 || ^7.0",
+                "zendframework/zend-eventmanager": "^2.6.2 || ^3.0",
+                "zendframework/zend-servicemanager": "^2.7.5 || ^3.0.3",
+                "zendframework/zend-stdlib": "^2.7 || ^3.0"
+            },
+            "require-dev": {
+                "phpbench/phpbench": "^0.10.0",
+                "phpunit/phpunit": "^4.8",
+                "zendframework/zend-coding-standard": "~1.0.0",
+                "zendframework/zend-serializer": "^2.6",
+                "zendframework/zend-session": "^2.6.2"
+            },
+            "suggest": {
+                "ext-apc": "APC or compatible extension, to use the APC storage adapter",
+                "ext-apcu": "APCU >= 5.1.0, to use the APCu storage adapter",
+                "ext-dba": "DBA, to use the DBA storage adapter",
+                "ext-memcache": "Memcache >= 2.0.0 to use the Memcache storage adapter",
+                "ext-memcached": "Memcached >= 1.0.0 to use the Memcached storage adapter",
+                "ext-mongo": "Mongo, to use MongoDb storage adapter",
+                "ext-redis": "Redis, to use Redis storage adapter",
+                "ext-wincache": "WinCache, to use the WinCache storage adapter",
+                "ext-xcache": "XCache, to use the XCache storage adapter",
+                "mongofill/mongofill": "Alternative to ext-mongo - a pure PHP implementation designed as a drop in replacement",
+                "zendframework/zend-serializer": "Zend\\Serializer component",
+                "zendframework/zend-session": "Zend\\Session component"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.7-dev",
+                    "dev-develop": "2.8-dev"
+                },
+                "zf": {
+                    "component": "Zend\\Cache",
+                    "config-provider": "Zend\\Cache\\ConfigProvider"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Zend\\Cache\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "description": "provides a generic way to cache any data",
+            "homepage": "https://github.com/zendframework/zend-cache",
+            "keywords": [
+                "cache",
+                "zf2"
+            ],
+            "time": "2016-12-16T11:35:47+00:00"
+        },
+        {
+            "name": "zendframework/zend-captcha",
+            "version": "2.7.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/zendframework/zend-captcha.git",
+                "reference": "2d56293a5ae3e45e7c8ee7030aa8b305768d8014"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/zendframework/zend-captcha/zipball/2d56293a5ae3e45e7c8ee7030aa8b305768d8014",
+                "reference": "2d56293a5ae3e45e7c8ee7030aa8b305768d8014",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^5.6 || ^7.0",
+                "zendframework/zend-math": "^2.6 || ^3.0",
+                "zendframework/zend-stdlib": "^2.7 || ^3.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "~4.8",
+                "zendframework/zend-coding-standard": "~1.0.0",
+                "zendframework/zend-session": "^2.6",
+                "zendframework/zend-text": "^2.6",
+                "zendframework/zend-validator": "^2.6",
+                "zendframework/zendservice-recaptcha": "^3.0"
+            },
+            "suggest": {
+                "zendframework/zend-i18n-resources": "Translations of captcha messages",
+                "zendframework/zend-session": "Zend\\Session component",
+                "zendframework/zend-text": "Zend\\Text component",
+                "zendframework/zend-validator": "Zend\\Validator component",
+                "zendframework/zendservice-recaptcha": "ZendService\\ReCaptcha component"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.7-dev",
+                    "dev-develop": "2.8-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Zend\\Captcha\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "homepage": "https://github.com/zendframework/zend-captcha",
+            "keywords": [
+                "captcha",
+                "zf2"
+            ],
+            "time": "2017-02-23T08:09:44+00:00"
+        },
+        {
+            "name": "zendframework/zend-code",
+            "version": "2.6.3",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/zendframework/zend-code.git",
+                "reference": "95033f061b083e16cdee60530ec260d7d628b887"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/zendframework/zend-code/zipball/95033f061b083e16cdee60530ec260d7d628b887",
+                "reference": "95033f061b083e16cdee60530ec260d7d628b887",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^5.5 || 7.0.0 - 7.0.4 || ^7.0.6",
+                "zendframework/zend-eventmanager": "^2.6 || ^3.0"
+            },
+            "require-dev": {
+                "doctrine/annotations": "~1.0",
+                "fabpot/php-cs-fixer": "1.7.*",
+                "phpunit/phpunit": "^4.8.21",
+                "zendframework/zend-stdlib": "^2.7 || ^3.0"
+            },
+            "suggest": {
+                "doctrine/annotations": "Doctrine\\Common\\Annotations >=1.0 for annotation features",
+                "zendframework/zend-stdlib": "Zend\\Stdlib component"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.6-dev",
+                    "dev-develop": "2.7-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Zend\\Code\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "description": "provides facilities to generate arbitrary code using an object oriented interface",
+            "homepage": "https://github.com/zendframework/zend-code",
+            "keywords": [
+                "code",
+                "zf2"
+            ],
+            "time": "2016-04-20T17:26:42+00:00"
+        },
+        {
+            "name": "zendframework/zend-config",
+            "version": "2.6.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/zendframework/zend-config.git",
+                "reference": "2920e877a9f6dca9fa8f6bd3b1ffc2e19bb1e30d"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/zendframework/zend-config/zipball/2920e877a9f6dca9fa8f6bd3b1ffc2e19bb1e30d",
+                "reference": "2920e877a9f6dca9fa8f6bd3b1ffc2e19bb1e30d",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^5.5 || ^7.0",
+                "zendframework/zend-stdlib": "^2.7 || ^3.0"
+            },
+            "require-dev": {
+                "fabpot/php-cs-fixer": "1.7.*",
+                "phpunit/phpunit": "~4.0",
+                "zendframework/zend-filter": "^2.6",
+                "zendframework/zend-i18n": "^2.5",
+                "zendframework/zend-json": "^2.6.1",
+                "zendframework/zend-servicemanager": "^2.7.5 || ^3.0.3"
+            },
+            "suggest": {
+                "zendframework/zend-filter": "Zend\\Filter component",
+                "zendframework/zend-i18n": "Zend\\I18n component",
+                "zendframework/zend-json": "Zend\\Json to use the Json reader or writer classes",
+                "zendframework/zend-servicemanager": "Zend\\ServiceManager for use with the Config Factory to retrieve reader and writer instances"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.6-dev",
+                    "dev-develop": "2.7-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Zend\\Config\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "description": "provides a nested object property based user interface for accessing this configuration data within application code",
+            "homepage": "https://github.com/zendframework/zend-config",
+            "keywords": [
+                "config",
+                "zf2"
+            ],
+            "time": "2016-02-04T23:01:10+00:00"
+        },
+        {
+            "name": "zendframework/zend-console",
+            "version": "2.6.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/zendframework/zend-console.git",
+                "reference": "cbbdfdfa0564aa20d1c6c6ef3daeafe6aec02360"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/zendframework/zend-console/zipball/cbbdfdfa0564aa20d1c6c6ef3daeafe6aec02360",
+                "reference": "cbbdfdfa0564aa20d1c6c6ef3daeafe6aec02360",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^5.5 || ^7.0",
+                "zendframework/zend-stdlib": "^2.7 || ^3.0"
+            },
+            "require-dev": {
+                "fabpot/php-cs-fixer": "1.7.*",
+                "phpunit/phpunit": "^4.0",
+                "zendframework/zend-filter": "^2.6",
+                "zendframework/zend-json": "^2.6",
+                "zendframework/zend-validator": "^2.5"
+            },
+            "suggest": {
+                "zendframework/zend-filter": "To support DefaultRouteMatcher usage",
+                "zendframework/zend-validator": "To support DefaultRouteMatcher usage"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.6-dev",
+                    "dev-develop": "2.7-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Zend\\Console\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "homepage": "https://github.com/zendframework/zend-console",
+            "keywords": [
+                "console",
+                "zf2"
+            ],
+            "time": "2016-02-09T17:15:12+00:00"
+        },
+        {
+            "name": "zendframework/zend-crypt",
+            "version": "3.2.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/zendframework/zend-crypt.git",
+                "reference": "274cdcb77a2165d6aff36b606e9d1c687ba9386c"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/zendframework/zend-crypt/zipball/274cdcb77a2165d6aff36b606e9d1c687ba9386c",
+                "reference": "274cdcb77a2165d6aff36b606e9d1c687ba9386c",
+                "shasum": ""
+            },
+            "require": {
+                "container-interop/container-interop": "~1.0",
+                "ext-mbstring": "*",
+                "php": "^5.6 || ^7.0",
+                "zendframework/zend-math": "^3.0",
+                "zendframework/zend-stdlib": "^2.7 || ^3.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^5.6.7",
+                "squizlabs/php_codesniffer": "^2.3.1"
+            },
+            "suggest": {
+                "ext-openssl": "Required for most features of Zend\\Crypt"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "3.1-dev",
+                    "dev-develop": "3.2-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Zend\\Crypt\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "homepage": "https://github.com/zendframework/zend-crypt",
+            "keywords": [
+                "crypt",
+                "zf2"
+            ],
+            "time": "2016-12-06T15:33:37+00:00"
+        },
+        {
+            "name": "zendframework/zend-db",
+            "version": "2.8.2",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/zendframework/zend-db.git",
+                "reference": "5926a1a2e7e035546b690cb7d4c11a3c47db2c98"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/zendframework/zend-db/zipball/5926a1a2e7e035546b690cb7d4c11a3c47db2c98",
+                "reference": "5926a1a2e7e035546b690cb7d4c11a3c47db2c98",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^5.5 || ^7.0",
+                "zendframework/zend-stdlib": "^2.7 || ^3.0"
+            },
+            "require-dev": {
+                "fabpot/php-cs-fixer": "1.7.*",
+                "phpunit/phpunit": "~4.0",
+                "zendframework/zend-eventmanager": "^2.6.2 || ^3.0",
+                "zendframework/zend-hydrator": "^1.1 || ^2.1",
+                "zendframework/zend-servicemanager": "^2.7.5 || ^3.0.3"
+            },
+            "suggest": {
+                "zendframework/zend-eventmanager": "Zend\\EventManager component",
+                "zendframework/zend-hydrator": "Zend\\Hydrator component for using HydratingResultSets",
+                "zendframework/zend-servicemanager": "Zend\\ServiceManager component"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.8-dev",
+                    "dev-develop": "2.9-dev"
+                },
+                "zf": {
+                    "component": "Zend\\Db",
+                    "config-provider": "Zend\\Db\\ConfigProvider"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Zend\\Db\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "homepage": "https://github.com/zendframework/zend-db",
+            "keywords": [
+                "db",
+                "zf2"
+            ],
+            "time": "2016-08-09T19:28:55+00:00"
+        },
+        {
+            "name": "zendframework/zend-diactoros",
+            "version": "1.4.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/zendframework/zend-diactoros.git",
+                "reference": "b03f285a333f51e58c95cce54109a4a9ed691436"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/zendframework/zend-diactoros/zipball/b03f285a333f51e58c95cce54109a4a9ed691436",
+                "reference": "b03f285a333f51e58c95cce54109a4a9ed691436",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^5.4 || ^7.0",
+                "psr/http-message": "~1.0"
+            },
+            "provide": {
+                "psr/http-message-implementation": "1.0"
+            },
+            "require-dev": {
+                "ext-dom": "*",
+                "ext-libxml": "*",
+                "phpunit/phpunit": "^4.6 || ^5.5",
+                "zendframework/zend-coding-standard": "~1.0.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.4-dev",
+                    "dev-develop": "1.5-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Zend\\Diactoros\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-2-Clause"
+            ],
+            "description": "PSR HTTP Message implementations",
+            "homepage": "https://github.com/zendframework/zend-diactoros",
+            "keywords": [
+                "http",
+                "psr",
+                "psr-7"
+            ],
+            "time": "2017-04-06T16:18:34+00:00"
+        },
+        {
+            "name": "zendframework/zend-dom",
+            "version": "2.6.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/zendframework/zend-dom.git",
+                "reference": "a9e145b2b52fe6de5a7a6b0ddb5c773c2c72d59e"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/zendframework/zend-dom/zipball/a9e145b2b52fe6de5a7a6b0ddb5c773c2c72d59e",
+                "reference": "a9e145b2b52fe6de5a7a6b0ddb5c773c2c72d59e",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.5"
+            },
+            "require-dev": {
+                "fabpot/php-cs-fixer": "1.7.*",
+                "phpunit/phpunit": "~4.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.5-dev",
+                    "dev-develop": "2.6-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Zend\\Dom\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "description": "provides tools for working with DOM documents and structures",
+            "homepage": "https://github.com/zendframework/zend-dom",
+            "keywords": [
+                "dom",
+                "zf2"
+            ],
+            "time": "2015-10-14T03:37:48+00:00"
+        },
+        {
+            "name": "zendframework/zend-escaper",
+            "version": "2.5.2",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/zendframework/zend-escaper.git",
+                "reference": "2dcd14b61a72d8b8e27d579c6344e12c26141d4e"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/zendframework/zend-escaper/zipball/2dcd14b61a72d8b8e27d579c6344e12c26141d4e",
+                "reference": "2dcd14b61a72d8b8e27d579c6344e12c26141d4e",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.5"
+            },
+            "require-dev": {
+                "fabpot/php-cs-fixer": "1.7.*",
+                "phpunit/phpunit": "~4.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.5-dev",
+                    "dev-develop": "2.6-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Zend\\Escaper\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "homepage": "https://github.com/zendframework/zend-escaper",
+            "keywords": [
+                "escaper",
+                "zf2"
+            ],
+            "time": "2016-06-30T19:48:38+00:00"
+        },
+        {
+            "name": "zendframework/zend-eventmanager",
+            "version": "3.1.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/zendframework/zend-eventmanager.git",
+                "reference": "c3bce7b7d47c54040b9ae51bc55491c72513b75d"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/zendframework/zend-eventmanager/zipball/c3bce7b7d47c54040b9ae51bc55491c72513b75d",
+                "reference": "c3bce7b7d47c54040b9ae51bc55491c72513b75d",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^5.6 || ^7.0"
+            },
+            "require-dev": {
+                "athletic/athletic": "^0.1",
+                "container-interop/container-interop": "^1.1.0",
+                "phpunit/phpunit": "^5.6",
+                "zendframework/zend-coding-standard": "~1.0.0",
+                "zendframework/zend-stdlib": "^2.7.3 || ^3.0"
+            },
+            "suggest": {
+                "container-interop/container-interop": "^1.1.0, to use the lazy listeners feature",
+                "zendframework/zend-stdlib": "^2.7.3 || ^3.0, to use the FilterChain feature"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "3.1-dev",
+                    "dev-develop": "3.2-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Zend\\EventManager\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "description": "Trigger and listen to events within a PHP application",
+            "homepage": "https://github.com/zendframework/zend-eventmanager",
+            "keywords": [
+                "event",
+                "eventmanager",
+                "events",
+                "zf2"
+            ],
+            "time": "2016-12-19T21:47:12+00:00"
+        },
+        {
+            "name": "zendframework/zend-feed",
+            "version": "2.8.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/zendframework/zend-feed.git",
+                "reference": "94579e805dd108683209fe14b3b5d4276de3de6e"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/zendframework/zend-feed/zipball/94579e805dd108683209fe14b3b5d4276de3de6e",
+                "reference": "94579e805dd108683209fe14b3b5d4276de3de6e",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^5.6 || ^7.0",
+                "zendframework/zend-escaper": "^2.5",
+                "zendframework/zend-stdlib": "^2.7 || ^3.1"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^6.0.8 || ^5.7.15",
+                "psr/http-message": "^1.0",
+                "zendframework/zend-cache": "^2.6",
+                "zendframework/zend-coding-standard": "~1.0.0",
+                "zendframework/zend-db": "^2.7",
+                "zendframework/zend-http": "^2.5.4",
+                "zendframework/zend-servicemanager": "^2.7.5 || ^3.0.3",
+                "zendframework/zend-validator": "^2.6"
+            },
+            "suggest": {
+                "psr/http-message": "PSR-7 ^1.0, if you wish to use Zend\\Feed\\Reader\\Http\\Psr7ResponseDecorator",
+                "zendframework/zend-cache": "Zend\\Cache component, for optionally caching feeds between requests",
+                "zendframework/zend-db": "Zend\\Db component, for use with PubSubHubbub",
+                "zendframework/zend-http": "Zend\\Http for PubSubHubbub, and optionally for use with Zend\\Feed\\Reader",
+                "zendframework/zend-servicemanager": "Zend\\ServiceManager component, for easily extending ExtensionManager implementations",
+                "zendframework/zend-validator": "Zend\\Validator component, for validating email addresses used in Atom feeds and entries ehen using the Writer subcomponent"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.8-dev",
+                    "dev-develop": "2.9-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Zend\\Feed\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "description": "provides functionality for consuming RSS and Atom feeds",
+            "homepage": "https://github.com/zendframework/zend-feed",
+            "keywords": [
+                "feed",
+                "zf2"
+            ],
+            "time": "2017-04-01T15:03:14+00:00"
+        },
+        {
+            "name": "zendframework/zend-filter",
+            "version": "2.7.2",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/zendframework/zend-filter.git",
+                "reference": "b8d0ff872f126631bf63a932e33aa2d22d467175"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/zendframework/zend-filter/zipball/b8d0ff872f126631bf63a932e33aa2d22d467175",
+                "reference": "b8d0ff872f126631bf63a932e33aa2d22d467175",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^5.5 || ^7.0",
+                "zendframework/zend-stdlib": "^2.7 || ^3.0"
+            },
+            "require-dev": {
+                "pear/archive_tar": "^1.4",
+                "phpunit/phpunit": "^6.0.10 || ^5.7.17",
+                "zendframework/zend-coding-standard": "~1.0.0",
+                "zendframework/zend-crypt": "^2.6 || ^3.0",
+                "zendframework/zend-servicemanager": "^2.7.5 || ^3.0.3",
+                "zendframework/zend-uri": "^2.5"
+            },
+            "suggest": {
+                "zendframework/zend-crypt": "Zend\\Crypt component, for encryption filters",
+                "zendframework/zend-i18n": "Zend\\I18n component for filters depending on i18n functionality",
+                "zendframework/zend-servicemanager": "Zend\\ServiceManager component, for using the filter chain functionality",
+                "zendframework/zend-uri": "Zend\\Uri component, for the UriNormalize filter"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.7-dev",
+                    "dev-develop": "2.8-dev"
+                },
+                "zf": {
+                    "component": "Zend\\Filter",
+                    "config-provider": "Zend\\Filter\\ConfigProvider"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Zend\\Filter\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "description": "provides a set of commonly needed data filters",
+            "homepage": "https://github.com/zendframework/zend-filter",
+            "keywords": [
+                "filter",
+                "zf2"
+            ],
+            "time": "2017-05-17T20:56:17+00:00"
+        },
+        {
+            "name": "zendframework/zend-form",
+            "version": "2.10.2",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/zendframework/zend-form.git",
+                "reference": "252db729887844025772bb8045f8df605850ed9c"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/zendframework/zend-form/zipball/252db729887844025772bb8045f8df605850ed9c",
+                "reference": "252db729887844025772bb8045f8df605850ed9c",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^7.0 || ^5.6",
+                "zendframework/zend-hydrator": "^1.1 || ^2.1",
+                "zendframework/zend-inputfilter": "^2.6",
+                "zendframework/zend-stdlib": "^2.7 || ^3.0"
+            },
+            "require-dev": {
+                "doctrine/annotations": "~1.0",
+                "phpunit/phpunit": "^6.0.8 || ^5.7.15",
+                "zendframework/zend-cache": "^2.6.1",
+                "zendframework/zend-captcha": "^2.7.1",
+                "zendframework/zend-code": "^2.6 || ^3.0",
+                "zendframework/zend-coding-standard": "~1.0.0",
+                "zendframework/zend-escaper": "^2.5",
+                "zendframework/zend-eventmanager": "^2.6.2 || ^3.0",
+                "zendframework/zend-filter": "^2.6",
+                "zendframework/zend-i18n": "^2.6",
+                "zendframework/zend-servicemanager": "^2.7.5 || ^3.0.3",
+                "zendframework/zend-session": "^2.6.2",
+                "zendframework/zend-text": "^2.6",
+                "zendframework/zend-validator": "^2.6",
+                "zendframework/zend-view": "^2.6.2",
+                "zendframework/zendservice-recaptcha": "^3.0.0"
+            },
+            "suggest": {
+                "zendframework/zend-captcha": "^2.7.1, required for using CAPTCHA form elements",
+                "zendframework/zend-code": "^2.6 || ^3.0, required to use zend-form annotations support",
+                "zendframework/zend-eventmanager": "^2.6.2 || ^3.0, reuired for zend-form annotations support",
+                "zendframework/zend-i18n": "^2.6, required when using zend-form view helpers",
+                "zendframework/zend-servicemanager": "^2.7.5 || ^3.0.3, required to use the form factories or provide services",
+                "zendframework/zend-view": "^2.6.2, required for using the zend-form view helpers",
+                "zendframework/zendservice-recaptcha": "in order to use the ReCaptcha form element"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.10-dev",
+                    "dev-develop": "2.11-dev"
+                },
+                "zf": {
+                    "component": "Zend\\Form",
+                    "config-provider": "Zend\\Form\\ConfigProvider"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Zend\\Form\\": "src/"
+                },
+                "files": [
+                    "autoload/formElementManagerPolyfill.php"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "homepage": "https://github.com/zendframework/zend-form",
+            "keywords": [
+                "form",
+                "zf2"
+            ],
+            "time": "2017-05-18T14:59:53+00:00"
+        },
+        {
+            "name": "zendframework/zend-http",
+            "version": "2.6.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/zendframework/zend-http.git",
+                "reference": "09f4d279f46d86be63171ff62ee0f79eca878678"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/zendframework/zend-http/zipball/09f4d279f46d86be63171ff62ee0f79eca878678",
+                "reference": "09f4d279f46d86be63171ff62ee0f79eca878678",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^5.5 || ^7.0",
+                "zendframework/zend-loader": "^2.5",
+                "zendframework/zend-stdlib": "^2.5 || ^3.0",
+                "zendframework/zend-uri": "^2.5",
+                "zendframework/zend-validator": "^2.5"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^4.0",
+                "zendframework/zend-coding-standard": "~1.0.0",
+                "zendframework/zend-config": "^2.5"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.6-dev",
+                    "dev-develop": "2.7-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Zend\\Http\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "description": "provides an easy interface for performing Hyper-Text Transfer Protocol (HTTP) requests",
+            "homepage": "https://github.com/zendframework/zend-http",
+            "keywords": [
+                "http",
+                "zf2"
+            ],
+            "time": "2017-01-31T14:41:02+00:00"
+        },
+        {
+            "name": "zendframework/zend-hydrator",
+            "version": "1.1.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/zendframework/zend-hydrator.git",
+                "reference": "22652e1661a5a10b3f564cf7824a2206cf5a4a65"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/zendframework/zend-hydrator/zipball/22652e1661a5a10b3f564cf7824a2206cf5a4a65",
+                "reference": "22652e1661a5a10b3f564cf7824a2206cf5a4a65",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^5.5 || ^7.0",
+                "zendframework/zend-stdlib": "^2.7 || ^3.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "~4.0",
+                "squizlabs/php_codesniffer": "^2.0@dev",
+                "zendframework/zend-eventmanager": "^2.6.2 || ^3.0",
+                "zendframework/zend-filter": "^2.6",
+                "zendframework/zend-inputfilter": "^2.6",
+                "zendframework/zend-serializer": "^2.6.1",
+                "zendframework/zend-servicemanager": "^2.7.5 || ^3.0.3"
+            },
+            "suggest": {
+                "zendframework/zend-eventmanager": "^2.6.2 || ^3.0, to support aggregate hydrator usage",
+                "zendframework/zend-filter": "^2.6, to support naming strategy hydrator usage",
+                "zendframework/zend-serializer": "^2.6.1, to use the SerializableStrategy",
+                "zendframework/zend-servicemanager": "^2.7.5 || ^3.0.3, to support hydrator plugin manager usage"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-release-1.0": "1.0-dev",
+                    "dev-release-1.1": "1.1-dev",
+                    "dev-master": "2.0-dev",
+                    "dev-develop": "2.1-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Zend\\Hydrator\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "homepage": "https://github.com/zendframework/zend-hydrator",
+            "keywords": [
+                "hydrator",
+                "zf2"
+            ],
+            "time": "2016-02-18T22:38:26+00:00"
+        },
+        {
+            "name": "zendframework/zend-i18n",
+            "version": "2.7.4",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/zendframework/zend-i18n.git",
+                "reference": "d3431e29cc00c2a1c6704e601d4371dbf24f6a31"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/zendframework/zend-i18n/zipball/d3431e29cc00c2a1c6704e601d4371dbf24f6a31",
+                "reference": "d3431e29cc00c2a1c6704e601d4371dbf24f6a31",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^7.0 || ^5.6",
+                "zendframework/zend-stdlib": "^2.7 || ^3.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^6.0.8 || ^5.7.15",
+                "zendframework/zend-cache": "^2.6.1",
+                "zendframework/zend-coding-standard": "~1.0.0",
+                "zendframework/zend-config": "^2.6",
+                "zendframework/zend-eventmanager": "^2.6.2 || ^3.0",
+                "zendframework/zend-filter": "^2.6.1",
+                "zendframework/zend-servicemanager": "^2.7.5 || ^3.0.3",
+                "zendframework/zend-validator": "^2.6",
+                "zendframework/zend-view": "^2.6.3"
+            },
+            "suggest": {
+                "ext-intl": "Required for most features of Zend\\I18n; included in default builds of PHP",
+                "zendframework/zend-cache": "Zend\\Cache component",
+                "zendframework/zend-config": "Zend\\Config component",
+                "zendframework/zend-eventmanager": "You should install this package to use the events in the translator",
+                "zendframework/zend-filter": "You should install this package to use the provided filters",
+                "zendframework/zend-i18n-resources": "Translation resources",
+                "zendframework/zend-servicemanager": "Zend\\ServiceManager component",
+                "zendframework/zend-validator": "You should install this package to use the provided validators",
+                "zendframework/zend-view": "You should install this package to use the provided view helpers"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.7-dev",
+                    "dev-develop": "2.8-dev"
+                },
+                "zf": {
+                    "component": "Zend\\I18n",
+                    "config-provider": "Zend\\I18n\\ConfigProvider"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Zend\\I18n\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "homepage": "https://github.com/zendframework/zend-i18n",
+            "keywords": [
+                "i18n",
+                "zf2"
+            ],
+            "time": "2017-05-17T17:00:12+00:00"
+        },
+        {
+            "name": "zendframework/zend-inputfilter",
+            "version": "2.7.4",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/zendframework/zend-inputfilter.git",
+                "reference": "699ab4916e0aa73104e1f9ff068ef6d33c5f5fe4"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/zendframework/zend-inputfilter/zipball/699ab4916e0aa73104e1f9ff068ef6d33c5f5fe4",
+                "reference": "699ab4916e0aa73104e1f9ff068ef6d33c5f5fe4",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^7.0 || ^5.6",
+                "zendframework/zend-filter": "^2.6",
+                "zendframework/zend-stdlib": "^2.7 || ^3.0",
+                "zendframework/zend-validator": "^2.6"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^6.0.8 || ^5.7.15",
+                "zendframework/zend-coding-standard": "~1.0.0",
+                "zendframework/zend-servicemanager": "^2.7.5 || ^3.0.3"
+            },
+            "suggest": {
+                "zendframework/zend-servicemanager": "To support plugin manager support"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.7-dev",
+                    "dev-develop": "2.8-dev"
+                },
+                "zf": {
+                    "component": "Zend\\InputFilter",
+                    "config-provider": "Zend\\InputFilter\\ConfigProvider"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Zend\\InputFilter\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "homepage": "https://github.com/zendframework/zend-inputfilter",
+            "keywords": [
+                "inputfilter",
+                "zf2"
+            ],
+            "time": "2017-05-18T14:20:56+00:00"
+        },
+        {
+            "name": "zendframework/zend-json",
+            "version": "3.0.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/zendframework/zend-json.git",
+                "reference": "f42a1588e75c2a3e338cd94c37906231e616daab"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/zendframework/zend-json/zipball/f42a1588e75c2a3e338cd94c37906231e616daab",
+                "reference": "f42a1588e75c2a3e338cd94c37906231e616daab",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^5.5 || ^7.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "~4.0",
+                "squizlabs/php_codesniffer": "^2.3",
+                "zendframework/zend-stdlib": "^2.7 || ^3.0"
+            },
+            "suggest": {
+                "zendframework/zend-json-server": "For implementing JSON-RPC servers",
+                "zendframework/zend-xml2json": "For converting XML documents to JSON"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "3.0-dev",
+                    "dev-develop": "3.1-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Zend\\Json\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "description": "provides convenience methods for serializing native PHP to JSON and decoding JSON to native PHP",
+            "homepage": "https://github.com/zendframework/zend-json",
+            "keywords": [
+                "json",
+                "zf2"
+            ],
+            "time": "2016-04-01T02:34:00+00:00"
+        },
+        {
+            "name": "zendframework/zend-loader",
+            "version": "2.5.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/zendframework/zend-loader.git",
+                "reference": "c5fd2f071bde071f4363def7dea8dec7393e135c"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/zendframework/zend-loader/zipball/c5fd2f071bde071f4363def7dea8dec7393e135c",
+                "reference": "c5fd2f071bde071f4363def7dea8dec7393e135c",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.23"
+            },
+            "require-dev": {
+                "fabpot/php-cs-fixer": "1.7.*",
+                "phpunit/phpunit": "~4.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.5-dev",
+                    "dev-develop": "2.6-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Zend\\Loader\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "homepage": "https://github.com/zendframework/zend-loader",
+            "keywords": [
+                "loader",
+                "zf2"
+            ],
+            "time": "2015-06-03T14:05:47+00:00"
+        },
+        {
+            "name": "zendframework/zend-log",
+            "version": "2.9.2",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/zendframework/zend-log.git",
+                "reference": "bf7489578d092d6ff7508117d1d920a4764fbd6a"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/zendframework/zend-log/zipball/bf7489578d092d6ff7508117d1d920a4764fbd6a",
+                "reference": "bf7489578d092d6ff7508117d1d920a4764fbd6a",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^5.6 || ^7.0",
+                "psr/log": "^1.0",
+                "zendframework/zend-servicemanager": "^2.7.5 || ^3.0.3",
+                "zendframework/zend-stdlib": "^2.7 || ^3.0"
+            },
+            "provide": {
+                "psr/log-implementation": "1.0.0"
+            },
+            "require-dev": {
+                "mikey179/vfsstream": "^1.6",
+                "phpunit/phpunit": "^5.7.15 || ^6.0.8",
+                "zendframework/zend-coding-standard": "~1.0.0",
+                "zendframework/zend-db": "^2.6",
+                "zendframework/zend-escaper": "^2.5",
+                "zendframework/zend-filter": "^2.5",
+                "zendframework/zend-mail": "^2.6.1",
+                "zendframework/zend-validator": "^2.6"
+            },
+            "suggest": {
+                "ext-mongo": "mongo extension to use Mongo writer",
+                "ext-mongodb": "mongodb extension to use MongoDB writer",
+                "zendframework/zend-console": "Zend\\Console component to use the RequestID log processor",
+                "zendframework/zend-db": "Zend\\Db component to use the database log writer",
+                "zendframework/zend-escaper": "Zend\\Escaper component, for use in the XML log formatter",
+                "zendframework/zend-mail": "Zend\\Mail component to use the email log writer",
+                "zendframework/zend-validator": "Zend\\Validator component to block invalid log messages"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.9-dev",
+                    "dev-develop": "2.10-dev"
+                },
+                "zf": {
+                    "component": "Zend\\Log",
+                    "config-provider": "Zend\\Log\\ConfigProvider"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Zend\\Log\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "description": "component for general purpose logging",
+            "homepage": "https://github.com/zendframework/zend-log",
+            "keywords": [
+                "log",
+                "logging",
+                "zf2"
+            ],
+            "time": "2017-05-17T16:03:26+00:00"
+        },
+        {
+            "name": "zendframework/zend-mail",
+            "version": "2.8.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/zendframework/zend-mail.git",
+                "reference": "248230940ab1453b2a532a8fde76c5a6470d7aad"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/zendframework/zend-mail/zipball/248230940ab1453b2a532a8fde76c5a6470d7aad",
+                "reference": "248230940ab1453b2a532a8fde76c5a6470d7aad",
+                "shasum": ""
+            },
+            "require": {
+                "ext-iconv": "*",
+                "php": "^7.0 || ^5.6",
+                "zendframework/zend-loader": "^2.5",
+                "zendframework/zend-mime": "^2.5",
+                "zendframework/zend-stdlib": "^2.7 || ^3.0",
+                "zendframework/zend-validator": "^2.6"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^6.0.8 || ^5.7.15",
+                "zendframework/zend-coding-standard": "~1.0.0",
+                "zendframework/zend-config": "^2.6",
+                "zendframework/zend-crypt": "^2.6",
+                "zendframework/zend-servicemanager": "^2.7.5 || ^3.0.3"
+            },
+            "suggest": {
+                "ext-intl": "Handle IDN in AddressList hostnames",
+                "zendframework/zend-crypt": "Crammd5 support in SMTP Auth",
+                "zendframework/zend-servicemanager": "^2.7.5 || ^3.0.3 when using SMTP to deliver messages"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.8-dev",
+                    "dev-develop": "2.9-dev"
+                },
+                "zf": {
+                    "component": "Zend\\Mail",
+                    "config-provider": "Zend\\Mail\\ConfigProvider"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Zend\\Mail\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "description": "provides generalized functionality to compose and send both text and MIME-compliant multipart e-mail messages",
+            "homepage": "https://github.com/zendframework/zend-mail",
+            "keywords": [
+                "mail",
+                "zf2"
+            ],
+            "time": "2017-06-08T20:03:58+00:00"
+        },
+        {
+            "name": "zendframework/zend-math",
+            "version": "3.0.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/zendframework/zend-math.git",
+                "reference": "fda3b4e6c3bb15c35adc6db38b2eacabaa243e65"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/zendframework/zend-math/zipball/fda3b4e6c3bb15c35adc6db38b2eacabaa243e65",
+                "reference": "fda3b4e6c3bb15c35adc6db38b2eacabaa243e65",
+                "shasum": ""
+            },
+            "require": {
+                "ext-mbstring": "*",
+                "paragonie/random_compat": "^2.0.2",
+                "php": "^5.5 || ^7.0"
+            },
+            "require-dev": {
+                "fabpot/php-cs-fixer": "1.7.*",
+                "phpunit/phpunit": "~4.0"
+            },
+            "suggest": {
+                "ext-bcmath": "If using the bcmath functionality",
+                "ext-gmp": "If using the gmp functionality"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "3.0-dev",
+                    "dev-develop": "3.1-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Zend\\Math\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "homepage": "https://github.com/zendframework/zend-math",
+            "keywords": [
+                "math",
+                "zf2"
+            ],
+            "time": "2016-04-28T17:37:42+00:00"
+        },
+        {
+            "name": "zendframework/zend-mime",
+            "version": "2.6.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/zendframework/zend-mime.git",
+                "reference": "9e53a97a3c190d45cc5d584daaaf487d509a9285"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/zendframework/zend-mime/zipball/9e53a97a3c190d45cc5d584daaaf487d509a9285",
+                "reference": "9e53a97a3c190d45cc5d584daaaf487d509a9285",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^5.5 || ^7.0",
+                "zendframework/zend-stdlib": "^2.7 || ^3.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^4.7 || ^5.7",
+                "zendframework/zend-coding-standard": "~1.0.0",
+                "zendframework/zend-mail": "^2.6"
+            },
+            "suggest": {
+                "zendframework/zend-mail": "Zend\\Mail component"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.6-dev",
+                    "dev-develop": "2.7-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Zend\\Mime\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "homepage": "https://github.com/zendframework/zend-mime",
+            "keywords": [
+                "mime",
+                "zf2"
+            ],
+            "time": "2017-01-16T16:43:38+00:00"
+        },
+        {
+            "name": "zendframework/zend-modulemanager",
+            "version": "2.7.2",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/zendframework/zend-modulemanager.git",
+                "reference": "2a59ab9a0dd7699a55050dff659ab0f28272b46e"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/zendframework/zend-modulemanager/zipball/2a59ab9a0dd7699a55050dff659ab0f28272b46e",
+                "reference": "2a59ab9a0dd7699a55050dff659ab0f28272b46e",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^5.5 || ^7.0",
+                "zendframework/zend-config": "^2.6",
+                "zendframework/zend-eventmanager": "^2.6.2 || ^3.0",
+                "zendframework/zend-stdlib": "^2.7 || ^3.0"
+            },
+            "require-dev": {
+                "fabpot/php-cs-fixer": "1.7.*",
+                "phpunit/phpunit": "~4.0",
+                "zendframework/zend-console": "^2.6",
+                "zendframework/zend-di": "^2.6",
+                "zendframework/zend-loader": "^2.5",
+                "zendframework/zend-mvc": "^2.7",
+                "zendframework/zend-servicemanager": "^2.7.5 || ^3.0.3"
+            },
+            "suggest": {
+                "zendframework/zend-config": "Zend\\Config component",
+                "zendframework/zend-console": "Zend\\Console component",
+                "zendframework/zend-loader": "Zend\\Loader component",
+                "zendframework/zend-mvc": "Zend\\Mvc component",
+                "zendframework/zend-servicemanager": "Zend\\ServiceManager component"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.7-dev",
+                    "dev-develop": "2.8-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Zend\\ModuleManager\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "homepage": "https://github.com/zendframework/zend-modulemanager",
+            "keywords": [
+                "modulemanager",
+                "zf2"
+            ],
+            "time": "2016-05-16T21:21:11+00:00"
+        },
+        {
+            "name": "zendframework/zend-mvc",
+            "version": "2.7.8",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/zendframework/zend-mvc.git",
+                "reference": "d374f7c64ee2b6c491bd3d9f54a5ef45ec492089"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/zendframework/zend-mvc/zipball/d374f7c64ee2b6c491bd3d9f54a5ef45ec492089",
+                "reference": "d374f7c64ee2b6c491bd3d9f54a5ef45ec492089",
+                "shasum": ""
+            },
+            "require": {
+                "container-interop/container-interop": "^1.1",
+                "php": "^5.5 || ^7.0",
+                "zendframework/zend-eventmanager": "^2.6.2 || ^3.0",
+                "zendframework/zend-form": "^2.7",
+                "zendframework/zend-hydrator": "^1.1 || ^2.1",
+                "zendframework/zend-psr7bridge": "^0.2",
+                "zendframework/zend-servicemanager": "^2.7.5 || ^3.0.3",
+                "zendframework/zend-stdlib": "^2.7.5 || ^3.0"
+            },
+            "require-dev": {
+                "fabpot/php-cs-fixer": "1.7.*",
+                "phpunit/phpunit": "^4.5",
+                "sebastian/version": "^1.0.4",
+                "zendframework/zend-authentication": "^2.5.3",
+                "zendframework/zend-cache": "^2.6.1",
+                "zendframework/zend-console": "^2.6",
+                "zendframework/zend-di": "^2.6",
+                "zendframework/zend-filter": "^2.6.1",
+                "zendframework/zend-http": "^2.5.4",
+                "zendframework/zend-i18n": "^2.6",
+                "zendframework/zend-inputfilter": "^2.6",
+                "zendframework/zend-json": "^2.6.1",
+                "zendframework/zend-log": "^2.7.1",
+                "zendframework/zend-modulemanager": "^2.7.1",
+                "zendframework/zend-serializer": "^2.6.1",
+                "zendframework/zend-session": "^2.6.2",
+                "zendframework/zend-text": "^2.6",
+                "zendframework/zend-uri": "^2.5",
+                "zendframework/zend-validator": "^2.6",
+                "zendframework/zend-version": "^2.5",
+                "zendframework/zend-view": "^2.6.3"
+            },
+            "suggest": {
+                "zendframework/zend-authentication": "Zend\\Authentication component for Identity plugin",
+                "zendframework/zend-config": "Zend\\Config component",
+                "zendframework/zend-console": "Zend\\Console component",
+                "zendframework/zend-di": "Zend\\Di component",
+                "zendframework/zend-filter": "Zend\\Filter component",
+                "zendframework/zend-http": "Zend\\Http component",
+                "zendframework/zend-i18n": "Zend\\I18n component for translatable segments",
+                "zendframework/zend-inputfilter": "Zend\\Inputfilter component",
+                "zendframework/zend-json": "Zend\\Json component",
+                "zendframework/zend-log": "Zend\\Log component",
+                "zendframework/zend-modulemanager": "Zend\\ModuleManager component",
+                "zendframework/zend-serializer": "Zend\\Serializer component",
+                "zendframework/zend-session": "Zend\\Session component for FlashMessenger, PRG, and FPRG plugins",
+                "zendframework/zend-text": "Zend\\Text component",
+                "zendframework/zend-uri": "Zend\\Uri component",
+                "zendframework/zend-validator": "Zend\\Validator component",
+                "zendframework/zend-version": "Zend\\Version component",
+                "zendframework/zend-view": "Zend\\View component"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.7-dev",
+                    "dev-develop": "3.0-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Zend\\Mvc\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "homepage": "https://github.com/zendframework/zend-mvc",
+            "keywords": [
+                "mvc",
+                "zf2"
+            ],
+            "time": "2016-05-31T17:18:50+00:00"
+        },
+        {
+            "name": "zendframework/zend-paginator",
+            "version": "2.7.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/zendframework/zend-paginator.git",
+                "reference": "42211f3e1e8230953c641e91fec5aa9fe964eb95"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/zendframework/zend-paginator/zipball/42211f3e1e8230953c641e91fec5aa9fe964eb95",
+                "reference": "42211f3e1e8230953c641e91fec5aa9fe964eb95",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^5.5 || ^7.0",
+                "zendframework/zend-stdlib": "^2.7 || ^3.0"
+            },
+            "require-dev": {
+                "fabpot/php-cs-fixer": "1.7.*",
+                "phpunit/phpunit": "~4.0",
+                "zendframework/zend-cache": "^2.6.1",
+                "zendframework/zend-config": "^2.6.0",
+                "zendframework/zend-db": "^2.7",
+                "zendframework/zend-filter": "^2.6.1",
+                "zendframework/zend-json": "^2.6.1",
+                "zendframework/zend-servicemanager": "^2.7.5 || ^3.0.3",
+                "zendframework/zend-view": "^2.6.3"
+            },
+            "suggest": {
+                "zendframework/zend-cache": "Zend\\Cache component to support cache features",
+                "zendframework/zend-db": "Zend\\Db component",
+                "zendframework/zend-filter": "Zend\\Filter component",
+                "zendframework/zend-json": "Zend\\Json component",
+                "zendframework/zend-servicemanager": "Zend\\ServiceManager component",
+                "zendframework/zend-view": "Zend\\View component"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.7-dev",
+                    "dev-develop": "2.8-dev"
+                },
+                "zf": {
+                    "component": "Zend\\Paginator",
+                    "config-provider": "Zend\\Paginator\\ConfigProvider"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Zend\\Paginator\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "homepage": "https://github.com/zendframework/zend-paginator",
+            "keywords": [
+                "paginator",
+                "zf2"
+            ],
+            "time": "2016-04-11T21:18:13+00:00"
+        },
+        {
+            "name": "zendframework/zend-psr7bridge",
+            "version": "0.2.2",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/zendframework/zend-psr7bridge.git",
+                "reference": "86c0b53b0c6381391c4add4a93a56e51d5c74605"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/zendframework/zend-psr7bridge/zipball/86c0b53b0c6381391c4add4a93a56e51d5c74605",
+                "reference": "86c0b53b0c6381391c4add4a93a56e51d5c74605",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.5",
+                "psr/http-message": "^1.0",
+                "zendframework/zend-diactoros": "^1.1",
+                "zendframework/zend-http": "^2.5"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^4.7",
+                "squizlabs/php_codesniffer": "^2.3"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0-dev",
+                    "dev-develop": "1.1-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Zend\\Psr7Bridge\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "description": "PSR-7 <-> Zend\\Http bridge",
+            "homepage": "https://github.com/zendframework/zend-psr7bridge",
+            "keywords": [
+                "http",
+                "psr",
+                "psr-7"
+            ],
+            "time": "2016-05-10T21:44:39+00:00"
+        },
+        {
+            "name": "zendframework/zend-serializer",
+            "version": "2.8.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/zendframework/zend-serializer.git",
+                "reference": "ff74ea020f5f90866eb28365327e9bc765a61a6e"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/zendframework/zend-serializer/zipball/ff74ea020f5f90866eb28365327e9bc765a61a6e",
+                "reference": "ff74ea020f5f90866eb28365327e9bc765a61a6e",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^5.6 || ^7.0",
+                "zendframework/zend-json": "^2.5 || ^3.0",
+                "zendframework/zend-stdlib": "^2.7 || ^3.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^4.5",
+                "squizlabs/php_codesniffer": "^2.3.1",
+                "zendframework/zend-math": "^2.6",
+                "zendframework/zend-servicemanager": "^2.7.5 || ^3.0.3"
+            },
+            "suggest": {
+                "zendframework/zend-math": "(^2.6 || ^3.0) To support Python Pickle serialization",
+                "zendframework/zend-servicemanager": "(^2.7.5 || ^3.0.3) To support plugin manager support"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.8-dev",
+                    "dev-develop": "2.9-dev"
+                },
+                "zf": {
+                    "component": "Zend\\Serializer",
+                    "config-provider": "Zend\\Serializer\\ConfigProvider"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Zend\\Serializer\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "description": "provides an adapter based interface to simply generate storable representation of PHP types by different facilities, and recover",
+            "homepage": "https://github.com/zendframework/zend-serializer",
+            "keywords": [
+                "serializer",
+                "zf2"
+            ],
+            "time": "2016-06-21T17:01:55+00:00"
+        },
+        {
+            "name": "zendframework/zend-server",
+            "version": "2.7.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/zendframework/zend-server.git",
+                "reference": "7cb617ca3e9b24579f544a244ee79ae61f480914"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/zendframework/zend-server/zipball/7cb617ca3e9b24579f544a244ee79ae61f480914",
+                "reference": "7cb617ca3e9b24579f544a244ee79ae61f480914",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^5.6 || ^7.0",
+                "zendframework/zend-code": "^2.5 || ^3.0",
+                "zendframework/zend-stdlib": "^2.5 || ^3.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^4.8",
+                "squizlabs/php_codesniffer": "^2.3.1"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.7-dev",
+                    "dev-develop": "2.8-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Zend\\Server\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "homepage": "https://github.com/zendframework/zend-server",
+            "keywords": [
+                "server",
+                "zf2"
+            ],
+            "time": "2016-06-20T22:27:55+00:00"
+        },
+        {
+            "name": "zendframework/zend-servicemanager",
+            "version": "2.7.5",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/zendframework/zend-servicemanager.git",
+                "reference": "fb5b54db5ead533b38e311f14e9c01a79218bf2b"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/zendframework/zend-servicemanager/zipball/fb5b54db5ead533b38e311f14e9c01a79218bf2b",
+                "reference": "fb5b54db5ead533b38e311f14e9c01a79218bf2b",
+                "shasum": ""
+            },
+            "require": {
+                "container-interop/container-interop": "~1.0",
+                "php": "^5.5 || ^7.0"
+            },
+            "require-dev": {
+                "athletic/athletic": "dev-master",
+                "fabpot/php-cs-fixer": "1.7.*",
+                "phpunit/phpunit": "~4.0",
+                "zendframework/zend-di": "~2.5",
+                "zendframework/zend-mvc": "~2.5"
+            },
+            "suggest": {
+                "ocramius/proxy-manager": "ProxyManager 0.5.* to handle lazy initialization of services",
+                "zendframework/zend-di": "Zend\\Di component"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.7-dev",
+                    "dev-develop": "3.0-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Zend\\ServiceManager\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "homepage": "https://github.com/zendframework/zend-servicemanager",
+            "keywords": [
+                "servicemanager",
+                "zf2"
+            ],
+            "time": "2016-02-02T14:11:46+00:00"
+        },
+        {
+            "name": "zendframework/zend-session",
+            "version": "2.8.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/zendframework/zend-session.git",
+                "reference": "b1486c382decc241de8b1c7778eaf2f0a884f67d"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/zendframework/zend-session/zipball/b1486c382decc241de8b1c7778eaf2f0a884f67d",
+                "reference": "b1486c382decc241de8b1c7778eaf2f0a884f67d",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^7.0 || ^5.6",
+                "zendframework/zend-eventmanager": "^2.6.2 || ^3.0",
+                "zendframework/zend-stdlib": "^2.7 || ^3.0"
+            },
+            "require-dev": {
+                "container-interop/container-interop": "^1.1",
+                "mongodb/mongodb": "^1.0.1",
+                "phpunit/phpunit": "^6.0.8 || ^5.7.15",
+                "zendframework/zend-cache": "^2.6.1",
+                "zendframework/zend-coding-standard": "~1.0.0",
+                "zendframework/zend-db": "^2.7",
+                "zendframework/zend-http": "^2.5.4",
+                "zendframework/zend-servicemanager": "^2.7.5 || ^3.0.3",
+                "zendframework/zend-validator": "^2.6"
+            },
+            "suggest": {
+                "mongodb/mongodb": "If you want to use the MongoDB session save handler",
+                "zendframework/zend-cache": "Zend\\Cache component",
+                "zendframework/zend-db": "Zend\\Db component",
+                "zendframework/zend-http": "Zend\\Http component",
+                "zendframework/zend-servicemanager": "Zend\\ServiceManager component",
+                "zendframework/zend-validator": "Zend\\Validator component"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.8-dev",
+                    "dev-develop": "2.9-dev"
+                },
+                "zf": {
+                    "component": "Zend\\Session",
+                    "config-provider": "Zend\\Session\\ConfigProvider"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Zend\\Session\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "description": "manage and preserve session data, a logical complement of cookie data, across multiple page requests by the same client",
+            "homepage": "https://github.com/zendframework/zend-session",
+            "keywords": [
+                "session",
+                "zf2"
+            ],
+            "time": "2017-06-19T21:31:39+00:00"
+        },
+        {
+            "name": "zendframework/zend-soap",
+            "version": "2.6.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/zendframework/zend-soap.git",
+                "reference": "2d6012e7231cce550219eccfc80836a028d20bf1"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/zendframework/zend-soap/zipball/2d6012e7231cce550219eccfc80836a028d20bf1",
+                "reference": "2d6012e7231cce550219eccfc80836a028d20bf1",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^5.5 || ^7.0",
+                "zendframework/zend-server": "^2.6.1",
+                "zendframework/zend-stdlib": "^2.7 || ^3.0",
+                "zendframework/zend-uri": "^2.5.2"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^4.8",
+                "squizlabs/php_codesniffer": "^2.3.1",
+                "zendframework/zend-config": "^2.6",
+                "zendframework/zend-http": "^2.5.4"
+            },
+            "suggest": {
+                "zendframework/zend-http": "Zend\\Http component"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.6-dev",
+                    "dev-develop": "2.7-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Zend\\Soap\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "homepage": "https://github.com/zendframework/zend-soap",
+            "keywords": [
+                "soap",
+                "zf2"
+            ],
+            "time": "2016-04-21T16:06:27+00:00"
+        },
+        {
+            "name": "zendframework/zend-stdlib",
+            "version": "2.7.7",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/zendframework/zend-stdlib.git",
+                "reference": "0e44eb46788f65e09e077eb7f44d2659143bcc1f"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/zendframework/zend-stdlib/zipball/0e44eb46788f65e09e077eb7f44d2659143bcc1f",
+                "reference": "0e44eb46788f65e09e077eb7f44d2659143bcc1f",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^5.5 || ^7.0",
+                "zendframework/zend-hydrator": "~1.1"
+            },
+            "require-dev": {
+                "athletic/athletic": "~0.1",
+                "fabpot/php-cs-fixer": "1.7.*",
+                "phpunit/phpunit": "~4.0",
+                "zendframework/zend-config": "~2.5",
+                "zendframework/zend-eventmanager": "~2.5",
+                "zendframework/zend-filter": "~2.5",
+                "zendframework/zend-inputfilter": "~2.5",
+                "zendframework/zend-serializer": "~2.5",
+                "zendframework/zend-servicemanager": "~2.5"
+            },
+            "suggest": {
+                "zendframework/zend-eventmanager": "To support aggregate hydrator usage",
+                "zendframework/zend-filter": "To support naming strategy hydrator usage",
+                "zendframework/zend-serializer": "Zend\\Serializer component",
+                "zendframework/zend-servicemanager": "To support hydrator plugin manager usage"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-release-2.7": "2.7-dev",
+                    "dev-master": "3.0-dev",
+                    "dev-develop": "3.1-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Zend\\Stdlib\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "homepage": "https://github.com/zendframework/zend-stdlib",
+            "keywords": [
+                "stdlib",
+                "zf2"
+            ],
+            "time": "2016-04-12T21:17:31+00:00"
+        },
+        {
+            "name": "zendframework/zend-text",
+            "version": "2.6.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/zendframework/zend-text.git",
+                "reference": "07ad9388e4d4f12620ad37b52a5b0e4ee7845f92"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/zendframework/zend-text/zipball/07ad9388e4d4f12620ad37b52a5b0e4ee7845f92",
+                "reference": "07ad9388e4d4f12620ad37b52a5b0e4ee7845f92",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^5.5 || ^7.0",
+                "zendframework/zend-servicemanager": "^2.7.5 || ^3.0.3",
+                "zendframework/zend-stdlib": "^2.7 || ^3.0"
+            },
+            "require-dev": {
+                "fabpot/php-cs-fixer": "1.7.*",
+                "phpunit/phpunit": "~4.0",
+                "zendframework/zend-config": "^2.6"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.6-dev",
+                    "dev-develop": "2.7-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Zend\\Text\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "homepage": "https://github.com/zendframework/zend-text",
+            "keywords": [
+                "text",
+                "zf2"
+            ],
+            "time": "2016-02-08T19:03:52+00:00"
+        },
+        {
+            "name": "zendframework/zend-uri",
+            "version": "2.5.2",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/zendframework/zend-uri.git",
+                "reference": "0bf717a239432b1a1675ae314f7c4acd742749ed"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/zendframework/zend-uri/zipball/0bf717a239432b1a1675ae314f7c4acd742749ed",
+                "reference": "0bf717a239432b1a1675ae314f7c4acd742749ed",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^5.5 || ^7.0",
+                "zendframework/zend-escaper": "^2.5",
+                "zendframework/zend-validator": "^2.5"
+            },
+            "require-dev": {
+                "fabpot/php-cs-fixer": "1.7.*",
+                "phpunit/phpunit": "~4.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.5-dev",
+                    "dev-develop": "2.6-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Zend\\Uri\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "description": "a component that aids in manipulating and validating » Uniform Resource Identifiers (URIs)",
+            "homepage": "https://github.com/zendframework/zend-uri",
+            "keywords": [
+                "uri",
+                "zf2"
+            ],
+            "time": "2016-02-17T22:38:51+00:00"
+        },
+        {
+            "name": "zendframework/zend-validator",
+            "version": "2.9.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/zendframework/zend-validator.git",
+                "reference": "c9a8160a0191e34bb98ac1ecd4e453391c424bb3"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/zendframework/zend-validator/zipball/c9a8160a0191e34bb98ac1ecd4e453391c424bb3",
+                "reference": "c9a8160a0191e34bb98ac1ecd4e453391c424bb3",
+                "shasum": ""
+            },
+            "require": {
+                "container-interop/container-interop": "^1.1",
+                "php": "^5.6 || ^7.0",
+                "zendframework/zend-stdlib": "^2.7.6 || ^3.1"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^6.0.8 || ^5.7.15",
+                "zendframework/zend-cache": "^2.6.1",
+                "zendframework/zend-coding-standard": "~1.0.0",
+                "zendframework/zend-config": "^2.6",
+                "zendframework/zend-db": "^2.7",
+                "zendframework/zend-filter": "^2.6",
+                "zendframework/zend-http": "^2.5.4",
+                "zendframework/zend-i18n": "^2.6",
+                "zendframework/zend-math": "^2.6",
+                "zendframework/zend-servicemanager": "^2.7.5 || ^3.0.3",
+                "zendframework/zend-session": "^2.6.2",
+                "zendframework/zend-uri": "^2.5"
+            },
+            "suggest": {
+                "zendframework/zend-db": "Zend\\Db component, required by the (No)RecordExists validator",
+                "zendframework/zend-filter": "Zend\\Filter component, required by the Digits validator",
+                "zendframework/zend-i18n": "Zend\\I18n component to allow translation of validation error messages",
+                "zendframework/zend-i18n-resources": "Translations of validator messages",
+                "zendframework/zend-math": "Zend\\Math component, required by the Csrf validator",
+                "zendframework/zend-servicemanager": "Zend\\ServiceManager component to allow using the ValidatorPluginManager and validator chains",
+                "zendframework/zend-session": "Zend\\Session component, required by the Csrf validator",
+                "zendframework/zend-uri": "Zend\\Uri component, required by the Uri and Sitemap\\Loc validators"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.9-dev",
+                    "dev-develop": "2.10-dev"
+                },
+                "zf": {
+                    "component": "Zend\\Validator",
+                    "config-provider": "Zend\\Validator\\ConfigProvider"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Zend\\Validator\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "description": "provides a set of commonly needed validators",
+            "homepage": "https://github.com/zendframework/zend-validator",
+            "keywords": [
+                "validator",
+                "zf2"
+            ],
+            "time": "2017-05-17T22:06:13+00:00"
+        },
+        {
+            "name": "zendframework/zend-view",
+            "version": "2.9.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/zendframework/zend-view.git",
+                "reference": "3b6342c381c4437a03fc81d0064c0bb8924914d3"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/zendframework/zend-view/zipball/3b6342c381c4437a03fc81d0064c0bb8924914d3",
+                "reference": "3b6342c381c4437a03fc81d0064c0bb8924914d3",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^5.6 || ^7.0",
+                "zendframework/zend-eventmanager": "^2.6.2 || ^3.0",
+                "zendframework/zend-loader": "^2.5",
+                "zendframework/zend-stdlib": "^2.7 || ^3.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^5.7.15 || ^6.0.8",
+                "zendframework/zend-authentication": "^2.5",
+                "zendframework/zend-cache": "^2.6.1",
+                "zendframework/zend-coding-standard": "~1.0.0",
+                "zendframework/zend-config": "^2.6",
+                "zendframework/zend-console": "^2.6",
+                "zendframework/zend-escaper": "^2.5",
+                "zendframework/zend-feed": "^2.7",
+                "zendframework/zend-filter": "^2.6.1",
+                "zendframework/zend-http": "^2.5.4",
+                "zendframework/zend-i18n": "^2.6",
+                "zendframework/zend-json": "^2.6.1",
+                "zendframework/zend-log": "^2.7",
+                "zendframework/zend-modulemanager": "^2.7.1",
+                "zendframework/zend-mvc": "^2.7 || ^3.0",
+                "zendframework/zend-navigation": "^2.5",
+                "zendframework/zend-paginator": "^2.5",
+                "zendframework/zend-permissions-acl": "^2.6",
+                "zendframework/zend-router": "^3.0.1",
+                "zendframework/zend-serializer": "^2.6.1",
+                "zendframework/zend-servicemanager": "^2.7.5 || ^3.0.3",
+                "zendframework/zend-session": "^2.6.2",
+                "zendframework/zend-uri": "^2.5"
+            },
+            "suggest": {
+                "zendframework/zend-authentication": "Zend\\Authentication component",
+                "zendframework/zend-escaper": "Zend\\Escaper component",
+                "zendframework/zend-feed": "Zend\\Feed component",
+                "zendframework/zend-filter": "Zend\\Filter component",
+                "zendframework/zend-http": "Zend\\Http component",
+                "zendframework/zend-i18n": "Zend\\I18n component",
+                "zendframework/zend-json": "Zend\\Json component",
+                "zendframework/zend-mvc": "Zend\\Mvc component",
+                "zendframework/zend-navigation": "Zend\\Navigation component",
+                "zendframework/zend-paginator": "Zend\\Paginator component",
+                "zendframework/zend-permissions-acl": "Zend\\Permissions\\Acl component",
+                "zendframework/zend-servicemanager": "Zend\\ServiceManager component",
+                "zendframework/zend-uri": "Zend\\Uri component"
+            },
+            "bin": [
+                "bin/templatemap_generator.php"
+            ],
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.9-dev",
+                    "dev-develop": "3.0-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Zend\\View\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "description": "provides a system of helpers, output filters, and variable escaping",
+            "homepage": "https://github.com/zendframework/zend-view",
+            "keywords": [
+                "view",
+                "zf2"
+            ],
+            "time": "2017-03-21T15:05:56+00:00"
+        },
+        {
+            "name": "zendframework/zendrest",
+            "version": "2.0.2",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/zendframework/ZendRest.git",
+                "reference": "7427d242b4546e5aef1206d2c97e402109d8843e"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/zendframework/ZendRest/zipball/7427d242b4546e5aef1206d2c97e402109d8843e",
+                "reference": "7427d242b4546e5aef1206d2c97e402109d8843e",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.3",
+                "zendframework/zend-http": "~2.0",
+                "zendframework/zend-uri": "~2.0",
+                "zendframework/zendxml": "~1.0-dev"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-0": {
+                    "ZendRest": "library/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "homepage": "http://packages.zendframework.com/",
+            "keywords": [
+                "rest",
+                "zf2"
+            ],
+            "time": "2014-03-05T22:32:09+00:00"
+        },
+        {
+            "name": "zendframework/zendservice-amazon",
+            "version": "2.3.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/zendframework/ZendService_Amazon.git",
+                "reference": "95347a55fec8adaace67707fdd66de1ea005b346"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/zendframework/ZendService_Amazon/zipball/95347a55fec8adaace67707fdd66de1ea005b346",
+                "reference": "95347a55fec8adaace67707fdd66de1ea005b346",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^5.6 || ^7.0",
+                "zendframework/zend-crypt": "^2.6 || ^3.2",
+                "zendframework/zend-http": "^2.6",
+                "zendframework/zend-json": "^2.6 || ^3.0",
+                "zendframework/zendrest": "~2.0",
+                "zendframework/zendxml": "^1.0"
+            },
+            "require-dev": {
+                "malukenho/docheader": "^0.1.5",
+                "phpunit/phpunit": "^6.0.8 || ^5.7.15",
+                "zendframework/zend-coding-standard": "~1.0.0",
+                "zendframework/zend-i18n": "~2.0"
+            },
+            "suggest": {
+                "zendframework/zend-uri": "Zend\\Uri component"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.2.x-dev",
+                    "dev-develop": "2.3.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "ZendService\\Amazon\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "description": "OOP wrapper for the Amazon web service",
+            "homepage": "http://packages.zendframework.com/",
+            "keywords": [
+                "amazon",
+                "ec2",
+                "s3",
+                "simpledb",
+                "sqs",
+                "zf2"
+            ],
+            "time": "2017-06-22T01:59:37+00:00"
+        },
+        {
+            "name": "zendframework/zendservice-recaptcha",
+            "version": "3.0.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/zendframework/ZendService_ReCaptcha.git",
+                "reference": "6c6877c07c8ac73b187911ea5d264a640b234361"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/zendframework/ZendService_ReCaptcha/zipball/6c6877c07c8ac73b187911ea5d264a640b234361",
+                "reference": "6c6877c07c8ac73b187911ea5d264a640b234361",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^5.6 || ^7.0",
+                "zendframework/zend-http": "^2.5.4",
+                "zendframework/zend-json": "^2.6.1 || ^3.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^5.7 || ^6.0",
+                "zendframework/zend-coding-standard": "~1.0.0",
+                "zendframework/zend-config": "^2.0",
+                "zendframework/zend-validator": "^2.8.2"
+            },
+            "suggest": {
+                "zendframework/zend-validator": "~2.0, if using ReCaptcha's Mailhide API"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "3.0-dev",
+                    "dev-develop": "3.1-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "ZendService\\ReCaptcha\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "description": "OOP wrapper for the ReCaptcha web service",
+            "homepage": "http://packages.zendframework.com/",
+            "keywords": [
+                "recaptcha",
+                "zf2"
+            ],
+            "time": "2017-02-09T21:38:25+00:00"
+        },
+        {
+            "name": "zendframework/zendxml",
+            "version": "1.0.2",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/zendframework/ZendXml.git",
+                "reference": "7b64507bc35d841c9c5802d67f6f87ef8e1a58c9"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/zendframework/ZendXml/zipball/7b64507bc35d841c9c5802d67f6f87ef8e1a58c9",
+                "reference": "7b64507bc35d841c9c5802d67f6f87ef8e1a58c9",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^5.3.3 || ^7.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^3.7 || ^4.0",
+                "squizlabs/php_codesniffer": "^1.5"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0-dev"
+                }
+            },
+            "autoload": {
+                "psr-0": {
+                    "ZendXml\\": "library/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "description": "Utility library for XML usage, best practices, and security in PHP",
+            "homepage": "http://packages.zendframework.com/",
+            "keywords": [
+                "security",
+                "xml",
+                "zf2"
+            ],
+            "time": "2016-02-04T21:02:08+00:00"
+        },
+        {
+            "name": "zf-commons/zfc-rbac",
+            "version": "v2.6.3",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/ZF-Commons/zfc-rbac.git",
+                "reference": "dd1857a88474e2a77996b1fb858f927510762819"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/ZF-Commons/zfc-rbac/zipball/dd1857a88474e2a77996b1fb858f927510762819",
+                "reference": "dd1857a88474e2a77996b1fb858f927510762819",
+                "shasum": ""
+            },
+            "require": {
+                "php": "~5.6 || ~7.0",
+                "zendframework/zend-config": "~2.2 || ^3.1",
+                "zendframework/zend-eventmanager": "^2.6.3 || ^3.0",
+                "zendframework/zend-mvc": "~2.7 || ^3.0",
+                "zendframework/zend-servicemanager": "^2.7.5 || ^3.0.3",
+                "zfr/rbac": "~1.2"
+            },
+            "require-dev": {
+                "doctrine/common": "~2.4",
+                "doctrine/doctrine-module": "~1.1",
+                "doctrine/doctrine-orm-module": "^1.0",
+                "phpunit/phpunit": "~4.8.26",
+                "satooshi/php-coveralls": "~0.6",
+                "squizlabs/php_codesniffer": "2.6.*",
+                "zendframework/zend-authentication": "~2.2",
+                "zendframework/zend-developer-tools": "~1.1",
+                "zendframework/zend-http": "~2.2",
+                "zendframework/zend-i18n": "~2.7.3",
+                "zendframework/zend-log": "~2.2",
+                "zendframework/zend-serializer": "~2.2",
+                "zendframework/zend-view": "~2.2"
+            },
+            "suggest": {
+                "doctrine/doctrine-module": "if you want to use Doctrine role provider",
+                "zendframework/zend-developer-tools": "if you want to show information about the roles"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.4-dev",
+                    "dev-develop": "3.0-dev"
+                }
+            },
+            "autoload": {
+                "psr-0": {
+                    "ZfcRbac\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Kyle Spraggs",
+                    "email": "theman@spiffyjr.me",
+                    "homepage": "http://www.spiffyjr.me/"
+                },
+                {
+                    "name": "Jean-Marie Leroux",
+                    "email": "jmleroux.pro@gmail.com"
+                },
+                {
+                    "name": "Michaël Gallego",
+                    "email": "mic.gallego@gmail.com",
+                    "homepage": "http://www.michaelgallego.fr"
+                }
+            ],
+            "description": "Zend Framework 2 Module that provides a layer of features of Zend\\Permissions\\Rbac",
+            "homepage": "http://www.github.com/ZF-Commons/zfc-rbac",
+            "keywords": [
+                "module",
+                "permissions",
+                "rbac",
+                "zf2"
+            ],
+            "time": "2017-05-07T08:45:27+00:00"
+        },
+        {
+            "name": "zfr/rbac",
+            "version": "1.2.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/zf-fr/rbac.git",
+                "reference": "493711bfc2a637fd7c6f23b71b7b55a621c35d9d"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/zf-fr/rbac/zipball/493711bfc2a637fd7c6f23b71b7b55a621c35d9d",
+                "reference": "493711bfc2a637fd7c6f23b71b7b55a621c35d9d",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.4"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "~3.7",
+                "satooshi/php-coveralls": "~0.6",
+                "squizlabs/php_codesniffer": "1.4.*",
+                "zendframework/zend-servicemanager": "~2.2"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-0": {
+                    "Rbac\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Michaël Gallego",
+                    "email": "mic.gallego@gmail.com",
+                    "homepage": "http://michaelgallego.fr"
+                }
+            ],
+            "description": "Zend Framework 3 prototype for Zend\\Permissions\\Rbac.",
+            "homepage": "https://github.com/zf-fr/rbac",
+            "keywords": [
+                "rbac",
+                "security",
+                "zf2",
+                "zf3"
+            ],
+            "time": "2014-02-06T14:18:34+00:00"
+        }
+    ],
+    "packages-dev": [
+        {
+            "name": "behat/mink",
+            "version": "v1.7.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/minkphp/Mink.git",
+                "reference": "e6930b9c74693dff7f4e58577e1b1743399f3ff9"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/minkphp/Mink/zipball/e6930b9c74693dff7f4e58577e1b1743399f3ff9",
+                "reference": "e6930b9c74693dff7f4e58577e1b1743399f3ff9",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.1",
+                "symfony/css-selector": "~2.1|~3.0"
+            },
+            "require-dev": {
+                "symfony/phpunit-bridge": "~2.7|~3.0"
+            },
+            "suggest": {
+                "behat/mink-browserkit-driver": "extremely fast headless driver for Symfony\\Kernel-based apps (Sf2, Silex)",
+                "behat/mink-goutte-driver": "fast headless driver for any app without JS emulation",
+                "behat/mink-selenium2-driver": "slow, but JS-enabled driver for any app (requires Selenium2)",
+                "behat/mink-zombie-driver": "fast and JS-enabled headless driver for any app (requires node.js)"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.7.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Behat\\Mink\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Konstantin Kudryashov",
+                    "email": "ever.zet@gmail.com",
+                    "homepage": "http://everzet.com"
+                }
+            ],
+            "description": "Browser controller/emulator abstraction for PHP",
+            "homepage": "http://mink.behat.org/",
+            "keywords": [
+                "browser",
+                "testing",
+                "web"
+            ],
+            "time": "2016-03-05T08:26:18+00:00"
+        },
+        {
+            "name": "behat/mink-selenium2-driver",
+            "version": "v1.3.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/minkphp/MinkSelenium2Driver.git",
+                "reference": "473a9f3ebe0c134ee1e623ce8a9c852832020288"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/minkphp/MinkSelenium2Driver/zipball/473a9f3ebe0c134ee1e623ce8a9c852832020288",
+                "reference": "473a9f3ebe0c134ee1e623ce8a9c852832020288",
+                "shasum": ""
+            },
+            "require": {
+                "behat/mink": "~1.7@dev",
+                "instaclick/php-webdriver": "~1.1",
+                "php": ">=5.3.1"
+            },
+            "require-dev": {
+                "symfony/phpunit-bridge": "~2.7"
+            },
+            "type": "mink-driver",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.3.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Behat\\Mink\\Driver\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Konstantin Kudryashov",
+                    "email": "ever.zet@gmail.com",
+                    "homepage": "http://everzet.com"
+                },
+                {
+                    "name": "Pete Otaqui",
+                    "email": "pete@otaqui.com",
+                    "homepage": "https://github.com/pete-otaqui"
+                }
+            ],
+            "description": "Selenium2 (WebDriver) driver for Mink framework",
+            "homepage": "http://mink.behat.org/",
+            "keywords": [
+                "ajax",
+                "browser",
+                "javascript",
+                "selenium",
+                "testing",
+                "webdriver"
+            ],
+            "time": "2016-03-05T09:10:18+00:00"
+        },
+        {
+            "name": "cilex/cilex",
+            "version": "1.1.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/Cilex/Cilex.git",
+                "reference": "7acd965a609a56d0345e8b6071c261fbdb926cb5"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/Cilex/Cilex/zipball/7acd965a609a56d0345e8b6071c261fbdb926cb5",
+                "reference": "7acd965a609a56d0345e8b6071c261fbdb926cb5",
+                "shasum": ""
+            },
+            "require": {
+                "cilex/console-service-provider": "1.*",
+                "php": ">=5.3.3",
+                "pimple/pimple": "~1.0",
+                "symfony/finder": "~2.1",
+                "symfony/process": "~2.1"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "3.7.*",
+                "symfony/validator": "~2.1"
+            },
+            "suggest": {
+                "monolog/monolog": ">=1.0.0",
+                "symfony/validator": ">=1.0.0",
+                "symfony/yaml": ">=1.0.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0-dev"
+                }
+            },
+            "autoload": {
+                "psr-0": {
+                    "Cilex": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Mike van Riel",
+                    "email": "mike.vanriel@naenius.com"
+                }
+            ],
+            "description": "The PHP micro-framework for Command line tools based on the Symfony2 Components",
+            "homepage": "http://cilex.github.com",
+            "keywords": [
+                "cli",
+                "microframework"
+            ],
+            "time": "2014-03-29T14:03:13+00:00"
+        },
+        {
+            "name": "cilex/console-service-provider",
+            "version": "1.0.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/Cilex/console-service-provider.git",
+                "reference": "25ee3d1875243d38e1a3448ff94bdf944f70d24e"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/Cilex/console-service-provider/zipball/25ee3d1875243d38e1a3448ff94bdf944f70d24e",
+                "reference": "25ee3d1875243d38e1a3448ff94bdf944f70d24e",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.3",
+                "pimple/pimple": "1.*@dev",
+                "symfony/console": "~2.1"
+            },
+            "require-dev": {
+                "cilex/cilex": "1.*@dev",
+                "silex/silex": "1.*@dev"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0-dev"
+                }
+            },
+            "autoload": {
+                "psr-0": {
+                    "Cilex\\Provider\\Console": "src"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Beau Simensen",
+                    "email": "beau@dflydev.com",
+                    "homepage": "http://beausimensen.com"
+                },
+                {
+                    "name": "Mike van Riel",
+                    "email": "mike.vanriel@naenius.com"
+                }
+            ],
+            "description": "Console Service Provider",
+            "keywords": [
+                "cilex",
+                "console",
+                "pimple",
+                "service-provider",
+                "silex"
+            ],
+            "time": "2012-12-19T10:50:58+00:00"
+        },
+        {
+            "name": "doctrine/annotations",
+            "version": "v1.4.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/doctrine/annotations.git",
+                "reference": "54cacc9b81758b14e3ce750f205a393d52339e97"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/doctrine/annotations/zipball/54cacc9b81758b14e3ce750f205a393d52339e97",
+                "reference": "54cacc9b81758b14e3ce750f205a393d52339e97",
+                "shasum": ""
+            },
+            "require": {
+                "doctrine/lexer": "1.*",
+                "php": "^5.6 || ^7.0"
+            },
+            "require-dev": {
+                "doctrine/cache": "1.*",
+                "phpunit/phpunit": "^5.7"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.4.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Roman Borschel",
+                    "email": "roman@code-factory.org"
+                },
+                {
+                    "name": "Benjamin Eberlei",
+                    "email": "kontakt@beberlei.de"
+                },
+                {
+                    "name": "Guilherme Blanco",
+                    "email": "guilhermeblanco@gmail.com"
+                },
+                {
+                    "name": "Jonathan Wage",
+                    "email": "jonwage@gmail.com"
+                },
+                {
+                    "name": "Johannes Schmitt",
+                    "email": "schmittjoh@gmail.com"
+                }
+            ],
+            "description": "Docblock Annotations Parser",
+            "homepage": "http://www.doctrine-project.org",
+            "keywords": [
+                "annotations",
+                "docblock",
+                "parser"
+            ],
+            "time": "2017-02-24T16:22:25+00:00"
+        },
+        {
+            "name": "doctrine/instantiator",
+            "version": "1.0.5",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/doctrine/instantiator.git",
+                "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d",
+                "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3,<8.0-DEV"
+            },
+            "require-dev": {
+                "athletic/athletic": "~0.1.8",
+                "ext-pdo": "*",
+                "ext-phar": "*",
+                "phpunit/phpunit": "~4.0",
+                "squizlabs/php_codesniffer": "~2.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Marco Pivetta",
+                    "email": "ocramius@gmail.com",
+                    "homepage": "http://ocramius.github.com/"
+                }
+            ],
+            "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
+            "homepage": "https://github.com/doctrine/instantiator",
+            "keywords": [
+                "constructor",
+                "instantiate"
+            ],
+            "time": "2015-06-14T21:17:01+00:00"
+        },
+        {
+            "name": "doctrine/lexer",
+            "version": "v1.0.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/doctrine/lexer.git",
+                "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/doctrine/lexer/zipball/83893c552fd2045dd78aef794c31e694c37c0b8c",
+                "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.2"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-0": {
+                    "Doctrine\\Common\\Lexer\\": "lib/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Roman Borschel",
+                    "email": "roman@code-factory.org"
+                },
+                {
+                    "name": "Guilherme Blanco",
+                    "email": "guilhermeblanco@gmail.com"
+                },
+                {
+                    "name": "Johannes Schmitt",
+                    "email": "schmittjoh@gmail.com"
+                }
+            ],
+            "description": "Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers.",
+            "homepage": "http://www.doctrine-project.org",
+            "keywords": [
+                "lexer",
+                "parser"
+            ],
+            "time": "2014-09-09T13:34:57+00:00"
+        },
+        {
+            "name": "erusev/parsedown",
+            "version": "1.6.3",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/erusev/parsedown.git",
+                "reference": "728952b90a333b5c6f77f06ea9422b94b585878d"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/erusev/parsedown/zipball/728952b90a333b5c6f77f06ea9422b94b585878d",
+                "reference": "728952b90a333b5c6f77f06ea9422b94b585878d",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.0"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-0": {
+                    "Parsedown": ""
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Emanuil Rusev",
+                    "email": "hello@erusev.com",
+                    "homepage": "http://erusev.com"
+                }
+            ],
+            "description": "Parser for Markdown.",
+            "homepage": "http://parsedown.org",
+            "keywords": [
+                "markdown",
+                "parser"
+            ],
+            "time": "2017-05-14T14:47:48+00:00"
+        },
+        {
+            "name": "friendsofphp/php-cs-fixer",
+            "version": "v1.11.6",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git",
+                "reference": "41dc93abd2937a85a3889e28765231d574d2bac8"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/41dc93abd2937a85a3889e28765231d574d2bac8",
+                "reference": "41dc93abd2937a85a3889e28765231d574d2bac8",
+                "shasum": ""
+            },
+            "require": {
+                "ext-tokenizer": "*",
+                "php": ">=5.3.6",
+                "sebastian/diff": "~1.1",
+                "symfony/console": "~2.3|~3.0",
+                "symfony/event-dispatcher": "~2.1|~3.0",
+                "symfony/filesystem": "~2.1|~3.0",
+                "symfony/finder": "~2.1|~3.0",
+                "symfony/process": "~2.3|~3.0",
+                "symfony/stopwatch": "~2.5|~3.0"
+            },
+            "conflict": {
+                "hhvm": "<3.9"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^4.5|^5",
+                "satooshi/php-coveralls": "^0.7.1"
+            },
+            "bin": [
+                "php-cs-fixer"
+            ],
+            "type": "application",
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\CS\\": "Symfony/CS/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Dariusz Rumiński",
+                    "email": "dariusz.ruminski@gmail.com"
+                },
+                {
+                    "name": "Fabien Potencier",
+                    "email": "fabien@symfony.com"
+                }
+            ],
+            "description": "A tool to automatically fix PHP code style",
+            "time": "2016-07-22T06:46:28+00:00"
+        },
+        {
+            "name": "herrera-io/json",
+            "version": "1.0.3",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/kherge-php/json.git",
+                "reference": "60c696c9370a1e5136816ca557c17f82a6fa83f1"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/kherge-php/json/zipball/60c696c9370a1e5136816ca557c17f82a6fa83f1",
+                "reference": "60c696c9370a1e5136816ca557c17f82a6fa83f1",
+                "shasum": ""
+            },
+            "require": {
+                "ext-json": "*",
+                "justinrainbow/json-schema": ">=1.0,<2.0-dev",
+                "php": ">=5.3.3",
+                "seld/jsonlint": ">=1.0,<2.0-dev"
+            },
+            "require-dev": {
+                "herrera-io/phpunit-test-case": "1.*",
+                "mikey179/vfsstream": "1.1.0",
+                "phpunit/phpunit": "3.7.*"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0-dev"
+                }
+            },
+            "autoload": {
+                "files": [
+                    "src/lib/json_version.php"
+                ],
+                "psr-0": {
+                    "Herrera\\Json": "src/lib"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Kevin Herrera",
+                    "email": "kevin@herrera.io",
+                    "homepage": "http://kevin.herrera.io"
+                }
+            ],
+            "description": "A library for simplifying JSON linting and validation.",
+            "homepage": "http://herrera-io.github.com/php-json",
+            "keywords": [
+                "json",
+                "lint",
+                "schema",
+                "validate"
+            ],
+            "abandoned": "kherge/json",
+            "time": "2013-10-30T16:51:34+00:00"
+        },
+        {
+            "name": "herrera-io/phar-update",
+            "version": "1.0.3",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/kherge-abandoned/php-phar-update.git",
+                "reference": "00a79e1d5b8cf3c080a2e3becf1ddf7a7fea025b"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/kherge-abandoned/php-phar-update/zipball/00a79e1d5b8cf3c080a2e3becf1ddf7a7fea025b",
+                "reference": "00a79e1d5b8cf3c080a2e3becf1ddf7a7fea025b",
+                "shasum": ""
+            },
+            "require": {
+                "herrera-io/json": "1.*",
+                "kherge/version": "1.*",
+                "php": ">=5.3.3"
+            },
+            "require-dev": {
+                "herrera-io/phpunit-test-case": "1.*",
+                "mikey179/vfsstream": "1.1.0",
+                "phpunit/phpunit": "3.7.*"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0-dev"
+                }
+            },
+            "autoload": {
+                "files": [
+                    "src/lib/constants.php"
+                ],
+                "psr-0": {
+                    "Herrera\\Phar\\Update": "src/lib"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Kevin Herrera",
+                    "email": "kevin@herrera.io",
+                    "homepage": "http://kevin.herrera.io"
+                }
+            ],
+            "description": "A library for self-updating Phars.",
+            "homepage": "http://herrera-io.github.com/php-phar-update",
+            "keywords": [
+                "phar",
+                "update"
+            ],
+            "abandoned": true,
+            "time": "2013-10-30T17:23:01+00:00"
+        },
+        {
+            "name": "instaclick/php-webdriver",
+            "version": "1.4.5",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/instaclick/php-webdriver.git",
+                "reference": "6fa959452e774dcaed543faad3a9d1a37d803327"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/instaclick/php-webdriver/zipball/6fa959452e774dcaed543faad3a9d1a37d803327",
+                "reference": "6fa959452e774dcaed543faad3a9d1a37d803327",
+                "shasum": ""
+            },
+            "require": {
+                "ext-curl": "*",
+                "php": ">=5.3.2"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^4.8",
+                "satooshi/php-coveralls": "^1.0||^2.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.4.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-0": {
+                    "WebDriver": "lib/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "Apache-2.0"
+            ],
+            "authors": [
+                {
+                    "name": "Justin Bishop",
+                    "email": "jubishop@gmail.com",
+                    "role": "Developer"
+                },
+                {
+                    "name": "Anthon Pang",
+                    "email": "apang@softwaredevelopment.ca",
+                    "role": "Fork Maintainer"
+                }
+            ],
+            "description": "PHP WebDriver for Selenium 2",
+            "homepage": "http://instaclick.com/",
+            "keywords": [
+                "browser",
+                "selenium",
+                "webdriver",
+                "webtest"
+            ],
+            "time": "2017-06-30T04:02:48+00:00"
+        },
+        {
+            "name": "jms/metadata",
+            "version": "1.6.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/schmittjoh/metadata.git",
+                "reference": "6a06970a10e0a532fb52d3959547123b84a3b3ab"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/schmittjoh/metadata/zipball/6a06970a10e0a532fb52d3959547123b84a3b3ab",
+                "reference": "6a06970a10e0a532fb52d3959547123b84a3b3ab",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.0"
+            },
+            "require-dev": {
+                "doctrine/cache": "~1.0",
+                "symfony/cache": "~3.1"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.5.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-0": {
+                    "Metadata\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "Apache-2.0"
+            ],
+            "authors": [
+                {
+                    "name": "Johannes M. Schmitt",
+                    "email": "schmittjoh@gmail.com"
+                }
+            ],
+            "description": "Class/method/property metadata management in PHP",
+            "keywords": [
+                "annotations",
+                "metadata",
+                "xml",
+                "yaml"
+            ],
+            "time": "2016-12-05T10:18:33+00:00"
+        },
+        {
+            "name": "jms/parser-lib",
+            "version": "1.0.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/schmittjoh/parser-lib.git",
+                "reference": "c509473bc1b4866415627af0e1c6cc8ac97fa51d"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/schmittjoh/parser-lib/zipball/c509473bc1b4866415627af0e1c6cc8ac97fa51d",
+                "reference": "c509473bc1b4866415627af0e1c6cc8ac97fa51d",
+                "shasum": ""
+            },
+            "require": {
+                "phpoption/phpoption": ">=0.9,<2.0-dev"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0-dev"
+                }
+            },
+            "autoload": {
+                "psr-0": {
+                    "JMS\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "Apache2"
+            ],
+            "description": "A library for easily creating recursive-descent parsers.",
+            "time": "2012-11-18T18:08:43+00:00"
+        },
+        {
+            "name": "jms/serializer",
+            "version": "1.8.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/schmittjoh/serializer.git",
+                "reference": "ce65798f722c836f16d5d7d2e3ca9d21e0fb4331"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/schmittjoh/serializer/zipball/ce65798f722c836f16d5d7d2e3ca9d21e0fb4331",
+                "reference": "ce65798f722c836f16d5d7d2e3ca9d21e0fb4331",
+                "shasum": ""
+            },
+            "require": {
+                "doctrine/annotations": "^1.0",
+                "doctrine/instantiator": "^1.0.3",
+                "jms/metadata": "~1.1",
+                "jms/parser-lib": "1.*",
+                "php": ">=5.5.0",
+                "phpcollection/phpcollection": "~0.1",
+                "phpoption/phpoption": "^1.1"
+            },
+            "conflict": {
+                "jms/serializer-bundle": "<1.2.1",
+                "twig/twig": "<1.12"
+            },
+            "require-dev": {
+                "doctrine/orm": "~2.1",
+                "doctrine/phpcr-odm": "^1.3|^2.0",
+                "ext-pdo_sqlite": "*",
+                "jackalope/jackalope-doctrine-dbal": "^1.1.5",
+                "phpunit/phpunit": "^4.8|^5.0",
+                "propel/propel1": "~1.7",
+                "symfony/expression-language": "^2.6|^3.0",
+                "symfony/filesystem": "^2.1",
+                "symfony/form": "~2.1|^3.0",
+                "symfony/translation": "^2.1|^3.0",
+                "symfony/validator": "^2.2|^3.0",
+                "symfony/yaml": "^2.1|^3.0",
+                "twig/twig": "~1.12|~2.0"
+            },
+            "suggest": {
+                "doctrine/cache": "Required if you like to use cache functionality.",
+                "doctrine/collections": "Required if you like to use doctrine collection types as ArrayCollection.",
+                "symfony/yaml": "Required if you'd like to serialize data to YAML format."
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.8-dev"
+                }
+            },
+            "autoload": {
+                "psr-0": {
+                    "JMS\\Serializer": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "Apache-2.0"
+            ],
+            "authors": [
+                {
+                    "name": "Asmir Mustafic",
+                    "email": "goetas@gmail.com"
+                },
+                {
+                    "name": "Johannes M. Schmitt",
+                    "email": "schmittjoh@gmail.com"
+                }
+            ],
+            "description": "Library for (de-)serializing data of any complexity; supports XML, JSON, and YAML.",
+            "homepage": "http://jmsyst.com/libs/serializer",
+            "keywords": [
+                "deserialization",
+                "jaxb",
+                "json",
+                "serialization",
+                "xml"
+            ],
+            "time": "2017-07-13T11:23:56+00:00"
+        },
+        {
+            "name": "justinrainbow/json-schema",
+            "version": "1.6.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/justinrainbow/json-schema.git",
+                "reference": "cc84765fb7317f6b07bd8ac78364747f95b86341"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/justinrainbow/json-schema/zipball/cc84765fb7317f6b07bd8ac78364747f95b86341",
+                "reference": "cc84765fb7317f6b07bd8ac78364747f95b86341",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.29"
+            },
+            "require-dev": {
+                "json-schema/json-schema-test-suite": "1.1.0",
+                "phpdocumentor/phpdocumentor": "~2",
+                "phpunit/phpunit": "~3.7"
+            },
+            "bin": [
+                "bin/validate-json"
+            ],
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.6.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "JsonSchema\\": "src/JsonSchema/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Bruno Prieto Reis",
+                    "email": "bruno.p.reis@gmail.com"
+                },
+                {
+                    "name": "Justin Rainbow",
+                    "email": "justin.rainbow@gmail.com"
+                },
+                {
+                    "name": "Igor Wiedler",
+                    "email": "igor@wiedler.ch"
+                },
+                {
+                    "name": "Robert Schönthal",
+                    "email": "seroscho@googlemail.com"
+                }
+            ],
+            "description": "A library to validate a json schema.",
+            "homepage": "https://github.com/justinrainbow/json-schema",
+            "keywords": [
+                "json",
+                "schema"
+            ],
+            "time": "2016-01-25T15:43:01+00:00"
+        },
+        {
+            "name": "kherge/version",
+            "version": "1.0.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/kherge-abandoned/Version.git",
+                "reference": "f07cf83f8ce533be8f93d2893d96d674bbeb7e30"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/kherge-abandoned/Version/zipball/f07cf83f8ce533be8f93d2893d96d674bbeb7e30",
+                "reference": "f07cf83f8ce533be8f93d2893d96d674bbeb7e30",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.3"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0-dev"
+                }
+            },
+            "autoload": {
+                "psr-0": {
+                    "KevinGH\\Version": "src/lib/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Kevin Herrera",
+                    "email": "me@kevingh.com"
+                }
+            ],
+            "description": "A parsing and comparison library for semantic versioning.",
+            "homepage": "http://github.com/kherge/Version",
+            "abandoned": true,
+            "time": "2012-08-16T17:13:03+00:00"
+        },
+        {
+            "name": "monolog/monolog",
+            "version": "1.23.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/Seldaek/monolog.git",
+                "reference": "fd8c787753b3a2ad11bc60c063cff1358a32a3b4"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/Seldaek/monolog/zipball/fd8c787753b3a2ad11bc60c063cff1358a32a3b4",
+                "reference": "fd8c787753b3a2ad11bc60c063cff1358a32a3b4",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.0",
+                "psr/log": "~1.0"
+            },
+            "provide": {
+                "psr/log-implementation": "1.0.0"
+            },
+            "require-dev": {
+                "aws/aws-sdk-php": "^2.4.9 || ^3.0",
+                "doctrine/couchdb": "~1.0@dev",
+                "graylog2/gelf-php": "~1.0",
+                "jakub-onderka/php-parallel-lint": "0.9",
+                "php-amqplib/php-amqplib": "~2.4",
+                "php-console/php-console": "^3.1.3",
+                "phpunit/phpunit": "~4.5",
+                "phpunit/phpunit-mock-objects": "2.3.0",
+                "ruflin/elastica": ">=0.90 <3.0",
+                "sentry/sentry": "^0.13",
+                "swiftmailer/swiftmailer": "^5.3|^6.0"
+            },
+            "suggest": {
+                "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB",
+                "doctrine/couchdb": "Allow sending log messages to a CouchDB server",
+                "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)",
+                "ext-mongo": "Allow sending log messages to a MongoDB server",
+                "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server",
+                "mongodb/mongodb": "Allow sending log messages to a MongoDB server via PHP Driver",
+                "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib",
+                "php-console/php-console": "Allow sending log messages to Google Chrome",
+                "rollbar/rollbar": "Allow sending log messages to Rollbar",
+                "ruflin/elastica": "Allow sending log messages to an Elastic Search server",
+                "sentry/sentry": "Allow sending log messages to a Sentry server"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.0.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Monolog\\": "src/Monolog"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Jordi Boggiano",
+                    "email": "j.boggiano@seld.be",
+                    "homepage": "http://seld.be"
+                }
+            ],
+            "description": "Sends your logs to files, sockets, inboxes, databases and various web services",
+            "homepage": "http://github.com/Seldaek/monolog",
+            "keywords": [
+                "log",
+                "logging",
+                "psr-3"
+            ],
+            "time": "2017-06-19T01:22:40+00:00"
+        },
+        {
+            "name": "myclabs/deep-copy",
+            "version": "1.6.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/myclabs/DeepCopy.git",
+                "reference": "8e6e04167378abf1ddb4d3522d8755c5fd90d102"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/8e6e04167378abf1ddb4d3522d8755c5fd90d102",
+                "reference": "8e6e04167378abf1ddb4d3522d8755c5fd90d102",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.4.0"
+            },
+            "require-dev": {
+                "doctrine/collections": "1.*",
+                "phpunit/phpunit": "~4.1"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "DeepCopy\\": "src/DeepCopy/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "description": "Create deep copies (clones) of your objects",
+            "homepage": "https://github.com/myclabs/DeepCopy",
+            "keywords": [
+                "clone",
+                "copy",
+                "duplicate",
+                "object",
+                "object graph"
+            ],
+            "time": "2017-04-12T18:52:22+00:00"
+        },
+        {
+            "name": "nikic/php-parser",
+            "version": "v1.4.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/nikic/PHP-Parser.git",
+                "reference": "f78af2c9c86107aa1a34cd1dbb5bbe9eeb0d9f51"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/f78af2c9c86107aa1a34cd1dbb5bbe9eeb0d9f51",
+                "reference": "f78af2c9c86107aa1a34cd1dbb5bbe9eeb0d9f51",
+                "shasum": ""
+            },
+            "require": {
+                "ext-tokenizer": "*",
+                "php": ">=5.3"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.4-dev"
+                }
+            },
+            "autoload": {
+                "files": [
+                    "lib/bootstrap.php"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Nikita Popov"
+                }
+            ],
+            "description": "A PHP parser written in PHP",
+            "keywords": [
+                "parser",
+                "php"
+            ],
+            "time": "2015-09-19T14:15:08+00:00"
+        },
+        {
+            "name": "pdepend/pdepend",
+            "version": "2.5.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/pdepend/pdepend.git",
+                "reference": "0c50874333149c0dad5a2877801aed148f2767ff"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/pdepend/pdepend/zipball/0c50874333149c0dad5a2877801aed148f2767ff",
+                "reference": "0c50874333149c0dad5a2877801aed148f2767ff",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.7",
+                "symfony/config": "^2.3.0|^3",
+                "symfony/dependency-injection": "^2.3.0|^3",
+                "symfony/filesystem": "^2.3.0|^3"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^4.4.0,<4.8",
+                "squizlabs/php_codesniffer": "^2.0.0"
+            },
+            "bin": [
+                "src/bin/pdepend"
+            ],
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "PDepend\\": "src/main/php/PDepend"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "description": "Official version of pdepend to be handled with Composer",
+            "time": "2017-01-19T14:23:36+00:00"
+        },
+        {
+            "name": "phpcollection/phpcollection",
+            "version": "0.5.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/schmittjoh/php-collection.git",
+                "reference": "f2bcff45c0da7c27991bbc1f90f47c4b7fb434a6"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/schmittjoh/php-collection/zipball/f2bcff45c0da7c27991bbc1f90f47c4b7fb434a6",
+                "reference": "f2bcff45c0da7c27991bbc1f90f47c4b7fb434a6",
+                "shasum": ""
+            },
+            "require": {
+                "phpoption/phpoption": "1.*"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "0.4-dev"
+                }
+            },
+            "autoload": {
+                "psr-0": {
+                    "PhpCollection": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "Apache2"
+            ],
+            "authors": [
+                {
+                    "name": "Johannes M. Schmitt",
+                    "email": "schmittjoh@gmail.com"
+                }
+            ],
+            "description": "General-Purpose Collection Library for PHP",
+            "keywords": [
+                "collection",
+                "list",
+                "map",
+                "sequence",
+                "set"
+            ],
+            "time": "2015-05-17T12:39:23+00:00"
+        },
+        {
+            "name": "phpdocumentor/fileset",
+            "version": "1.0.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/phpDocumentor/Fileset.git",
+                "reference": "bfa78d8fa9763dfce6d0e5d3730c1d8ab25d34b0"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/phpDocumentor/Fileset/zipball/bfa78d8fa9763dfce6d0e5d3730c1d8ab25d34b0",
+                "reference": "bfa78d8fa9763dfce6d0e5d3730c1d8ab25d34b0",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.3",
+                "symfony/finder": "~2.1"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "~3.7"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-0": {
+                    "phpDocumentor": [
+                        "src/",
+                        "tests/unit/"
+                    ]
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "description": "Fileset component for collecting a set of files given directories and file paths",
+            "homepage": "http://www.phpdoc.org",
+            "keywords": [
+                "files",
+                "fileset",
+                "phpdoc"
+            ],
+            "time": "2013-08-06T21:07:42+00:00"
+        },
+        {
+            "name": "phpdocumentor/graphviz",
+            "version": "1.0.4",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/phpDocumentor/GraphViz.git",
+                "reference": "a906a90a9f230535f25ea31caf81b2323956283f"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/phpDocumentor/GraphViz/zipball/a906a90a9f230535f25ea31caf81b2323956283f",
+                "reference": "a906a90a9f230535f25ea31caf81b2323956283f",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.3"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "~4.0"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-0": {
+                    "phpDocumentor": [
+                        "src/",
+                        "tests/unit"
+                    ]
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Mike van Riel",
+                    "email": "mike.vanriel@naenius.com"
+                }
+            ],
+            "time": "2016-02-02T13:00:08+00:00"
+        },
+        {
+            "name": "phpdocumentor/phpdocumentor",
+            "version": "v2.9.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/phpDocumentor/phpDocumentor2.git",
+                "reference": "be607da0eef9b9249c43c5b4820d25d631c73667"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/phpDocumentor/phpDocumentor2/zipball/be607da0eef9b9249c43c5b4820d25d631c73667",
+                "reference": "be607da0eef9b9249c43c5b4820d25d631c73667",
+                "shasum": ""
+            },
+            "require": {
+                "cilex/cilex": "~1.0",
+                "erusev/parsedown": "~1.0",
+                "herrera-io/phar-update": "1.0.3",
+                "jms/serializer": ">=0.12",
+                "monolog/monolog": "~1.6",
+                "php": ">=5.3.3",
+                "phpdocumentor/fileset": "~1.0",
+                "phpdocumentor/graphviz": "~1.0",
+                "phpdocumentor/reflection": "^3.0",
+                "phpdocumentor/reflection-docblock": "~2.0",
+                "symfony/config": "~2.3",
+                "symfony/console": "~2.3",
+                "symfony/event-dispatcher": "~2.1",
+                "symfony/process": "~2.0",
+                "symfony/stopwatch": "~2.3",
+                "symfony/validator": "~2.2",
+                "twig/twig": "~1.3",
+                "zendframework/zend-cache": "~2.1",
+                "zendframework/zend-config": "~2.1",
+                "zendframework/zend-filter": "~2.1",
+                "zendframework/zend-i18n": "~2.1",
+                "zendframework/zend-serializer": "~2.1",
+                "zendframework/zend-servicemanager": "~2.1",
+                "zendframework/zend-stdlib": "~2.1",
+                "zetacomponents/document": ">=1.3.1"
+            },
+            "require-dev": {
+                "behat/behat": "~3.0",
+                "mikey179/vfsstream": "~1.2",
+                "mockery/mockery": "~0.9@dev",
+                "phpunit/phpunit": "~4.0",
+                "squizlabs/php_codesniffer": "~1.4",
+                "symfony/expression-language": "~2.4"
+            },
+            "suggest": {
+                "ext-twig": "Enabling the twig extension improves the generation of twig based templates.",
+                "ext-xslcache": "Enabling the XSLCache extension improves the generation of xml based templates."
+            },
+            "bin": [
+                "bin/phpdoc.php",
+                "bin/phpdoc"
+            ],
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-develop": "2.9-dev"
+                }
+            },
+            "autoload": {
+                "psr-0": {
+                    "phpDocumentor": [
+                        "src/",
+                        "tests/unit/"
+                    ],
+                    "Cilex\\Provider": [
+                        "src/"
+                    ]
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "description": "Documentation Generator for PHP",
+            "homepage": "http://www.phpdoc.org",
+            "keywords": [
+                "api",
+                "application",
+                "dga",
+                "documentation",
+                "phpdoc"
+            ],
+            "time": "2016-05-22T09:50:56+00:00"
+        },
+        {
+            "name": "phpdocumentor/reflection",
+            "version": "3.0.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/phpDocumentor/Reflection.git",
+                "reference": "793bfd92d9a0fc96ae9608fb3e947c3f59fb3a0d"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/phpDocumentor/Reflection/zipball/793bfd92d9a0fc96ae9608fb3e947c3f59fb3a0d",
+                "reference": "793bfd92d9a0fc96ae9608fb3e947c3f59fb3a0d",
+                "shasum": ""
+            },
+            "require": {
+                "nikic/php-parser": "^1.0",
+                "php": ">=5.3.3",
+                "phpdocumentor/reflection-docblock": "~2.0",
+                "psr/log": "~1.0"
+            },
+            "require-dev": {
+                "behat/behat": "~2.4",
+                "mockery/mockery": "~0.8",
+                "phpunit/phpunit": "~4.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-0": {
+                    "phpDocumentor": [
+                        "src/",
+                        "tests/unit/",
+                        "tests/mocks/"
+                    ]
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "description": "Reflection library to do Static Analysis for PHP Projects",
+            "homepage": "http://www.phpdoc.org",
+            "keywords": [
+                "phpDocumentor",
+                "phpdoc",
+                "reflection",
+                "static analysis"
+            ],
+            "time": "2016-05-21T08:42:32+00:00"
+        },
+        {
+            "name": "phpdocumentor/reflection-docblock",
+            "version": "2.0.5",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
+                "reference": "e6a969a640b00d8daa3c66518b0405fb41ae0c4b"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/e6a969a640b00d8daa3c66518b0405fb41ae0c4b",
+                "reference": "e6a969a640b00d8daa3c66518b0405fb41ae0c4b",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.3"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "~4.0"
+            },
+            "suggest": {
+                "dflydev/markdown": "~1.0",
+                "erusev/parsedown": "~1.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.0.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-0": {
+                    "phpDocumentor": [
+                        "src/"
+                    ]
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Mike van Riel",
+                    "email": "mike.vanriel@naenius.com"
+                }
+            ],
+            "time": "2016-01-25T08:17:30+00:00"
+        },
+        {
+            "name": "phploc/phploc",
+            "version": "3.0.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/phploc.git",
+                "reference": "74f917e6f80f291856989960d31afa44a4196859"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/phploc/zipball/74f917e6f80f291856989960d31afa44a4196859",
+                "reference": "74f917e6f80f291856989960d31afa44a4196859",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.6",
+                "sebastian/finder-facade": "~1.1",
+                "sebastian/git": "~2.1",
+                "sebastian/version": "~1.0.3|~2.0",
+                "symfony/console": "~2.5|~3.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "~5"
+            },
+            "bin": [
+                "phploc"
+            ],
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "3.0-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sebastian@phpunit.de",
+                    "role": "lead"
+                }
+            ],
+            "description": "A tool for quickly measuring the size of a PHP project.",
+            "homepage": "https://github.com/sebastianbergmann/phploc",
+            "time": "2016-04-25T08:11:21+00:00"
+        },
+        {
+            "name": "phpmd/phpmd",
+            "version": "2.6.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/phpmd/phpmd.git",
+                "reference": "4e9924b2c157a3eb64395460fcf56b31badc8374"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/phpmd/phpmd/zipball/4e9924b2c157a3eb64395460fcf56b31badc8374",
+                "reference": "4e9924b2c157a3eb64395460fcf56b31badc8374",
+                "shasum": ""
+            },
+            "require": {
+                "ext-xml": "*",
+                "pdepend/pdepend": "^2.5",
+                "php": ">=5.3.9"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^4.0",
+                "squizlabs/php_codesniffer": "^2.0"
+            },
+            "bin": [
+                "src/bin/phpmd"
+            ],
+            "type": "project",
+            "autoload": {
+                "psr-0": {
+                    "PHPMD\\": "src/main/php"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Manuel Pichler",
+                    "email": "github@manuel-pichler.de",
+                    "homepage": "https://github.com/manuelpichler",
+                    "role": "Project Founder"
+                },
+                {
+                    "name": "Other contributors",
+                    "homepage": "https://github.com/phpmd/phpmd/graphs/contributors",
+                    "role": "Contributors"
+                },
+                {
+                    "name": "Marc Würth",
+                    "email": "ravage@bluewin.ch",
+                    "homepage": "https://github.com/ravage84",
+                    "role": "Project Maintainer"
+                }
+            ],
+            "description": "PHPMD is a spin-off project of PHP Depend and aims to be a PHP equivalent of the well known Java tool PMD.",
+            "homepage": "http://phpmd.org/",
+            "keywords": [
+                "mess detection",
+                "mess detector",
+                "pdepend",
+                "phpmd",
+                "pmd"
+            ],
+            "time": "2017-01-20T14:41:10+00:00"
+        },
+        {
+            "name": "phpoption/phpoption",
+            "version": "1.5.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/schmittjoh/php-option.git",
+                "reference": "94e644f7d2051a5f0fcf77d81605f152eecff0ed"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/94e644f7d2051a5f0fcf77d81605f152eecff0ed",
+                "reference": "94e644f7d2051a5f0fcf77d81605f152eecff0ed",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "4.7.*"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.3-dev"
+                }
+            },
+            "autoload": {
+                "psr-0": {
+                    "PhpOption\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "Apache2"
+            ],
+            "authors": [
+                {
+                    "name": "Johannes M. Schmitt",
+                    "email": "schmittjoh@gmail.com"
+                }
+            ],
+            "description": "Option Type for PHP",
+            "keywords": [
+                "language",
+                "option",
+                "php",
+                "type"
+            ],
+            "time": "2015-07-25T16:39:46+00:00"
+        },
+        {
+            "name": "phpspec/prophecy",
+            "version": "v1.7.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/phpspec/prophecy.git",
+                "reference": "93d39f1f7f9326d746203c7c056f300f7f126073"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/phpspec/prophecy/zipball/93d39f1f7f9326d746203c7c056f300f7f126073",
+                "reference": "93d39f1f7f9326d746203c7c056f300f7f126073",
+                "shasum": ""
+            },
+            "require": {
+                "doctrine/instantiator": "^1.0.2",
+                "php": "^5.3|^7.0",
+                "phpdocumentor/reflection-docblock": "^2.0|^3.0.2",
+                "sebastian/comparator": "^1.1|^2.0",
+                "sebastian/recursion-context": "^1.0|^2.0|^3.0"
+            },
+            "require-dev": {
+                "phpspec/phpspec": "^2.5|^3.2",
+                "phpunit/phpunit": "^4.8 || ^5.6.5"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.6.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-0": {
+                    "Prophecy\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Konstantin Kudryashov",
+                    "email": "ever.zet@gmail.com",
+                    "homepage": "http://everzet.com"
+                },
+                {
+                    "name": "Marcello Duarte",
+                    "email": "marcello.duarte@gmail.com"
+                }
+            ],
+            "description": "Highly opinionated mocking framework for PHP 5.3+",
+            "homepage": "https://github.com/phpspec/prophecy",
+            "keywords": [
+                "Double",
+                "Dummy",
+                "fake",
+                "mock",
+                "spy",
+                "stub"
+            ],
+            "time": "2017-03-02T20:05:34+00:00"
+        },
+        {
+            "name": "phpunit/php-code-coverage",
+            "version": "4.0.8",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
+                "reference": "ef7b2f56815df854e66ceaee8ebe9393ae36a40d"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ef7b2f56815df854e66ceaee8ebe9393ae36a40d",
+                "reference": "ef7b2f56815df854e66ceaee8ebe9393ae36a40d",
+                "shasum": ""
+            },
+            "require": {
+                "ext-dom": "*",
+                "ext-xmlwriter": "*",
+                "php": "^5.6 || ^7.0",
+                "phpunit/php-file-iterator": "^1.3",
+                "phpunit/php-text-template": "^1.2",
+                "phpunit/php-token-stream": "^1.4.2 || ^2.0",
+                "sebastian/code-unit-reverse-lookup": "^1.0",
+                "sebastian/environment": "^1.3.2 || ^2.0",
+                "sebastian/version": "^1.0 || ^2.0"
+            },
+            "require-dev": {
+                "ext-xdebug": "^2.1.4",
+                "phpunit/phpunit": "^5.7"
+            },
+            "suggest": {
+                "ext-xdebug": "^2.5.1"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "4.0.x-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sb@sebastian-bergmann.de",
+                    "role": "lead"
+                }
+            ],
+            "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
+            "homepage": "https://github.com/sebastianbergmann/php-code-coverage",
+            "keywords": [
+                "coverage",
+                "testing",
+                "xunit"
+            ],
+            "time": "2017-04-02T07:44:40+00:00"
+        },
+        {
+            "name": "phpunit/php-file-iterator",
+            "version": "1.4.2",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/php-file-iterator.git",
+                "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/3cc8f69b3028d0f96a9078e6295d86e9bf019be5",
+                "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.3"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.4.x-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sb@sebastian-bergmann.de",
+                    "role": "lead"
+                }
+            ],
+            "description": "FilterIterator implementation that filters files based on a list of suffixes.",
+            "homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
+            "keywords": [
+                "filesystem",
+                "iterator"
+            ],
+            "time": "2016-10-03T07:40:28+00:00"
+        },
+        {
+            "name": "phpunit/php-text-template",
+            "version": "1.2.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/php-text-template.git",
+                "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
+                "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.3"
+            },
+            "type": "library",
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sebastian@phpunit.de",
+                    "role": "lead"
+                }
+            ],
+            "description": "Simple template engine.",
+            "homepage": "https://github.com/sebastianbergmann/php-text-template/",
+            "keywords": [
+                "template"
+            ],
+            "time": "2015-06-21T13:50:34+00:00"
+        },
+        {
+            "name": "phpunit/php-timer",
+            "version": "1.0.9",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/php-timer.git",
+                "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f",
+                "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^5.3.3 || ^7.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sb@sebastian-bergmann.de",
+                    "role": "lead"
+                }
+            ],
+            "description": "Utility class for timing",
+            "homepage": "https://github.com/sebastianbergmann/php-timer/",
+            "keywords": [
+                "timer"
+            ],
+            "time": "2017-02-26T11:10:40+00:00"
+        },
+        {
+            "name": "phpunit/php-token-stream",
+            "version": "1.4.11",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/php-token-stream.git",
+                "reference": "e03f8f67534427a787e21a385a67ec3ca6978ea7"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/e03f8f67534427a787e21a385a67ec3ca6978ea7",
+                "reference": "e03f8f67534427a787e21a385a67ec3ca6978ea7",
+                "shasum": ""
+            },
+            "require": {
+                "ext-tokenizer": "*",
+                "php": ">=5.3.3"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "~4.2"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.4-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sebastian@phpunit.de"
+                }
+            ],
+            "description": "Wrapper around PHP's tokenizer extension.",
+            "homepage": "https://github.com/sebastianbergmann/php-token-stream/",
+            "keywords": [
+                "tokenizer"
+            ],
+            "time": "2017-02-27T10:12:30+00:00"
+        },
+        {
+            "name": "phpunit/phpunit",
+            "version": "5.7.15",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/phpunit.git",
+                "reference": "b99112aecc01f62acf3d81a3f59646700a1849e5"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/b99112aecc01f62acf3d81a3f59646700a1849e5",
+                "reference": "b99112aecc01f62acf3d81a3f59646700a1849e5",
+                "shasum": ""
+            },
+            "require": {
+                "ext-dom": "*",
+                "ext-json": "*",
+                "ext-libxml": "*",
+                "ext-mbstring": "*",
+                "ext-xml": "*",
+                "myclabs/deep-copy": "~1.3",
+                "php": "^5.6 || ^7.0",
+                "phpspec/prophecy": "^1.6.2",
+                "phpunit/php-code-coverage": "^4.0.4",
+                "phpunit/php-file-iterator": "~1.4",
+                "phpunit/php-text-template": "~1.2",
+                "phpunit/php-timer": "^1.0.6",
+                "phpunit/phpunit-mock-objects": "^3.2",
+                "sebastian/comparator": "^1.2.4",
+                "sebastian/diff": "~1.2",
+                "sebastian/environment": "^1.3.4 || ^2.0",
+                "sebastian/exporter": "~2.0",
+                "sebastian/global-state": "^1.1",
+                "sebastian/object-enumerator": "~2.0",
+                "sebastian/resource-operations": "~1.0",
+                "sebastian/version": "~1.0.3|~2.0",
+                "symfony/yaml": "~2.1|~3.0"
+            },
+            "conflict": {
+                "phpdocumentor/reflection-docblock": "3.0.2"
+            },
+            "require-dev": {
+                "ext-pdo": "*"
+            },
+            "suggest": {
+                "ext-xdebug": "*",
+                "phpunit/php-invoker": "~1.1"
+            },
+            "bin": [
+                "phpunit"
+            ],
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "5.7.x-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sebastian@phpunit.de",
+                    "role": "lead"
+                }
+            ],
+            "description": "The PHP Unit Testing framework.",
+            "homepage": "https://phpunit.de/",
+            "keywords": [
+                "phpunit",
+                "testing",
+                "xunit"
+            ],
+            "time": "2017-03-02T15:22:43+00:00"
+        },
+        {
+            "name": "phpunit/phpunit-mock-objects",
+            "version": "3.4.4",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git",
+                "reference": "a23b761686d50a560cc56233b9ecf49597cc9118"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/a23b761686d50a560cc56233b9ecf49597cc9118",
+                "reference": "a23b761686d50a560cc56233b9ecf49597cc9118",
+                "shasum": ""
+            },
+            "require": {
+                "doctrine/instantiator": "^1.0.2",
+                "php": "^5.6 || ^7.0",
+                "phpunit/php-text-template": "^1.2",
+                "sebastian/exporter": "^1.2 || ^2.0"
+            },
+            "conflict": {
+                "phpunit/phpunit": "<5.4.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^5.4"
+            },
+            "suggest": {
+                "ext-soap": "*"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "3.2.x-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sb@sebastian-bergmann.de",
+                    "role": "lead"
+                }
+            ],
+            "description": "Mock Object library for PHPUnit",
+            "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/",
+            "keywords": [
+                "mock",
+                "xunit"
+            ],
+            "time": "2017-06-30T09:13:00+00:00"
+        },
+        {
+            "name": "pimple/pimple",
+            "version": "v1.1.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/silexphp/Pimple.git",
+                "reference": "2019c145fe393923f3441b23f29bbdfaa5c58c4d"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/silexphp/Pimple/zipball/2019c145fe393923f3441b23f29bbdfaa5c58c4d",
+                "reference": "2019c145fe393923f3441b23f29bbdfaa5c58c4d",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.1.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-0": {
+                    "Pimple": "lib/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Fabien Potencier",
+                    "email": "fabien@symfony.com"
+                }
+            ],
+            "description": "Pimple is a simple Dependency Injection Container for PHP 5.3",
+            "homepage": "http://pimple.sensiolabs.org",
+            "keywords": [
+                "container",
+                "dependency injection"
+            ],
+            "time": "2013-11-22T08:30:29+00:00"
+        },
+        {
+            "name": "sebastian/code-unit-reverse-lookup",
+            "version": "1.0.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git",
+                "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/4419fcdb5eabb9caa61a27c7a1db532a6b55dd18",
+                "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^5.6 || ^7.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^5.7 || ^6.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0.x-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sebastian@phpunit.de"
+                }
+            ],
+            "description": "Looks up which function or method a line of code belongs to",
+            "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/",
+            "time": "2017-03-04T06:30:41+00:00"
+        },
+        {
+            "name": "sebastian/comparator",
+            "version": "1.2.4",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/comparator.git",
+                "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2b7424b55f5047b47ac6e5ccb20b2aea4011d9be",
+                "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.3",
+                "sebastian/diff": "~1.2",
+                "sebastian/exporter": "~1.2 || ~2.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "~4.4"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.2.x-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Jeff Welch",
+                    "email": "whatthejeff@gmail.com"
+                },
+                {
+                    "name": "Volker Dusch",
+                    "email": "github@wallbash.com"
+                },
+                {
+                    "name": "Bernhard Schussek",
+                    "email": "bschussek@2bepublished.at"
+                },
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sebastian@phpunit.de"
+                }
+            ],
+            "description": "Provides the functionality to compare PHP values for equality",
+            "homepage": "http://www.github.com/sebastianbergmann/comparator",
+            "keywords": [
+                "comparator",
+                "compare",
+                "equality"
+            ],
+            "time": "2017-01-29T09:50:25+00:00"
+        },
+        {
+            "name": "sebastian/diff",
+            "version": "1.4.3",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/diff.git",
+                "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/7f066a26a962dbe58ddea9f72a4e82874a3975a4",
+                "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^5.3.3 || ^7.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.4-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Kore Nordmann",
+                    "email": "mail@kore-nordmann.de"
+                },
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sebastian@phpunit.de"
+                }
+            ],
+            "description": "Diff implementation",
+            "homepage": "https://github.com/sebastianbergmann/diff",
+            "keywords": [
+                "diff"
+            ],
+            "time": "2017-05-22T07:24:03+00:00"
+        },
+        {
+            "name": "sebastian/environment",
+            "version": "2.0.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/environment.git",
+                "reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/5795ffe5dc5b02460c3e34222fee8cbe245d8fac",
+                "reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^5.6 || ^7.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^5.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.0.x-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sebastian@phpunit.de"
+                }
+            ],
+            "description": "Provides functionality to handle HHVM/PHP environments",
+            "homepage": "http://www.github.com/sebastianbergmann/environment",
+            "keywords": [
+                "Xdebug",
+                "environment",
+                "hhvm"
+            ],
+            "time": "2016-11-26T07:53:53+00:00"
+        },
+        {
+            "name": "sebastian/exporter",
+            "version": "2.0.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/exporter.git",
+                "reference": "ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4",
+                "reference": "ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.3",
+                "sebastian/recursion-context": "~2.0"
+            },
+            "require-dev": {
+                "ext-mbstring": "*",
+                "phpunit/phpunit": "~4.4"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.0.x-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Jeff Welch",
+                    "email": "whatthejeff@gmail.com"
+                },
+                {
+                    "name": "Volker Dusch",
+                    "email": "github@wallbash.com"
+                },
+                {
+                    "name": "Bernhard Schussek",
+                    "email": "bschussek@2bepublished.at"
+                },
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sebastian@phpunit.de"
+                },
+                {
+                    "name": "Adam Harvey",
+                    "email": "aharvey@php.net"
+                }
+            ],
+            "description": "Provides the functionality to export PHP variables for visualization",
+            "homepage": "http://www.github.com/sebastianbergmann/exporter",
+            "keywords": [
+                "export",
+                "exporter"
+            ],
+            "time": "2016-11-19T08:54:04+00:00"
+        },
+        {
+            "name": "sebastian/finder-facade",
+            "version": "1.2.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/finder-facade.git",
+                "reference": "2a6f7f57efc0aa2d23297d9fd9e2a03111a8c0b9"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/finder-facade/zipball/2a6f7f57efc0aa2d23297d9fd9e2a03111a8c0b9",
+                "reference": "2a6f7f57efc0aa2d23297d9fd9e2a03111a8c0b9",
+                "shasum": ""
+            },
+            "require": {
+                "symfony/finder": "~2.3|~3.0",
+                "theseer/fdomdocument": "~1.3"
+            },
+            "type": "library",
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sebastian@phpunit.de",
+                    "role": "lead"
+                }
+            ],
+            "description": "FinderFacade is a convenience wrapper for Symfony's Finder component.",
+            "homepage": "https://github.com/sebastianbergmann/finder-facade",
+            "time": "2016-02-17T07:02:23+00:00"
+        },
+        {
+            "name": "sebastian/git",
+            "version": "2.1.4",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/git.git",
+                "reference": "815bbbc963cf35e5413df195aa29df58243ecd24"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/git/zipball/815bbbc963cf35e5413df195aa29df58243ecd24",
+                "reference": "815bbbc963cf35e5413df195aa29df58243ecd24",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.3"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.1-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sebastian@phpunit.de"
+                }
+            ],
+            "description": "Simple wrapper for Git",
+            "homepage": "http://www.github.com/sebastianbergmann/git",
+            "keywords": [
+                "git"
+            ],
+            "abandoned": true,
+            "time": "2017-01-23T20:57:12+00:00"
+        },
+        {
+            "name": "sebastian/global-state",
+            "version": "1.1.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/global-state.git",
+                "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4",
+                "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.3"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "~4.2"
+            },
+            "suggest": {
+                "ext-uopz": "*"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sebastian@phpunit.de"
+                }
+            ],
+            "description": "Snapshotting of global state",
+            "homepage": "http://www.github.com/sebastianbergmann/global-state",
+            "keywords": [
+                "global state"
+            ],
+            "time": "2015-10-12T03:26:01+00:00"
+        },
+        {
+            "name": "sebastian/object-enumerator",
+            "version": "2.0.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/object-enumerator.git",
+                "reference": "1311872ac850040a79c3c058bea3e22d0f09cbb7"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/1311872ac850040a79c3c058bea3e22d0f09cbb7",
+                "reference": "1311872ac850040a79c3c058bea3e22d0f09cbb7",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.6",
+                "sebastian/recursion-context": "~2.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "~5"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.0.x-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sebastian@phpunit.de"
+                }
+            ],
+            "description": "Traverses array structures and object graphs to enumerate all referenced objects",
+            "homepage": "https://github.com/sebastianbergmann/object-enumerator/",
+            "time": "2017-02-18T15:18:39+00:00"
+        },
+        {
+            "name": "sebastian/phpcpd",
+            "version": "2.0.4",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/phpcpd.git",
+                "reference": "24d9a880deadb0b8c9680e9cfe78e30b704225db"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/phpcpd/zipball/24d9a880deadb0b8c9680e9cfe78e30b704225db",
+                "reference": "24d9a880deadb0b8c9680e9cfe78e30b704225db",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.3",
+                "phpunit/php-timer": ">=1.0.6",
+                "sebastian/finder-facade": "~1.1",
+                "sebastian/version": "~1.0|~2.0",
+                "symfony/console": "~2.7|^3.0",
+                "theseer/fdomdocument": "~1.4"
+            },
+            "bin": [
+                "phpcpd"
+            ],
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.0-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sebastian@phpunit.de",
+                    "role": "lead"
+                }
+            ],
+            "description": "Copy/Paste Detector (CPD) for PHP code.",
+            "homepage": "https://github.com/sebastianbergmann/phpcpd",
+            "time": "2016-04-17T19:32:49+00:00"
+        },
+        {
+            "name": "sebastian/recursion-context",
+            "version": "2.0.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/recursion-context.git",
+                "reference": "2c3ba150cbec723aa057506e73a8d33bdb286c9a"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/2c3ba150cbec723aa057506e73a8d33bdb286c9a",
+                "reference": "2c3ba150cbec723aa057506e73a8d33bdb286c9a",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.3"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "~4.4"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.0.x-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Jeff Welch",
+                    "email": "whatthejeff@gmail.com"
+                },
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sebastian@phpunit.de"
+                },
+                {
+                    "name": "Adam Harvey",
+                    "email": "aharvey@php.net"
+                }
+            ],
+            "description": "Provides functionality to recursively process PHP variables",
+            "homepage": "http://www.github.com/sebastianbergmann/recursion-context",
+            "time": "2016-11-19T07:33:16+00:00"
+        },
+        {
+            "name": "sebastian/resource-operations",
+            "version": "1.0.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/resource-operations.git",
+                "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/ce990bb21759f94aeafd30209e8cfcdfa8bc3f52",
+                "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.6.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.0.x-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sebastian@phpunit.de"
+                }
+            ],
+            "description": "Provides a list of PHP built-in functions that operate on resources",
+            "homepage": "https://www.github.com/sebastianbergmann/resource-operations",
+            "time": "2015-07-28T20:34:47+00:00"
+        },
+        {
+            "name": "sebastian/version",
+            "version": "2.0.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/sebastianbergmann/version.git",
+                "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019",
+                "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.6"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.0.x-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Sebastian Bergmann",
+                    "email": "sebastian@phpunit.de",
+                    "role": "lead"
+                }
+            ],
+            "description": "Library that helps with managing the version number of Git-hosted PHP projects",
+            "homepage": "https://github.com/sebastianbergmann/version",
+            "time": "2016-10-03T07:35:21+00:00"
+        },
+        {
+            "name": "seld/jsonlint",
+            "version": "1.6.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/Seldaek/jsonlint.git",
+                "reference": "50d63f2858d87c4738d5b76a7dcbb99fa8cf7c77"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/50d63f2858d87c4738d5b76a7dcbb99fa8cf7c77",
+                "reference": "50d63f2858d87c4738d5b76a7dcbb99fa8cf7c77",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^5.3 || ^7.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^4.5"
+            },
+            "bin": [
+                "bin/jsonlint"
+            ],
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Seld\\JsonLint\\": "src/Seld/JsonLint/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Jordi Boggiano",
+                    "email": "j.boggiano@seld.be",
+                    "homepage": "http://seld.be"
+                }
+            ],
+            "description": "JSON Linter",
+            "keywords": [
+                "json",
+                "linter",
+                "parser",
+                "validator"
+            ],
+            "time": "2017-06-18T15:11:04+00:00"
+        },
+        {
+            "name": "squizlabs/php_codesniffer",
+            "version": "2.8.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
+                "reference": "d7cf0d894e8aa4c73712ee4a331cc1eaa37cdc7d"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/d7cf0d894e8aa4c73712ee4a331cc1eaa37cdc7d",
+                "reference": "d7cf0d894e8aa4c73712ee4a331cc1eaa37cdc7d",
+                "shasum": ""
+            },
+            "require": {
+                "ext-simplexml": "*",
+                "ext-tokenizer": "*",
+                "ext-xmlwriter": "*",
+                "php": ">=5.1.2"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "~4.0"
+            },
+            "bin": [
+                "scripts/phpcs",
+                "scripts/phpcbf"
+            ],
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.x-dev"
+                }
+            },
+            "autoload": {
+                "classmap": [
+                    "CodeSniffer.php",
+                    "CodeSniffer/CLI.php",
+                    "CodeSniffer/Exception.php",
+                    "CodeSniffer/File.php",
+                    "CodeSniffer/Fixer.php",
+                    "CodeSniffer/Report.php",
+                    "CodeSniffer/Reporting.php",
+                    "CodeSniffer/Sniff.php",
+                    "CodeSniffer/Tokens.php",
+                    "CodeSniffer/Reports/",
+                    "CodeSniffer/Tokenizers/",
+                    "CodeSniffer/DocGenerators/",
+                    "CodeSniffer/Standards/AbstractPatternSniff.php",
+                    "CodeSniffer/Standards/AbstractScopeSniff.php",
+                    "CodeSniffer/Standards/AbstractVariableSniff.php",
+                    "CodeSniffer/Standards/IncorrectPatternException.php",
+                    "CodeSniffer/Standards/Generic/Sniffs/",
+                    "CodeSniffer/Standards/MySource/Sniffs/",
+                    "CodeSniffer/Standards/PEAR/Sniffs/",
+                    "CodeSniffer/Standards/PSR1/Sniffs/",
+                    "CodeSniffer/Standards/PSR2/Sniffs/",
+                    "CodeSniffer/Standards/Squiz/Sniffs/",
+                    "CodeSniffer/Standards/Zend/Sniffs/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Greg Sherwood",
+                    "role": "lead"
+                }
+            ],
+            "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.",
+            "homepage": "http://www.squizlabs.com/php-codesniffer",
+            "keywords": [
+                "phpcs",
+                "standards"
+            ],
+            "time": "2017-03-01T22:17:45+00:00"
+        },
+        {
+            "name": "symfony/config",
+            "version": "v2.8.25",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/config.git",
+                "reference": "0b8541d18507d10204a08384640ff6df3c739ebe"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/config/zipball/0b8541d18507d10204a08384640ff6df3c739ebe",
+                "reference": "0b8541d18507d10204a08384640ff6df3c739ebe",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.9",
+                "symfony/filesystem": "~2.3|~3.0.0"
+            },
+            "require-dev": {
+                "symfony/yaml": "~2.7|~3.0.0"
+            },
+            "suggest": {
+                "symfony/yaml": "To use the yaml reference dumper"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.8-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\Component\\Config\\": ""
+                },
+                "exclude-from-classmap": [
+                    "/Tests/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Fabien Potencier",
+                    "email": "fabien@symfony.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Symfony Config Component",
+            "homepage": "https://symfony.com",
+            "time": "2017-04-12T14:07:15+00:00"
+        },
+        {
+            "name": "symfony/console",
+            "version": "v2.8.25",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/console.git",
+                "reference": "46e65f8d98c9ab629bbfcc16a4ff023f61c37fb2"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/console/zipball/46e65f8d98c9ab629bbfcc16a4ff023f61c37fb2",
+                "reference": "46e65f8d98c9ab629bbfcc16a4ff023f61c37fb2",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.9",
+                "symfony/debug": "^2.7.2|~3.0.0",
+                "symfony/polyfill-mbstring": "~1.0"
+            },
+            "require-dev": {
+                "psr/log": "~1.0",
+                "symfony/event-dispatcher": "~2.1|~3.0.0",
+                "symfony/process": "~2.1|~3.0.0"
+            },
+            "suggest": {
+                "psr/log": "For using the console logger",
+                "symfony/event-dispatcher": "",
+                "symfony/process": ""
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.8-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\Component\\Console\\": ""
+                },
+                "exclude-from-classmap": [
+                    "/Tests/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Fabien Potencier",
+                    "email": "fabien@symfony.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Symfony Console Component",
+            "homepage": "https://symfony.com",
+            "time": "2017-07-03T08:04:30+00:00"
+        },
+        {
+            "name": "symfony/css-selector",
+            "version": "v3.3.5",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/css-selector.git",
+                "reference": "4d882dced7b995d5274293039370148e291808f2"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/css-selector/zipball/4d882dced7b995d5274293039370148e291808f2",
+                "reference": "4d882dced7b995d5274293039370148e291808f2",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.5.9"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "3.3-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\Component\\CssSelector\\": ""
+                },
+                "exclude-from-classmap": [
+                    "/Tests/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Jean-François Simon",
+                    "email": "jeanfrancois.simon@sensiolabs.com"
+                },
+                {
+                    "name": "Fabien Potencier",
+                    "email": "fabien@symfony.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Symfony CssSelector Component",
+            "homepage": "https://symfony.com",
+            "time": "2017-05-01T15:01:29+00:00"
+        },
+        {
+            "name": "symfony/debug",
+            "version": "v3.0.9",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/debug.git",
+                "reference": "697c527acd9ea1b2d3efac34d9806bf255278b0a"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/debug/zipball/697c527acd9ea1b2d3efac34d9806bf255278b0a",
+                "reference": "697c527acd9ea1b2d3efac34d9806bf255278b0a",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.5.9",
+                "psr/log": "~1.0"
+            },
+            "conflict": {
+                "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2"
+            },
+            "require-dev": {
+                "symfony/class-loader": "~2.8|~3.0",
+                "symfony/http-kernel": "~2.8|~3.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "3.0-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\Component\\Debug\\": ""
+                },
+                "exclude-from-classmap": [
+                    "/Tests/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Fabien Potencier",
+                    "email": "fabien@symfony.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Symfony Debug Component",
+            "homepage": "https://symfony.com",
+            "time": "2016-07-30T07:22:48+00:00"
+        },
+        {
+            "name": "symfony/dependency-injection",
+            "version": "v3.2.12",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/dependency-injection.git",
+                "reference": "c1170b063674f000b154a5809bb9e373a773d4c0"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/c1170b063674f000b154a5809bb9e373a773d4c0",
+                "reference": "c1170b063674f000b154a5809bb9e373a773d4c0",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.5.9"
+            },
+            "conflict": {
+                "symfony/yaml": "<3.2"
+            },
+            "require-dev": {
+                "symfony/config": "~2.8|~3.0",
+                "symfony/expression-language": "~2.8|~3.0",
+                "symfony/yaml": "~3.2"
+            },
+            "suggest": {
+                "symfony/config": "",
+                "symfony/expression-language": "For using expressions in service container configuration",
+                "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them",
+                "symfony/yaml": ""
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "3.2-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\Component\\DependencyInjection\\": ""
+                },
+                "exclude-from-classmap": [
+                    "/Tests/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Fabien Potencier",
+                    "email": "fabien@symfony.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Symfony DependencyInjection Component",
+            "homepage": "https://symfony.com",
+            "time": "2017-07-17T14:04:01+00:00"
+        },
+        {
+            "name": "symfony/event-dispatcher",
+            "version": "v2.8.25",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/event-dispatcher.git",
+                "reference": "1377400fd641d7d1935981546aaef780ecd5bf6d"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/1377400fd641d7d1935981546aaef780ecd5bf6d",
+                "reference": "1377400fd641d7d1935981546aaef780ecd5bf6d",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.9"
+            },
+            "require-dev": {
+                "psr/log": "~1.0",
+                "symfony/config": "^2.0.5|~3.0.0",
+                "symfony/dependency-injection": "~2.6|~3.0.0",
+                "symfony/expression-language": "~2.6|~3.0.0",
+                "symfony/stopwatch": "~2.3|~3.0.0"
+            },
+            "suggest": {
+                "symfony/dependency-injection": "",
+                "symfony/http-kernel": ""
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.8-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\Component\\EventDispatcher\\": ""
+                },
+                "exclude-from-classmap": [
+                    "/Tests/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Fabien Potencier",
+                    "email": "fabien@symfony.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Symfony EventDispatcher Component",
+            "homepage": "https://symfony.com",
+            "time": "2017-06-02T07:47:27+00:00"
+        },
+        {
+            "name": "symfony/filesystem",
+            "version": "v3.0.9",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/filesystem.git",
+                "reference": "b2da5009d9bacbd91d83486aa1f44c793a8c380d"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/filesystem/zipball/b2da5009d9bacbd91d83486aa1f44c793a8c380d",
+                "reference": "b2da5009d9bacbd91d83486aa1f44c793a8c380d",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.5.9"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "3.0-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\Component\\Filesystem\\": ""
+                },
+                "exclude-from-classmap": [
+                    "/Tests/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Fabien Potencier",
+                    "email": "fabien@symfony.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Symfony Filesystem Component",
+            "homepage": "https://symfony.com",
+            "time": "2016-07-20T05:43:46+00:00"
+        },
+        {
+            "name": "symfony/finder",
+            "version": "v2.8.25",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/finder.git",
+                "reference": "4f4e84811004e065a3bb5ceeb1d9aa592630f9ad"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/finder/zipball/4f4e84811004e065a3bb5ceeb1d9aa592630f9ad",
+                "reference": "4f4e84811004e065a3bb5ceeb1d9aa592630f9ad",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.9"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.8-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\Component\\Finder\\": ""
+                },
+                "exclude-from-classmap": [
+                    "/Tests/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Fabien Potencier",
+                    "email": "fabien@symfony.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Symfony Finder Component",
+            "homepage": "https://symfony.com",
+            "time": "2017-06-01T20:52:29+00:00"
+        },
+        {
+            "name": "symfony/polyfill-mbstring",
+            "version": "v1.4.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/polyfill-mbstring.git",
+                "reference": "f29dca382a6485c3cbe6379f0c61230167681937"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/f29dca382a6485c3cbe6379f0c61230167681937",
+                "reference": "f29dca382a6485c3cbe6379f0c61230167681937",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.3"
+            },
+            "suggest": {
+                "ext-mbstring": "For best performance"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.4-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\Polyfill\\Mbstring\\": ""
+                },
+                "files": [
+                    "bootstrap.php"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Nicolas Grekas",
+                    "email": "p@tchwork.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Symfony polyfill for the Mbstring extension",
+            "homepage": "https://symfony.com",
+            "keywords": [
+                "compatibility",
+                "mbstring",
+                "polyfill",
+                "portable",
+                "shim"
+            ],
+            "time": "2017-06-09T14:24:12+00:00"
+        },
+        {
+            "name": "symfony/process",
+            "version": "v2.8.25",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/process.git",
+                "reference": "57e52a0a6a80ea0aec4fc1b785a7920a95cb88a8"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/process/zipball/57e52a0a6a80ea0aec4fc1b785a7920a95cb88a8",
+                "reference": "57e52a0a6a80ea0aec4fc1b785a7920a95cb88a8",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.9"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.8-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\Component\\Process\\": ""
+                },
+                "exclude-from-classmap": [
+                    "/Tests/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Fabien Potencier",
+                    "email": "fabien@symfony.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Symfony Process Component",
+            "homepage": "https://symfony.com",
+            "time": "2017-07-03T08:04:30+00:00"
+        },
+        {
+            "name": "symfony/stopwatch",
+            "version": "v2.8.25",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/stopwatch.git",
+                "reference": "e02577b841394a78306d7b547701bb7bb705bad5"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/stopwatch/zipball/e02577b841394a78306d7b547701bb7bb705bad5",
+                "reference": "e02577b841394a78306d7b547701bb7bb705bad5",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.9"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.8-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\Component\\Stopwatch\\": ""
+                },
+                "exclude-from-classmap": [
+                    "/Tests/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Fabien Potencier",
+                    "email": "fabien@symfony.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Symfony Stopwatch Component",
+            "homepage": "https://symfony.com",
+            "time": "2017-04-12T14:07:15+00:00"
+        },
+        {
+            "name": "symfony/translation",
+            "version": "v3.0.9",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/translation.git",
+                "reference": "eee6c664853fd0576f21ae25725cfffeafe83f26"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/translation/zipball/eee6c664853fd0576f21ae25725cfffeafe83f26",
+                "reference": "eee6c664853fd0576f21ae25725cfffeafe83f26",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.5.9",
+                "symfony/polyfill-mbstring": "~1.0"
+            },
+            "conflict": {
+                "symfony/config": "<2.8"
+            },
+            "require-dev": {
+                "psr/log": "~1.0",
+                "symfony/config": "~2.8|~3.0",
+                "symfony/intl": "~2.8|~3.0",
+                "symfony/yaml": "~2.8|~3.0"
+            },
+            "suggest": {
+                "psr/log": "To use logging capability in translator",
+                "symfony/config": "",
+                "symfony/yaml": ""
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "3.0-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\Component\\Translation\\": ""
+                },
+                "exclude-from-classmap": [
+                    "/Tests/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Fabien Potencier",
+                    "email": "fabien@symfony.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Symfony Translation Component",
+            "homepage": "https://symfony.com",
+            "time": "2016-07-30T07:22:48+00:00"
+        },
+        {
+            "name": "symfony/validator",
+            "version": "v2.8.25",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/validator.git",
+                "reference": "6c019627f2a69b9ab2ac41fd53102148a55af564"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/validator/zipball/6c019627f2a69b9ab2ac41fd53102148a55af564",
+                "reference": "6c019627f2a69b9ab2ac41fd53102148a55af564",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.3.9",
+                "symfony/polyfill-mbstring": "~1.0",
+                "symfony/translation": "~2.4|~3.0.0"
+            },
+            "require-dev": {
+                "doctrine/annotations": "~1.0",
+                "doctrine/cache": "~1.0",
+                "egulias/email-validator": "^1.2.1",
+                "symfony/config": "~2.2|~3.0.0",
+                "symfony/expression-language": "~2.4|~3.0.0",
+                "symfony/http-foundation": "~2.3|~3.0.0",
+                "symfony/intl": "~2.7.25|^2.8.18|~3.2.5",
+                "symfony/property-access": "~2.3|~3.0.0",
+                "symfony/yaml": "^2.0.5|~3.0.0"
+            },
+            "suggest": {
+                "doctrine/annotations": "For using the annotation mapping. You will also need doctrine/cache.",
+                "doctrine/cache": "For using the default cached annotation reader and metadata cache.",
+                "egulias/email-validator": "Strict (RFC compliant) email validation",
+                "symfony/config": "",
+                "symfony/expression-language": "For using the 2.4 Expression validator",
+                "symfony/http-foundation": "",
+                "symfony/intl": "",
+                "symfony/property-access": "For using the 2.4 Validator API",
+                "symfony/yaml": ""
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.8-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\Component\\Validator\\": ""
+                },
+                "exclude-from-classmap": [
+                    "/Tests/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Fabien Potencier",
+                    "email": "fabien@symfony.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Symfony Validator Component",
+            "homepage": "https://symfony.com",
+            "time": "2017-07-03T08:04:30+00:00"
+        },
+        {
+            "name": "theseer/fdomdocument",
+            "version": "1.6.6",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/theseer/fDOMDocument.git",
+                "reference": "6e8203e40a32a9c770bcb62fe37e68b948da6dca"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/theseer/fDOMDocument/zipball/6e8203e40a32a9c770bcb62fe37e68b948da6dca",
+                "reference": "6e8203e40a32a9c770bcb62fe37e68b948da6dca",
+                "shasum": ""
+            },
+            "require": {
+                "ext-dom": "*",
+                "lib-libxml": "*",
+                "php": ">=5.3.3"
+            },
+            "type": "library",
+            "autoload": {
+                "classmap": [
+                    "src/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Arne Blankerts",
+                    "email": "arne@blankerts.de",
+                    "role": "lead"
+                }
+            ],
+            "description": "The classes contained within this repository extend the standard DOM to use exceptions at all occasions of errors instead of PHP warnings or notices. They also add various custom methods and shortcuts for convenience and to simplify the usage of DOM.",
+            "homepage": "https://github.com/theseer/fDOMDocument",
+            "time": "2017-06-30T11:53:12+00:00"
+        },
+        {
+            "name": "twig/twig",
+            "version": "v1.27.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/twigphp/Twig.git",
+                "reference": "3c6c0033fd3b5679c6e1cb60f4f9766c2b424d97"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/twigphp/Twig/zipball/3c6c0033fd3b5679c6e1cb60f4f9766c2b424d97",
+                "reference": "3c6c0033fd3b5679c6e1cb60f4f9766c2b424d97",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.2.7"
+            },
+            "require-dev": {
+                "symfony/debug": "~2.7",
+                "symfony/phpunit-bridge": "~2.7"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "1.27-dev"
+                }
+            },
+            "autoload": {
+                "psr-0": {
+                    "Twig_": "lib/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "BSD-3-Clause"
+            ],
+            "authors": [
+                {
+                    "name": "Fabien Potencier",
+                    "email": "fabien@symfony.com",
+                    "homepage": "http://fabien.potencier.org",
+                    "role": "Lead Developer"
+                },
+                {
+                    "name": "Armin Ronacher",
+                    "email": "armin.ronacher@active-4.com",
+                    "role": "Project Founder"
+                },
+                {
+                    "name": "Twig Team",
+                    "homepage": "http://twig.sensiolabs.org/contributors",
+                    "role": "Contributors"
+                }
+            ],
+            "description": "Twig, the flexible, fast, and secure template language for PHP",
+            "homepage": "http://twig.sensiolabs.org",
+            "keywords": [
+                "templating"
+            ],
+            "time": "2016-10-25T19:17:17+00:00"
+        },
+        {
+            "name": "zetacomponents/base",
+            "version": "1.9",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/zetacomponents/Base.git",
+                "reference": "f20df24e8de3e48b6b69b2503f917e457281e687"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/zetacomponents/Base/zipball/f20df24e8de3e48b6b69b2503f917e457281e687",
+                "reference": "f20df24e8de3e48b6b69b2503f917e457281e687",
+                "shasum": ""
+            },
+            "require-dev": {
+                "zetacomponents/unit-test": "*"
+            },
+            "type": "library",
+            "autoload": {
+                "classmap": [
+                    "src"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "Apache-2.0"
+            ],
+            "authors": [
+                {
+                    "name": "Sergey Alexeev"
+                },
+                {
+                    "name": "Sebastian Bergmann"
+                },
+                {
+                    "name": "Jan Borsodi"
+                },
+                {
+                    "name": "Raymond Bosman"
+                },
+                {
+                    "name": "Frederik Holljen"
+                },
+                {
+                    "name": "Kore Nordmann"
+                },
+                {
+                    "name": "Derick Rethans"
+                },
+                {
+                    "name": "Vadym Savchuk"
+                },
+                {
+                    "name": "Tobias Schlitt"
+                },
+                {
+                    "name": "Alexandru Stanoi"
+                }
+            ],
+            "description": "The Base package provides the basic infrastructure that all packages rely on. Therefore every component relies on this package.",
+            "homepage": "https://github.com/zetacomponents",
+            "time": "2014-09-19T03:28:34+00:00"
+        },
+        {
+            "name": "zetacomponents/document",
+            "version": "1.3.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/zetacomponents/Document.git",
+                "reference": "688abfde573cf3fe0730f82538fbd7aa9fc95bc8"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/zetacomponents/Document/zipball/688abfde573cf3fe0730f82538fbd7aa9fc95bc8",
+                "reference": "688abfde573cf3fe0730f82538fbd7aa9fc95bc8",
+                "shasum": ""
+            },
+            "require": {
+                "zetacomponents/base": "*"
+            },
+            "require-dev": {
+                "zetacomponents/unit-test": "dev-master"
+            },
+            "type": "library",
+            "autoload": {
+                "classmap": [
+                    "src"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "Apache-2.0"
+            ],
+            "authors": [
+                {
+                    "name": "Sebastian Bergmann"
+                },
+                {
+                    "name": "Kore Nordmann"
+                },
+                {
+                    "name": "Derick Rethans"
+                },
+                {
+                    "name": "Tobias Schlitt"
+                },
+                {
+                    "name": "Alexandru Stanoi"
+                }
+            ],
+            "description": "The Document components provides a general conversion framework for different semantic document markup languages like XHTML, Docbook, RST and similar.",
+            "homepage": "https://github.com/zetacomponents",
+            "time": "2013-12-19T11:40:00+00:00"
+        }
+    ],
+    "aliases": [],
+    "minimum-stability": "stable",
+    "stability-flags": {
+        "ahand/mobileesp": 20,
+        "pear/validate_ispn": 20
+    },
+    "prefer-stable": false,
+    "prefer-lowest": false,
+    "platform": {
+        "php": ">=5.6"
+    },
+    "platform-dev": []
+}
diff --git a/config/application.config.php b/config/application.config.php
index 5a39bff34ca019f7e409732fc9e1118badaab701..6a2033d10d1f416204e1883381851323d2495d01 100644
--- a/config/application.config.php
+++ b/config/application.config.php
@@ -2,7 +2,7 @@
 
 // Set up modules:
 $modules = array(
-    'ZfcRbac', 'VuFindTheme', 'VuFindSearch', 'VuFind', 'VuFindAdmin'
+    'ZfcRbac', 'VuFindTheme', 'VuFindSearch', 'VuFind', 'VuFindAdmin', 'VuFindApi'
 );
 if (PHP_SAPI == 'cli' && !defined('VUFIND_PHPUNIT_RUNNING')) {
     $modules[] = 'VuFindConsole';
diff --git a/config/vufind/Demo.ini b/config/vufind/Demo.ini
index 0c20010ecfd4ce4e494c2db873da398d949ef930..6cb15e2558548cb518a005dff9e6b272c7a11ba4 100644
--- a/config/vufind/Demo.ini
+++ b/config/vufind/Demo.ini
@@ -60,15 +60,15 @@ cancelHolds = 50
 cancelILLRequests = 50
 cancelStorageRetrievalRequests = 50
 changePassword = 33
-checkILLRequestBlock = 10
 checkILLRequestIsValid = 10
+checkIntermittentFailure = 0  ; chance of simulating low-level system failure
 checkRenewBlock = 25
-checkRequestBlock = 10
 checkRequestIsValid = 10
-checkStorageRetrievalRequestBlock = 10
 checkStorageRetrievalRequestIsValid = 10
+getAccountBlocks = 10
 getDefaultRequestGroup = 50
 getHoldDefaultRequiredDate = 50
+getRequestBlocks = 10
 placeHold = 50
 placeILLRequest = 50
 placeStorageRetrievalRequest = 50
diff --git a/config/vufind/KohaILSDI.ini b/config/vufind/KohaILSDI.ini
index d4561db68119886fb3cceb4d8a9876f5d39eb951..fcb401786a4949491f2623ee8ef69e11c193c7a6 100755
--- a/config/vufind/KohaILSDI.ini
+++ b/config/vufind/KohaILSDI.ini
@@ -36,13 +36,21 @@ defaultRequiredDate = 0:1:0
 ; extraHoldFields - A colon-separated list used to display extra visible fields in the
 ; place holds form. Supported values are "comments", "requiredByDate" and
 ; "pickUpLocation"
-extraHoldFields = comments:pickUpLocation:requiredByDate
+; Note: As of the time of writing, eventhough ILSDI API docs have long declared
+; support for 'comments' and 'requiredByDate' options when placing holds, these
+; features might not yet be implemented (nulling any input passed to the appropriate
+; functions). Should you decide to use them in extraHoldFields, please check that data
+; entered in appropriate hold form is properly passed to Koha.
+extraHoldFields = pickUpLocation
 
 ; A Pick Up Location Code used to pre-select the pick up location drop
 ; down list and provide a default option if others are not
 ; available. The default of 'false' will force users to pick a pickup
 ; location. By setting this to a Koha location code (e.g. '"MAIN"'),
 ; Vufind will default to that location.
+; If no defaultPickUpLocation and no pickupLocations are defined,
+; the driver will try to use the actual holdingbranch(es) of the item/title 
+; as a fallback.
 defaultPickUpLocation = "MAIN"
 
 ; branchcodes for libraries avalaible as pickup locations
diff --git a/config/vufind/SearchApiRecordFields.yaml b/config/vufind/SearchApiRecordFields.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..4f67a719b64c3d73930996cca91742be7159976c
--- /dev/null
+++ b/config/vufind/SearchApiRecordFields.yaml
@@ -0,0 +1,384 @@
+# Key is the field name that can be requested. It has the following subkeys:
+# - vufind.method: name to call (either in the SearchApiController class or the record driver)
+# - vufind.default: true if the field is displayed by default when the request does not specify fields
+# - Swagger specification fields describing the returned data.
+#
+# See http://swagger.io/specification/ for information on the Swagger-specific fields
+#
+accessRestrictions:
+  vufind.method: getAccessRestrictions
+  description: Access restriction notes
+  type: array
+  items:
+    type: string
+authors:
+  vufind.method: getDeduplicatedAuthors
+  vufind.default: true
+  description: >-
+    Deduplicated author information including main, corporate and secondary
+    authors
+  type: array
+  items:
+    $ref: '#/definitions/Authors'
+awards:
+  vufind.method: getAwards
+  description: Award notes
+  type: array
+  items:
+    type: string
+bibliographicLevel:
+  vufind.method: getBibliographicLevel
+  description: Bibliographic level
+  type: string
+  enum:
+    - Monograph
+    - Serial
+    - MonographPart
+    - SerialPart
+    - Collection
+    - CollectionPart
+    - Unknown
+bibliographyNotes:
+  vufind.method: getBibliographyNotes
+  description: Bibliography notes
+  type: array
+  items:
+    type: string
+callNumbers:
+  vufind.method: getCallNumbers
+  description: Call numbers
+  type: array
+  items:
+    type: string
+childRecordCount:
+  vufind.method: getChildRecordCount
+  description: Number of child records
+  type: integer
+cleanDoi:
+  vufind.method: getCleanDOI
+  description: First valid DOI
+  type: string
+cleanIsbn:
+  vufind.method: getCleanISBN
+  description: First valid ISBN favoring ISBN-10 over ISBN-13 when possible
+  type: string
+cleanIssn:
+  vufind.method: getCleanISSN
+  description: Base portion of the first listed ISSN
+  type: string
+cleanOclcNumber:
+  vufind.method: getCleanOCLCNum
+  description: First OCLC number
+  type: string
+containerEndPage:
+  vufind.method: getContainerEndPage
+  description: End page in the containing item
+  type: string
+containerIssue:
+  vufind.method: getContainerIssue
+  description: Issue number of the containing item
+  type: string
+containerReference:
+  vufind.method: getContainerReference
+  description: Reference to the containing item
+  type: string
+containerStartPage:
+  vufind.method: getContainerStartPage
+  description: Start page in the containing item
+  type: string
+containerTitle:
+  vufind.method: getContainerTitle
+  description: Title of the containing item
+  type: string
+containerVolume:
+  vufind.method: getContainerVolume
+  description: Volume of the containing item
+  type: string
+corporateAuthors:
+  vufind.method: getCorporateAuthors
+  description: Main corporate authors
+  type: array
+  items:
+    type: string
+dedupIds:
+  vufind.method: "Formatter::getDedupIds"
+  description: IDs of all records deduplicated with the current record
+  type: array
+  items:
+    type: string
+edition:
+  vufind.method: getEdition
+  description: Edition
+  type: string
+findingAids:
+  vufind.method: getFindingAids
+  description: Finding aids
+  type: array
+  items:
+    type: string
+formats:
+  vufind.method: getFormats
+  vufind.default: true
+  description: Formats
+  type: array
+  items:
+    type: string
+fullRecord:
+  vufind.method: "Formatter::getFullRecord"
+  description: Full metadata record (typically XML)
+  type: array
+  items:
+    type: string
+generalNotes:
+  vufind.method: getGeneralNotes
+  description: General notes
+  type: array
+  items:
+    type: string
+geoLocations:
+  vufind.method: getGeoLocation
+  description: Geographic locations (e.g. points, bounding boxes)
+  type: array
+  items:
+    type: string
+hierarchicalPlaceNames:
+  vufind.method: getHierarchicalPlaceNames
+  description: Hierarchical place names concatenated for display
+  type: array
+  items:
+    type: string
+hierarchyParentId:
+  vufind.method: getHierarchyParentId
+  description: Parent record IDs for hierarchical records
+  type: array
+  items:
+    type: string
+hierarchyParentTitle:
+  vufind.method: getHierarchyParentTitle
+  description: Parent record titles for hierarchical records
+  type: array
+  items:
+    type: string
+hierarchyTopId:
+  vufind.method: getHierarchyTopId
+  description: Hierarchy top record IDs for hierarchical records
+  type: array
+  items:
+    type: string
+hierarchyTopTitle:
+  vufind.method: getHierarchyTopTitle
+  description: Hierarchy top record titles for hierarchical records
+  type: array
+  items:
+    type: string
+humanReadablePublicationDates:
+  vufind.method: getHumanReadablePublicationDates
+  description: Publication dates in human-readable format
+  type: array
+  items:
+    type: string
+id:
+  vufind.method: getUniqueID
+  vufind.default: true
+  description: Record unique ID (can be used in the record endpoint)
+  type: string
+institutions:
+  vufind.method: getInstitutions
+  description: Institutions the record belongs to
+  type: array
+  items:
+    type: string
+isbns:
+  vufind.method: getISBNs
+  description: ISBNs
+  type: array
+  items:
+    type: string
+isCollection:
+  vufind.method: isCollection
+  description: Whether the record is a collection node in a hierarchy
+  type: boolean
+issns:
+  vufind.method: getISSNs
+  description: ISSNs
+  type: array
+  items:
+    type: string
+languages:
+  vufind.method: getLanguages
+  vufind.default: true
+  description: Languages
+  type: array
+  items:
+    type: string
+lccn:
+  vufind.method: getLCCN
+  description: LCCNs
+  type: array
+  items:
+    type: string
+newerTitles:
+  vufind.method: getNewerTitles
+  description: Successor titles
+  type: array
+  items:
+    type: string
+oclc:
+  vufind.method: getOCLC
+  description: OCLC numbers
+  type: array
+  items:
+    type: string
+openUrl:
+  vufind.method: getOpenUrl
+  description: OpenURL
+  type: string
+physicalDescriptions:
+  vufind.method: getPhysicalDescriptions
+  description: Physical dimensions etc.
+  type: array
+  items:
+    type: string
+placesOfPublication:
+  vufind.method: getPlacesOfPublication
+  description: Places of publication
+  type: array
+  items:
+    type: string
+playingTimes:
+  vufind.method: getPlayingTimes
+  description: Playing times (durations)
+  type: array
+  items:
+    type: string
+previousTitles:
+  vufind.method: getPreviousTitles
+  description: Predecessor titles
+  type: array
+  items:
+    type: string
+primaryAuthors:
+  vufind.method: getPrimaryAuthors
+  description: Primary authors
+  type: array
+  items:
+    type: string
+productionCredits:
+  vufind.method: getProductionCredits
+  description: Production credits
+  type: array
+  items:
+    type: string
+publicationDates:
+  vufind.method: getPublicationDates
+  description: Publication dates
+  type: array
+  items:
+    type: string
+publishers:
+  vufind.method: getPublishers
+  description: Publishers
+  type: array
+  items:
+    type: string
+rawData:
+  vufind.method: "Formatter::getRawData"
+  description: All data in the index fields
+  type: string
+recordLinks:
+  vufind.method: getAllRecordLinks
+  description: Links to other related records
+  type: array
+  items:
+    $ref: '#/definitions/RecordLink'
+recordPage:
+  vufind.method: "Formatter::getRecordPage"
+  description: Link to the record page in the UI
+  type: string
+relationshipNotes:
+  vufind.method: getRelationshipNotes
+  description: Notes describing relationships to other items
+  type: array
+  items:
+    type: string
+secondaryAuthors:
+  vufind.method: getSecondaryAuthors
+  description: Secondary authors
+  type: array
+  items:
+    type: string
+series:
+  vufind.method: getSeries
+  vufind.default: true
+  description: Series
+  type: array
+  items:
+    type: string
+shortTitle:
+  vufind.method: getShortTitle
+  description: Short title (title excluding any subtitle)
+  type: string
+subjects:
+  vufind.method: getAllSubjectHeadings
+  vufind.default: true
+  description: >
+    Subject headings as an array from the least specific to the most specific
+  type: array
+  items:
+    type: array
+    items:
+      type: string
+subjectsExtended:
+  vufind.method: "Formatter::getExtendedSubjectHeadings"
+  description: Subject headings with type and source information
+  type: array
+  items:
+    $ref: '#/definitions/Subject'
+subTitle:
+  vufind.method: getSubTitle
+  description: Subtitle
+  type: string
+summary:
+  vufind.method: getSummary
+  description: Summary
+  type: array
+  items:
+    type: string
+systemDetails:
+  vufind.method: getSystemDetails
+  description: Technical details on the represented item
+  type: array
+  items:
+    type: string
+targetAudienceNotes:
+  vufind.method: getTargetAudienceNotes
+  description: Notes about the target audience
+  type: array
+  items:
+    type: string
+title:
+  vufind.method: getTitle
+  vufind.default: true
+  description: Title including any subtitle
+  type: string
+titleSection:
+  vufind.method: getTitleSection
+  description: Part/section portion of the title
+  type: string
+titleStatement:
+  vufind.method: getTitleStatement
+  description: Statement of responsibility that goes with the title
+  type: string
+toc:
+  vufind.method: getTOC
+  description: Table of contents
+  type: array
+  items:
+    type: string
+urls:
+  vufind.method: "Formatter::getURLs"
+  vufind.default: true
+  description: URLs contained in the record
+  type: array
+  items:
+    $ref: '#/definitions/Url'
diff --git a/config/vufind/Summon.ini b/config/vufind/Summon.ini
index 910d04f484948cfe07e4ac5aad5b9ba06f6fce61..3318d70b9bbb5551c7b41cdbba9a67df0cda900d 100644
--- a/config/vufind/Summon.ini
+++ b/config/vufind/Summon.ini
@@ -115,6 +115,7 @@ dateRange[] = PublicationDate
 ;IsPeerReviewed:true = peer_reviewed_limit
 IsScholarly:true = scholarly_limit
 IsFullText:true = fulltext_limit
+openAccessFilter:true = open_access_limit
 excludeNewspapers:true = exclude_newspapers
 holdingsOnly:false = add_other_libraries
 queryExpansion:true = include_synonyms
diff --git a/config/vufind/Voyager.ini b/config/vufind/Voyager.ini
index 49f0b8027216106a4ddd8f48617cdd2485ce07ee..c911a165470716a7f38f1968b010f13e46d472ea 100644
--- a/config/vufind/Voyager.ini
+++ b/config/vufind/Voyager.ini
@@ -20,6 +20,11 @@ login_field = LAST_NAME
 ; user has no PIN code. Disabled by default.
 ;fallback_login_field = LAST_NAME
 
+; Colon-separated list of barcode statuses ( see PATRON_BARCODE_STATUS table in
+; Voyager's database) that allow a user to log in. By default only barcodes with
+; status 1 (active) or 4 (expired) are allowed.
+;allowed_barcode_statuses = 1:4:5
+
 ; These settings affect the Fund list used as a limiter in the "new items" module:
 [Funds]
 ; Uncomment this line to turn off the fund list entirely.
diff --git a/config/vufind/VoyagerRestful.ini b/config/vufind/VoyagerRestful.ini
index bc960bce839c5235cc736be5238516db95a61a3f..06beb4dc90bcbccde11f240dd47268a28a6dc913 100644
--- a/config/vufind/VoyagerRestful.ini
+++ b/config/vufind/VoyagerRestful.ini
@@ -20,6 +20,11 @@ login_field = LAST_NAME
 ; user has no PIN code. Disabled by default.
 ;fallback_login_field = LAST_NAME
 
+; Colon-separated list of barcode statuses ( see PATRON_BARCODE_STATUS table in
+; Voyager's database) that allow a user to log in. By default only barcodes with
+; status 1 (active) or 4 (expired) are allowed.
+;allowed_barcode_statuses = 1:4:5
+
 ; This is the timeout value for making HTTP requests to the Voyager API.
 http_timeout = 30
 
@@ -46,7 +51,7 @@ http_timeout = 30
 ;parent_fund = 0
 
 ; These settings are used by the Voyager Restful Services - details at
-; http://www.exlibrisgroup.org/display/VoyagerOI/Introduction+to+Voyager+RESTful+APIs
+; https://developers.exlibrisgroup.com/voyager/apis/RESTfulWebServices
 [WebServices]
 host = 1.2.3.4
 port = 7014
@@ -54,7 +59,7 @@ app = vxws
 
 ; Patron and site information -- these two settings can often be set to the same value.  To
 ; find your possible values, use the GetUBSitesService service as documented here:
-; http://www.exlibrisgroup.org/display/VoyagerOI/GetUBSitesService
+; https://developers.exlibrisgroup.com/voyager/apis/XMLoverHTTPWebServices/GetUBSitesService
 patronHomeUbId = "1@XXXXX"
 dbKey = "1@XXXXX"
 
@@ -181,8 +186,12 @@ disableAvailabilityCheckForRequestGroups = "15:19:21:32"
 ;excludedItemLocations = "2:4:23:10"
 
 ; By default a patron can place a hold on records he/she already has on loan.
-; Uncomment this setting to prevent placing a hold on something already on loan for
-; the patron.
+; This setting can be used to modify this behavior. Must be one of the following:
+; 1) false to indicate that loans are not checked (default setting).
+; 2) true to indicate that any loan on the bibliographic record prevents further
+; holds.
+; 3) "same-item" to indicate that a loan on the specific item prevents placing a hold
+; on it.
 ;checkLoans = true
 
 ; Optional help texts that can be displayed on the hold form
diff --git a/config/vufind/channels.ini b/config/vufind/channels.ini
new file mode 100644
index 0000000000000000000000000000000000000000..522236fbaa3346b172cd16fd75f9241d0a643273
--- /dev/null
+++ b/config/vufind/channels.ini
@@ -0,0 +1,119 @@
+; This configuration file controls the channeled browse functionality.
+
+; This section contains general global settings.
+[General]
+; If no "source" value is passed as a GET parameter to the Channels/Home screen,
+; this section controls which source will be used:
+default_home_source = "Solr"
+
+; This section controls which providers are used for Solr searches/records.
+; Providers may be followed by a colon and the name of a configuration section
+; to use. If no configuration section is provided, the default of
+; "provider.[providername]" will be used.
+;
+; Available providers:
+;
+; facets - Find records matching facet values from search results (or try to find
+; other records matching the facet values of a specific record).
+;
+; listitems - Display items from specific public user lists.
+;
+; random - Pick random results from the result set (in search results) or from
+; the search backend from which the record was retrieved (in record results).
+;
+; similaritems - Find records similar to a specific record, or to top hits in a
+; set of search results.
+[source.Solr]
+; Providers to use on the home page (these will be populated with a blank search
+; by default; order matters!)
+home[] = "facets:provider.facets.home"
+;home[] = "random"
+;home[] = "listitems"
+; Providers to use for record-based channels (order matters!)
+record[] = "similaritems"
+record[] = "facets"
+; Providers to use for search-based channels (order matters!)
+search[] = "facets"
+search[] = "similaritems"
+
+; This section controls which providers are used for Summon searches/records.
+; See [source.Solr] above for more details.
+[source.Summon]
+; Providers to use on the home page (these will be populated with a blank search
+; by default; order matters!)
+home[] = "facets:provider.facets.Summon.home"
+; Providers to use for record-based channels (order matters!)
+record[] = "facets:provider.facets.Summon"
+; Providers to use for search-based channels (order matters!)
+search[] = "facets:provider.facets.Summon"
+
+; This section contains home-page-specific settings for the Facets channel provider
+[provider.facets.home]
+; Facet fields to use (field name => description).
+fields[topic_facet] = "Topic"
+fields[author_facet] = "Author"
+fields[format] = "Format"
+; Maximum number of different fields to suggest in the channel list.
+maxFieldsToSuggest = 3
+; Maximum number of values to suggest per field.
+maxValuesToSuggestPerField = 2
+
+; This section contains default settings for the Facets channel provider
+[provider.facets]
+; Facet fields to use (field name => description).
+fields[topic_facet] = "Topic"
+fields[author_facet] = "Author"
+; Maximum number of different fields to suggest in the channel list.
+maxFieldsToSuggest = 2
+; Maximum number of values to suggest per field.
+maxValuesToSuggestPerField = 2
+
+; This section contains home-page-specific settings for the Facets channel provider
+; used by Summon searches.
+[provider.facets.Summon.home]
+; Facet fields to use (field name => description).
+fields[SubjectTerms] = "Topic"
+fields[DatabaseName] = "Database"
+fields[ContentType] = "Format"
+; Maximum number of different fields to suggest in the channel list.
+maxFieldsToSuggest = 3
+; Maximum number of values to suggest per field.
+maxValuesToSuggestPerField = 1
+
+; This section contains default settings for the Facets channel provider used by
+; Summon searches.
+[provider.facets.Summon]
+; Facet fields to use (field name => description).
+fields[SubjectTerms] = "Topic"
+fields[DatabaseName] = "Database"
+; Maximum number of different fields to suggest in the channel list.
+maxFieldsToSuggest = 2
+; Maximum number of values to suggest per field.
+maxValuesToSuggestPerField = 2
+
+; This section contains default settings for the List channel provider
+[provider.listitems]
+; You may include any number of id lines; a channel will be created for each list
+; ID specified, and these IDs will be displayed first.
+;ids[] = 1
+; Should we include public lists not included in the whitelist above?
+displayPublicLists = true
+; How many lists should we display initially? (The rest can be added on demand)
+initialListsToDisplay = 2
+
+; This section contains default settings for the Random channel provider
+[provider.random]
+; Number of results to include in the channel.
+channelSize = 20
+; Determines if the records are selected from the entire backend or from the current
+; result set (if applicable -- only applies to search-driven channels). Valid values
+; are "retain" to limit results to the current result set or "disregard" to use the
+; entire backend.
+mode = "retain"
+
+; This section contains default settings for the SimilarItems channel provider
+[provider.similaritems]
+; Number of results to include in each channel.
+channelSize = 20
+; Maximum number of records to examine for similar results.
+maxRecordsToExamine = 2
\ No newline at end of file
diff --git a/config/vufind/combined.ini b/config/vufind/combined.ini
index 977e88247fc383bea510976e730a82550afdbf48..58249f5ca4518559cb346b9fbb867a4ce353b421 100644
--- a/config/vufind/combined.ini
+++ b/config/vufind/combined.ini
@@ -9,9 +9,7 @@
 ; label = The header on the column
 ; sublabel = Text to display below the header (optional)
 ; more_link = The text of the link to access more results; set to false to
-;        disable all "more results" links for this entry. Note that disabling
-;        more_link will not impact the jquerymobile theme, which handles
-;        combined search in a simplified manner.
+;        disable all "more results" links for this entry.
 ; ajax = If true, these results will load via AJAX; otherwise, they will load
 ;        inline (default = false)
 ; hide_if_empty = If true, this section will be completely suppressed from
@@ -44,16 +42,17 @@
 ; The order of sections in this file will control the display order of search
 ; results on screen.
 
-; This section controls how columns will be formatted in most themes (jquerymobile
-; ignores these settings).
+; This section controls how columns will be formatted
 [Layout]
 ; This is the maximum number of columns to use.
 columns = 3
 ; Stack placement determines where the remainder of the modules are placed after
-; columns have been exhausted. 'distributed' will wrap the columns and even out the
-; data. 'left' and 'right' will create a stack. ie. If you have 2 columns, the first
-; two modules set below will get columns to themselves and the reset will be put in
-; the same column on the far left/right.
+; columns have been exhausted.
+; 'distributed' will wrap the columns and even out the data (default setting).
+; 'left' and 'right' will specify which column to place the remainder of the lists
+;                    after each column has been given one list.
+; 'left' will result in a distribution of [0,3,4+], 1, 2.
+; 'right' will result in a distribution of 0, 1, [2,3,4+].
 ;
 ; distributed, left, right
 stack_placement = distributed
@@ -84,4 +83,4 @@ ajax = true
 ; will work correctly in this context.
 [RecommendationModules]
 ;top[] = SummonDatabasesDeferred
-;bottom[] = EuropeanaResultsDeferred
\ No newline at end of file
+;bottom[] = EuropeanaResultsDeferred
diff --git a/config/vufind/config.ini b/config/vufind/config.ini
index 214229bab573da7409fba00fe4752cb26818977c..28d981dcdf5185bd11cad74a0d50a577b395d2e6 100644
--- a/config/vufind/config.ini
+++ b/config/vufind/config.ini
@@ -28,12 +28,18 @@ email           = support@myuniversity.edu
 title           = "Library Catalog"
 ; This is the default theme for non-mobile devices (or all devices if mobile_theme
 ; is disabled below). Available standard themes:
-;   bootstrap3 = HTML5 theme using Bootstrap 3 + jQuery libraries, with minimal
-;               styling
+;   bootstrap3 = HTML5 theme using Bootstrap 3 + jQuery libraries, with minimal styling
 ;   bootprint3 = bootstrap3 theme with more attractive default styling applied
 ;                (named after the earlier, now-deprecated blueprint theme)
+;   sandal     = bootstrap3 theme with a "flat" styling applied (a newer look
+;                than bootprint3).
 theme           = bootprint3
 
+; Uncomment the following line to use a different default theme for mobile devices.
+; You may not wish to use this setting if you are using one of the Bootstrap-based
+; standard themes since they support responsive design.
+;mobile_theme    = mobile
+
 ; Automatic asset minification and concatenation setting. When active, HeadScript
 ; and HeadLink will concatenate and minify all viable files to reduce requests and
 ; load times. This setting is off by default.
@@ -49,11 +55,6 @@ theme           = bootprint3
 ; Example: "development:off; production:js,css"
 ;asset_pipeline = "production:js"
 
-; Uncomment the following line to use a different default theme for mobile devices.
-; You may not wish to use this setting if you are using one of the Bootstrap-based
-; standard themes since they support responsive design. Available mobile theme:
-;   jquerymobile = Theme built using jQuery Mobile framework
-;mobile_theme    = jquerymobile
 ; This is a comma-separated list of themes that may be accessed via the ?ui GET
 ; parameter.  Each entry has two parts: the value used on the URL followed by the
 ; actual theme name.  For example, http://library.myuniversity.edu/vufind?ui=theme1
@@ -61,6 +62,7 @@ theme           = bootprint3
 ; of "standard" and "mobile" are reserved for the default and mobile themes defined
 ; above.
 ;alternate_themes = theme1:myTheme1,theme2:myTheme2
+
 ; This is a comma-separated list of theme options that will be displayed to the user
 ; as a drop-down.  Each entry has two parts: a value for the "ui" GET parameter and
 ; an on-screen description.  "standard" refers to the "theme" setting above, "mobile"
@@ -112,6 +114,8 @@ mirrorSidebarInRTL = true
 resultThumbnailsOnLeft = true
 ; Put favorites list thumbnails on the left (true) or right (false)
 listThumbnailsOnLeft = true
+; Put hold/checkedout/ILL/etc. item thumbnails on the left (true) or right (false)
+accountThumbnailsOnLeft = true
 ; Show thumbnail on opposite side in right-to-left languages?
 mirrorThumbnailsRTL = true
 ; Handle menu as an offcanvas slider at mobile sizes (in bootstrap3-based themes)
@@ -120,12 +124,15 @@ offcanvas = false
 showBookBag = false
 ; Set the maximum amount of items allowed in the Book Bag - Default is 100
 bookBagMaxSize = 100
+; Show individual add/remove bookbag buttons in search results? (Supersedes cart
+; checkboxes and bulk action buttons unless showBulkOptions is true).
+bookbagTogglesInSearch = true
 ; Display bulk items (export, save, etc.) and checkboxes on search result screens?
 showBulkOptions = false
 ; Should users be allowed to save searches in their accounts?
 allowSavedSearches = true
 ; Generator value to display in an HTML header <meta> tag:
-generator = "VuFind 3.1.3"
+generator = "VuFind 4.0.1"
 
 ; This section allows you to configure the mechanism used for storing user
 ; sessions.  Available types: File, Memcache, Database.
@@ -159,6 +166,11 @@ lifetime                    = 3600 ; Session lasts for 1 hour
 ; Set the domain used for cookies (sometimes useful for sharing the cookies across
 ; subdomains); by default, cookies will be restricted to the current hostname.
 ;domain = ".example.edu"
+; This sets the session cookie's name. Comment this out to use the default
+; PHP_SESS_ID value. If running multiple versions of VuFind (or multiple PHP
+; applications) on the same host, it is strongly recommended to give each a
+; different session_name setting to avoid data contamination.
+session_name = VUFIND_SESSION
 
 ; Please set the ILS that VuFind will interact with.
 ;
@@ -240,7 +252,8 @@ title_level_holds_mode = "disabled"
 ; the item information provided by the ILS driver.
 ;
 ; Most commonly-used values:
-; - holdings_id (Use holdings record id if available, location name otherwise - Default)
+; - holdings_id,location (Use holdings record id if available, location name as
+;   secondary - Default)
 ; - location (Use location name)
 ;
 ; See https://vufind.org/wiki/development:plugins:ils_drivers#getholding for
@@ -253,7 +266,7 @@ title_level_holds_mode = "disabled"
 ;
 ; You may use multiple group keys (delimited by comma), e.g.,
 ; - item_agency_id,location
-;holdings_grouping = holdings_id
+;holdings_grouping = holdings_id,location
 
 ; Text fields such as holdings_notes gathered from items to be displayed in each
 ; holdings group in the display order.
@@ -372,44 +385,6 @@ ils_encryption_key = false
 ;[ChoiceAuth]
 ;choice_order = Shibboleth,Database
 
-; This section will allow you to control whether VuFind should record usage
-; statistics.
-[Statistics]
-; You can uncomment one or more of these lines to enable statistics tracking.
-; Each enabled mode will write stats to a different target (Solr stats index,
-; flat file, or database tables).  Some modes require additional settings below.
-;
-; Currently, VuFind stores statistics in two different contexts: searches and
-; record views.  By default, an enabled mode will log both types of stats.  If
-; you want to log different types of stats to different targets, you can use a
-; qualifier -- for example, "mode[] = Solr:Record" and "mode[] = Db:Search".
-; Multiple targets may be separated by commas.  Do not use qualifiers unless you
-; really need to -- logging all statistics to the same target makes reporting
-; more effective.
-;
-; Note: Statistics gathering includes browser detection.  For best results, make
-; sure you have a recent browscap.ini file configured in PHP.  See
-; http://php.net/manual/en/function.get-browser.php#refsect1-function.get-browser-notes
-;mode[] = Solr
-;mode[] = File
-;mode[] = Db
-
-; When using the Solr mode, specify the address of a Solr server containing a
-; "stats" core here; if no URL is specified, [Index]/url below will be used.
-;solr            = http://localhost:8080/solr
-
-; When using the File mode, specify a directory for saving stat files here.
-; NOTE: As currently implemented, File mode is NOT RECOMMENDED FOR USE IN PRODUCTION.
-;file            = /usr/local/vufind/local/logs
-
-; When displaying search statistics in the Admin module, do you want to see a single
-; merged list, or separate grouped lists by module (Solr, Summon, etc.)
-searchesBySource = false
-
-; When display record view statistics in the Admin module, do you want to see a
-; single merged list, or separate grouped lists by module (Solr, Summon, etc.)
-recordsBySource = false
-
 ; This section defines the location/behavior of the Solr index and requires no
 ; changes for most installations
 [Index]
@@ -467,6 +442,12 @@ maximum_recipients = 1
 ; setting from the [Site] section used as a last resort.
 disable_from = false
 
+; Being a special case of mail message, sending record results via SMS ("Text this")
+; may be "enabled" or "disabled" ("enabled" by default).
+; Should you choose to leave it enabled, see also sms.ini for further
+; configuration options.
+sms = enabled
+
 ; This section needs to be changed to match your database connection information
 [Database]
 database          = mysql://root@localhost/vufind
@@ -487,6 +468,10 @@ database          = mysql://root@localhost/vufind
 ; LDAP with TLS.
 ;host            = ldap.myuniversity.edu
 ;port            = 389       ; LDAPS usually uses port 636 instead
+; By default, when you use regular LDAP (not LDAPS), VuFind uses TLS security.
+; You can set disable_tls to true to bypass TLS if your server does not support
+; it. Note that this setting is ignored if you use ldaps:// in the host setting.
+;disable_tls     = false
 ;basedn          = "o=myuniversity.edu"
 ;username        = uid
 ; separator string for mapping multi-valued ldap-fields to a user attribute
@@ -522,6 +507,13 @@ database          = mysql://root@localhost/vufind
 ; Server param with the identity provider entityID if a Shibboleth session exists.
 ; If omitted, Shib-Identity-Provider is used.
 ;idpserverparam = Shib-Identity-Provider
+; Optional: Session ID parameter for SAML2 single logout support. If omitted, single
+; logout support is disabled. Note that if SLO support is enabled, Shibboleth session
+; ID's are tracked in external_session table which may need to be cleaned up with the
+; expire_session_mappings command line utility. See
+; https://vufind.org/wiki/configuration:shibboleth for more information on how
+; to configure the single logout support.
+;session_id = Shib-Session-ID
 ; Optional: you may set attribute names and values to be used as a filter;
 ; users will only be logged into VuFind if they match these filters.
 ;userattribute_1       = entitlement
@@ -638,9 +630,26 @@ database          = mysql://root@localhost/vufind
 ;coversize = false
 
 ; You can select Syndetics, LibraryThing, Summon, Amazon, Booksite, OpenLibrary,
-; Contentcafe, Buchhandel.de and/or Google Books.
+; Contentcafe, Buchhandel.de, Google Books, and/or LocalFile.
 ;   Note: Summon service takes a Serials Solutions client key, NOT Summon API key!
-;coverimages     = Syndetics:MySyndeticsId,Amazon:MyAccessKeyId,Booksite,LibraryThing:MyLibraryThingId,Google,OpenLibrary,Summon:MySerialsSolutionsClientKey,Contentcafe:MyContentCafeID
+;   For LocalFile:PathToFile, you may use a combination of directory path information
+;        and tokens for filename and image type. If you have multiple directories
+;        in which you have stored coverimages, you can specify multiple paths to search
+;        by specifying multiple LocalFile:PathToFile in the coverage images list below.
+;        Allowed tokens:
+;          %anyimage%         - Match known image file extensions (gif, jpg, etc.)
+;          %isbn10%           - 10-digit ISBN
+;          %isbn13%           - 13-digit ISBN
+;          %issn%             - ISSN
+;          %oclc%             - OCLC Number
+;          %recordid%         - Bibliographic record ID
+;          %size%             - Size (small/medium/large)
+;          %source%           - Search backend of record (e.g. Summon, Solr, etc.)
+;          %upc%              - UPC Number
+;          %vufind-home%      - The VUFIND_HOME environment variable
+;          %vufind-local-dir% - The VUFIND_LOCAL_DIR environment variable
+;        Example: LocalFile:%vufind-local-dir%/path/to/file/%size%/issn/%issn%.%anyimage%
+;coverimages     = Syndetics:MySyndeticsId,Amazon:MyAccessKeyId,Booksite,LibraryThing:MyLibraryThingId,Google,OpenLibrary,Summon:MySerialsSolutionsClientKey,Contentcafe:MyContentCafeID,LocalFile:PathToFile
 
 ; This setting controls which services will have images cached on your local disk.
 ; Set to true to cache all applicable services. Set to false to disable caching. Set
@@ -707,7 +716,7 @@ authors         = Wikipedia
 ;amazonassociate = MyAmazonAssociateID
 
 ; You can select from Google, OpenLibrary, HathiTrust.  You should consult
-; http://code.google.com/apis/books/branding.html before using Google Book Search.
+; https://developers.google.com/books/branding before using Google Book Search.
 ;previews       = Google,OpenLibrary,HathiTrust
 
 ; This setting controls whether or not cover images are linked to previews when
@@ -740,8 +749,7 @@ authors         = Wikipedia
 ;europeanaAPI = INSERTKEY
 
 ; Geographic Display
-; recordMap can be set to either 'google' or 'openlayers';
-; 'google' will only display point features
+; recordMap can be set to 'openlayers';
 ; 'openlayers' will display point and rectangle features. Default setting
 ; (see import/marc_local.properties for more information).
 ; Map Tab Options:
@@ -763,13 +771,13 @@ authors         = Wikipedia
 ;mapLabels = file:geosearch_test_lookup.txt
 ;displayCoords = true
 
-; If you set recordMap = google, then Google requires that you obtain an API key.
-; For more information on obtaining an API key, see:
-; https://developers.google.com/maps/documentation/javascript/get-api-key#key
-;googleMapApiKey = "your-key-here"
-
 ; This section controls the behavior of the cover generator when makeDynamicCovers
 ; above is non-false.
+;
+; Note that any of these settings may be filtered to be size-specific by subscripting
+; the key with a size. You can use a key of * for a default to use when a specific
+; size is not matched. This allows adjustment of certain elements for different
+; thumbnail sizes. See the "size" setting below for an example.
 [DynamicCovers]
 ; This controls the background layer of the generated image; options:
 ; - solid: display a solid color
@@ -833,7 +841,9 @@ authors         = Wikipedia
 ; defines a WxH rectangle. wrapWidth constrains the text size (and must be no
 ; larger than the width of the canvas). topPadding and bottomPadding push the
 ; text away from the edges of the canvas.
-;size = 128
+;size[*] = 128
+;size[medium] = 200
+;size[large] = 500
 ;topPadding = 19
 ;bottomPadding = 3
 ;wrapWidth = 110
@@ -988,6 +998,31 @@ replace_other_urls = true
 ;[EZproxy]
 ;host            = http://proxy.myuniversity.edu
 
+; By default, when the 'host' setting above is active, VuFind will prefix links in
+; records using EZproxy's "?qurl=" mechanism. If you need to set a host for ticket
+; authentication (below) but you want to disable the prefixing behavior, set this
+; to false.
+;prefixLinks = true
+
+; Uncomment the following line and change the password to something secret to enable
+; EZproxy ticket authentication.
+;secret = "verysecretpassword"
+;
+; To enable ticket authentication in EZproxy, you will also need the following in
+; EZproxy's user.txt or ezproxy.usr for older versions (without the leading
+; semicolons and spaces):
+;
+; ::CGI=https://vufind-server/ExternalAuth/EzproxyLogin?url=^R
+; ::Ticket
+; TimeValid 10
+; SHA512 verysecretpassword
+;
+; Uncomment and modify the following line to use another hashing algorithm with the
+; EZproxy authentication if necessary. SHA512 is the default, but it requires at
+; least EZproxy version 6.1. Use "SHA1" for older EZproxy versions, and remember to
+; replace SHA512 with SHA1 also in EZproxy's configuration file.
+;secret_hash_method = "SHA512"
+
 ; These settings affect RefWorks record exports.  They rarely need to be changed.
 [RefWorks]
 vendor          = VuFind
@@ -1123,6 +1158,12 @@ skip_numeric = true
 ; any sections not listed here will be merged on a section-by-section basis.
 ;override_full_sections = "Languages,AlphaBrowse_Types"
 
+; This setting is for allowing arrays to be merged with the values of their parents
+; arrays. If override_full_sections is set for a section the arrays will always be
+; overridden.
+; For legacy reasons merging of arrays is disabled by default.
+;merge_array_settings = false
+
 ; This section controls which language options are available to your users.
 ; If you offer more than one option, a control will appear in the user
 ; interface to allow user selection.  If you only activate one language,
@@ -1320,6 +1361,7 @@ hide_holdings[] = "World Wide Web"
 ; record view page.
 ;
 ; Available options:
+;    Channels - Display links to channels of content related to record
 ;    Similar - Similarity based on Solr lookup
 ;    WorldCatSimilar - Similarity based on WorldCat lookup
 related[] = "Similar"
@@ -1455,6 +1497,12 @@ treeSearchLimit = 100
 ; Uncomment the following setting to track additional information about searches
 ; and displayed records with Piwik's custom variables
 ;custom_variables = true
+; By default, Piwik searches are tracked using the format "Backend|Search Terms."
+; If you need to differentiate searches coming from multiple VuFind instances using
+; a shared site_id, you can set the searchPrefix to add an additional prefix to
+; the string, for example "SiteA|Backend|Search Terms." Most users will want to
+; leave this disabled.
+;searchPrefix = "SiteA|"
 
 ; Uncomment portions of this section to activate tabs in the search box for switching
 ; between search modules. Keys are search backend names, values are labels for use in
@@ -1497,6 +1545,22 @@ treeSearchLimit = 100
 ; Use * for all supported forms
 ;forms = changePassword, email, newAccount, passwordRecovery, sms
 
+
+; This section can be used to display default text inside the search boxes, useful
+; for instructions. Format:
+;
+; backend = Placeholder text
+;
+; You can use a "default" setting if you want a standard string displayed across
+; all backends not otherwise specified. You can qualify backend names with a
+; colon-delimited suffix if you wish to use special placeholders in combination
+; with filtered search tabs (see [SearchTabsFilters] above).
+[SearchPlaceholder]
+;default = "Enter search terms here..."
+;Solr = "Search the catalog"
+;Solr:filtered = "Search the filtered catalog"
+;Summon = "Search Summon"
+
 ; This section controls VuFind's social features.
 [Social]
 ; Comments may be "enabled" or "disabled" (default = "enabled")
diff --git a/config/vufind/facets.ini b/config/vufind/facets.ini
index 5d7096df24fa2a5c88bc6cec49baaf408292ca26..a9c5279d401c86c1963a96ea765adb9e9f34f3e1 100644
--- a/config/vufind/facets.ini
+++ b/config/vufind/facets.ini
@@ -23,6 +23,12 @@ publishDate        = "adv_search_year"  ; share year string w/advanced search pa
 [ResultsTop]
 topic_facet        = "Suggested Topics"
 
+; This section is used to specify labels for facets that may be applied by parts
+; of VuFind other than the facet lists defined in this file (for example, the
+; hierarchical browse of the BrowseController, or the Geographic Search).
+[ExtraFacetLabels]
+long_lat = "Geographic Search"
+
 ; This section is used to identify facets for special treatment by the SideFacets
 ; recommendations module.
 [SpecialFacets]
diff --git a/config/vufind/httpd-vufind.conf b/config/vufind/httpd-vufind.conf
index ddbb03a287824c630bafcf56dc6a3a9fc1da8cfe..31b94863c4e9493bc2aa2b632388bf8adf5702ac 100644
--- a/config/vufind/httpd-vufind.conf
+++ b/config/vufind/httpd-vufind.conf
@@ -60,9 +60,9 @@ Alias /vufind /usr/local/vufind/public
   # Uncomment this line to put VuFind into development mode in order to see more detailed messages:
   #SetEnv VUFIND_ENV development
 
-  # Uncomment this line if you want to use the XHProf profiler; this is a developer-oriented option
-  # that most users will not need.  Make sure the XHProf PHP libraries are available on your include
-  # path.  See https://vufind.org/jira/browse/VUFIND-419 for more details.
+  # Uncomment this line if you want to use the XHProf or Tideways profiler; this is a
+  # developer-oriented option that most users will not need.
+  # See https://vufind.org/wiki/development:profiling for more details.
   #SetEnv VUFIND_PROFILER_XHPROF http://url/to/your/xhprof/web/interface
 
   # This line points to the local override directory where you should place your customized files
@@ -75,6 +75,7 @@ Alias /vufind /usr/local/vufind/public
   # encounter unexpected side effects -- while this directory may be outside of the
   # local settings directory, there should be exactly one separate cache location per
   # local settings directory.
+  # If you adjust this, be sure to change the public cache AliasMatch above to match.
   #SetEnv VUFIND_CACHE_DIR /usr/local/vufind/local/cache
 
   # This line specifies additional Zend Framework 2 modules to load after the standard VuFind module.
diff --git a/config/vufind/permissions.ini b/config/vufind/permissions.ini
index e480e9d1e45b86ba2bcb47c2630198e3ce29a48c..ee7fe291f1772fa8a989259868ef1b16181e6667 100644
--- a/config/vufind/permissions.ini
+++ b/config/vufind/permissions.ini
@@ -131,3 +131,25 @@ permission = access.StaffViewTab
 ;ipRange[] = 1.2.3.1-1.2.3.254 ; for the IP-range of your university's network
 ;role = loggedin ; if you want to allow authenticated users to use Primo module
 ;permission = primoOnCampus.MYINSTITUTION
+
+; Example Shibboleth logout API access permission. 
+; See https://vufind.org/wiki/configuration:shibboleth for more information.
+;[api.ShibbolethLogoutNotification]
+;permission = access.api.ShibbolethLogoutNotification
+;require = ANY
+;ipRange[] = '127.0.0.1'
+;ipRange[] = '::1'
+
+; Example EZproxy authorization permission.
+; See https://vufind.org/wiki/configuration:ezproxy for more information.
+[ezproxy.authorized]
+permission = ezproxy.authorized
+role = loggedin
+
+; Search and Record API permissions.
+;[api.SearchAndRecord]
+;permission[] = access.api.Search
+;permission[] = access.api.Record
+;require = ANY
+;ipRange[] = '127.0.0.1'
+;ipRange[] = '::1'
diff --git a/config/vufind/searchbox.ini b/config/vufind/searchbox.ini
index 365da2ad6e1cbf30709bfee9dc9d63a671c2526e..d6f8e48ee8e7999b7e8fdb3f3b2cadba47ca4d56 100644
--- a/config/vufind/searchbox.ini
+++ b/config/vufind/searchbox.ini
@@ -9,7 +9,10 @@ combinedHandlers = false
 ; of settings with the following keys:
 ;
 ; type[] = "VuFind" for an internal search module or "External" for an external URL
-; target[] = Search class ID for "VuFind" type, URL for "External" type
+; target[] = Search class ID for "VuFind" type, URL for "External" type; by default,
+;            the user's search terms will be appended to the end of the URL in
+;            "External" mode. You may use a %%lookfor%% placeholder string in the
+;            URL to force the query to be injected at a specific position.
 ; label[] = Label for this value (subject to translation)
 [CombinedHandlers]
 type[] = VuFind
diff --git a/config/vufind/searches.ini b/config/vufind/searches.ini
index f00e92a5ca6703d48628ac5800a22faf040e98eb..5008b5855267bd1350727ff5d4a85f8f2d1e01bd 100644
--- a/config/vufind/searches.ini
+++ b/config/vufind/searches.ini
@@ -317,14 +317,17 @@ CallNumber = callnumber-sort
 ;       Displays see and see also results to user based on search of Authority Index.
 ;       Any number of filter queries may be specified as parameters to limit which
 ;       set of authority records is used for recommendations; for example:
-;           AuthorityRecommend:record_type:Heading* OR Topical*:source:LCNAF
+;           AuthorityRecommend:record_type:Heading* OR Topical*:source:FAST
 ;       limits record_type to strings starting with "Heading" or "Topical" and
-;       limits source to LCNAF.  A special field name of "__resultlimit__" may be
+;       limits source to FAST.  A special field name of "__resultlimit__" may be
 ;       used to suppress authority results when the result set contains more items
 ;       than the number specified as the corresponding value (e.g. if you configure
 ;       AuthorityRecommend:__resultlimit__:50 then authority recommendations will
 ;       only display on result screens displaying fewer than 50 hits; by default,
 ;       recommendations will always display). Filtering is optional.
+; Channels
+;       Display a link to the Channeled Browse functionality leading to channels of
+;       records related to the current search.
 ; MapSelection:[ini section]:[ini name]
 ;       Enable geographic searching capability via OpenLayers3 API by activating
 ;       this module. Records must be indexed using the geographic search and display
@@ -337,15 +340,6 @@ CallNumber = callnumber-sort
 ;       fields.  This is designed for a field containing four-digit years.  Zooming
 ;       is set to either true or false and controls whether or not selecting part of
 ;       the graph zooms in to greater detail.
-; ResultGoogleMapAjax:[facets]
-;       Show a Google Map with markers for all result items which have long/latitude
-;       data (be sure to turn on location indexing in import/marc_local.properties).
-;       Each marker will show the number of items which are in the long_lat
-;       facet. A separate call is made when a marker is clicked to retrieve the
-;       first 5 records on that location facet. The map uses clustering to
-;       combine markers where there are more than one marker close together into
-;       clusters. The facets parameter is the name of the extra config file which
-;       holds the facet information(default "facets.ini").
 ; TopFacets:[ini section]:[ini name]
 ;       Display facets listed in the specified section of the specified ini file;
 ;       if [ini name] is left out, it defaults to "facets."
@@ -363,6 +357,11 @@ CallNumber = callnumber-sort
 ;
 ; AlphaBrowseLink:index
 ;       Use the query to generate a link to the specified alphabrowse index
+; DOI:[prefix]
+;       Detect DOIs in the user search query. If a DOI makes up part of the search,
+;       display a link to resolve it. If it makes up the entire query, redirect to
+;       the resolver automatically. [prefix] is the URL of the resolver to which
+;       the DOI itself will be appended.
 ; Libraryh3lp:[type]:[id]:[skin]
 ;       Display a chat box for the Libraryh3lp service. [type] indicats the type
 ;       of chat being used (either "queue" or "user"). [id] is the name of the
diff --git a/config/vufind/searchspecs.yaml b/config/vufind/searchspecs.yaml
index 5e94d5cf055dab578a701f352ea878066470e5b9..13448bc5ab039304b1beb242a874dc66db441ce1 100644
--- a/config/vufind/searchspecs.yaml
+++ b/config/vufind/searchspecs.yaml
@@ -154,7 +154,7 @@
 # Note that you may create a "@parent_yaml" entry at the very top of the file to
 # inherit sections from another file. For example:
 #
-# @parent_yaml: "/path/to/my/file.yaml"
+# "@parent_yaml": "/path/to/my/file.yaml"
 #
 # Only sections not found in this file will be loaded in from the parent file.
 # In some complex scenarios, this can be a useful way of sharing settings
diff --git a/harvest/harvest_oai.php b/harvest/harvest_oai.php
index c08364b9fcf94402d81a9afb56f86cc21f39f9ce..a364a9a31b989d37560545aa9cd99ff7c924689b 100644
--- a/harvest/harvest_oai.php
+++ b/harvest/harvest_oai.php
@@ -26,7 +26,7 @@
  * @link     https://vufind.org/wiki/indexing:oai-pmh Wiki
  */
 
-// Load the Zend framework -- this will automatically trigger the appropriate
-// controller action based on directory and file names
-define('CLI_DIR', __DIR__);     // save directory name of current script
+// Manipulate command line to load correct route, then load Zend Framework:
+array_unshift($_SERVER['argv'], array_shift($_SERVER['argv']), 'harvest', 'harvest_oai');
+$_SERVER['argc'] += 2;
 require_once __DIR__ . '/../public/index.php';
\ No newline at end of file
diff --git a/harvest/merge-marc.php b/harvest/merge-marc.php
index 87335875b6d233c36c5ecdea24a34e43c108862b..779f18766feac06518c83214c03f655c20b88a80 100644
--- a/harvest/merge-marc.php
+++ b/harvest/merge-marc.php
@@ -27,7 +27,7 @@
  * @link     https://vufind.org/wiki/development:architecture:authority_control Wiki
  */
 
-// Load the Zend framework -- this will automatically trigger the appropriate
-// controller action based on directory and file names
-define('CLI_DIR', __DIR__);     // save directory name of current script
+// Manipulate command line to load correct route, then load Zend Framework:
+array_unshift($_SERVER['argv'], array_shift($_SERVER['argv']), 'harvest', 'merge-marc');
+$_SERVER['argc'] += 2;
 require_once __DIR__ . '/../public/index.php';
\ No newline at end of file
diff --git a/harvest/oai.ini b/harvest/oai.ini
index 54f494b1800d515d6b4cdf5058080ba248f83f20..7fc22feb9d6caef45b0ff5b3123db8588bea8b08 100644
--- a/harvest/oai.ini
+++ b/harvest/oai.ini
@@ -24,6 +24,7 @@
 ; sslcafile = "/etc/pki/tls/cert.pem" ; e.g. for CentOS systems
 ; sslverifypeer = true
 ; sanitize = true
+; sanitizeRegex[] = "/[^\x{0009}\x{000a}\x{000d}\x{0020}-\x{D7FF}\x{E000}-\x{FFFD}]+/u"
 ; badXMLLog = bad.log
 ; httpUser = myUsername
 ; httpPass = myPassword
@@ -60,6 +61,11 @@
 ; attributes to this tag, e.g., <collection attr="value"> will correctly
 ; wrap the records in <collection attr="value"></collection> tags.
 ;
+; globalSearch[] and globalReplace[] may be used to manipulate the raw XML metadata
+; documents with regular expressions. This should be used with caution but can be
+; helpful when compensating for server-side encoding/markup errors. You may use
+; multiple pairs of search and replace settings to perform multiple manipulations.
+;
 ; idPrefix is the OAI-specific prefix attached to ID values.  If you provide the
 ; value here, it will be automatically stripped for you when generating filenames,
 ; injecting IDs and tracking deleted records.  If you omit the setting, full
@@ -120,6 +126,10 @@
 ; sanitize may be set to true to strip illegal characters from XML responses; it
 ; defaults to false, assuming that the OAI-PMH server you are harvesting from will
 ; provide you with valid data.
+; 
+; sanitizeRegex may be set to an array of regex strings used to sanitize XML retrieved
+; from an OAI-PMH source. Any text sequences matching these expressions will be 
+; replaced with blank spaces.
 ;
 ; badXMLLog may be set to a filename (which will be created within your harvest
 ; directory) to contain copies of bad XML that was fixed when the sanitize setting
@@ -140,4 +150,8 @@
 ;idSearch[] = "/\//"
 ;idReplace[] = "-"
 ;injectId = "identifier"
-;injectDate = "datestamp"
\ No newline at end of file
+;injectDate = "datestamp"
+;
+; Further examples for harvesting OAI-PMH sources available to the general
+; public may be found on this wiki page:
+; https://vufind.org/wiki/indexing:open_data_sources
diff --git a/import/browse-indexing.jar b/import/browse-indexing.jar
index 8f3be925d57100979828bca0b948244b60509191..33ae93b4edea90d3119419f64b38c41f2e63638f 100644
Binary files a/import/browse-indexing.jar and b/import/browse-indexing.jar differ
diff --git a/import/import-xsl.php b/import/import-xsl.php
index db1230ce550add43d150deeb8ec1da0005bb7fb0..0aec5d90e4ad9f0e3864dd27e11745b9da9e8c61 100644
--- a/import/import-xsl.php
+++ b/import/import-xsl.php
@@ -27,7 +27,7 @@
  * @link     https://vufind.org/wiki/indexing Wiki
  */
 
-// Load the Zend framework -- this will automatically trigger the appropriate
-// controller action based on directory and file names
-define('CLI_DIR', __DIR__);     // save directory name of current script
+// Manipulate command line to load correct route, then load Zend Framework:
+array_unshift($_SERVER['argv'], array_shift($_SERVER['argv']), 'import', 'import-xsl');
+$_SERVER['argc'] += 2;
 require_once __DIR__ . '/../public/index.php';
diff --git a/import/index_java/src/org/solrmarc/index/VuFindIndexer.java b/import/index_java/src/org/solrmarc/index/VuFindIndexer.java
deleted file mode 100644
index 9fdb43b5f1552b337179b49bc0b0483cd98b0e66..0000000000000000000000000000000000000000
--- a/import/index_java/src/org/solrmarc/index/VuFindIndexer.java
+++ /dev/null
@@ -1,2762 +0,0 @@
-package org.solrmarc.index;
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import java.io.File;
-import java.io.FileReader;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.BufferedReader;
-import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
-import java.lang.StringBuilder;
-import java.text.ParseException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.LinkedHashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.sql.*;
-import java.text.SimpleDateFormat;
-
-import org.apache.log4j.Logger;
-import org.marc4j.marc.ControlField;
-import org.marc4j.marc.DataField;
-import org.marc4j.marc.Record;
-import org.marc4j.marc.Subfield;
-import org.marc4j.marc.VariableField;
-import org.solrmarc.callnum.DeweyCallNumber;
-import org.solrmarc.callnum.LCCallNumber;
-import org.solrmarc.tools.CallNumUtils;
-import org.solrmarc.tools.SolrMarcIndexerException;
-import org.solrmarc.tools.Utils;
-import org.ini4j.Ini;
-
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-
-import org.w3c.dom.Document;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-
-/**
- *
- * @author Robert Haschart
- * @version $Id: VuFindIndexer.java 224 2008-11-05 19:33:21Z asnagy $
- *
- */
-public class VuFindIndexer extends SolrIndexer
-{
-    // Initialize logging category
-    static Logger logger = Logger.getLogger(VuFindIndexer.class.getName());
-
-    // Initialize VuFind database connection (null until explicitly activated)
-    private Connection vufindDatabase = null;
-    private UpdateDateTracker tracker = null;
-
-    // the SimpleDateFormat class is not Thread-safe the below line were changes to be not static 
-    // which given the rest of the design of SolrMarc will make them work correctly.
-    private SimpleDateFormat marc005date = new SimpleDateFormat("yyyyMMddHHmmss.S");
-    private SimpleDateFormat marc008date = new SimpleDateFormat("yyMMdd");
-
-    private static final Pattern COORDINATES_PATTERN = Pattern.compile("^([eEwWnNsS])(\\d{3})(\\d{2})(\\d{2})");
-    private static final Pattern HDMSHDD_PATTERN = Pattern.compile("^([eEwWnNsS])(\\d+(\\.\\d+)?)");
-    private static final Pattern PMDD_PATTERN = Pattern.compile("^([+-])(\\d+(\\.\\d+)?)");
-
-    private static ConcurrentHashMap<String, Ini> configCache = new ConcurrentHashMap<String, Ini>();
-    private ConcurrentHashMap<String, String> relatorSynonymLookup = new ConcurrentHashMap<String, String>();
-    private Set<String> knownRelators = new LinkedHashSet<String>();
-
-    // Shutdown flag:
-    private boolean shuttingDown = false;
-
-    // VuFind-specific configs:
-    private Properties vuFindConfigs = null;
-
-    /**
-     * Default constructor
-     * @param propertiesMapFile the {@code x_index.properties} file mapping solr
-     *  field names to values in the marc records
-     * @param propertyDirs array of directories holding properties files
-     * @throws Exception if {@code SolrIndexer} constructor threw an exception.
-     */
-    public VuFindIndexer(final String propertiesMapFile, final String[] propertyDirs)
-            throws FileNotFoundException, IOException, ParseException {
-        super(propertiesMapFile, propertyDirs);
-        try {
-            vuFindConfigs = Utils.loadProperties(propertyDirs, "vufind.properties");
-        } catch (IllegalArgumentException e) {
-            // If the properties load failed, don't worry about it -- we'll use defaults.
-        }
-    }
-
-    /**
-     * Log an error message and throw a fatal exception.
-     * @param msg message to log
-     */
-    private void dieWithError(String msg)
-    {
-        logger.error(msg);
-        throw new SolrMarcIndexerException(SolrMarcIndexerException.EXIT, msg);
-    }
-
-    /**
-     * Given the base name of a configuration file, locate the full path.
-     * @param filename base name of a configuration file
-     */
-    private File findConfigFile(String filename)
-    {
-        // Find VuFind's home directory in the environment; if it's not available,
-        // try using a relative path on the assumption that we are currently in
-        // VuFind's import subdirectory:
-        String vufindHome = System.getenv("VUFIND_HOME");
-        if (vufindHome == null) {
-            vufindHome = "..";
-        }
-
-        // Check for VuFind 2.0's local directory environment variable:
-        String vufindLocal = System.getenv("VUFIND_LOCAL_DIR");
-
-        // Get the relative VuFind path from the properties file, defaulting to
-        // the 2.0-style config/vufind if necessary.
-        String relativeConfigPath = Utils.getProperty(
-            vuFindConfigs, "vufind.config.relative_path", "config/vufind"
-        );
-
-        // Try several different locations for the file -- VuFind 2 local dir,
-        // VuFind 2 base dir, VuFind 1 base dir.
-        File file;
-        if (vufindLocal != null) {
-            file = new File(vufindLocal + "/" + relativeConfigPath + "/" + filename);
-            if (file.exists()) {
-                return file;
-            }
-        }
-        file = new File(vufindHome + "/" + relativeConfigPath + "/" + filename);
-        if (file.exists()) {
-            return file;
-        }
-        file = new File(vufindHome + "/web/conf/" + filename);
-        return file;
-    }
-
-    /**
-     * Sanitize a VuFind configuration setting.
-     * @param str configuration setting
-     */
-    private String sanitizeConfigSetting(String str)
-    {
-        // Drop comments if necessary:
-        int pos = str.indexOf(';');
-        if (pos >= 0) {
-            str = str.substring(0, pos).trim();
-        }
-
-        // Strip wrapping quotes if necessary (the ini reader won't do this for us):
-        if (str.startsWith("\"")) {
-            str = str.substring(1, str.length());
-        }
-        if (str.endsWith("\"")) {
-            str = str.substring(0, str.length() - 1);
-        }
-        return str;
-    }
-
-    /**
-     * Load an ini file.
-     * @param filename name of {@code .ini} file
-     */
-    public Ini loadConfigFile(String filename)
-    {
-        // Retrieve the file if it is not already cached.
-        if (!configCache.containsKey(filename)) {
-            Ini ini = new Ini();
-            try {
-                ini.load(new FileReader(findConfigFile(filename)));
-                configCache.putIfAbsent(filename, ini);
-            } catch (Throwable e) {
-                dieWithError("Unable to access " + filename);
-            }
-        }
-        return configCache.get(filename);
-    }
-
-    /**
-     * Get a section from a VuFind configuration file.
-     * @param filename configuration file name
-     * @param section section name within the file
-     */
-    public Map<String, String> getConfigSection(String filename, String section)
-    {
-        // Grab the ini file.
-        Ini ini = loadConfigFile(filename);
-        Map<String, String> retVal = ini.get(section);
-
-        String parent = ini.get("Parent_Config", "path");
-        while (parent != null) {
-            Ini parentIni = loadConfigFile(parent);
-            Map<String, String> parentSection = parentIni.get(section);
-            for (String key : parentSection.keySet()) {
-                if (!retVal.containsKey(key)) {
-                    retVal.put(key, parentSection.get(key));
-                }
-            }
-            parent = parentIni.get("Parent_Config", "path");
-        }
-
-        // Check to see if we need to worry about an override file:
-        String override = ini.get("Extra_Config", "local_overrides");
-        if (override != null) {
-            Map<String, String> overrideSection = loadConfigFile(override).get(section);
-            for (String key : overrideSection.keySet()) {
-                retVal.put(key, overrideSection.get(key));
-            }
-        }
-        return retVal;
-    }
-
-    /**
-     * Get a setting from a VuFind configuration file.
-     * @param filename configuration file name
-     * @param section section name within the file
-     * @param setting setting name within the section
-     */
-    public String getConfigSetting(String filename, String section, String setting)
-    {
-        String retVal = null;
-
-        // Grab the ini file.
-        Ini ini = loadConfigFile(filename);
-
-        // Check to see if we need to worry about an override file:
-        String override = ini.get("Extra_Config", "local_overrides");
-        if (override != null) {
-            Ini overrideIni = loadConfigFile(override);
-            retVal = overrideIni.get(section, setting);
-            if (retVal != null) {
-                return sanitizeConfigSetting(retVal);
-            }
-        }
-
-        // Try to find the requested setting:
-        retVal = ini.get(section, setting);
-
-        //  No setting?  Check for a parent configuration:
-        while (retVal == null) {
-            String parent = ini.get("Parent_Config", "path");
-            if (parent !=  null) {
-                try {
-                    ini.load(new FileReader(new File(parent)));
-                } catch (Throwable e) {
-                    dieWithError("Unable to access " + parent);
-                }
-                retVal = ini.get(section, setting);
-            } else {
-                break;
-            }
-        }
-
-        // Return the processed setting:
-        return retVal == null ? null : sanitizeConfigSetting(retVal);
-    }
-
-    /**
-     * Connect to the VuFind database if we do not already have a connection.
-     */
-    private void connectToDatabase()
-    {
-        // Already connected?  Do nothing further!
-        if (vufindDatabase != null) {
-            return;
-        }
-
-        String dsn = getConfigSetting("config.ini", "Database", "database");
-
-        try {
-            // Parse key settings from the PHP-style DSN:
-            String username = "";
-            String password = "";
-            String classname = "invalid";
-            String prefix = "invalid";
-            if (dsn.substring(0, 8).equals("mysql://")) {
-                classname = "com.mysql.jdbc.Driver";
-                prefix = "mysql";
-            } else if (dsn.substring(0, 8).equals("pgsql://")) {
-                classname = "org.postgresql.Driver";
-                prefix = "postgresql";
-            }
-
-            Class.forName(classname).newInstance();
-            String[] parts = dsn.split("://");
-            if (parts.length > 1) {
-                parts = parts[1].split("@");
-                if (parts.length > 1) {
-                    dsn = prefix + "://" + parts[1];
-                    parts = parts[0].split(":");
-                    username = parts[0];
-                    if (parts.length > 1) {
-                        password = parts[1];
-                    }
-                }
-            }
-
-            // Connect to the database:
-            vufindDatabase = DriverManager.getConnection("jdbc:" + dsn, username, password);
-        } catch (Throwable e) {
-            dieWithError("Unable to connect to VuFind database");
-        }
-
-        Runtime.getRuntime().addShutdownHook(new VuFindShutdownThread(this));
-    }
-
-    private void disconnectFromDatabase()
-    {
-        if (vufindDatabase != null) {
-            try {
-                vufindDatabase.close();
-            } catch (SQLException e) {
-                System.err.println("Unable to disconnect from VuFind database");
-                logger.error("Unable to disconnect from VuFind database");
-            }
-        }
-    }
-
-    public void shutdown()
-    {
-        disconnectFromDatabase();
-        shuttingDown = true;
-    }
-
-    class VuFindShutdownThread extends Thread
-    {
-        private VuFindIndexer indexer;
-
-        public VuFindShutdownThread(VuFindIndexer i)
-        {
-            indexer = i;
-        }
-
-        public void run()
-        {
-            indexer.shutdown();
-        }
-    }
-
-    /**
-     * Establish UpdateDateTracker object if not already available.
-     */
-    private void loadUpdateDateTracker() throws java.sql.SQLException
-    {
-        if (tracker == null) {
-            connectToDatabase();
-            tracker = new UpdateDateTracker(vufindDatabase);
-        }
-    }
-
-    /**
-     * Support method for getLatestTransaction.
-     * @return Date extracted from 005 (or very old date, if unavailable)
-     */
-    private java.util.Date normalize005Date(String input)
-    {
-        // Normalize "null" strings to a generic bad value:
-        if (input == null) {
-            input = "null";
-        }
-
-        // Try to parse the date; default to "millisecond 0" (very old date) if we can't
-        // parse the data successfully.
-        java.util.Date retVal;
-        try {
-            retVal = marc005date.parse(input);
-        } catch(java.text.ParseException e) {
-            retVal = new java.util.Date(0);
-        }
-        return retVal;
-    }
-
-    /**
-     * Support method for getLatestTransaction.
-     * @return Date extracted from 008 (or very old date, if unavailable)
-     */
-    private java.util.Date normalize008Date(String input)
-    {
-        // Normalize "null" strings to a generic bad value:
-        if (input == null || input.length() < 6) {
-            input = "null";
-        }
-
-        // Try to parse the date; default to "millisecond 0" (very old date) if we can't
-        // parse the data successfully.
-        java.util.Date retVal;
-        try {
-            retVal = marc008date.parse(input.substring(0, 6));
-        } catch(java.lang.StringIndexOutOfBoundsException e) {
-            retVal = new java.util.Date(0);
-        } catch(java.text.ParseException e) {
-            retVal = new java.util.Date(0);
-        }
-        return retVal;
-    }
-
-    /**
-     * Extract the latest transaction date from the MARC record.  This is useful
-     * for detecting when a record has changed since the last time it was indexed.
-     *
-     * @param record MARC record
-     * @return Latest transaction date.
-     */
-    public java.util.Date getLatestTransaction(Record record) {
-        // First try the 005 -- this is most likely to have a precise transaction date:
-        Set<String> dates = getFieldList(record, "005");
-        if (dates != null) {
-            Iterator<String> dateIter = dates.iterator();
-            if (dateIter.hasNext()) {
-                return normalize005Date(dateIter.next());
-            }
-        }
-
-        // No luck with 005?  Try 008 next -- less precise, but better than nothing:
-        dates = getFieldList(record, "008");
-        if (dates != null) {
-            Iterator<String> dateIter = dates.iterator();
-            if (dateIter.hasNext()) {
-                return normalize008Date(dateIter.next());
-            }
-        }
-
-        // If we got this far, we couldn't find a valid value; return an arbitrary date:
-        return new java.util.Date(0);
-    }
-
-    /**
-     * Get all available publishers from the record.
-     *
-     * @param  record MARC record
-     * @return set of publishers
-     */
-    public Set<String> getPublishers(final Record record) {
-        Set<String> publishers = new LinkedHashSet<String>();
-
-        // First check old-style 260b name:
-        List<VariableField> list260 = record.getVariableFields("260");
-        for (VariableField vf : list260)
-        {
-            DataField df = (DataField) vf;
-            String currentString = "";
-            for (Subfield current : df.getSubfields('b')) {
-                currentString = currentString.trim().concat(" " + current.getData()).trim();
-            }
-            if (currentString.length() > 0) {
-                publishers.add(currentString);
-            }
-        }
-
-        // Now track down relevant RDA-style 264b names; we only care about
-        // copyright and publication names (and ignore copyright names if
-        // publication names are present).
-        Set<String> pubNames = new LinkedHashSet<String>();
-        Set<String> copyNames = new LinkedHashSet<String>();
-        List<VariableField> list264 = record.getVariableFields("264");
-        for (VariableField vf : list264)
-        {
-            DataField df = (DataField) vf;
-            String currentString = "";
-            for (Subfield current : df.getSubfields('b')) {
-                currentString = currentString.trim().concat(" " + current.getData()).trim();
-            }
-            if (currentString.length() > 0) {
-                char ind2 = df.getIndicator2();
-                switch (ind2)
-                {
-                    case '1':
-                        pubNames.add(currentString);
-                        break;
-                    case '4':
-                        copyNames.add(currentString);
-                        break;
-                }
-            }
-        }
-        if (pubNames.size() > 0) {
-            publishers.addAll(pubNames);
-        } else if (copyNames.size() > 0) {
-            publishers.addAll(copyNames);
-        }
-
-        return publishers;
-    }
-
-    /**
-     * Get all available dates from the record.
-     *
-     * @param  record MARC record
-     * @return set of dates
-     */
-    public Set<String> getDates(final Record record) {
-        Set<String> dates = new LinkedHashSet<String>();
-
-        // First check old-style 260c date:
-        List<VariableField> list260 = record.getVariableFields("260");
-        for (VariableField vf : list260) {
-            DataField df = (DataField) vf;
-            List<Subfield> currentDates = df.getSubfields('c');
-            for (Subfield sf : currentDates) {
-                String currentDateStr = Utils.cleanDate(sf.getData());
-                if (currentDateStr != null) dates.add(currentDateStr);
-            }
-        }
-
-        // Now track down relevant RDA-style 264c dates; we only care about
-        // copyright and publication dates (and ignore copyright dates if
-        // publication dates are present).
-        Set<String> pubDates = new LinkedHashSet<String>();
-        Set<String> copyDates = new LinkedHashSet<String>();
-        List<VariableField> list264 = record.getVariableFields("264");
-        for (VariableField vf : list264) {
-            DataField df = (DataField) vf;
-            List<Subfield> currentDates = df.getSubfields('c');
-            for (Subfield sf : currentDates) {
-                String currentDateStr = Utils.cleanDate(sf.getData());
-                char ind2 = df.getIndicator2();
-                switch (ind2)
-                {
-                    case '1':
-                        if (currentDateStr != null) pubDates.add(currentDateStr);
-                        break;
-                    case '4':
-                        if (currentDateStr != null) copyDates.add(currentDateStr);
-                        break;
-                }
-            }
-        }
-        if (pubDates.size() > 0) {
-            dates.addAll(pubDates);
-        } else if (copyDates.size() > 0) {
-            dates.addAll(copyDates);
-        }
-
-        return dates;
-    }
-
-    /**
-     * Get the earliest publication date from the record.
-     *
-     * @param  record MARC record
-     * @return earliest date
-     */
-    public String getFirstDate(final Record record) {
-        String result = null;
-        Set<String> dates = getDates(record);
-        for(String current: dates) {
-            if (result == null || Integer.parseInt(current) < Integer.parseInt(result)) {
-                result = current;
-            }
-        }
-        return result;
-    }
-
-    /**
-     * Determine Record Format(s)
-     *
-     * @param  record MARC record
-     * @return set of record formats
-     */
-    public Set<String> getFormat(final Record record){
-        Set<String> result = new LinkedHashSet<String>();
-        String leader = record.getLeader().toString();
-        char leaderBit;
-        ControlField fixedField = (ControlField) record.getVariableField("008");
-        DataField title = (DataField) record.getVariableField("245");
-        String formatString;
-        char formatCode = ' ';
-        char formatCode2 = ' ';
-        char formatCode4 = ' ';
-
-        // check if there's an h in the 245
-        if (title != null) {
-            if (title.getSubfield('h') != null){
-                if (title.getSubfield('h').getData().toLowerCase().contains("[electronic resource]")) {
-                    result.add("Electronic");
-                    return result;
-                }
-            }
-        }
-
-        // check the 007 - this is a repeating field
-        List<VariableField> fields = record.getVariableFields("007");
-        Iterator<VariableField> fieldsIter = fields.iterator();
-        if (fields != null) {
-            // TODO: update loop to for(:) syntax, but problem with type casting.
-            ControlField formatField;
-            while(fieldsIter.hasNext()) {
-                formatField = (ControlField) fieldsIter.next();
-                formatString = formatField.getData().toUpperCase();
-                formatCode = formatString.length() > 0 ? formatString.charAt(0) : ' ';
-                formatCode2 = formatString.length() > 1 ? formatString.charAt(1) : ' ';
-                formatCode4 = formatString.length() > 4 ? formatString.charAt(4) : ' ';
-                switch (formatCode) {
-                    case 'A':
-                        switch(formatCode2) {
-                            case 'D':
-                                result.add("Atlas");
-                                break;
-                            default:
-                                result.add("Map");
-                                break;
-                        }
-                        break;
-                    case 'C':
-                        switch(formatCode2) {
-                            case 'A':
-                                result.add("TapeCartridge");
-                                break;
-                            case 'B':
-                                result.add("ChipCartridge");
-                                break;
-                            case 'C':
-                                result.add("DiscCartridge");
-                                break;
-                            case 'F':
-                                result.add("TapeCassette");
-                                break;
-                            case 'H':
-                                result.add("TapeReel");
-                                break;
-                            case 'J':
-                                result.add("FloppyDisk");
-                                break;
-                            case 'M':
-                            case 'O':
-                                result.add("CDROM");
-                                break;
-                            case 'R':
-                                // Do not return - this will cause anything with an
-                                // 856 field to be labeled as "Electronic"
-                                break;
-                            default:
-                                result.add("Software");
-                                break;
-                        }
-                        break;
-                    case 'D':
-                        result.add("Globe");
-                        break;
-                    case 'F':
-                        result.add("Braille");
-                        break;
-                    case 'G':
-                        switch(formatCode2) {
-                            case 'C':
-                            case 'D':
-                                result.add("Filmstrip");
-                                break;
-                            case 'T':
-                                result.add("Transparency");
-                                break;
-                            default:
-                                result.add("Slide");
-                                break;
-                        }
-                        break;
-                    case 'H':
-                        result.add("Microfilm");
-                        break;
-                    case 'K':
-                        switch(formatCode2) {
-                            case 'C':
-                                result.add("Collage");
-                                break;
-                            case 'D':
-                                result.add("Drawing");
-                                break;
-                            case 'E':
-                                result.add("Painting");
-                                break;
-                            case 'F':
-                                result.add("Print");
-                                break;
-                            case 'G':
-                                result.add("Photonegative");
-                                break;
-                            case 'J':
-                                result.add("Print");
-                                break;
-                            case 'L':
-                                result.add("Drawing");
-                                break;
-                            case 'O':
-                                result.add("FlashCard");
-                                break;
-                            case 'N':
-                                result.add("Chart");
-                                break;
-                            default:
-                                result.add("Photo");
-                                break;
-                        }
-                        break;
-                    case 'M':
-                        switch(formatCode2) {
-                            case 'F':
-                                result.add("VideoCassette");
-                                break;
-                            case 'R':
-                                result.add("Filmstrip");
-                                break;
-                            default:
-                                result.add("MotionPicture");
-                                break;
-                        }
-                        break;
-                    case 'O':
-                        result.add("Kit");
-                        break;
-                    case 'Q':
-                        result.add("MusicalScore");
-                        break;
-                    case 'R':
-                        result.add("SensorImage");
-                        break;
-                    case 'S':
-                        switch(formatCode2) {
-                            case 'D':
-                                result.add("SoundDisc");
-                                break;
-                            case 'S':
-                                result.add("SoundCassette");
-                                break;
-                            default:
-                                result.add("SoundRecording");
-                                break;
-                        }
-                        break;
-                    case 'V':
-                        switch(formatCode2) {
-                            case 'C':
-                                result.add("VideoCartridge");
-                                break;
-                            case 'D':
-                                switch(formatCode4) {
-                                    case 'S':
-                                        result.add("BRDisc");
-                                        break;
-                                    case 'V':
-                                    default:
-                                        result.add("VideoDisc");
-                                        break;
-                                }
-                                break;
-                            case 'F':
-                                result.add("VideoCassette");
-                                break;
-                            case 'R':
-                                result.add("VideoReel");
-                                break;
-                            default:
-                                result.add("Video");
-                                break;
-                        }
-                        break;
-                }
-            }
-            if (!result.isEmpty()) {
-                return result;
-            }
-        }
-
-        // check the Leader at position 6
-        leaderBit = leader.charAt(6);
-        switch (Character.toUpperCase(leaderBit)) {
-            case 'C':
-            case 'D':
-                result.add("MusicalScore");
-                break;
-            case 'E':
-            case 'F':
-                result.add("Map");
-                break;
-            case 'G':
-                result.add("Slide");
-                break;
-            case 'I':
-                result.add("SoundRecording");
-                break;
-            case 'J':
-                result.add("MusicRecording");
-                break;
-            case 'K':
-                result.add("Photo");
-                break;
-            case 'M':
-                result.add("Electronic");
-                break;
-            case 'O':
-            case 'P':
-                result.add("Kit");
-                break;
-            case 'R':
-                result.add("PhysicalObject");
-                break;
-            case 'T':
-                result.add("Manuscript");
-                break;
-        }
-        if (!result.isEmpty()) {
-            return result;
-        }
-
-        // check the Leader at position 7
-        leaderBit = leader.charAt(7);
-        switch (Character.toUpperCase(leaderBit)) {
-            // Monograph
-            case 'M':
-                if (formatCode == 'C') {
-                    result.add("eBook");
-                } else {
-                    result.add("Book");
-                }
-                break;
-            // Component parts
-            case 'A':
-                result.add("BookComponentPart");
-                break;
-            case 'B':
-                result.add("SerialComponentPart");
-                break;
-            // Serial
-            case 'S':
-                // Look in 008 to determine what type of Continuing Resource
-                formatCode = fixedField.getData().toUpperCase().charAt(21);
-                switch (formatCode) {
-                    case 'N':
-                        result.add("Newspaper");
-                        break;
-                    case 'P':
-                        result.add("Journal");
-                        break;
-                    default:
-                        result.add("Serial");
-                        break;
-                }
-        }
-
-        // Nothing worked!
-        if (result.isEmpty()) {
-            result.add("Unknown");
-        }
-
-        return result;
-    }
-
-    /**
-     * Get call numbers of a specific type.
-     * 
-     * <p>{@code fieldSpec} is of form {@literal 098abc:099ab}, does not accept subfield ranges.
-     *
-     *
-     * @param record  current MARC record
-     * @param fieldSpec  which MARC fields / subfields need to be analyzed
-     * @param callTypeSf  subfield containing call number type, single character only
-     * @param callType  literal call number code
-     * @param result  a collection to gather the call numbers
-     * @return collection of call numbers, same object as {@code result}
-     */
-    public static Collection<String> getCallNumberByTypeCollector(
-            Record record, String fieldSpec, String callTypeSf, String callType, Collection<String> result) {
-        for (String tag : fieldSpec.split(":")) {
-            // Check to ensure tag length is at least 3 characters
-            if (tag.length() < 3) {
-                //TODO: Should this go to a log? Better message for a bad tag in a field spec?
-                System.err.println("Invalid tag specified: " + tag);
-                continue;
-            }
-            String dfTag = tag.substring(0, 3);
-            String sfSpec = null;
-            if (tag.length() > 3) {
-                    sfSpec = tag.substring(3);
-            }
-
-            // do all fields for this tag
-            for (VariableField vf : record.getVariableFields(dfTag)) {
-                // Assume tag represents a DataField
-                DataField df = (DataField) vf;
-                boolean callTypeMatch = false;
-                
-                // Assume call type subfield could repeat
-                for (Subfield typeSf : df.getSubfields(callTypeSf)) {
-                    if (callTypeSf.indexOf(typeSf.getCode()) != -1 && typeSf.getData().equals(callType)) {
-                        callTypeMatch = true;
-                    }
-                }
-                System.err.println("callTypeMatch after loop: " + callTypeMatch);
-                if (callTypeMatch) {
-                    result.add(df.getSubfieldsAsString(sfSpec));
-                }
-            } // end loop over variable fields
-        } // end loop over fieldSpec
-        return result;
-    }
-    
-
-    /**
-     * Get call numbers of a specific type.
-     * 
-     * <p>{@code fieldSpec} is of form {@literal 098abc:099ab}, does not accept subfield ranges.
-     *
-     * @param record  current MARC record
-     * @param fieldSpec  which MARC fields / subfields need to be analyzed
-     * @param callTypeSf  subfield containing call number type, single character only
-     * @param callType  literal call number code
-     * @return set of call numbers
-     */
-    public static Set<String> getCallNumberByType(Record record, String fieldSpec, String callTypeSf, String callType) {
-        return (Set<String>) getCallNumberByTypeCollector(record, fieldSpec, callTypeSf, callType,
-                new LinkedHashSet<String>());
-    }
-
-    /**
-     * Get call numbers of a specific type.
-     * 
-     * <p>{@code fieldSpec} is of form {@literal 098abc:099ab}, does not accept subfield ranges.
-     *
-     * @param record  current MARC record
-     * @param fieldSpec  which MARC fields / subfields need to be analyzed
-     * @param callTypeSf  subfield containing call number type, single character only
-     * @param callType  literal call number code
-     * @return list of call numbers
-     */
-    public static List<String> getCallNumberByTypeAsList(Record record, String fieldSpec, String callTypeSf, String callType) {
-        return (List<String>) getCallNumberByTypeCollector(record, fieldSpec, callTypeSf, callType,
-                new ArrayList<String>());
-    }
-    
-    /**
-     * Extract the full call number from a record, stripped of spaces
-     * @param record MARC record
-     * @return Call number label
-     * @deprecated Obsolete as of VuFind 2.4.
-     *          This method exists only to support the VuFind call number search, version <= 2.3.
-     *          As of VuFind 2.4, the munging for call number search in handled entirely in Solr.
-     */
-    @Deprecated
-    public String getFullCallNumber(final Record record) {
-
-        return(getFullCallNumber(record, "099ab:090ab:050ab"));
-    }
-
-    /**
-     * Extract the full call number from a record, stripped of spaces
-     * @param record MARC record
-     * @param fieldSpec taglist for call number fields
-     * @return Call number label
-     * @deprecated Obsolete as of VuFind 2.4.
-     *          This method exists only to support the VuFind call number search, version <= 2.3.
-     *          As of VuFind 2.4, the munging for call number search in handled entirely in Solr.
-     */
-    @Deprecated
-    public String getFullCallNumber(final Record record, String fieldSpec) {
-
-        String val = getFirstFieldVal(record, fieldSpec);
-
-        if (val != null) {
-            return val.toUpperCase().replaceAll(" ", "");
-        } else {
-            return val;
-        }
-    }
-
-    /**
-     * Extract the call number label from a record
-     * @param record MARC record
-     * @return Call number label
-     */
-    public String getCallNumberLabel(final Record record) {
-
-        return getCallNumberLabel(record, "090a:050a");
-    }
-
-    /**
-     * Extract the call number label from a record
-     * @param record MARC record
-     * @param fieldSpec taglist for call number fields
-     * @return Call number label
-     */
-    public String getCallNumberLabel(final Record record, String fieldSpec) {
-
-        String val = getFirstFieldVal(record, fieldSpec);
-
-        if (val != null) {
-            int dotPos = val.indexOf(".");
-            if (dotPos > 0) {
-                val = val.substring(0, dotPos);
-            }
-            return val.toUpperCase();
-        } else {
-            return val;
-        }
-    }
-
-    /**
-     * Extract the subject component of the call number
-     *
-     * Can return null
-     *
-     * @param record MARC record
-     * @return Call number subject letters
-     */
-    public String getCallNumberSubject(final Record record) {
-
-        return(getCallNumberSubject(record, "090a:050a"));
-    }
-
-    /**
-     * Extract the subject component of the call number
-     *
-     * Can return null
-     *
-     * @param record current MARC record
-     * @return Call number subject letters
-     */
-    public String getCallNumberSubject(final Record record, String fieldSpec) {
-
-        String val = getFirstFieldVal(record, fieldSpec);
-
-        if (val != null) {
-            String [] callNumberSubject = val.toUpperCase().split("[^A-Z]+");
-            if (callNumberSubject.length > 0)
-            {
-                return callNumberSubject[0];
-            }
-        }
-        return(null);
-    }
-
-    /**
-     * Normalize a single LC call number
-     * @param record current MARC record
-     * @return String Normalized LCCN
-     */
-    public String getFullCallNumberNormalized(final Record record) {
-
-        return(getFullCallNumberNormalized(record, "099ab:090ab:050ab"));
-    }
-
-    /**
-     * Normalize a single LC call number
-     * @param record current MARC record
-     * @param fieldSpec which MARC fields / subfields need to be analyzed
-     * @return String Normalized LC call number
-     */
-    public String getFullCallNumberNormalized(final Record record, String fieldSpec) {
-
-        // TODO: is the null fieldSpec still an issue?
-        if (fieldSpec != null) {
-            String cn = getFirstFieldVal(record, fieldSpec);
-            return (new LCCallNumber(cn)).getShelfKey();
-        }
-        // If we got this far, we couldn't find a valid value:
-        return null;
-    }
-
-    /**
-     * Determine if a record is illustrated.
-     *
-     * @param  LC call number
-     * @return "Illustrated" or "Not Illustrated"
-     */
-    public String isIllustrated(Record record) {
-        String leader = record.getLeader().toString();
-
-        // Does the leader indicate this is a "language material" that might have extra
-        // illustration details in the fixed fields?
-        if (leader.charAt(6) == 'a') {
-            String currentCode = "";         // for use in loops below
-
-            // List of 008/18-21 codes that indicate illustrations:
-            String illusCodes = "abcdefghijklmop";
-
-            // Check the illustration characters of the 008:
-            ControlField fixedField = (ControlField) record.getVariableField("008");
-            if (fixedField != null) {
-                String fixedFieldText = fixedField.getData().toLowerCase();
-                for (int i = 18; i <= 21; i++) {
-                    if (i < fixedFieldText.length()) {
-                        currentCode = fixedFieldText.substring(i, i + 1);
-                        if (illusCodes.contains(currentCode)) {
-                            return "Illustrated";
-                        }
-                    }
-                }
-            }
-
-            // Now check if any 006 fields apply:
-            List<VariableField> fields = record.getVariableFields("006");
-            Iterator<VariableField> fieldsIter = fields.iterator();
-            if (fields != null) {
-                while(fieldsIter.hasNext()) {
-                    fixedField = (ControlField) fieldsIter.next();
-                    String fixedFieldText = fixedField.getData().toLowerCase();
-                    for (int i = 1; i <= 4; i++) {
-                         if (i < fixedFieldText.length()) {
-                            currentCode = fixedFieldText.substring(i, i + 1);
-                            if (illusCodes.contains(currentCode)) {
-                                return "Illustrated";
-                            }
-                        }
-                    }
-                }
-            }
-        }
-
-        // Now check for interesting strings in 300 subfield b:
-        List<VariableField> fields = record.getVariableFields("300");
-        Iterator<VariableField> fieldsIter = fields.iterator();
-        if (fields != null) {
-            DataField physical;
-            while(fieldsIter.hasNext()) {
-                physical = (DataField) fieldsIter.next();
-                List<Subfield> subfields = physical.getSubfields('b');
-                for (Subfield sf: subfields) {
-                    String desc = sf.getData().toLowerCase();
-                    if (desc.contains("ill.") || desc.contains("illus.")) {
-                        return "Illustrated";
-                    }
-                }
-            }
-        }
-
-        // If we made it this far, we found no sign of illustrations:
-        return "Not Illustrated";
-    }
-
-
-    /**
-     * Normalize LC numbers for sorting purposes (use only the first valid number!).
-     * Will return first call number found if none pass validation,
-     * or empty string if no call numbers.
-     *
-     * @param  record current MARC record
-     * @param  fieldSpec which MARC fields / subfields need to be analyzed
-     * @return sortable shelf key of the first valid LC number encountered, 
-     *         otherwise shelf key of the first call number found.
-     */
-    public String getLCSortable(Record record, String fieldSpec) {
-        // Loop through the specified MARC fields:
-        Set<String> input = getFieldList(record, fieldSpec);
-        String firstCall = "";
-        for (String current : input) {
-            // If this is a valid LC number, return the sortable shelf key:
-            LCCallNumber callNum = new LCCallNumber(current);
-            if (callNum.isValid()) {
-                return callNum.getShelfKey();   // RETURN first valid
-            }
-            if (firstCall.length() == 0) {
-                firstCall = current;
-            }
-        }
-
-        // If we made it this far, did not find a valid LC number, so use what we have:
-        return new LCCallNumber(firstCall).getShelfKey();
-    }
-
-    /**
-     * Get sort key for first LC call number, identified by call type.
-     * 
-     * <p>{@code fieldSpec} is of form {@literal 098abc:099ab}, does not accept subfield ranges.
-     *
-     *
-     * @param record  current MARC record
-     * @param fieldSpec  which MARC fields / subfields need to be analyzed
-     * @param callTypeSf  subfield containing call number type, single character only
-     * @param callType  literal call number code
-     * @return sort key for first identified LC call number
-     */
-    public String getLCSortableByType(
-            Record record, String fieldSpec, String callTypeSf, String callType) {
-        String sortKey = null;
-        for (String tag : fieldSpec.split(":")) {
-            // Check to ensure tag length is at least 3 characters
-            if (tag.length() < 3) {
-                //TODO: Should this go to a log? Better message for a bad tag in a field spec?
-                System.err.println("Invalid tag specified: " + tag);
-                continue;
-            }
-            String dfTag = tag.substring(0, 3);
-            String sfSpec = null;
-            if (tag.length() > 3) {
-                    sfSpec = tag.substring(3);
-            }
-
-            // do all fields for this tag
-            for (VariableField vf : record.getVariableFields(dfTag)) {
-                // Assume tag represents a DataField
-                DataField df = (DataField) vf;
-                boolean callTypeMatch = false;
-                
-                // Assume call type subfield could repeat
-                for (Subfield typeSf : df.getSubfields(callTypeSf)) {
-                    if (callTypeSf.indexOf(typeSf.getCode()) != -1 && typeSf.getData().equals(callType)) {
-                        callTypeMatch = true;
-                    }
-                }
-                // take the first call number coded as LC
-                if (callTypeMatch) {
-                    sortKey = new LCCallNumber(df.getSubfieldsAsString(sfSpec)).getShelfKey();
-                    break;
-                }
-            } // end loop over variable fields
-        } // end loop over fieldSpec
-        return sortKey;
-    }
-
-    /**
-     * Extract a numeric portion of the Dewey decimal call number
-     *
-     * Can return null
-     *
-     * @param record current MARC record
-     * @param fieldSpec which MARC fields / subfields need to be analyzed
-     * @param precisionStr a decimal number (represented in string format) showing the
-     *  desired precision of the returned number; i.e. 100 to round to nearest hundred,
-     *  10 to round to nearest ten, 0.1 to round to nearest tenth, etc.
-     * @return Set containing requested numeric portions of Dewey decimal call numbers
-     */
-    public Set<String> getDeweyNumber(Record record, String fieldSpec, String precisionStr) {
-        // Initialize our return value:
-        Set<String> result = new LinkedHashSet<String>();
-
-        // Precision comes in as a string, but we need to convert it to a float:
-        float precision = Float.parseFloat(precisionStr);
-
-        // Loop through the specified MARC fields:
-        Set<String> input = getFieldList(record, fieldSpec);
-        for (String current: input) {
-            DeweyCallNumber callNum = new DeweyCallNumber(current);
-            if (callNum.isValid()) {
-                // Convert the numeric portion of the call number into a float:
-                float currentVal = Float.parseFloat(callNum.getClassification());
-                
-                // Round the call number value to the specified precision:
-                Float finalVal = new Float(Math.floor(currentVal / precision) * precision);
-                
-                // Convert the rounded value back to a string (with leading zeros) and save it:
-                // TODO: Provide different conversion to remove CallNumUtils dependency
-                result.add(CallNumUtils.normalizeFloat(finalVal.toString(), 3, -1));
-            }
-        }
-
-        // If we found no call number matches, return null; otherwise, return our results:
-        if (result.isEmpty())
-            return null;
-        return result;
-    }
-
-    /**
-     * Normalize Dewey numbers for searching purposes (uppercase/stripped spaces)
-     *
-     * Can return null
-     *
-     * @param record current MARC record
-     * @param fieldSpec which MARC fields / subfields need to be analyzed
-     * @return Set containing normalized Dewey numbers extracted from specified fields.
-     */
-    public Set<String> getDeweySearchable(Record record, String fieldSpec) {
-        // Initialize our return value:
-        Set<String> result = new LinkedHashSet<String>();
-
-        // Loop through the specified MARC fields:
-        Set<String> input = getFieldList(record, fieldSpec);
-        Iterator<String> iter = input.iterator();
-        while (iter.hasNext()) {
-            // Get the current string to work on:
-            String current = iter.next();
-
-            // Add valid strings to the set, normalizing them to be all uppercase
-            // and free from whitespace.
-            DeweyCallNumber callNum = new DeweyCallNumber(current);
-            if (callNum.isValid()) {
-                result.add(callNum.toString().toUpperCase().replaceAll(" ", ""));
-            }
-        }
-
-        // If we found no call numbers, return null; otherwise, return our results:
-        if (result.isEmpty())
-            return null;
-        return result;
-    }
-
-    /**
-     * Normalize Dewey numbers for sorting purposes (use only the first valid number!)
-     *
-     * Can return null
-     *
-     * @param record current MARC record
-     * @param fieldSpec which MARC fields / subfields need to be analyzed
-     * @return String containing the first valid Dewey number encountered, normalized
-     *         for sorting purposes.
-     */
-    public String getDeweySortable(Record record, String fieldSpec) {
-        // Loop through the specified MARC fields:
-        Set<String> input = getFieldList(record, fieldSpec);
-        Iterator<String> iter = input.iterator();
-        while (iter.hasNext()) {
-            // Get the current string to work on:
-            String current = iter.next();
-
-            // If this is a valid Dewey number, return the sortable shelf key:
-            DeweyCallNumber callNum = new DeweyCallNumber(current);
-            if (callNum.isValid()) {
-                return callNum.getShelfKey();
-            }
-        }
-
-        // If we made it this far, we didn't find a valid sortable Dewey number:
-        return null;
-    }
-
-    /**
-     * Get sort key for first Dewey call number, identified by call type.
-     * 
-     * <p>{@code fieldSpec} is of form {@literal 098abc:099ab}, does not accept subfield ranges.
-     *
-     *
-     * @param record  current MARC record
-     * @param fieldSpec  which MARC fields / subfields need to be analyzed
-     * @param callTypeSf  subfield containing call number type, single character only
-     * @param callType  literal call number code
-     * @return sort key for first identified Dewey call number
-     */
-    public static String getDeweySortableByType(
-            Record record, String fieldSpec, String callTypeSf, String callType) {
-        String sortKey = null;
-        for (String tag : fieldSpec.split(":")) {
-            // Check to ensure tag length is at least 3 characters
-            if (tag.length() < 3) {
-                //TODO: Should this go to a log? Better message for a bad tag in a field spec?
-                System.err.println("Invalid tag specified: " + tag);
-                continue;
-            }
-            String dfTag = tag.substring(0, 3);
-            String sfSpec = null;
-            if (tag.length() > 3) {
-                    sfSpec = tag.substring(3);
-            }
-
-            // do all fields for this tag
-            for (VariableField vf : record.getVariableFields(dfTag)) {
-                // Assume tag represents a DataField
-                DataField df = (DataField) vf;
-                boolean callTypeMatch = false;
-                
-                // Assume call type subfield could repeat
-                for (Subfield typeSf : df.getSubfields(callTypeSf)) {
-                    if (callTypeSf.indexOf(typeSf.getCode()) != -1 && typeSf.getData().equals(callType)) {
-                        callTypeMatch = true;
-                    }
-                }
-                // take the first call number coded as Dewey
-                if (callTypeMatch) {
-                    sortKey = new DeweyCallNumber(df.getSubfieldsAsString(sfSpec)).getShelfKey();
-                    break;
-                }
-            } // end loop over variable fields
-        } // end loop over fieldSpec
-        return sortKey;
-    }
-
-    
-    /**
-     * Normalize Dewey numbers for AlphaBrowse sorting purposes (use all numbers!)
-     *
-     * Can return null
-     *
-     * @param record current MARC record
-     * @param fieldSpec which MARC fields / subfields need to be analyzed
-     * @return List containing normalized Dewey numbers extracted from specified fields.
-     */
-    public List<String> getDeweySortables(Record record, String fieldSpec) {
-        // Initialize our return value:
-        List<String> result = new LinkedList<String>();
-
-        // Loop through the specified MARC fields:
-        Set<String> input = getFieldList(record, fieldSpec);
-        Iterator<String> iter = input.iterator();
-        while (iter.hasNext()) {
-            // Get the current string to work on:
-            String current = iter.next();
-
-            // gather all sort keys, even if number is not valid
-            DeweyCallNumber callNum = new DeweyCallNumber(current);
-            result.add(callNum.getShelfKey());
-        }
-
-        // If we found no call numbers, return null; otherwise, return our results:
-        if (result.isEmpty())
-            return null;
-        return result;
-    }
-
-    /**
-     * The following several methods are designed to get latitude and longitude
-     * coordinates.
-     * Records can have multiple coordinates sets of points and/or rectangles.
-     * Points are represented by coordinate sets where N=S E=W.
-     *
-     * code adapted from xrosecky - Moravian Library
-     * https://github.com/moravianlibrary/VuFind-2.x/blob/master/import/index_scripts/geo.bsh
-     * and incorporates VuFind location.bsh functionality for GoogleMap display.
-     */
-
-    /**
-     * Convert MARC coordinates into location_geo format.
-     *
-     * @param  Record record
-     * @return List   geo_coordinates
-     */
-    public List<String> getAllCoordinates(Record record) {
-        List<String> geo_coordinates = new ArrayList<String>();
-        List<VariableField> list034 = record.getVariableFields("034");
-        if (list034 != null) {
-            for (VariableField vf : list034) {
-                DataField df = (DataField) vf;
-                String d = df.getSubfield('d').getData();
-                String e = df.getSubfield('e').getData();
-                String f = df.getSubfield('f').getData();
-                String g = df.getSubfield('g').getData();
-                //System.out.println("raw Coords: "+d+" "+e+" "+f+" "+g);
-
-                // Check to see if there are only 2 coordinates
-                // If so, copy them into the corresponding coordinate fields
-                if ((d !=null && (e == null || e.trim().equals(""))) && (f != null && (g==null || g.trim().equals("")))) {
-                    e = d;
-                    g = f;
-                }
-                if ((e !=null && (d == null || d.trim().equals(""))) && (g != null && (f==null || f.trim().equals("")))) {
-                    d = e;
-                    f = g;
-                }
-
-                // Check and convert coordinates to +/- decimal degrees
-                Double west = convertCoordinate(d);
-                Double east = convertCoordinate(e);
-                Double north = convertCoordinate(f);
-                Double south = convertCoordinate(g);
-
-                // New Format for indexing coordinates in Solr 5.0 - minX, maxX, maxY, minY
-                // Note - storage in Solr follows the WENS order, but display is WSEN order
-                String result = String.format("ENVELOPE(%s,%s,%s,%s)", new Object[] { west, east, north, south });
-
-                if (validateCoordinates(west, east, north, south)) {
-                    geo_coordinates.add(result);
-                }
-            }
-        }
-        return geo_coordinates;
-    }
-
-    /**
-     * Get point coordinates for GoogleMap display.
-     *
-     * @param  Record record
-     * @return List   coordinates
-     */
-    public List<String> getPointCoordinates(Record record) {
-        List<String> coordinates = new ArrayList<String>();
-        List<VariableField> list034 = record.getVariableFields("034");
-        if (list034 != null) {
-            for (VariableField vf : list034) {
-                DataField df = (DataField) vf;
-                String d = df.getSubfield('d').getData();
-                String e = df.getSubfield('e').getData();
-                String f = df.getSubfield('f').getData();
-                String g = df.getSubfield('g').getData();
-
-                // Check to see if there are only 2 coordinates
-                if ((d !=null && (e == null || e.trim().equals(""))) && (f != null && (g==null || g.trim().equals("")))) {
-                    Double long_val = convertCoordinate(d);
-                    Double lat_val = convertCoordinate(f);
-                    String longlatCoordinate = Double.toString(long_val) + ',' + Double.toString(lat_val);
-                    coordinates.add(longlatCoordinate);
-                }
-                if ((e !=null && (d == null || d.trim().equals(""))) && (g != null && (f==null || f.trim().equals("")))) {
-                    Double long_val = convertCoordinate(e);
-                    Double lat_val = convertCoordinate(g);
-                    String longlatCoordinate = Double.toString(long_val) + ',' + Double.toString(lat_val);
-                    coordinates.add(longlatCoordinate);
-                }
-                // Check if N=S and E=W
-                if (d.equals(e) && f.equals(g)) {
-                    Double long_val = convertCoordinate(d);
-                    Double lat_val = convertCoordinate(f);
-                    String longlatCoordinate = Double.toString(long_val) + ',' + Double.toString(lat_val);
-                    coordinates.add(longlatCoordinate);
-                }
-            }
-        }
-        return coordinates;
-    }
-
-    /**
-     * Get all available coordinates from the record.
-     *
-     * @param  Record record
-     * @return List   geo_coordinates
-     */
-    public List<String> getDisplayCoordinates(Record record) {
-        List<String> geo_coordinates = new ArrayList<String>();
-        List<VariableField> list034 = record.getVariableFields("034");
-        if (list034 != null) {
-            for (VariableField vf : list034) {
-                DataField df = (DataField) vf;
-                String west = df.getSubfield('d').getData();
-                String east = df.getSubfield('e').getData();
-                String north = df.getSubfield('f').getData();
-                String south = df.getSubfield('g').getData();
-                String result = String.format("%s %s %s %s", new Object[] { west, east, north, south });
-                if (west != null || east != null || north != null || south != null) {
-                    geo_coordinates.add(result);
-                }
-            }
-        }
-        return geo_coordinates;
-    }
-
-    /**
-     * Check coordinate type HDMS HDD or +/-DD.
-     *
-     * @param  String coordinateStr
-     * @return Double coordinate
-     */
-    protected Double convertCoordinate(String coordinateStr) {
-        Double coordinate = Double.NaN;
-        Matcher HDmatcher = HDMSHDD_PATTERN.matcher(coordinateStr);
-        Matcher PMDmatcher = PMDD_PATTERN.matcher(coordinateStr);
-        if (HDmatcher.matches()) {
-            String hemisphere = HDmatcher.group(1).toUpperCase();
-            Double degrees = Double.parseDouble(HDmatcher.group(2));
-            // Check for HDD or HDMS
-            if (hemisphere.equals("N") || hemisphere.equals("S")) {
-                if (degrees > 90) {
-                    String hdmsCoordinate = hemisphere+"0"+HDmatcher.group(2);
-                    coordinate = coordinateToDecimal(hdmsCoordinate);
-                } else {
-                    coordinate = Double.parseDouble(HDmatcher.group(2));
-                    if (hemisphere.equals("S")) {
-                        coordinate *= -1;
-                    }
-                }
-            }
-            if (hemisphere.equals("E") || hemisphere.equals("W")) {
-                if (degrees > 180) {
-                    String hdmsCoordinate = HDmatcher.group(0);
-                    coordinate = coordinateToDecimal(hdmsCoordinate);
-                } else {
-                    coordinate = Double.parseDouble(HDmatcher.group(2));
-                    if (hemisphere.equals("W")) {
-                        coordinate *= -1;
-                    }
-                }
-            }
-            return coordinate;
-        } else if (PMDmatcher.matches()) {
-            String hemisphere = PMDmatcher.group(1);
-            coordinate = Double.parseDouble(PMDmatcher.group(2));
-            if (hemisphere.equals("-")) {
-                coordinate *= -1;
-            }
-            return coordinate;
-        } else {
-            return null;
-        }
-    }
-
-    /**
-     * Convert HDMS coordinates to decimal degrees.
-     *
-     * @param  String coordinateStr
-     * @return Double coordinate
-     */
-    protected Double coordinateToDecimal(String coordinateStr) {
-        Matcher matcher = COORDINATES_PATTERN.matcher(coordinateStr);
-        if (matcher.matches()) {
-            String hemisphere = matcher.group(1).toUpperCase();
-            int degrees = Integer.parseInt(matcher.group(2));
-            int minutes = Integer.parseInt(matcher.group(3));
-            int seconds = Integer.parseInt(matcher.group(4));
-            double coordinate = degrees + (minutes / 60.0) + (seconds / 3600.0);
-            if (hemisphere.equals("W") || hemisphere.equals("S")) {
-                coordinate *= -1;
-            }
-            return coordinate;
-        }
-        return null;
-    }
-
-    /**
-     * Check decimal degree coordinates to make sure they are valid.
-     *
-     * @param  Double west, east, north, south
-     * @return boolean
-     */
-    protected boolean validateCoordinates(Double west, Double east, Double north, Double south) {
-        if (west == null || east == null || north == null || south == null) {
-            return false;
-        }
-        if (west > 180.0 || west < -180.0 || east > 180.0 || east < -180.0) {
-            return false;
-        }
-        if (north > 90.0 || north < -90.0 || south > 90.0 || south < -90.0) {
-            return false;
-        }
-        if (north < south || west > east) {
-            return false;
-        }
-        return true;
-    }
-
-    /**
-     * THIS FUNCTION HAS BEEN DEPRECATED.
-     * Determine the longitude and latitude of the items location.
-     *
-     * @param  record current MARC record
-     * @return string of form "longitude, latitude"
-     */
-    public String getLongLat(Record record) {
-        // Check 034 subfield d and f
-        List<VariableField> fields = record.getVariableFields("034");
-        Iterator<VariableField> fieldsIter = fields.iterator();
-        if (fields != null) {
-            DataField physical;
-            while(fieldsIter.hasNext()) {
-                physical = (DataField) fieldsIter.next();
-                String val = null;
-
-                List<Subfield> subfields_d = physical.getSubfields('d');
-                Iterator<Subfield> subfieldsIter_d = subfields_d.iterator();
-                if (subfields_d != null) {
-                    while (subfieldsIter_d.hasNext()) {
-                        val = subfieldsIter_d.next().getData().trim();
-                        if (!val.matches("-?\\d+(.\\d+)?")) {
-                            return null;
-                        }
-                    }
-                }
-                List<Subfield> subfields_f = physical.getSubfields('f');
-                Iterator<Subfield> subfieldsIter_f = subfields_f.iterator();
-                if (subfields_f != null) {
-                    while (subfieldsIter_f.hasNext()) {
-                        String val2 = subfieldsIter_f.next().getData().trim();
-                        if (!val2.matches("-?\\d+(.\\d+)?")) {
-                            return null;
-                        }
-                        val = val + ',' + val2;
-                    }
-                }
-                return val;
-            }
-        }
-        //otherwise return null
-        return null;
-    }
-
-    /**
-     * Update the index date in the database for the specified core/ID pair.  We
-     * maintain a database of "first/last indexed" times separately from Solr to
-     * allow the history of our indexing activity to be stored permanently in a
-     * fashion that can survive even a total Solr rebuild.
-     */
-    public UpdateDateTracker updateTracker(String core, String id, java.util.Date latestTransaction)
-    {
-        // Update the database (if necessary):
-        try {
-            // Initialize date tracker if not already initialized:
-            loadUpdateDateTracker();
-
-            tracker.index(core, id, latestTransaction);
-        } catch (java.sql.SQLException e) {
-            // If we're in the process of shutting down, an error is expected:
-            if (!shuttingDown) {
-                dieWithError("Unexpected database error");
-            }
-        }
-
-        // Send back the tracker object so the caller can use it (helpful for
-        // use in BeanShell scripts).
-        return tracker;
-    }
-
-    /**
-     * Get the "first indexed" date for the current record.  (This is the first
-     * time that SolrMarc ever encountered this particular record).
-     *
-     * @param record current MARC record
-     * @param fieldSpec fields / subfields to be analyzed
-     * @param core core name
-     * @return ID string
-     */
-    public String getFirstIndexed(Record record, String fieldSpec, String core) {
-        // Update the database, then send back the first indexed date:
-        updateTracker(core, getFirstFieldVal(record, fieldSpec), getLatestTransaction(record));
-        return tracker.getFirstIndexed();
-    }
-
-    /**
-     * Get the "first indexed" date for the current record.  (This is the first
-     * time that SolrMarc ever encountered this particular record).
-     *
-     * @param record current MARC record
-     * @param fieldSpec fields / subfields to be analyzed
-     * @return ID string
-     */
-    public String getFirstIndexed(Record record, String fieldSpec) {
-        return getFirstIndexed(record, fieldSpec, "biblio");
-    }
-
-    /**
-     * Get the "first indexed" date for the current record.  (This is the first
-     * time that SolrMarc ever encountered this particular record).
-     *
-     * @param record current MARC record
-     * @return ID string
-     */
-    public String getFirstIndexed(Record record) {
-        return getFirstIndexed(record, "001", "biblio");
-    }
-
-    /**
-     * Get the "last indexed" date for the current record.  (This is the last time
-     * the record changed from SolrMarc's perspective).
-     *
-     * @param record current MARC record
-     * @param fieldSpec fields / subfields to be analyzed
-     * @param core core name
-     * @return ID string
-     */
-    public String getLastIndexed(Record record, String fieldSpec, String core) {
-        // Update the database, then send back the last indexed date:
-        updateTracker(core, getFirstFieldVal(record, fieldSpec), getLatestTransaction(record));
-        return tracker.getLastIndexed();
-    }
-
-    /**
-     * Get the "last indexed" date for the current record.  (This is the last time
-     * the record changed from SolrMarc's perspective).
-     *
-     * @param record current MARC record
-     * @param fieldSpec fields / subfields to analyze
-     * @return ID string
-     */
-    public String getLastIndexed(Record record, String fieldSpec) {
-        return getLastIndexed(record, fieldSpec, "biblio");
-    }
-
-    /**
-     * Get the "last indexed" date for the current record.  (This is the last time
-     * the record changed from SolrMarc's perspective).
-     *
-     * @param record current MARC record
-     * @return ID string
-     */
-    public String getLastIndexed(Record record) {
-        return getLastIndexed(record, "001", "biblio");
-    }
-
-    /**
-     * Load configurations for the full text parser.  Return an array containing the
-     * parser type in the first element and the parser configuration in the second
-     * element.
-     *
-     * @return String[]
-     */
-    public String[] getFulltextParserSettings()
-    {
-        String parserType = getConfigSetting(
-            "fulltext.ini", "General", "parser"
-        );
-        if (null != parserType) {
-            parserType = parserType.toLowerCase();
-        }
-
-        // Is Aperture active?
-        String aperturePath = getConfigSetting(
-            "fulltext.ini", "Aperture", "webcrawler"
-        );
-        if ((null == parserType && null != aperturePath)
-            || (null != parserType && parserType.equals("aperture"))
-        ) {
-            String[] array = { "aperture", aperturePath };
-            return array;
-        }
-
-        // Is Tika active?
-        String tikaPath = getConfigSetting(
-            "fulltext.ini", "Tika", "path"
-        );
-        if ((null == parserType && null != tikaPath)
-            || (null != parserType && parserType.equals("tika"))
-        ) {
-            String[] array = { "tika", tikaPath };
-            return array;
-        }
-
-        // No recognized parser found:
-        String[] array = { "none", null };
-        return array;
-    }
-
-    /**
-     * Extract full-text from the documents referenced in the tags
-     *
-     * @param Record record current MARC record
-     * @param String field spec to search for URLs
-     * @param String only harvest files matching this extension (null for all)
-     * @return String The full-text
-     */
-    public String getFulltext(Record record, String fieldSpec, String extension) {
-        String result = "";
-
-        // Get the web crawler settings (and return no text if it is unavailable)
-        String[] parserSettings = getFulltextParserSettings();
-        if (parserSettings[0].equals("none")) {
-            return null;
-        }
-
-        // Loop through the specified MARC fields:
-        Set<String> fields = getFieldList(record, fieldSpec);
-        Iterator<String> fieldsIter = fields.iterator();
-        if (fields != null) {
-            while(fieldsIter.hasNext()) {
-                // Get the current string to work on (and sanitize spaces):
-                String current = fieldsIter.next().replaceAll(" ", "%20");
-                // Filter by file extension
-                if (extension == null || current.endsWith(extension)) {
-                    // Load the parser output for each tag into a string
-                    result = result + harvestWithParser(current, parserSettings);
-                }
-            }
-        }
-        // return string to SolrMarc
-        return result;
-    }
-
-    /**
-     * Extract full-text from the documents referenced in the tags
-     *
-     * @param Record record current MARC record
-     * @param String field spec to search for URLs
-     * @return String The full-text
-     */
-    public String getFulltext(Record record, String fieldSpec) {
-        return getFulltext(record, fieldSpec, null);
-    }
-
-    /**
-     * Extract full-text from the documents referenced in the tags
-     *
-     * @param Record record current MARC record
-     * @return String The full-text
-     */
-    public String getFulltext(Record record) {
-        return getFulltext(record, "856u", null);
-    }
-
-    /**
-     * Clean up XML data generated by Aperture
-     *
-     * @param f file to clean
-     * @return a fixed version of the file
-     */
-    public File sanitizeApertureOutput(File f) throws IOException
-    {
-        //clean up the aperture xml output
-        File tempFile = File.createTempFile("buffer", ".tmp");
-        FileOutputStream fw = new FileOutputStream(tempFile);
-        OutputStreamWriter writer = new OutputStreamWriter(fw, "UTF8");
-
-        //delete this control character from the File and save
-        FileReader fr = new FileReader(f);
-        BufferedReader br = new BufferedReader(fr);
-        while (br.ready()) {
-            writer.write(sanitizeFullText(br.readLine()));
-        }
-        writer.close();
-        br.close();
-        fr.close();
-
-        return tempFile;
-    }
-
-    /**
-     * Clean up bad characters in the full text.
-     *
-     * @param text text to clean
-     * @return cleaned text
-     */
-    public String sanitizeFullText(String text)
-    {
-        String badChars = "[^\\u0009\\u000A\\u000D\\u0020-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]+";
-        return text.replaceAll(badChars, " ");
-    }
-
-    /**
-     * Harvest the contents of a document file (PDF, Word, etc.) using Aperture.
-     * This method will only work if Aperture is properly configured in the
-     * fulltext.ini file.  Without proper configuration, this will simply return an
-     * empty string.
-     *
-     * @param url the url extracted from the MARC tag.
-     * @param aperturePath The path to Aperture
-     * @return full-text extracted from url
-     */
-    public String harvestWithAperture(String url, String aperturePath) {
-        String plainText = "";
-        // Create temp file.
-        File f = null;
-        try {
-            f = File.createTempFile("apt", ".txt");
-        } catch (Throwable e) {
-            dieWithError("Unable to create temporary file for full text harvest.");
-        }
-
-        // Delete temp file when program exits.
-        f.deleteOnExit();
-
-        // Construct the command to call Aperture
-        String cmd = aperturePath + " -o " + f.getAbsolutePath().toString()  + " -x " + url;
-
-        // Call Aperture
-        //System.out.println("Loading fulltext from " + url + ". Please wait ...");
-        try {
-            Process p = Runtime.getRuntime().exec(cmd);
-            
-            // Debugging output
-            /*
-            BufferedReader stdInput = new BufferedReader(new
-                InputStreamReader(p.getInputStream()));
-            String s;
-            while ((s = stdInput.readLine()) != null) {
-                System.out.println(s);
-            }
-            */
-            
-            // Wait for Aperture to finish
-            p.waitFor();
-        } catch (Throwable e) {
-            logger.error("Problem executing Aperture -- " + e.getMessage());
-        }
-
-        // Parse Aperture XML output
-        Document xmlDoc = null;
-        try {
-            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
-            DocumentBuilder db = dbf.newDocumentBuilder();
-            File tempFile = sanitizeApertureOutput(f);
-            xmlDoc = db.parse(tempFile);
-            NodeList nl = xmlDoc.getElementsByTagName("plainTextContent");
-            if(nl != null && nl.getLength() > 0) {
-                Node node = nl.item(0);
-                if (node.getNodeType() == Node.ELEMENT_NODE) {
-                    plainText = plainText + node.getTextContent();
-                }
-            }
-
-            // we'll hold onto the temp file if it failed to parse for debugging;
-            // only set it up to be deleted if we've made it this far successfully.
-            tempFile.deleteOnExit();
-        } catch (Throwable e) {
-            logger.error("Problem parsing Aperture XML -- " + e.getMessage());
-        }
-
-        return plainText;
-    }
-
-    /**
-     * Harvest the contents of a document file (PDF, Word, etc.) using Tika.
-     * This method will only work if Tika is properly configured in the fulltext.ini
-     * file.  Without proper configuration, this will simply return an empty string.
-     *
-     * @param url the url extracted from the MARC tag.
-     * @param scraperPath path to Tika
-     * @return the full-text
-     */
-    public String harvestWithTika(String url, String scraperPath) {
-
-        // Construct the command
-        String cmd = "java -jar " + scraperPath + " -t -eUTF8 " + url;
-
-        StringBuilder stringBuilder= new StringBuilder();
-
-        // Call our scraper
-        //System.out.println("Loading fulltext from " + url + ". Please wait ...");
-        try {
-            Process p = Runtime.getRuntime().exec(cmd);
-            BufferedReader stdInput = new BufferedReader(new
-                InputStreamReader(p.getInputStream(), "UTF8"));
-
-            // We'll build the string from the command output
-            String s;
-            while ((s = stdInput.readLine()) != null) {
-                stringBuilder.append(s);
-            }
-        } catch (Throwable e) {
-            logger.error("Problem with Tika -- " + e.getMessage());
-        }
-
-        return sanitizeFullText(stringBuilder.toString());
-    }
-
-    /**
-     * Harvest the contents of a document file (PDF, Word, etc.) using the active parser.
-     *
-     * @param url the URL extracted from the MARC tag.
-     * @param settings configuration settings from {@code getFulltextParserSettings}.
-     * @return the full-text
-     */
-    public String harvestWithParser(String url, String[] settings) {
-        if (settings[0].equals("aperture")) {
-            return harvestWithAperture(url, settings[1]);
-        } else if (settings[0].equals("tika")) {
-            return harvestWithTika(url, settings[1]);
-        }
-        return null;
-    }
-
-    /**
-     * Get access to the Logger object.
-     *
-     * @return Logger
-     */
-    public Logger getLogger()
-    {
-        return logger;
-    }
-
-    /**
-     * Extract all valid relator terms from a list of subfields using a whitelist.
-     * @param subfields        List of subfields to check
-     * @param permittedRoles   Whitelist to check against
-     * @param indexRawRelators Should we index relators raw, as found
-     * in the MARC (true) or index mapped versions (false)?
-     * @return Set of valid relator terms
-     */
-    public Set<String> getValidRelatorsFromSubfields(List<Subfield> subfields, List<String> permittedRoles, Boolean indexRawRelators)
-    {
-        Set<String> relators = new LinkedHashSet<String>();
-        for (int j = 0; j < subfields.size(); j++) {
-            String raw = subfields.get(j).getData();
-            String current = normalizeRelatorString(raw);
-            if (permittedRoles.contains(current)) {
-                relators.add(indexRawRelators ? raw : mapRelatorStringToCode(current));
-            }
-        }
-        return relators;
-    }
-
-    /**
-     * Is this relator term unknown to author-classification.ini?
-     * @param current relator to check
-     * @return True if unknown
-     */
-    public Boolean isUnknownRelator(String current)
-    {
-        // If we haven't loaded known relators yet, do so now:
-        if (knownRelators.size() == 0) {
-            Map<String, String> all = getConfigSection("author-classification.ini", "RelatorSynonyms");
-            for (String key : all.keySet()) {
-                knownRelators.add(normalizeRelatorString(key));
-                for (String synonym: all.get(key).split("\\|")) {
-                    knownRelators.add(normalizeRelatorString(synonym));
-                }
-            }
-        }
-        return !knownRelators.contains(normalizeRelatorString(current));
-    }
-
-    /**
-     * Extract all valid relator terms from a list of subfields using a whitelist.
-     * @param subfields      List of subfields to check
-     * @return Set of valid relator terms
-     */
-    public Set<String> getUnknownRelatorsFromSubfields(List<Subfield> subfields)
-    {
-        Set<String> relators = new LinkedHashSet<String>();
-        for (int j = 0; j < subfields.size(); j++) {
-            String current = subfields.get(j).getData().trim();
-            if (current.length() > 0 && isUnknownRelator(current)) {
-                logger.info("Unknown relator: " + current);
-                relators.add(current);
-            }
-        }
-        return relators;
-    }
-
-    /**
-     * Extract all values that meet the specified relator requirements.
-     * @param authorField           Field to analyze
-     * @param noRelatorAllowed      Array of tag names which are allowed to be used with
-     * no declared relator.
-     * @param relatorConfig         The setting in author-classification.ini which
-     * defines which relator terms are acceptable (or a colon-delimited list)
-     * @param unknownRelatorAllowed Array of tag names whose relators should be indexed 
-     * even if they are not listed in author-classification.ini.
-     * @param indexRawRelators      Set to "true" to index relators raw, as found
-     * in the MARC or "false" to index mapped versions.
-     * @return Set
-     */
-    public Set<String> getValidRelators(DataField authorField,
-        String[] noRelatorAllowed, String relatorConfig,
-        String[] unknownRelatorAllowed, String indexRawRelators
-    ) {
-        // get tag number from Field
-        String tag = authorField.getTag();
-        List<Subfield> subfieldE = authorField.getSubfields('e');
-        List<Subfield> subfield4 = authorField.getSubfields('4');
-
-        Set<String> relators = new LinkedHashSet<String>();
-
-        // if no relator is found, check to see if the current tag is in the "no
-        // relator allowed" list.
-        if (subfieldE.size() == 0 && subfield4.size() == 0) {
-            if (Arrays.asList(noRelatorAllowed).contains(tag)) {
-                relators.add("");
-            }
-        } else {
-            // If we got this far, we need to figure out what type of relation they have
-            List permittedRoles = normalizeRelatorStringList(Arrays.asList(loadRelatorConfig(relatorConfig)));
-            relators.addAll(getValidRelatorsFromSubfields(subfieldE, permittedRoles, indexRawRelators.toLowerCase().equals("true")));
-            relators.addAll(getValidRelatorsFromSubfields(subfield4, permittedRoles, indexRawRelators.toLowerCase().equals("true")));
-            if (Arrays.asList(unknownRelatorAllowed).contains(tag)) {
-                Set<String> unknown = getUnknownRelatorsFromSubfields(subfieldE);
-                if (unknown.size() == 0) {
-                    unknown = getUnknownRelatorsFromSubfields(subfield4);
-                }
-                relators.addAll(unknown);
-            }
-        }
-        return relators;
-    }
-
-    /**
-     * Parse a SolrMarc fieldspec into a map of tag name to set of subfield strings
-     * (note that we need to map to a set rather than a single string, because the
-     * same tag may repeat with different subfields to extract different sections
-     * of the same field into distinct values).
-     *
-     * @param tagList The field specification to parse
-     * @return HashMap
-     */
-    protected HashMap<String, Set<String>> getParsedTagList(String tagList)
-    {
-        String[] tags = tagList.split(":");//convert string input to array
-        HashMap<String, Set<String>> tagMap = new HashMap<String, Set<String>>();
-        //cut tags array up into key/value pairs in hash map
-        Set<String> currentSet;
-        for(int i = 0; i < tags.length; i++){
-            String tag = tags[i].substring(0, 3);
-            if (!tagMap.containsKey(tag)) {
-                currentSet = new LinkedHashSet<String>();
-                tagMap.put(tag, currentSet);
-            } else {
-                currentSet = tagMap.get(tag);
-            }
-            currentSet.add(tags[i].substring(3));
-        }
-        return tagMap;
-    }
-
-    /**
-     * Filter values retrieved using tagList to include only those whose relator
-     * values are acceptable. Used for separating different types of authors.
-     *
-     * @param record               The record (fed in automatically)
-     * @param tagList              The field specification to read
-     * @param acceptWithoutRelator Colon-delimited list of tags whose values should
-     * be accepted even if no relator subfield is defined
-     * @param relatorConfig        The setting in author-classification.ini which
-     * defines which relator terms are acceptable (or a colon-delimited list)
-     * @param acceptUnknownRelators Colon-delimited list of tags whose relators
-     * should be indexed even if they are not listed in author-classification.ini.
-     * @param indexRawRelators      Set to "true" to index relators raw, as found
-     * in the MARC or "false" to index mapped versions.
-     * @param firstOnly            Return first result only?
-     * @return List result
-     */
-    public List<String> getAuthorsFilteredByRelator(Record record, String tagList,
-        String acceptWithoutRelator, String relatorConfig,
-        String acceptUnknownRelators, String indexRawRelators, Boolean firstOnly
-    ) {
-        List<String> result = new LinkedList<String>();
-        String[] noRelatorAllowed = acceptWithoutRelator.split(":");
-        String[] unknownRelatorAllowed = acceptUnknownRelators.split(":");
-        HashMap<String, Set<String>> parsedTagList = getParsedTagList(tagList);
-        List fields = getFieldSetMatchingTagList(record, tagList);
-        Iterator fieldsIter = fields.iterator();
-        if (fields != null){
-            DataField authorField;
-            while (fieldsIter.hasNext()){
-                authorField = (DataField) fieldsIter.next();
-                // add all author types to the result set; if we have multiple relators, repeat the authors
-                for (String iterator: getValidRelators(authorField, noRelatorAllowed, relatorConfig, unknownRelatorAllowed, indexRawRelators)) {
-                    for (String subfields : parsedTagList.get(authorField.getTag())) {
-                        String current = getDataFromVariableField(authorField, "["+subfields+"]", " ", false);
-                        // TODO: we may eventually be able to use this line instead,
-                        // but right now it's not handling separation between the
-                        // subfields correctly, so it's commented out until that is
-                        // fixed.
-                        //String current = authorField.getSubfieldsAsString(subfields);
-                        if (null != current) {
-                            result.add(current);
-                            if (firstOnly) {
-                                return result;
-                            }
-                        }
-                    }
-                }
-            }
-        }
-        return result;
-    }
-
-    /**
-     * Filter values retrieved using tagList to include only those whose relator
-     * values are acceptable. Used for separating different types of authors.
-     *
-     * @param record               The record (fed in automatically)
-     * @param tagList              The field specification to read
-     * @param acceptWithoutRelator Colon-delimited list of tags whose values should
-     * be accepted even if no relator subfield is defined
-     * @param relatorConfig        The setting in author-classification.ini which
-     * defines which relator terms are acceptable (or a colon-delimited list)
-     * @return List result
-     */
-    public List<String> getAuthorsFilteredByRelator(Record record, String tagList,
-        String acceptWithoutRelator, String relatorConfig
-    ) {
-        // default firstOnly to false!
-        return getAuthorsFilteredByRelator(
-            record, tagList, acceptWithoutRelator, relatorConfig,
-            acceptWithoutRelator, "false", false
-        );
-    }
-
-    /**
-     * Filter values retrieved using tagList to include only those whose relator
-     * values are acceptable. Used for separating different types of authors.
-     *
-     * @param record               The record (fed in automatically)
-     * @param tagList              The field specification to read
-     * @param acceptWithoutRelator Colon-delimited list of tags whose values should
-     * be accepted even if no relator subfield is defined
-     * @param relatorConfig        The setting in author-classification.ini which
-     * defines which relator terms are acceptable (or a colon-delimited list)
-     * @return List result
-     * @param acceptUnknownRelators Colon-delimited list of tags whose relators
-     * should be indexed even if they are not listed in author-classification.ini.
-     */
-    public List<String> getAuthorsFilteredByRelator(Record record, String tagList,
-        String acceptWithoutRelator, String relatorConfig,
-        String acceptUnknownRelators
-    ) {
-        // default firstOnly to false!
-        return getAuthorsFilteredByRelator(
-            record, tagList, acceptWithoutRelator, relatorConfig,
-            acceptUnknownRelators, "false", false
-        );
-    }
-
-    /**
-     * Filter values retrieved using tagList to include only those whose relator
-     * values are acceptable. Used for separating different types of authors.
-     *
-     * @param record               The record (fed in automatically)
-     * @param tagList              The field specification to read
-     * @param acceptWithoutRelator Colon-delimited list of tags whose values should
-     * be accepted even if no relator subfield is defined
-     * @param relatorConfig        The setting in author-classification.ini which
-     * defines which relator terms are acceptable (or a colon-delimited list)
-     * @return List result
-     * @param acceptUnknownRelators Colon-delimited list of tags whose relators
-     * should be indexed even if they are not listed in author-classification.ini.
-     * @param indexRawRelators      Set to "true" to index relators raw, as found
-     * in the MARC or "false" to index mapped versions.
-     */
-    public List<String> getAuthorsFilteredByRelator(Record record, String tagList,
-        String acceptWithoutRelator, String relatorConfig,
-        String acceptUnknownRelators, String indexRawRelators
-    ) {
-        // default firstOnly to false!
-        return getAuthorsFilteredByRelator(
-            record, tagList, acceptWithoutRelator, relatorConfig,
-            acceptUnknownRelators, indexRawRelators, false
-        );
-    }
-
-    /**
-     * If the provided relator is included in the synonym list, convert it back to
-     * a code (for better standardization/translation).
-     *
-     * @param relator Relator code to check
-     * @return Code version, if found, or raw string if no match found.
-     */
-    public String mapRelatorStringToCode(String relator)
-    {
-        String normalizedRelator = normalizeRelatorString(relator);
-        return relatorSynonymLookup.containsKey(normalizedRelator)
-            ? relatorSynonymLookup.get(normalizedRelator) : relator;
-    }
-
-    /**
-     * Filter values retrieved using tagList to include only those whose relator
-     * values are acceptable. Used for separating different types of authors.
-     *
-     * @param record                The record (fed in automatically)
-     * @param tagList               The field specification to read
-     * @param acceptWithoutRelator  Colon-delimited list of tags whose values should
-     * be accepted even if no relator subfield is defined
-     * @param relatorConfig         The setting in author-classification.ini which
-     * defines which relator terms  are acceptable (or a colon-delimited list)
-     * @param acceptUnknownRelators Colon-delimited list of tags whose relators
-     * should be indexed even if they are not listed in author-classification.ini.
-     * @param indexRawRelators      Set to "true" to index relators raw, as found
-     * in the MARC or "false" to index mapped versions.
-     * @return String
-     */
-    public String getFirstAuthorFilteredByRelator(Record record, String tagList,
-        String acceptWithoutRelator, String relatorConfig,
-        String acceptUnknownRelators, String indexRawRelators
-    ) {
-        List<String> result = getAuthorsFilteredByRelator(
-            record, tagList, acceptWithoutRelator, relatorConfig,
-            acceptUnknownRelators, indexRawRelators, true
-        );
-        for (String s : result) {
-            return s;
-        }
-        return null;
-    }
-
-    /**
-     * Filter values retrieved using tagList to include only those whose relator
-     * values are acceptable. Used for separating different types of authors.
-     *
-     * @param record                The record (fed in automatically)
-     * @param tagList               The field specification to read
-     * @param acceptWithoutRelator  Colon-delimited list of tags whose values should
-     * be accepted even if no relator subfield is defined
-     * @param relatorConfig         The setting in author-classification.ini which
-     * defines which relator terms  are acceptable (or a colon-delimited list)
-     * @return String
-     */
-    public String getFirstAuthorFilteredByRelator(Record record, String tagList,
-        String acceptWithoutRelator, String relatorConfig
-    ) {
-        return getFirstAuthorFilteredByRelator(
-            record, tagList, acceptWithoutRelator, relatorConfig,
-            acceptWithoutRelator, "false"
-        );
-    }
-
-    /**
-     * Filter values retrieved using tagList to include only those whose relator
-     * values are acceptable. Used for separating different types of authors.
-     *
-     * @param record                The record (fed in automatically)
-     * @param tagList               The field specification to read
-     * @param acceptWithoutRelator  Colon-delimited list of tags whose values should
-     * be accepted even if no relator subfield is defined
-     * @param relatorConfig         The setting in author-classification.ini which
-     * defines which relator terms  are acceptable (or a colon-delimited list)
-     * @param acceptUnknownRelators Colon-delimited list of tags whose relators
-     * should be indexed even if they are not listed in author-classification.ini.
-     * @return String
-     */
-    public String getFirstAuthorFilteredByRelator(Record record, String tagList,
-        String acceptWithoutRelator, String relatorConfig,
-        String acceptUnknownRelators
-    ) {
-        return getFirstAuthorFilteredByRelator(
-            record, tagList, acceptWithoutRelator, relatorConfig,
-            acceptUnknownRelators, "false"
-        );
-    }
-
-    /**
-     * Filter values retrieved using tagList to include only those whose relator
-     * values are acceptable. Used for saving relators of authors separated by different
-     * types.
-     *
-     * @param record               The record (fed in automatically)
-     * @param tagList              The field specification to read
-     * @param acceptWithoutRelator Colon-delimited list of tags whose values should
-     * be accepted even if no relator subfield is defined
-     * @param relatorConfig        The setting in author-classification.ini which
-     * defines which relator terms are acceptable (or a colon-delimited list)
-     * @param acceptUnknownRelators Colon-delimited list of tags whose relators
-     * should be indexed even if they are not listed in author-classification.ini.
-     * @param indexRawRelators      Set to "true" to index relators raw, as found
-     * in the MARC or "false" to index mapped versions.
-     * @param firstOnly            Return first result only?
-     * @return List result
-     */
-    public List getRelatorsFilteredByRelator(Record record, String tagList,
-        String acceptWithoutRelator, String relatorConfig,
-        String acceptUnknownRelators, String indexRawRelators, Boolean firstOnly
-    ) {
-        List result = new LinkedList();
-        String[] noRelatorAllowed = acceptWithoutRelator.split(":");
-        String[] unknownRelatorAllowed = acceptUnknownRelators.split(":");
-        HashMap<String, Set<String>> parsedTagList = getParsedTagList(tagList);
-        List fields = getFieldSetMatchingTagList(record, tagList);
-        Iterator fieldsIter = fields.iterator();
-        if (fields != null){
-            DataField authorField;
-            while (fieldsIter.hasNext()){
-                authorField = (DataField) fieldsIter.next();
-                //add all author types to the result set
-                result.addAll(getValidRelators(authorField, noRelatorAllowed, relatorConfig, unknownRelatorAllowed, indexRawRelators));
-            }
-        }
-        return result;
-    }
-
-    /**
-     * Filter values retrieved using tagList to include only those whose relator
-     * values are acceptable. Used for saving relators of authors separated by different
-     * types.
-     *
-     * @param record               The record (fed in automatically)
-     * @param tagList              The field specification to read
-     * @param acceptWithoutRelator Colon-delimited list of tags whose values should
-     * be accepted even if no relator subfield is defined
-     * @param relatorConfig        The setting in author-classification.ini which
-     * defines which relator terms are acceptable (or a colon-delimited list)
-     * @param acceptUnknownRelators Colon-delimited list of tags whose relators
-     * should be indexed even if they are not listed in author-classification.ini.
-     * @param indexRawRelators      Set to "true" to index relators raw, as found
-     * in the MARC or "false" to index mapped versions.
-     * @return List result
-     */
-    public List getRelatorsFilteredByRelator(Record record, String tagList,
-        String acceptWithoutRelator, String relatorConfig,
-        String acceptUnknownRelators, String indexRawRelators
-    ) {
-        // default firstOnly to false!
-        return getRelatorsFilteredByRelator(
-            record, tagList, acceptWithoutRelator, relatorConfig,
-            acceptUnknownRelators, indexRawRelators, false
-        );
-    }
-
-    /**
-     * Filter values retrieved using tagList to include only those whose relator
-     * values are acceptable. Used for saving relators of authors separated by different
-     * types.
-     *
-     * @param record               The record (fed in automatically)
-     * @param tagList              The field specification to read
-     * @param acceptWithoutRelator Colon-delimited list of tags whose values should
-     * be accepted even if no relator subfield is defined
-     * @param relatorConfig        The setting in author-classification.ini which
-     * defines which relator terms are acceptable (or a colon-delimited list)
-     * @param acceptUnknownRelators Colon-delimited list of tags whose relators
-     * should be indexed even if they are not listed in author-classification.ini.
-     * @return List result
-     */
-    public List getRelatorsFilteredByRelator(Record record, String tagList,
-        String acceptWithoutRelator, String relatorConfig,
-        String acceptUnknownRelators
-    ) {
-        // default firstOnly to false!
-        return getRelatorsFilteredByRelator(
-            record, tagList, acceptWithoutRelator, relatorConfig,
-            acceptUnknownRelators, "false", false
-        );
-    }
-
-    /**
-     * Filter values retrieved using tagList to include only those whose relator
-     * values are acceptable. Used for saving relators of authors separated by different
-     * types.
-     *
-     * @param record               The record (fed in automatically)
-     * @param tagList              The field specification to read
-     * @param acceptWithoutRelator Colon-delimited list of tags whose values should
-     * be accepted even if no relator subfield is defined
-     * @param relatorConfig        The setting in author-classification.ini which
-     * defines which relator terms are acceptable (or a colon-delimited list)
-     * @return List result
-     */
-    public List getRelatorsFilteredByRelator(Record record, String tagList,
-        String acceptWithoutRelator, String relatorConfig
-    ) {
-        // default firstOnly to false!
-        return getRelatorsFilteredByRelator(
-            record, tagList, acceptWithoutRelator, relatorConfig,
-            acceptWithoutRelator, "false", false
-        );
-    }
-
-    /**
-     * This method fetches relator definitions from ini file and casts them to an
-     * array. If a colon-delimited string is passed in, this will be directly parsed
-     * instead of resorting to .ini loading.
-     *
-     * @param setting Setting to load from .ini or colon-delimited list.
-     * @return String[]
-     */
-    protected String[] loadRelatorConfig(String setting){
-        StringBuilder relators = new StringBuilder();
-
-        // check for pipe-delimited string
-        String[] relatorSettings = setting.split("\\|");
-        for (String relatorSetting: relatorSettings) {
-            // check for colon-delimited string
-            String[] relatorArray = relatorSetting.split(":");
-            if (relatorArray.length > 1) {
-                for (int i = 0; i < relatorArray.length; i++) {
-                    relators.append(relatorArray[i]).append(",");
-                }
-            } else {
-                relators.append(getConfigSetting(
-                    "author-classification.ini", "AuthorRoles", relatorSetting
-                )).append(",");
-            }
-        }
-
-        return relators.toString().split(",");
-    }
-
-    /**
-     * Normalizes a relator string and returns a list containing the normalized
-     * relator plus any configured synonyms.
-     *
-     * @param relator Relator term to normalize
-     * @return List of strings
-     */
-    public List<String> normalizeRelatorAndAddSynonyms(String relator)
-    {
-        List<String> newList = new ArrayList<String>();
-        String normalized = normalizeRelatorString(relator);
-        newList.add(normalized);
-        String synonyms = getConfigSetting(
-            "author-classification.ini", "RelatorSynonyms", relator
-        );
-        if (null != synonyms && synonyms.length() > 0) {
-            for (String synonym: synonyms.split("\\|")) {
-                String normalizedSynonym = normalizeRelatorString(synonym);
-                relatorSynonymLookup.put(normalizedSynonym, relator);
-                newList.add(normalizedSynonym);
-            }
-        }
-        return newList;
-    }
-
-    /**
-     * Normalizes the strings in a list.
-     *
-     * @param stringList List of strings to be normalized
-     * @return Normalized List of strings 
-     */
-    protected List<String> normalizeRelatorStringList(List<String> stringList)
-    {
-        List<String> newList = new ArrayList<String>();
-        for (String relator: stringList) {
-            newList.addAll(normalizeRelatorAndAddSynonyms(relator));
-        }
-        return newList;
-    }
-
-    /**
-     * Normalizes a string
-     *
-     * @param string String to be normalized
-     * @return string
-     */
-    protected String normalizeRelatorString(String string)
-    {
-        return string
-            .trim()
-            .toLowerCase()
-            .replaceAll("\\p{Punct}+", "");    //POSIX character class Punctuation: One of !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~
-    }
-
-    /**
-     * Filter values retrieved using tagList to include only those whose relator
-     * values are acceptable. Used for separating different types of authors.
-     *
-     * @param record               The record (fed in automatically)
-     * @param tagList              The field specification to read
-     * @param acceptWithoutRelator Colon-delimited list of tags whose values should
-     * be accepted even if no relator subfield is defined
-     * @param relatorConfig        The setting in author-classification.ini which
-     * defines which relator terms are acceptable (or a colon-delimited list)
-     * @param acceptUnknownRelators Colon-delimited list of tags whose relators
-     * should be indexed even if they are not listed in author-classification.ini.
-     * @param indexRawRelators      Set to "true" to index relators raw, as found
-     * in the MARC or "false" to index mapped versions.
-     * @return List result
-     */
-    public List<String> getAuthorInitialsFilteredByRelator(Record record,
-        String tagList, String acceptWithoutRelator, String relatorConfig,
-        String acceptUnknownRelators, String indexRawRelators
-    ) {
-        List<String> authors = getAuthorsFilteredByRelator(
-            record, tagList, acceptWithoutRelator, relatorConfig,
-            acceptUnknownRelators, indexRawRelators
-        );
-        List<String> result = new LinkedList<String>();
-        for (String author : authors) {
-            result.add(processInitials(author));
-        }
-        return result;
-    }
-
-    /**
-     * Filter values retrieved using tagList to include only those whose relator
-     * values are acceptable. Used for separating different types of authors.
-     *
-     * @param record               The record (fed in automatically)
-     * @param tagList              The field specification to read
-     * @param acceptWithoutRelator Colon-delimited list of tags whose values should
-     * be accepted even if no relator subfield is defined
-     * @param relatorConfig        The setting in author-classification.ini which
-     * defines which relator terms are acceptable (or a colon-delimited list)
-     * @return List result
-     */
-    public List<String> getAuthorInitialsFilteredByRelator(Record record,
-        String tagList, String acceptWithoutRelator, String relatorConfig
-    ) {
-        return getAuthorInitialsFilteredByRelator(
-            record, tagList, acceptWithoutRelator, relatorConfig,
-            acceptWithoutRelator, "false"
-        );
-    }
-
-    /**
-     * Filter values retrieved using tagList to include only those whose relator
-     * values are acceptable. Used for separating different types of authors.
-     *
-     * @param record               The record (fed in automatically)
-     * @param tagList              The field specification to read
-     * @param acceptWithoutRelator Colon-delimited list of tags whose values should
-     * be accepted even if no relator subfield is defined
-     * @param relatorConfig        The setting in author-classification.ini which
-     * defines which relator terms are acceptable (or a colon-delimited list)
-     * @param acceptUnknownRelators Colon-delimited list of tags whose relators
-     * should be indexed even if they are not listed in author-classification.ini.
-     * @return List result
-     */
-    public List<String> getAuthorInitialsFilteredByRelator(Record record,
-        String tagList, String acceptWithoutRelator, String relatorConfig,
-        String acceptUnknownRelators
-    ) {
-        return getAuthorInitialsFilteredByRelator(
-            record, tagList, acceptWithoutRelator, relatorConfig,
-            acceptUnknownRelators, "false"
-        );
-    }
-    
-    /**
-     * Takes a name and cuts it into initials
-     * @param authorName e.g. Yeats, William Butler
-     * @return initials e.g. w b y wb
-     */
-    protected String processInitials(String authorName) {
-        Boolean isPersonalName = false;
-        // we guess that if there is a comma before the end - this is a personal name
-        if ((authorName.indexOf(',') > 0) 
-            && (authorName.indexOf(',') < authorName.length()-1)) {
-            isPersonalName = true;
-        }
-        // get rid of non-alphabet chars but keep hyphens and accents 
-        authorName = authorName.replaceAll("[^\\p{L} -]", "").toLowerCase();
-        String[] names = authorName.split(" "); //split into tokens on spaces
-        // if this is a personal name we'll reorganise to put lastname at the end
-        String result = "";
-        if (isPersonalName) {
-            String lastName = names[0]; 
-            for (int i = 0; i < names.length-1; i++) {
-                names[i] = names[i+1];
-            }
-            names[names.length-1] = lastName;
-        }
-        // put all the initials together in a space separated string
-        for (String name : names) {
-            if (name.length() > 0) {
-                String initial = name.substring(0,1);
-                // if there is a hyphenated name, use both initials
-                int pos = name.indexOf('-');
-                if (pos > 0 && pos < name.length() - 1) {
-                    String extra = name.substring(pos+1, pos+2);
-                    initial = initial + " " + extra;
-                }
-                result += " " + initial; 
-            }
-        }
-        // grab all initials and stick them together
-        String smushAll = result.replaceAll(" ", "");
-        // if it's a long personal name, get all but the last initials as well
-        // e.g. wb for william butler yeats
-        if (names.length > 2 && isPersonalName) {
-            String smushPers = result.substring(0,result.length()-1).replaceAll(" ","");
-            result = result + " " + smushPers;
-        }
-        // now we have initials separate and together
-        if (!result.trim().equals(smushAll)) {
-            result += " " + smushAll; 
-        }
-        result = result.trim();
-        return result;
-    }
-
-    /**
-     * Normalize trailing punctuation. This mimics the functionality built into VuFind's
-     * textFacet field type, so that you can get equivalent values when indexing into
-     * a string field. (Useful for docValues support).
-     *
-     * Can return null
-     *
-     * @param record current MARC record
-     * @param fieldSpec which MARC fields / subfields need to be analyzed
-     * @return Set containing normalized values
-     */
-    public Set<String> normalizeTrailingPunctuation(Record record, String fieldSpec) {
-        // Initialize our return value:
-        Set<String> result = new LinkedHashSet<String>();
-
-        // Loop through the specified MARC fields:
-        Set<String> input = getFieldList(record, fieldSpec);
-        Pattern pattern = Pattern.compile("(?<!\b[A-Z])[.\\s]*$");
-        for (String current: input) {
-            result.add(pattern.matcher(current).replaceAll(""));
-        }
-
-        // If we found no matches, return null; otherwise, return our results:
-        return result.isEmpty() ? null : result;
-    }
-}
\ No newline at end of file
diff --git a/import/index_java/src/org/vufind/index/CallNumberTools.java b/import/index_java/src/org/vufind/index/CallNumberTools.java
new file mode 100644
index 0000000000000000000000000000000000000000..00138e4e1e533d5c400b9916e29ad7cbef7709a5
--- /dev/null
+++ b/import/index_java/src/org/vufind/index/CallNumberTools.java
@@ -0,0 +1,517 @@
+package org.vufind.index;
+/**
+ * Call number indexing routines.
+ *
+ * Copyright (C) Villanova University 2017.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+import org.marc4j.marc.Record;
+import org.marc4j.marc.VariableField;
+import org.marc4j.marc.DataField;
+import org.marc4j.marc.Subfield;
+import org.solrmarc.callnum.DeweyCallNumber;
+import org.solrmarc.callnum.LCCallNumber;
+import org.solrmarc.index.SolrIndexer;
+import org.solrmarc.tools.CallNumUtils;
+
+/**
+ * Call number indexing routines.
+ */
+public class CallNumberTools
+{
+    /**
+     * Extract the full call number from a record, stripped of spaces
+     * @param record MARC record
+     * @return Call number label
+     * @deprecated Obsolete as of VuFind 2.4.
+     *          This method exists only to support the VuFind call number search, version <= 2.3.
+     *          As of VuFind 2.4, the munging for call number search in handled entirely in Solr.
+     */
+    @Deprecated
+    public String getFullCallNumber(final Record record) {
+
+        return(getFullCallNumber(record, "099ab:090ab:050ab"));
+    }
+
+    /**
+     * Extract the full call number from a record, stripped of spaces
+     * @param record MARC record
+     * @param fieldSpec taglist for call number fields
+     * @return Call number label
+     * @deprecated Obsolete as of VuFind 2.4.
+     *          This method exists only to support the VuFind call number search, version <= 2.3.
+     *          As of VuFind 2.4, the munging for call number search in handled entirely in Solr.
+     */
+    @Deprecated
+    public String getFullCallNumber(final Record record, String fieldSpec) {
+
+        String val = SolrIndexer.instance().getFirstFieldVal(record, fieldSpec);
+
+        if (val != null) {
+            return val.toUpperCase().replaceAll(" ", "");
+        } else {
+            return val;
+        }
+    }
+
+    /**
+     * Extract the call number label from a record
+     * @param record MARC record
+     * @return Call number label
+     */
+    public String getCallNumberLabel(final Record record) {
+
+        return getCallNumberLabel(record, "090a:050a");
+    }
+
+    /**
+     * Extract the call number label from a record
+     * @param record MARC record
+     * @param fieldSpec taglist for call number fields
+     * @return Call number label
+     */
+    public String getCallNumberLabel(final Record record, String fieldSpec) {
+
+        String val = SolrIndexer.instance().getFirstFieldVal(record, fieldSpec);
+
+        if (val != null) {
+            int dotPos = val.indexOf(".");
+            if (dotPos > 0) {
+                val = val.substring(0, dotPos);
+            }
+            return val.toUpperCase();
+        } else {
+            return val;
+        }
+    }
+
+    /**
+     * Extract the subject component of the call number
+     *
+     * Can return null
+     *
+     * @param record MARC record
+     * @return Call number subject letters
+     */
+    public String getCallNumberSubject(final Record record) {
+
+        return(getCallNumberSubject(record, "090a:050a"));
+    }
+
+    /**
+     * Extract the subject component of the call number
+     *
+     * Can return null
+     *
+     * @param record current MARC record
+     * @return Call number subject letters
+     */
+    public String getCallNumberSubject(final Record record, String fieldSpec) {
+
+        String val = SolrIndexer.instance().getFirstFieldVal(record, fieldSpec);
+
+        if (val != null) {
+            String [] callNumberSubject = val.toUpperCase().split("[^A-Z]+");
+            if (callNumberSubject.length > 0)
+            {
+                return callNumberSubject[0];
+            }
+        }
+        return(null);
+    }
+
+    /**
+     * Normalize a single LC call number
+     * @param record current MARC record
+     * @return String Normalized LCCN
+     */
+    public String getFullCallNumberNormalized(final Record record) {
+
+        return(getFullCallNumberNormalized(record, "099ab:090ab:050ab"));
+    }
+
+    /**
+     * Normalize a single LC call number
+     * @param record current MARC record
+     * @param fieldSpec which MARC fields / subfields need to be analyzed
+     * @return String Normalized LC call number
+     */
+    public String getFullCallNumberNormalized(final Record record, String fieldSpec) {
+
+        // TODO: is the null fieldSpec still an issue?
+        if (fieldSpec != null) {
+            String cn = SolrIndexer.instance().getFirstFieldVal(record, fieldSpec);
+            return (new LCCallNumber(cn)).getShelfKey();
+        }
+        // If we got this far, we couldn't find a valid value:
+        return null;
+    }
+
+    /**
+     * Get call numbers of a specific type.
+     * 
+     * <p>{@code fieldSpec} is of form {@literal 098abc:099ab}, does not accept subfield ranges.
+     *
+     *
+     * @param record  current MARC record
+     * @param fieldSpec  which MARC fields / subfields need to be analyzed
+     * @param callTypeSf  subfield containing call number type, single character only
+     * @param callType  literal call number code
+     * @param result  a collection to gather the call numbers
+     * @return collection of call numbers, same object as {@code result}
+     */
+    public static Collection<String> getCallNumberByTypeCollector(
+            Record record, String fieldSpec, String callTypeSf, String callType, Collection<String> result) {
+        for (String tag : fieldSpec.split(":")) {
+            // Check to ensure tag length is at least 3 characters
+            if (tag.length() < 3) {
+                //TODO: Should this go to a log? Better message for a bad tag in a field spec?
+                System.err.println("Invalid tag specified: " + tag);
+                continue;
+            }
+            String dfTag = tag.substring(0, 3);
+            String sfSpec = null;
+            if (tag.length() > 3) {
+                    sfSpec = tag.substring(3);
+            }
+
+            // do all fields for this tag
+            for (VariableField vf : record.getVariableFields(dfTag)) {
+                // Assume tag represents a DataField
+                DataField df = (DataField) vf;
+                boolean callTypeMatch = false;
+                
+                // Assume call type subfield could repeat
+                for (Subfield typeSf : df.getSubfields(callTypeSf)) {
+                    if (callTypeSf.indexOf(typeSf.getCode()) != -1 && typeSf.getData().equals(callType)) {
+                        callTypeMatch = true;
+                    }
+                }
+                System.err.println("callTypeMatch after loop: " + callTypeMatch);
+                if (callTypeMatch) {
+                    result.add(df.getSubfieldsAsString(sfSpec));
+                }
+            } // end loop over variable fields
+        } // end loop over fieldSpec
+        return result;
+    }
+    
+
+    /**
+     * Get call numbers of a specific type.
+     * 
+     * <p>{@code fieldSpec} is of form {@literal 098abc:099ab}, does not accept subfield ranges.
+     *
+     * @param record  current MARC record
+     * @param fieldSpec  which MARC fields / subfields need to be analyzed
+     * @param callTypeSf  subfield containing call number type, single character only
+     * @param callType  literal call number code
+     * @return set of call numbers
+     */
+    public static Set<String> getCallNumberByType(Record record, String fieldSpec, String callTypeSf, String callType) {
+        return (Set<String>) getCallNumberByTypeCollector(record, fieldSpec, callTypeSf, callType,
+                new LinkedHashSet<String>());
+    }
+
+    /**
+     * Get call numbers of a specific type.
+     * 
+     * <p>{@code fieldSpec} is of form {@literal 098abc:099ab}, does not accept subfield ranges.
+     *
+     * @param record  current MARC record
+     * @param fieldSpec  which MARC fields / subfields need to be analyzed
+     * @param callTypeSf  subfield containing call number type, single character only
+     * @param callType  literal call number code
+     * @return list of call numbers
+     */
+    public static List<String> getCallNumberByTypeAsList(Record record, String fieldSpec, String callTypeSf, String callType) {
+        return (List<String>) getCallNumberByTypeCollector(record, fieldSpec, callTypeSf, callType,
+                new ArrayList<String>());
+    }
+
+    /**
+     * Normalize LC numbers for sorting purposes (use only the first valid number!).
+     * Will return first call number found if none pass validation,
+     * or empty string if no call numbers.
+     *
+     * @param  record current MARC record
+     * @param  fieldSpec which MARC fields / subfields need to be analyzed
+     * @return sortable shelf key of the first valid LC number encountered, 
+     *         otherwise shelf key of the first call number found.
+     */
+    public String getLCSortable(Record record, String fieldSpec) {
+        // Loop through the specified MARC fields:
+        Set<String> input = SolrIndexer.instance().getFieldList(record, fieldSpec);
+        String firstCall = "";
+        for (String current : input) {
+            // If this is a valid LC number, return the sortable shelf key:
+            LCCallNumber callNum = new LCCallNumber(current);
+            if (callNum.isValid()) {
+                return callNum.getShelfKey();   // RETURN first valid
+            }
+            if (firstCall.length() == 0) {
+                firstCall = current;
+            }
+        }
+
+        // If we made it this far, did not find a valid LC number, so use what we have:
+        return new LCCallNumber(firstCall).getShelfKey();
+    }
+
+    /**
+     * Get sort key for first LC call number, identified by call type.
+     * 
+     * <p>{@code fieldSpec} is of form {@literal 098abc:099ab}, does not accept subfield ranges.
+     *
+     *
+     * @param record  current MARC record
+     * @param fieldSpec  which MARC fields / subfields need to be analyzed
+     * @param callTypeSf  subfield containing call number type, single character only
+     * @param callType  literal call number code
+     * @return sort key for first identified LC call number
+     */
+    public String getLCSortableByType(
+            Record record, String fieldSpec, String callTypeSf, String callType) {
+        String sortKey = null;
+        for (String tag : fieldSpec.split(":")) {
+            // Check to ensure tag length is at least 3 characters
+            if (tag.length() < 3) {
+                //TODO: Should this go to a log? Better message for a bad tag in a field spec?
+                System.err.println("Invalid tag specified: " + tag);
+                continue;
+            }
+            String dfTag = tag.substring(0, 3);
+            String sfSpec = null;
+            if (tag.length() > 3) {
+                    sfSpec = tag.substring(3);
+            }
+
+            // do all fields for this tag
+            for (VariableField vf : record.getVariableFields(dfTag)) {
+                // Assume tag represents a DataField
+                DataField df = (DataField) vf;
+                boolean callTypeMatch = false;
+                
+                // Assume call type subfield could repeat
+                for (Subfield typeSf : df.getSubfields(callTypeSf)) {
+                    if (callTypeSf.indexOf(typeSf.getCode()) != -1 && typeSf.getData().equals(callType)) {
+                        callTypeMatch = true;
+                    }
+                }
+                // take the first call number coded as LC
+                if (callTypeMatch) {
+                    sortKey = new LCCallNumber(df.getSubfieldsAsString(sfSpec)).getShelfKey();
+                    break;
+                }
+            } // end loop over variable fields
+        } // end loop over fieldSpec
+        return sortKey;
+    }
+
+    /**
+     * Extract a numeric portion of the Dewey decimal call number
+     *
+     * Can return null
+     *
+     * @param record current MARC record
+     * @param fieldSpec which MARC fields / subfields need to be analyzed
+     * @param precisionStr a decimal number (represented in string format) showing the
+     *  desired precision of the returned number; i.e. 100 to round to nearest hundred,
+     *  10 to round to nearest ten, 0.1 to round to nearest tenth, etc.
+     * @return Set containing requested numeric portions of Dewey decimal call numbers
+     */
+    public Set<String> getDeweyNumber(Record record, String fieldSpec, String precisionStr) {
+        // Initialize our return value:
+        Set<String> result = new LinkedHashSet<String>();
+
+        // Precision comes in as a string, but we need to convert it to a float:
+        float precision = Float.parseFloat(precisionStr);
+
+        // Loop through the specified MARC fields:
+        Set<String> input = SolrIndexer.instance().getFieldList(record, fieldSpec);
+        for (String current: input) {
+            DeweyCallNumber callNum = new DeweyCallNumber(current);
+            if (callNum.isValid()) {
+                // Convert the numeric portion of the call number into a float:
+                float currentVal = Float.parseFloat(callNum.getClassification());
+                
+                // Round the call number value to the specified precision:
+                Float finalVal = new Float(Math.floor(currentVal / precision) * precision);
+                
+                // Convert the rounded value back to a string (with leading zeros) and save it:
+                // TODO: Provide different conversion to remove CallNumUtils dependency
+                result.add(CallNumUtils.normalizeFloat(finalVal.toString(), 3, -1));
+            }
+        }
+
+        // If we found no call number matches, return null; otherwise, return our results:
+        if (result.isEmpty())
+            return null;
+        return result;
+    }
+
+    /**
+     * Normalize Dewey numbers for searching purposes (uppercase/stripped spaces)
+     *
+     * Can return null
+     *
+     * @param record current MARC record
+     * @param fieldSpec which MARC fields / subfields need to be analyzed
+     * @return Set containing normalized Dewey numbers extracted from specified fields.
+     */
+    public Set<String> getDeweySearchable(Record record, String fieldSpec) {
+        // Initialize our return value:
+        Set<String> result = new LinkedHashSet<String>();
+
+        // Loop through the specified MARC fields:
+        Set<String> input = SolrIndexer.instance().getFieldList(record, fieldSpec);
+        Iterator<String> iter = input.iterator();
+        while (iter.hasNext()) {
+            // Get the current string to work on:
+            String current = iter.next();
+
+            // Add valid strings to the set, normalizing them to be all uppercase
+            // and free from whitespace.
+            DeweyCallNumber callNum = new DeweyCallNumber(current);
+            if (callNum.isValid()) {
+                result.add(callNum.toString().toUpperCase().replaceAll(" ", ""));
+            }
+        }
+
+        // If we found no call numbers, return null; otherwise, return our results:
+        if (result.isEmpty())
+            return null;
+        return result;
+    }
+
+    /**
+     * Normalize Dewey numbers for sorting purposes (use only the first valid number!)
+     *
+     * Can return null
+     *
+     * @param record current MARC record
+     * @param fieldSpec which MARC fields / subfields need to be analyzed
+     * @return String containing the first valid Dewey number encountered, normalized
+     *         for sorting purposes.
+     */
+    public String getDeweySortable(Record record, String fieldSpec) {
+        // Loop through the specified MARC fields:
+        Set<String> input = SolrIndexer.instance().getFieldList(record, fieldSpec);
+        Iterator<String> iter = input.iterator();
+        while (iter.hasNext()) {
+            // Get the current string to work on:
+            String current = iter.next();
+
+            // If this is a valid Dewey number, return the sortable shelf key:
+            DeweyCallNumber callNum = new DeweyCallNumber(current);
+            if (callNum.isValid()) {
+                return callNum.getShelfKey();
+            }
+        }
+
+        // If we made it this far, we didn't find a valid sortable Dewey number:
+        return null;
+    }
+
+    /**
+     * Get sort key for first Dewey call number, identified by call type.
+     * 
+     * <p>{@code fieldSpec} is of form {@literal 098abc:099ab}, does not accept subfield ranges.
+     *
+     *
+     * @param record  current MARC record
+     * @param fieldSpec  which MARC fields / subfields need to be analyzed
+     * @param callTypeSf  subfield containing call number type, single character only
+     * @param callType  literal call number code
+     * @return sort key for first identified Dewey call number
+     */
+    public static String getDeweySortableByType(
+            Record record, String fieldSpec, String callTypeSf, String callType) {
+        String sortKey = null;
+        for (String tag : fieldSpec.split(":")) {
+            // Check to ensure tag length is at least 3 characters
+            if (tag.length() < 3) {
+                //TODO: Should this go to a log? Better message for a bad tag in a field spec?
+                System.err.println("Invalid tag specified: " + tag);
+                continue;
+            }
+            String dfTag = tag.substring(0, 3);
+            String sfSpec = null;
+            if (tag.length() > 3) {
+                    sfSpec = tag.substring(3);
+            }
+
+            // do all fields for this tag
+            for (VariableField vf : record.getVariableFields(dfTag)) {
+                // Assume tag represents a DataField
+                DataField df = (DataField) vf;
+                boolean callTypeMatch = false;
+                
+                // Assume call type subfield could repeat
+                for (Subfield typeSf : df.getSubfields(callTypeSf)) {
+                    if (callTypeSf.indexOf(typeSf.getCode()) != -1 && typeSf.getData().equals(callType)) {
+                        callTypeMatch = true;
+                    }
+                }
+                // take the first call number coded as Dewey
+                if (callTypeMatch) {
+                    sortKey = new DeweyCallNumber(df.getSubfieldsAsString(sfSpec)).getShelfKey();
+                    break;
+                }
+            } // end loop over variable fields
+        } // end loop over fieldSpec
+        return sortKey;
+    }
+
+    
+    /**
+     * Normalize Dewey numbers for AlphaBrowse sorting purposes (use all numbers!)
+     *
+     * Can return null
+     *
+     * @param record current MARC record
+     * @param fieldSpec which MARC fields / subfields need to be analyzed
+     * @return List containing normalized Dewey numbers extracted from specified fields.
+     */
+    public List<String> getDeweySortables(Record record, String fieldSpec) {
+        // Initialize our return value:
+        List<String> result = new LinkedList<String>();
+
+        // Loop through the specified MARC fields:
+        Set<String> input = SolrIndexer.instance().getFieldList(record, fieldSpec);
+        Iterator<String> iter = input.iterator();
+        while (iter.hasNext()) {
+            // Get the current string to work on:
+            String current = iter.next();
+
+            // gather all sort keys, even if number is not valid
+            DeweyCallNumber callNum = new DeweyCallNumber(current);
+            result.add(callNum.getShelfKey());
+        }
+
+        // If we found no call numbers, return null; otherwise, return our results:
+        if (result.isEmpty())
+            return null;
+        return result;
+    }
+}
\ No newline at end of file
diff --git a/import/index_java/src/org/vufind/index/ConfigManager.java b/import/index_java/src/org/vufind/index/ConfigManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..d9f25087780f1f1cb74304638973b56ba62e1a99
--- /dev/null
+++ b/import/index_java/src/org/vufind/index/ConfigManager.java
@@ -0,0 +1,234 @@
+package org.vufind.index;
+/**
+ * VuFind configuration manager
+ *
+ * Copyright (C) Villanova University 2017.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+import java.io.File;
+import java.io.FileReader;
+import java.util.Map;
+import java.util.Properties;
+import java.util.concurrent.ConcurrentHashMap;
+import org.solrmarc.index.indexer.ValueIndexerFactory;
+import org.solrmarc.tools.PropertyUtils;
+import org.solrmarc.tools.SolrMarcIndexerException;
+import org.ini4j.Ini;
+import org.apache.log4j.Logger;
+
+/**
+ * VuFind configuration manager
+ */
+public class ConfigManager
+{
+    // Initialize logging category
+    static Logger logger = Logger.getLogger(ConfigManager.class.getName());
+    private static ConcurrentHashMap<String, Ini> configCache = new ConcurrentHashMap<String, Ini>();
+    private Properties vuFindConfigs = null;
+    private static ThreadLocal<ConfigManager> managerCache = 
+        new ThreadLocal<ConfigManager>()
+        {
+            @Override
+            protected ConfigManager initialValue()
+            {
+                return new ConfigManager();
+            }
+        };
+
+    public ConfigManager()
+    {
+        try {
+            vuFindConfigs = PropertyUtils.loadProperties(ValueIndexerFactory.instance().getHomeDirs(), "vufind.properties");
+        } catch (IllegalArgumentException e) {
+            // If the properties load failed, don't worry about it -- we'll use defaults.
+        }
+    }
+
+    public static ConfigManager instance()
+    {
+        return managerCache.get();
+    }
+
+    /**
+     * Given the base name of a configuration file, locate the full path.
+     * @param filename base name of a configuration file
+     */
+    private File findConfigFile(String filename)
+    {
+        // Find VuFind's home directory in the environment; if it's not available,
+        // try using a relative path on the assumption that we are currently in
+        // VuFind's import subdirectory:
+        String vufindHome = System.getenv("VUFIND_HOME");
+        if (vufindHome == null) {
+            vufindHome = "..";
+        }
+
+        // Check for VuFind 2.0's local directory environment variable:
+        String vufindLocal = System.getenv("VUFIND_LOCAL_DIR");
+
+        // Get the relative VuFind path from the properties file, defaulting to
+        // the 2.0-style config/vufind if necessary.
+        String relativeConfigPath = PropertyUtils.getProperty(
+            vuFindConfigs, "vufind.config.relative_path", "config/vufind"
+        );
+
+        // Try several different locations for the file -- VuFind 2 local dir,
+        // VuFind 2 base dir, VuFind 1 base dir.
+        File file;
+        if (vufindLocal != null) {
+            file = new File(vufindLocal + "/" + relativeConfigPath + "/" + filename);
+            if (file.exists()) {
+                return file;
+            }
+        }
+        file = new File(vufindHome + "/" + relativeConfigPath + "/" + filename);
+        if (file.exists()) {
+            return file;
+        }
+        file = new File(vufindHome + "/web/conf/" + filename);
+        return file;
+    }
+
+    /**
+     * Sanitize a VuFind configuration setting.
+     * @param str configuration setting
+     */
+    private String sanitizeConfigSetting(String str)
+    {
+        // Drop comments if necessary:
+        int pos = str.indexOf(';');
+        if (pos >= 0) {
+            str = str.substring(0, pos).trim();
+        }
+
+        // Strip wrapping quotes if necessary (the ini reader won't do this for us):
+        if (str.startsWith("\"")) {
+            str = str.substring(1, str.length());
+        }
+        if (str.endsWith("\"")) {
+            str = str.substring(0, str.length() - 1);
+        }
+        return str;
+    }
+
+    /**
+     * Load an ini file.
+     * @param filename name of {@code .ini} file
+     */
+    public Ini loadConfigFile(String filename)
+    {
+        // Retrieve the file if it is not already cached.
+        if (!configCache.containsKey(filename)) {
+            Ini ini = new Ini();
+            try {
+                ini.load(new FileReader(findConfigFile(filename)));
+                configCache.putIfAbsent(filename, ini);
+            } catch (Throwable e) {
+                dieWithError("Unable to access " + filename);
+            }
+        }
+        return configCache.get(filename);
+    }
+
+    /**
+     * Get a section from a VuFind configuration file.
+     * @param filename configuration file name
+     * @param section section name within the file
+     */
+    public Map<String, String> getConfigSection(String filename, String section)
+    {
+        // Grab the ini file.
+        Ini ini = loadConfigFile(filename);
+        Map<String, String> retVal = ini.get(section);
+
+        String parent = ini.get("Parent_Config", "path");
+        while (parent != null) {
+            Ini parentIni = loadConfigFile(parent);
+            Map<String, String> parentSection = parentIni.get(section);
+            for (String key : parentSection.keySet()) {
+                if (!retVal.containsKey(key)) {
+                    retVal.put(key, parentSection.get(key));
+                }
+            }
+            parent = parentIni.get("Parent_Config", "path");
+        }
+
+        // Check to see if we need to worry about an override file:
+        String override = ini.get("Extra_Config", "local_overrides");
+        if (override != null) {
+            Map<String, String> overrideSection = loadConfigFile(override).get(section);
+            for (String key : overrideSection.keySet()) {
+                retVal.put(key, overrideSection.get(key));
+            }
+        }
+        return retVal;
+    }
+
+    /**
+     * Get a setting from a VuFind configuration file.
+     * @param filename configuration file name
+     * @param section section name within the file
+     * @param setting setting name within the section
+     */
+    public String getConfigSetting(String filename, String section, String setting)
+    {
+        String retVal = null;
+
+        // Grab the ini file.
+        Ini ini = loadConfigFile(filename);
+
+        // Check to see if we need to worry about an override file:
+        String override = ini.get("Extra_Config", "local_overrides");
+        if (override != null) {
+            Ini overrideIni = loadConfigFile(override);
+            retVal = overrideIni.get(section, setting);
+            if (retVal != null) {
+                return sanitizeConfigSetting(retVal);
+            }
+        }
+
+        // Try to find the requested setting:
+        retVal = ini.get(section, setting);
+
+        //  No setting?  Check for a parent configuration:
+        while (retVal == null) {
+            String parent = ini.get("Parent_Config", "path");
+            if (parent !=  null) {
+                try {
+                    ini.load(new FileReader(new File(parent)));
+                } catch (Throwable e) {
+                    dieWithError("Unable to access " + parent);
+                }
+                retVal = ini.get(section, setting);
+            } else {
+                break;
+            }
+        }
+
+        // Return the processed setting:
+        return retVal == null ? null : sanitizeConfigSetting(retVal);
+    }
+
+    /**
+     * Log an error message and throw a fatal exception.
+     * @param msg message to log
+     */
+    private void dieWithError(String msg)
+    {
+        logger.error(msg);
+        throw new SolrMarcIndexerException(SolrMarcIndexerException.EXIT, msg);
+    }
+}
\ No newline at end of file
diff --git a/import/index_java/src/org/vufind/index/CreatorTools.java b/import/index_java/src/org/vufind/index/CreatorTools.java
new file mode 100644
index 0000000000000000000000000000000000000000..3a50dd9ad89fb8144528229fdc9638533c5f7bb6
--- /dev/null
+++ b/import/index_java/src/org/vufind/index/CreatorTools.java
@@ -0,0 +1,725 @@
+package org.vufind.index;
+/**
+ * Indexing routines for dealing with creators and relator terms.
+ *
+ * Copyright (C) Villanova University 2017.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+import org.marc4j.marc.Record;
+import org.marc4j.marc.Subfield;
+import org.marc4j.marc.DataField;
+import org.solrmarc.index.SolrIndexer;
+import org.apache.log4j.Logger;
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Indexing routines for dealing with creators and relator terms.
+ */
+public class CreatorTools
+{
+    // Initialize logging category
+    static Logger logger = Logger.getLogger(CreatorTools.class.getName());
+
+    private ConcurrentHashMap<String, String> relatorSynonymLookup = RelatorContainer.instance().getSynonymLookup();
+    private Set<String> knownRelators = RelatorContainer.instance().getKnownRelators();
+
+    /**
+     * Extract all valid relator terms from a list of subfields using a whitelist.
+     * @param subfields        List of subfields to check
+     * @param permittedRoles   Whitelist to check against
+     * @param indexRawRelators Should we index relators raw, as found
+     * in the MARC (true) or index mapped versions (false)?
+     * @return Set of valid relator terms
+     */
+    public Set<String> getValidRelatorsFromSubfields(List<Subfield> subfields, List<String> permittedRoles, Boolean indexRawRelators)
+    {
+        Set<String> relators = new LinkedHashSet<String>();
+        for (int j = 0; j < subfields.size(); j++) {
+            String raw = subfields.get(j).getData();
+            String current = normalizeRelatorString(raw);
+            if (permittedRoles.contains(current)) {
+                relators.add(indexRawRelators ? raw : mapRelatorStringToCode(current));
+            }
+        }
+        return relators;
+    }
+
+    /**
+     * Is this relator term unknown to author-classification.ini?
+     * @param current relator to check
+     * @return True if unknown
+     */
+    public Boolean isUnknownRelator(String current)
+    {
+        // If we haven't loaded known relators yet, do so now:
+        if (knownRelators.size() == 0) {
+            Map<String, String> all = ConfigManager.instance().getConfigSection("author-classification.ini", "RelatorSynonyms");
+            for (String key : all.keySet()) {
+                knownRelators.add(normalizeRelatorString(key));
+                for (String synonym: all.get(key).split("\\|")) {
+                    knownRelators.add(normalizeRelatorString(synonym));
+                }
+            }
+        }
+        return !knownRelators.contains(normalizeRelatorString(current));
+    }
+
+    /**
+     * Extract all valid relator terms from a list of subfields using a whitelist.
+     * @param subfields      List of subfields to check
+     * @return Set of valid relator terms
+     */
+    public Set<String> getUnknownRelatorsFromSubfields(List<Subfield> subfields)
+    {
+        Set<String> relators = new LinkedHashSet<String>();
+        for (int j = 0; j < subfields.size(); j++) {
+            String current = subfields.get(j).getData().trim();
+            if (current.length() > 0 && isUnknownRelator(current)) {
+                logger.info("Unknown relator: " + current);
+                relators.add(current);
+            }
+        }
+        return relators;
+    }
+
+    /**
+     * Extract all values that meet the specified relator requirements.
+     * @param authorField           Field to analyze
+     * @param noRelatorAllowed      Array of tag names which are allowed to be used with
+     * no declared relator.
+     * @param relatorConfig         The setting in author-classification.ini which
+     * defines which relator terms are acceptable (or a colon-delimited list)
+     * @param unknownRelatorAllowed Array of tag names whose relators should be indexed 
+     * even if they are not listed in author-classification.ini.
+     * @param indexRawRelators      Set to "true" to index relators raw, as found
+     * in the MARC or "false" to index mapped versions.
+     * @return Set
+     */
+    public Set<String> getValidRelators(DataField authorField,
+        String[] noRelatorAllowed, String relatorConfig,
+        String[] unknownRelatorAllowed, String indexRawRelators
+    ) {
+        // get tag number from Field
+        String tag = authorField.getTag();
+        List<Subfield> subfieldE = authorField.getSubfields('e');
+        List<Subfield> subfield4 = authorField.getSubfields('4');
+
+        Set<String> relators = new LinkedHashSet<String>();
+
+        // if no relator is found, check to see if the current tag is in the "no
+        // relator allowed" list.
+        if (subfieldE.size() == 0 && subfield4.size() == 0) {
+            if (Arrays.asList(noRelatorAllowed).contains(tag)) {
+                relators.add("");
+            }
+        } else {
+            // If we got this far, we need to figure out what type of relation they have
+            List permittedRoles = normalizeRelatorStringList(Arrays.asList(loadRelatorConfig(relatorConfig)));
+            relators.addAll(getValidRelatorsFromSubfields(subfieldE, permittedRoles, indexRawRelators.toLowerCase().equals("true")));
+            relators.addAll(getValidRelatorsFromSubfields(subfield4, permittedRoles, indexRawRelators.toLowerCase().equals("true")));
+            if (Arrays.asList(unknownRelatorAllowed).contains(tag)) {
+                Set<String> unknown = getUnknownRelatorsFromSubfields(subfieldE);
+                if (unknown.size() == 0) {
+                    unknown = getUnknownRelatorsFromSubfields(subfield4);
+                }
+                relators.addAll(unknown);
+            }
+        }
+        return relators;
+    }
+
+    /**
+     * Parse a SolrMarc fieldspec into a map of tag name to set of subfield strings
+     * (note that we need to map to a set rather than a single string, because the
+     * same tag may repeat with different subfields to extract different sections
+     * of the same field into distinct values).
+     *
+     * @param tagList The field specification to parse
+     * @return HashMap
+     */
+    protected HashMap<String, Set<String>> getParsedTagList(String tagList)
+    {
+        String[] tags = tagList.split(":");//convert string input to array
+        HashMap<String, Set<String>> tagMap = new HashMap<String, Set<String>>();
+        //cut tags array up into key/value pairs in hash map
+        Set<String> currentSet;
+        for(int i = 0; i < tags.length; i++){
+            String tag = tags[i].substring(0, 3);
+            if (!tagMap.containsKey(tag)) {
+                currentSet = new LinkedHashSet<String>();
+                tagMap.put(tag, currentSet);
+            } else {
+                currentSet = tagMap.get(tag);
+            }
+            currentSet.add(tags[i].substring(3));
+        }
+        return tagMap;
+    }
+
+    /**
+     * Filter values retrieved using tagList to include only those whose relator
+     * values are acceptable. Used for separating different types of authors.
+     *
+     * @param record               The record (fed in automatically)
+     * @param tagList              The field specification to read
+     * @param acceptWithoutRelator Colon-delimited list of tags whose values should
+     * be accepted even if no relator subfield is defined
+     * @param relatorConfig        The setting in author-classification.ini which
+     * defines which relator terms are acceptable (or a colon-delimited list)
+     * @param acceptUnknownRelators Colon-delimited list of tags whose relators
+     * should be indexed even if they are not listed in author-classification.ini.
+     * @param indexRawRelators      Set to "true" to index relators raw, as found
+     * in the MARC or "false" to index mapped versions.
+     * @param firstOnly            Return first result only?
+     * @return List result
+     */
+    public List<String> getAuthorsFilteredByRelator(Record record, String tagList,
+        String acceptWithoutRelator, String relatorConfig,
+        String acceptUnknownRelators, String indexRawRelators, Boolean firstOnly
+    ) {
+        List<String> result = new LinkedList<String>();
+        String[] noRelatorAllowed = acceptWithoutRelator.split(":");
+        String[] unknownRelatorAllowed = acceptUnknownRelators.split(":");
+        HashMap<String, Set<String>> parsedTagList = getParsedTagList(tagList);
+        List fields = SolrIndexer.instance().getFieldSetMatchingTagList(record, tagList);
+        Iterator fieldsIter = fields.iterator();
+        if (fields != null){
+            DataField authorField;
+            while (fieldsIter.hasNext()){
+                authorField = (DataField) fieldsIter.next();
+                // add all author types to the result set; if we have multiple relators, repeat the authors
+                for (String iterator: getValidRelators(authorField, noRelatorAllowed, relatorConfig, unknownRelatorAllowed, indexRawRelators)) {
+                    for (String subfields : parsedTagList.get(authorField.getTag())) {
+                        String current = SolrIndexer.instance().getDataFromVariableField(authorField, "["+subfields+"]", " ", false);
+                        // TODO: we may eventually be able to use this line instead,
+                        // but right now it's not handling separation between the
+                        // subfields correctly, so it's commented out until that is
+                        // fixed.
+                        //String current = authorField.getSubfieldsAsString(subfields);
+                        if (null != current) {
+                            result.add(current);
+                            if (firstOnly) {
+                                return result;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Filter values retrieved using tagList to include only those whose relator
+     * values are acceptable. Used for separating different types of authors.
+     *
+     * @param record               The record (fed in automatically)
+     * @param tagList              The field specification to read
+     * @param acceptWithoutRelator Colon-delimited list of tags whose values should
+     * be accepted even if no relator subfield is defined
+     * @param relatorConfig        The setting in author-classification.ini which
+     * defines which relator terms are acceptable (or a colon-delimited list)
+     * @return List result
+     */
+    public List<String> getAuthorsFilteredByRelator(Record record, String tagList,
+        String acceptWithoutRelator, String relatorConfig
+    ) {
+        // default firstOnly to false!
+        return getAuthorsFilteredByRelator(
+            record, tagList, acceptWithoutRelator, relatorConfig,
+            acceptWithoutRelator, "false", false
+        );
+    }
+
+    /**
+     * Filter values retrieved using tagList to include only those whose relator
+     * values are acceptable. Used for separating different types of authors.
+     *
+     * @param record               The record (fed in automatically)
+     * @param tagList              The field specification to read
+     * @param acceptWithoutRelator Colon-delimited list of tags whose values should
+     * be accepted even if no relator subfield is defined
+     * @param relatorConfig        The setting in author-classification.ini which
+     * defines which relator terms are acceptable (or a colon-delimited list)
+     * @return List result
+     * @param acceptUnknownRelators Colon-delimited list of tags whose relators
+     * should be indexed even if they are not listed in author-classification.ini.
+     */
+    public List<String> getAuthorsFilteredByRelator(Record record, String tagList,
+        String acceptWithoutRelator, String relatorConfig,
+        String acceptUnknownRelators
+    ) {
+        // default firstOnly to false!
+        return getAuthorsFilteredByRelator(
+            record, tagList, acceptWithoutRelator, relatorConfig,
+            acceptUnknownRelators, "false", false
+        );
+    }
+
+    /**
+     * Filter values retrieved using tagList to include only those whose relator
+     * values are acceptable. Used for separating different types of authors.
+     *
+     * @param record               The record (fed in automatically)
+     * @param tagList              The field specification to read
+     * @param acceptWithoutRelator Colon-delimited list of tags whose values should
+     * be accepted even if no relator subfield is defined
+     * @param relatorConfig        The setting in author-classification.ini which
+     * defines which relator terms are acceptable (or a colon-delimited list)
+     * @return List result
+     * @param acceptUnknownRelators Colon-delimited list of tags whose relators
+     * should be indexed even if they are not listed in author-classification.ini.
+     * @param indexRawRelators      Set to "true" to index relators raw, as found
+     * in the MARC or "false" to index mapped versions.
+     */
+    public List<String> getAuthorsFilteredByRelator(Record record, String tagList,
+        String acceptWithoutRelator, String relatorConfig,
+        String acceptUnknownRelators, String indexRawRelators
+    ) {
+        // default firstOnly to false!
+        return getAuthorsFilteredByRelator(
+            record, tagList, acceptWithoutRelator, relatorConfig,
+            acceptUnknownRelators, indexRawRelators, false
+        );
+    }
+
+    /**
+     * If the provided relator is included in the synonym list, convert it back to
+     * a code (for better standardization/translation).
+     *
+     * @param relator Relator code to check
+     * @return Code version, if found, or raw string if no match found.
+     */
+    public String mapRelatorStringToCode(String relator)
+    {
+        String normalizedRelator = normalizeRelatorString(relator);
+        return relatorSynonymLookup.containsKey(normalizedRelator)
+            ? relatorSynonymLookup.get(normalizedRelator) : relator;
+    }
+
+    /**
+     * Filter values retrieved using tagList to include only those whose relator
+     * values are acceptable. Used for separating different types of authors.
+     *
+     * @param record                The record (fed in automatically)
+     * @param tagList               The field specification to read
+     * @param acceptWithoutRelator  Colon-delimited list of tags whose values should
+     * be accepted even if no relator subfield is defined
+     * @param relatorConfig         The setting in author-classification.ini which
+     * defines which relator terms  are acceptable (or a colon-delimited list)
+     * @param acceptUnknownRelators Colon-delimited list of tags whose relators
+     * should be indexed even if they are not listed in author-classification.ini.
+     * @param indexRawRelators      Set to "true" to index relators raw, as found
+     * in the MARC or "false" to index mapped versions.
+     * @return String
+     */
+    public String getFirstAuthorFilteredByRelator(Record record, String tagList,
+        String acceptWithoutRelator, String relatorConfig,
+        String acceptUnknownRelators, String indexRawRelators
+    ) {
+        List<String> result = getAuthorsFilteredByRelator(
+            record, tagList, acceptWithoutRelator, relatorConfig,
+            acceptUnknownRelators, indexRawRelators, true
+        );
+        for (String s : result) {
+            return s;
+        }
+        return null;
+    }
+
+    /**
+     * Filter values retrieved using tagList to include only those whose relator
+     * values are acceptable. Used for separating different types of authors.
+     *
+     * @param record                The record (fed in automatically)
+     * @param tagList               The field specification to read
+     * @param acceptWithoutRelator  Colon-delimited list of tags whose values should
+     * be accepted even if no relator subfield is defined
+     * @param relatorConfig         The setting in author-classification.ini which
+     * defines which relator terms  are acceptable (or a colon-delimited list)
+     * @return String
+     */
+    public String getFirstAuthorFilteredByRelator(Record record, String tagList,
+        String acceptWithoutRelator, String relatorConfig
+    ) {
+        return getFirstAuthorFilteredByRelator(
+            record, tagList, acceptWithoutRelator, relatorConfig,
+            acceptWithoutRelator, "false"
+        );
+    }
+
+    /**
+     * Filter values retrieved using tagList to include only those whose relator
+     * values are acceptable. Used for separating different types of authors.
+     *
+     * @param record                The record (fed in automatically)
+     * @param tagList               The field specification to read
+     * @param acceptWithoutRelator  Colon-delimited list of tags whose values should
+     * be accepted even if no relator subfield is defined
+     * @param relatorConfig         The setting in author-classification.ini which
+     * defines which relator terms  are acceptable (or a colon-delimited list)
+     * @param acceptUnknownRelators Colon-delimited list of tags whose relators
+     * should be indexed even if they are not listed in author-classification.ini.
+     * @return String
+     */
+    public String getFirstAuthorFilteredByRelator(Record record, String tagList,
+        String acceptWithoutRelator, String relatorConfig,
+        String acceptUnknownRelators
+    ) {
+        return getFirstAuthorFilteredByRelator(
+            record, tagList, acceptWithoutRelator, relatorConfig,
+            acceptUnknownRelators, "false"
+        );
+    }
+
+    /**
+     * Filter values retrieved using tagList to include only those whose relator
+     * values are acceptable. Used for saving relators of authors separated by different
+     * types.
+     *
+     * @param record               The record (fed in automatically)
+     * @param tagList              The field specification to read
+     * @param acceptWithoutRelator Colon-delimited list of tags whose values should
+     * be accepted even if no relator subfield is defined
+     * @param relatorConfig        The setting in author-classification.ini which
+     * defines which relator terms are acceptable (or a colon-delimited list)
+     * @param acceptUnknownRelators Colon-delimited list of tags whose relators
+     * should be indexed even if they are not listed in author-classification.ini.
+     * @param indexRawRelators      Set to "true" to index relators raw, as found
+     * in the MARC or "false" to index mapped versions.
+     * @param firstOnly            Return first result only?
+     * @return List result
+     */
+    public List getRelatorsFilteredByRelator(Record record, String tagList,
+        String acceptWithoutRelator, String relatorConfig,
+        String acceptUnknownRelators, String indexRawRelators, Boolean firstOnly
+    ) {
+        List result = new LinkedList();
+        String[] noRelatorAllowed = acceptWithoutRelator.split(":");
+        String[] unknownRelatorAllowed = acceptUnknownRelators.split(":");
+        HashMap<String, Set<String>> parsedTagList = getParsedTagList(tagList);
+        List fields = SolrIndexer.instance().getFieldSetMatchingTagList(record, tagList);
+        Iterator fieldsIter = fields.iterator();
+        if (fields != null){
+            DataField authorField;
+            while (fieldsIter.hasNext()){
+                authorField = (DataField) fieldsIter.next();
+                //add all author types to the result set
+                result.addAll(getValidRelators(authorField, noRelatorAllowed, relatorConfig, unknownRelatorAllowed, indexRawRelators));
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Filter values retrieved using tagList to include only those whose relator
+     * values are acceptable. Used for saving relators of authors separated by different
+     * types.
+     *
+     * @param record               The record (fed in automatically)
+     * @param tagList              The field specification to read
+     * @param acceptWithoutRelator Colon-delimited list of tags whose values should
+     * be accepted even if no relator subfield is defined
+     * @param relatorConfig        The setting in author-classification.ini which
+     * defines which relator terms are acceptable (or a colon-delimited list)
+     * @param acceptUnknownRelators Colon-delimited list of tags whose relators
+     * should be indexed even if they are not listed in author-classification.ini.
+     * @param indexRawRelators      Set to "true" to index relators raw, as found
+     * in the MARC or "false" to index mapped versions.
+     * @return List result
+     */
+    public List getRelatorsFilteredByRelator(Record record, String tagList,
+        String acceptWithoutRelator, String relatorConfig,
+        String acceptUnknownRelators, String indexRawRelators
+    ) {
+        // default firstOnly to false!
+        return getRelatorsFilteredByRelator(
+            record, tagList, acceptWithoutRelator, relatorConfig,
+            acceptUnknownRelators, indexRawRelators, false
+        );
+    }
+
+    /**
+     * Filter values retrieved using tagList to include only those whose relator
+     * values are acceptable. Used for saving relators of authors separated by different
+     * types.
+     *
+     * @param record               The record (fed in automatically)
+     * @param tagList              The field specification to read
+     * @param acceptWithoutRelator Colon-delimited list of tags whose values should
+     * be accepted even if no relator subfield is defined
+     * @param relatorConfig        The setting in author-classification.ini which
+     * defines which relator terms are acceptable (or a colon-delimited list)
+     * @param acceptUnknownRelators Colon-delimited list of tags whose relators
+     * should be indexed even if they are not listed in author-classification.ini.
+     * @return List result
+     */
+    public List getRelatorsFilteredByRelator(Record record, String tagList,
+        String acceptWithoutRelator, String relatorConfig,
+        String acceptUnknownRelators
+    ) {
+        // default firstOnly to false!
+        return getRelatorsFilteredByRelator(
+            record, tagList, acceptWithoutRelator, relatorConfig,
+            acceptUnknownRelators, "false", false
+        );
+    }
+
+    /**
+     * Filter values retrieved using tagList to include only those whose relator
+     * values are acceptable. Used for saving relators of authors separated by different
+     * types.
+     *
+     * @param record               The record (fed in automatically)
+     * @param tagList              The field specification to read
+     * @param acceptWithoutRelator Colon-delimited list of tags whose values should
+     * be accepted even if no relator subfield is defined
+     * @param relatorConfig        The setting in author-classification.ini which
+     * defines which relator terms are acceptable (or a colon-delimited list)
+     * @return List result
+     */
+    public List getRelatorsFilteredByRelator(Record record, String tagList,
+        String acceptWithoutRelator, String relatorConfig
+    ) {
+        // default firstOnly to false!
+        return getRelatorsFilteredByRelator(
+            record, tagList, acceptWithoutRelator, relatorConfig,
+            acceptWithoutRelator, "false", false
+        );
+    }
+
+    /**
+     * This method fetches relator definitions from ini file and casts them to an
+     * array. If a colon-delimited string is passed in, this will be directly parsed
+     * instead of resorting to .ini loading.
+     *
+     * @param setting Setting to load from .ini or colon-delimited list.
+     * @return String[]
+     */
+    protected String[] loadRelatorConfig(String setting){
+        StringBuilder relators = new StringBuilder();
+
+        // check for pipe-delimited string
+        String[] relatorSettings = setting.split("\\|");
+        for (String relatorSetting: relatorSettings) {
+            // check for colon-delimited string
+            String[] relatorArray = relatorSetting.split(":");
+            if (relatorArray.length > 1) {
+                for (int i = 0; i < relatorArray.length; i++) {
+                    relators.append(relatorArray[i]).append(",");
+                }
+            } else {
+                relators.append(ConfigManager.instance().getConfigSetting(
+                    "author-classification.ini", "AuthorRoles", relatorSetting
+                )).append(",");
+            }
+        }
+
+        return relators.toString().split(",");
+    }
+
+    /**
+     * Normalizes a relator string and returns a list containing the normalized
+     * relator plus any configured synonyms.
+     *
+     * @param relator Relator term to normalize
+     * @return List of strings
+     */
+    public List<String> normalizeRelatorAndAddSynonyms(String relator)
+    {
+        List<String> newList = new ArrayList<String>();
+        String normalized = normalizeRelatorString(relator);
+        newList.add(normalized);
+        String synonyms = ConfigManager.instance().getConfigSetting(
+            "author-classification.ini", "RelatorSynonyms", relator
+        );
+        if (null != synonyms && synonyms.length() > 0) {
+            for (String synonym: synonyms.split("\\|")) {
+                String normalizedSynonym = normalizeRelatorString(synonym);
+                relatorSynonymLookup.put(normalizedSynonym, relator);
+                newList.add(normalizedSynonym);
+            }
+        }
+        return newList;
+    }
+
+    /**
+     * Normalizes the strings in a list.
+     *
+     * @param stringList List of strings to be normalized
+     * @return Normalized List of strings 
+     */
+    protected List<String> normalizeRelatorStringList(List<String> stringList)
+    {
+        List<String> newList = new ArrayList<String>();
+        for (String relator: stringList) {
+            newList.addAll(normalizeRelatorAndAddSynonyms(relator));
+        }
+        return newList;
+    }
+
+    /**
+     * Normalizes a string
+     *
+     * @param string String to be normalized
+     * @return string
+     */
+    protected String normalizeRelatorString(String string)
+    {
+        return string
+            .trim()
+            .toLowerCase()
+            .replaceAll("\\p{Punct}+", "");    //POSIX character class Punctuation: One of !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~
+    }
+
+    /**
+     * Filter values retrieved using tagList to include only those whose relator
+     * values are acceptable. Used for separating different types of authors.
+     *
+     * @param record               The record (fed in automatically)
+     * @param tagList              The field specification to read
+     * @param acceptWithoutRelator Colon-delimited list of tags whose values should
+     * be accepted even if no relator subfield is defined
+     * @param relatorConfig        The setting in author-classification.ini which
+     * defines which relator terms are acceptable (or a colon-delimited list)
+     * @param acceptUnknownRelators Colon-delimited list of tags whose relators
+     * should be indexed even if they are not listed in author-classification.ini.
+     * @param indexRawRelators      Set to "true" to index relators raw, as found
+     * in the MARC or "false" to index mapped versions.
+     * @return List result
+     */
+    public List<String> getAuthorInitialsFilteredByRelator(Record record,
+        String tagList, String acceptWithoutRelator, String relatorConfig,
+        String acceptUnknownRelators, String indexRawRelators
+    ) {
+        List<String> authors = getAuthorsFilteredByRelator(
+            record, tagList, acceptWithoutRelator, relatorConfig,
+            acceptUnknownRelators, indexRawRelators
+        );
+        List<String> result = new LinkedList<String>();
+        for (String author : authors) {
+            result.add(processInitials(author));
+        }
+        return result;
+    }
+
+    /**
+     * Filter values retrieved using tagList to include only those whose relator
+     * values are acceptable. Used for separating different types of authors.
+     *
+     * @param record               The record (fed in automatically)
+     * @param tagList              The field specification to read
+     * @param acceptWithoutRelator Colon-delimited list of tags whose values should
+     * be accepted even if no relator subfield is defined
+     * @param relatorConfig        The setting in author-classification.ini which
+     * defines which relator terms are acceptable (or a colon-delimited list)
+     * @return List result
+     */
+    public List<String> getAuthorInitialsFilteredByRelator(Record record,
+        String tagList, String acceptWithoutRelator, String relatorConfig
+    ) {
+        return getAuthorInitialsFilteredByRelator(
+            record, tagList, acceptWithoutRelator, relatorConfig,
+            acceptWithoutRelator, "false"
+        );
+    }
+
+    /**
+     * Filter values retrieved using tagList to include only those whose relator
+     * values are acceptable. Used for separating different types of authors.
+     *
+     * @param record               The record (fed in automatically)
+     * @param tagList              The field specification to read
+     * @param acceptWithoutRelator Colon-delimited list of tags whose values should
+     * be accepted even if no relator subfield is defined
+     * @param relatorConfig        The setting in author-classification.ini which
+     * defines which relator terms are acceptable (or a colon-delimited list)
+     * @param acceptUnknownRelators Colon-delimited list of tags whose relators
+     * should be indexed even if they are not listed in author-classification.ini.
+     * @return List result
+     */
+    public List<String> getAuthorInitialsFilteredByRelator(Record record,
+        String tagList, String acceptWithoutRelator, String relatorConfig,
+        String acceptUnknownRelators
+    ) {
+        return getAuthorInitialsFilteredByRelator(
+            record, tagList, acceptWithoutRelator, relatorConfig,
+            acceptUnknownRelators, "false"
+        );
+    }
+    
+    /**
+     * Takes a name and cuts it into initials
+     * @param authorName e.g. Yeats, William Butler
+     * @return initials e.g. w b y wb
+     */
+    protected String processInitials(String authorName) {
+        Boolean isPersonalName = false;
+        // we guess that if there is a comma before the end - this is a personal name
+        if ((authorName.indexOf(',') > 0) 
+            && (authorName.indexOf(',') < authorName.length()-1)) {
+            isPersonalName = true;
+        }
+        // get rid of non-alphabet chars but keep hyphens and accents 
+        authorName = authorName.replaceAll("[^\\p{L} -]", "").toLowerCase();
+        String[] names = authorName.split(" "); //split into tokens on spaces
+        // if this is a personal name we'll reorganise to put lastname at the end
+        String result = "";
+        if (isPersonalName) {
+            String lastName = names[0]; 
+            for (int i = 0; i < names.length-1; i++) {
+                names[i] = names[i+1];
+            }
+            names[names.length-1] = lastName;
+        }
+        // put all the initials together in a space separated string
+        for (String name : names) {
+            if (name.length() > 0) {
+                String initial = name.substring(0,1);
+                // if there is a hyphenated name, use both initials
+                int pos = name.indexOf('-');
+                if (pos > 0 && pos < name.length() - 1) {
+                    String extra = name.substring(pos+1, pos+2);
+                    initial = initial + " " + extra;
+                }
+                result += " " + initial; 
+            }
+        }
+        // grab all initials and stick them together
+        String smushAll = result.replaceAll(" ", "");
+        // if it's a long personal name, get all but the last initials as well
+        // e.g. wb for william butler yeats
+        if (names.length > 2 && isPersonalName) {
+            String smushPers = result.substring(0,result.length()-1).replaceAll(" ","");
+            result = result + " " + smushPers;
+        }
+        // now we have initials separate and together
+        if (!result.trim().equals(smushAll)) {
+            result += " " + smushAll; 
+        }
+        result = result.trim();
+        return result;
+    }
+}
\ No newline at end of file
diff --git a/import/index_java/src/org/vufind/index/DatabaseManager.java b/import/index_java/src/org/vufind/index/DatabaseManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..43a4cb429d8aa74b451684978649cc280da05f66
--- /dev/null
+++ b/import/index_java/src/org/vufind/index/DatabaseManager.java
@@ -0,0 +1,156 @@
+package org.vufind.index;
+/**
+ * Database manager.
+ *
+ * Copyright (C) Villanova University 2017.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+import org.apache.log4j.Logger;
+import org.solrmarc.tools.SolrMarcIndexerException;
+import java.sql.*;
+
+/**
+ * Database manager.
+ */
+public class DatabaseManager
+{
+    // Initialize logging category
+    static Logger logger = Logger.getLogger(DatabaseManager.class.getName());
+
+    // Initialize VuFind database connection (null until explicitly activated)
+    private Connection vufindDatabase = null;
+
+    // Shutdown flag:
+    private boolean shuttingDown = false;
+
+    private static ThreadLocal<DatabaseManager> managerCache = 
+        new ThreadLocal<DatabaseManager>()
+        {
+            @Override
+            protected DatabaseManager initialValue()
+            {
+                return new DatabaseManager();
+            }
+        };
+
+    public static DatabaseManager instance()
+    {
+        return managerCache.get();
+    }
+
+    /**
+     * Log an error message and throw a fatal exception.
+     * @param msg message to log
+     */
+    private void dieWithError(String msg)
+    {
+        logger.error(msg);
+        throw new SolrMarcIndexerException(SolrMarcIndexerException.EXIT, msg);
+    }
+
+    /**
+     * Connect to the VuFind database if we do not already have a connection.
+     */
+    private void connectToDatabase()
+    {
+        // Already connected?  Do nothing further!
+        if (vufindDatabase != null) {
+            return;
+        }
+
+        String dsn = ConfigManager.instance().getConfigSetting("config.ini", "Database", "database");
+
+        try {
+            // Parse key settings from the PHP-style DSN:
+            String username = "";
+            String password = "";
+            String classname = "invalid";
+            String prefix = "invalid";
+            if (dsn.substring(0, 8).equals("mysql://")) {
+                classname = "com.mysql.jdbc.Driver";
+                prefix = "mysql";
+            } else if (dsn.substring(0, 8).equals("pgsql://")) {
+                classname = "org.postgresql.Driver";
+                prefix = "postgresql";
+            }
+
+            Class.forName(classname).newInstance();
+            String[] parts = dsn.split("://");
+            if (parts.length > 1) {
+                parts = parts[1].split("@");
+                if (parts.length > 1) {
+                    dsn = prefix + "://" + parts[1];
+                    parts = parts[0].split(":");
+                    username = parts[0];
+                    if (parts.length > 1) {
+                        password = parts[1];
+                    }
+                }
+            }
+
+            // Connect to the database:
+            vufindDatabase = DriverManager.getConnection("jdbc:" + dsn, username, password);
+        } catch (Throwable e) {
+            dieWithError("Unable to connect to VuFind database");
+        }
+
+        Runtime.getRuntime().addShutdownHook(new DatabaseManagerShutdownThread(this));
+    }
+
+    private void disconnectFromDatabase()
+    {
+        if (vufindDatabase != null) {
+            try {
+                vufindDatabase.close();
+            } catch (SQLException e) {
+                System.err.println("Unable to disconnect from VuFind database");
+                logger.error("Unable to disconnect from VuFind database");
+            }
+        }
+    }
+
+    public void shutdown()
+    {
+        disconnectFromDatabase();
+        shuttingDown = true;
+    }
+
+    public Connection getConnection()
+    {
+        connectToDatabase();
+        return vufindDatabase;
+    }
+
+    public boolean isShuttingDown()
+    {
+        return shuttingDown;
+    }
+
+    class DatabaseManagerShutdownThread extends Thread
+    {
+        private DatabaseManager manager;
+
+        public DatabaseManagerShutdownThread(DatabaseManager m)
+        {
+            manager = m;
+        }
+
+        public void run()
+        {
+            manager.shutdown();
+        }
+    }
+}
\ No newline at end of file
diff --git a/import/index_java/src/org/vufind/index/DateTools.java b/import/index_java/src/org/vufind/index/DateTools.java
new file mode 100644
index 0000000000000000000000000000000000000000..343b382df1cf3376150ec12df90cc61be3a57f71
--- /dev/null
+++ b/import/index_java/src/org/vufind/index/DateTools.java
@@ -0,0 +1,103 @@
+package org.vufind.index;
+/**
+ * Date indexing routines.
+ *
+ * Copyright (C) Villanova University 2017.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+import org.marc4j.marc.Record;
+import org.marc4j.marc.VariableField;
+import org.marc4j.marc.DataField;
+import org.marc4j.marc.Subfield;
+import org.solrmarc.tools.DataUtil;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Date indexing routines.
+ */
+public class DateTools
+{
+    /**
+     * Get all available dates from the record.
+     *
+     * @param  record MARC record
+     * @return set of dates
+     */
+    public Set<String> getDates(final Record record) {
+        Set<String> dates = new LinkedHashSet<String>();
+
+        // First check old-style 260c date:
+        List<VariableField> list260 = record.getVariableFields("260");
+        for (VariableField vf : list260) {
+            DataField df = (DataField) vf;
+            List<Subfield> currentDates = df.getSubfields('c');
+            for (Subfield sf : currentDates) {
+                String currentDateStr = DataUtil.cleanDate(sf.getData());
+                if (currentDateStr != null) dates.add(currentDateStr);
+            }
+        }
+
+        // Now track down relevant RDA-style 264c dates; we only care about
+        // copyright and publication dates (and ignore copyright dates if
+        // publication dates are present).
+        Set<String> pubDates = new LinkedHashSet<String>();
+        Set<String> copyDates = new LinkedHashSet<String>();
+        List<VariableField> list264 = record.getVariableFields("264");
+        for (VariableField vf : list264) {
+            DataField df = (DataField) vf;
+            List<Subfield> currentDates = df.getSubfields('c');
+            for (Subfield sf : currentDates) {
+                String currentDateStr = DataUtil.cleanDate(sf.getData());
+                char ind2 = df.getIndicator2();
+                switch (ind2)
+                {
+                    case '1':
+                        if (currentDateStr != null) pubDates.add(currentDateStr);
+                        break;
+                    case '4':
+                        if (currentDateStr != null) copyDates.add(currentDateStr);
+                        break;
+                }
+            }
+        }
+        if (pubDates.size() > 0) {
+            dates.addAll(pubDates);
+        } else if (copyDates.size() > 0) {
+            dates.addAll(copyDates);
+        }
+
+        return dates;
+    }
+
+    /**
+     * Get the earliest publication date from the record.
+     *
+     * @param  record MARC record
+     * @return earliest date
+     */
+    public String getFirstDate(final Record record) {
+        String result = null;
+        Set<String> dates = getDates(record);
+        for(String current: dates) {
+            if (result == null || Integer.parseInt(current) < Integer.parseInt(result)) {
+                result = current;
+            }
+        }
+        return result;
+    }
+}
\ No newline at end of file
diff --git a/import/index_java/src/org/vufind/index/FormatCalculator.java b/import/index_java/src/org/vufind/index/FormatCalculator.java
new file mode 100644
index 0000000000000000000000000000000000000000..0c97299cae8c73a1a52fd399e2024bf16480d9c5
--- /dev/null
+++ b/import/index_java/src/org/vufind/index/FormatCalculator.java
@@ -0,0 +1,327 @@
+package org.vufind.index;
+/**
+ * Format determination logic.
+ *
+ * Copyright (C) Villanova University 2017.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+import org.marc4j.marc.Record;
+import org.marc4j.marc.ControlField;
+import org.marc4j.marc.DataField;
+import org.marc4j.marc.VariableField;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Format determination logic.
+ */
+public class FormatCalculator
+{
+    /**
+     * Determine Record Format(s)
+     *
+     * @param  record MARC record
+     * @return set of record formats
+     */
+    public Set<String> getFormat(final Record record){
+        Set<String> result = new LinkedHashSet<String>();
+        String leader = record.getLeader().toString();
+        char leaderBit;
+        ControlField fixedField = (ControlField) record.getVariableField("008");
+        DataField title = (DataField) record.getVariableField("245");
+        String formatString;
+        char formatCode = ' ';
+        char formatCode2 = ' ';
+        char formatCode4 = ' ';
+
+        // check if there's an h in the 245
+        if (title != null) {
+            if (title.getSubfield('h') != null){
+                if (title.getSubfield('h').getData().toLowerCase().contains("[electronic resource]")) {
+                    result.add("Electronic");
+                    return result;
+                }
+            }
+        }
+
+        // check the 007 - this is a repeating field
+        List<VariableField> fields = record.getVariableFields("007");
+        Iterator<VariableField> fieldsIter = fields.iterator();
+        if (fields != null) {
+            // TODO: update loop to for(:) syntax, but problem with type casting.
+            ControlField formatField;
+            while(fieldsIter.hasNext()) {
+                formatField = (ControlField) fieldsIter.next();
+                formatString = formatField.getData().toUpperCase();
+                formatCode = formatString.length() > 0 ? formatString.charAt(0) : ' ';
+                formatCode2 = formatString.length() > 1 ? formatString.charAt(1) : ' ';
+                formatCode4 = formatString.length() > 4 ? formatString.charAt(4) : ' ';
+                switch (formatCode) {
+                    case 'A':
+                        switch(formatCode2) {
+                            case 'D':
+                                result.add("Atlas");
+                                break;
+                            default:
+                                result.add("Map");
+                                break;
+                        }
+                        break;
+                    case 'C':
+                        switch(formatCode2) {
+                            case 'A':
+                                result.add("TapeCartridge");
+                                break;
+                            case 'B':
+                                result.add("ChipCartridge");
+                                break;
+                            case 'C':
+                                result.add("DiscCartridge");
+                                break;
+                            case 'F':
+                                result.add("TapeCassette");
+                                break;
+                            case 'H':
+                                result.add("TapeReel");
+                                break;
+                            case 'J':
+                                result.add("FloppyDisk");
+                                break;
+                            case 'M':
+                            case 'O':
+                                result.add("CDROM");
+                                break;
+                            case 'R':
+                                // Do not return - this will cause anything with an
+                                // 856 field to be labeled as "Electronic"
+                                break;
+                            default:
+                                result.add("Software");
+                                break;
+                        }
+                        break;
+                    case 'D':
+                        result.add("Globe");
+                        break;
+                    case 'F':
+                        result.add("Braille");
+                        break;
+                    case 'G':
+                        switch(formatCode2) {
+                            case 'C':
+                            case 'D':
+                                result.add("Filmstrip");
+                                break;
+                            case 'T':
+                                result.add("Transparency");
+                                break;
+                            default:
+                                result.add("Slide");
+                                break;
+                        }
+                        break;
+                    case 'H':
+                        result.add("Microfilm");
+                        break;
+                    case 'K':
+                        switch(formatCode2) {
+                            case 'C':
+                                result.add("Collage");
+                                break;
+                            case 'D':
+                                result.add("Drawing");
+                                break;
+                            case 'E':
+                                result.add("Painting");
+                                break;
+                            case 'F':
+                                result.add("Print");
+                                break;
+                            case 'G':
+                                result.add("Photonegative");
+                                break;
+                            case 'J':
+                                result.add("Print");
+                                break;
+                            case 'L':
+                                result.add("Drawing");
+                                break;
+                            case 'O':
+                                result.add("FlashCard");
+                                break;
+                            case 'N':
+                                result.add("Chart");
+                                break;
+                            default:
+                                result.add("Photo");
+                                break;
+                        }
+                        break;
+                    case 'M':
+                        switch(formatCode2) {
+                            case 'F':
+                                result.add("VideoCassette");
+                                break;
+                            case 'R':
+                                result.add("Filmstrip");
+                                break;
+                            default:
+                                result.add("MotionPicture");
+                                break;
+                        }
+                        break;
+                    case 'O':
+                        result.add("Kit");
+                        break;
+                    case 'Q':
+                        result.add("MusicalScore");
+                        break;
+                    case 'R':
+                        result.add("SensorImage");
+                        break;
+                    case 'S':
+                        switch(formatCode2) {
+                            case 'D':
+                                result.add("SoundDisc");
+                                break;
+                            case 'S':
+                                result.add("SoundCassette");
+                                break;
+                            default:
+                                result.add("SoundRecording");
+                                break;
+                        }
+                        break;
+                    case 'V':
+                        switch(formatCode2) {
+                            case 'C':
+                                result.add("VideoCartridge");
+                                break;
+                            case 'D':
+                                switch(formatCode4) {
+                                    case 'S':
+                                        result.add("BRDisc");
+                                        break;
+                                    case 'V':
+                                    default:
+                                        result.add("VideoDisc");
+                                        break;
+                                }
+                                break;
+                            case 'F':
+                                result.add("VideoCassette");
+                                break;
+                            case 'R':
+                                result.add("VideoReel");
+                                break;
+                            default:
+                                result.add("Video");
+                                break;
+                        }
+                        break;
+                }
+            }
+            if (!result.isEmpty()) {
+                return result;
+            }
+        }
+
+        // check the Leader at position 6
+        leaderBit = leader.charAt(6);
+        switch (Character.toUpperCase(leaderBit)) {
+            case 'C':
+            case 'D':
+                result.add("MusicalScore");
+                break;
+            case 'E':
+            case 'F':
+                result.add("Map");
+                break;
+            case 'G':
+                result.add("Slide");
+                break;
+            case 'I':
+                result.add("SoundRecording");
+                break;
+            case 'J':
+                result.add("MusicRecording");
+                break;
+            case 'K':
+                result.add("Photo");
+                break;
+            case 'M':
+                result.add("Electronic");
+                break;
+            case 'O':
+            case 'P':
+                result.add("Kit");
+                break;
+            case 'R':
+                result.add("PhysicalObject");
+                break;
+            case 'T':
+                result.add("Manuscript");
+                break;
+        }
+        if (!result.isEmpty()) {
+            return result;
+        }
+
+        // check the Leader at position 7
+        leaderBit = leader.charAt(7);
+        switch (Character.toUpperCase(leaderBit)) {
+            // Monograph
+            case 'M':
+                if (formatCode == 'C') {
+                    result.add("eBook");
+                } else {
+                    result.add("Book");
+                }
+                break;
+            // Component parts
+            case 'A':
+                result.add("BookComponentPart");
+                break;
+            case 'B':
+                result.add("SerialComponentPart");
+                break;
+            // Serial
+            case 'S':
+                // Look in 008 to determine what type of Continuing Resource
+                formatCode = fixedField.getData().toUpperCase().charAt(21);
+                switch (formatCode) {
+                    case 'N':
+                        result.add("Newspaper");
+                        break;
+                    case 'P':
+                        result.add("Journal");
+                        break;
+                    default:
+                        result.add("Serial");
+                        break;
+                }
+        }
+
+        // Nothing worked!
+        if (result.isEmpty()) {
+            result.add("Unknown");
+        }
+
+        return result;
+    }
+}
\ No newline at end of file
diff --git a/import/index_java/src/org/vufind/index/FullTextTools.java b/import/index_java/src/org/vufind/index/FullTextTools.java
new file mode 100644
index 0000000000000000000000000000000000000000..0ab0bb3c7198cd465d1b158290154ca868f148c3
--- /dev/null
+++ b/import/index_java/src/org/vufind/index/FullTextTools.java
@@ -0,0 +1,311 @@
+package org.vufind.index;
+/**
+ * Full text retrieval indexing routines.
+ *
+ * Copyright (C) Villanova University 2017.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+import org.marc4j.marc.Record;
+import java.io.*;
+import java.util.Iterator;
+import java.util.Set;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.apache.log4j.Logger;
+import org.solrmarc.index.SolrIndexer;
+import org.solrmarc.tools.SolrMarcIndexerException;
+
+/**
+ * Full text retrieval indexing routines.
+ */
+public class FullTextTools
+{
+    // Initialize logging category
+    static Logger logger = Logger.getLogger(FullTextTools.class.getName());
+
+    /**
+     * Load configurations for the full text parser.  Return an array containing the
+     * parser type in the first element and the parser configuration in the second
+     * element.
+     *
+     * @return String[]
+     */
+    public String[] getFulltextParserSettings()
+    {
+        String parserType = ConfigManager.instance().getConfigSetting(
+            "fulltext.ini", "General", "parser"
+        );
+        if (null != parserType) {
+            parserType = parserType.toLowerCase();
+        }
+
+        // Is Aperture active?
+        String aperturePath = ConfigManager.instance().getConfigSetting(
+            "fulltext.ini", "Aperture", "webcrawler"
+        );
+        if ((null == parserType && null != aperturePath)
+            || (null != parserType && parserType.equals("aperture"))
+        ) {
+            String[] array = { "aperture", aperturePath };
+            return array;
+        }
+
+        // Is Tika active?
+        String tikaPath = ConfigManager.instance().getConfigSetting(
+            "fulltext.ini", "Tika", "path"
+        );
+        if ((null == parserType && null != tikaPath)
+            || (null != parserType && parserType.equals("tika"))
+        ) {
+            String[] array = { "tika", tikaPath };
+            return array;
+        }
+
+        // No recognized parser found:
+        String[] array = { "none", null };
+        return array;
+    }
+
+    /**
+     * Extract full-text from the documents referenced in the tags
+     *
+     * @param Record record current MARC record
+     * @param String field spec to search for URLs
+     * @param String only harvest files matching this extension (null for all)
+     * @return String The full-text
+     */
+    public String getFulltext(Record record, String fieldSpec, String extension) {
+        String result = "";
+
+        // Get the web crawler settings (and return no text if it is unavailable)
+        String[] parserSettings = getFulltextParserSettings();
+        if (parserSettings[0].equals("none")) {
+            return null;
+        }
+
+        // Loop through the specified MARC fields:
+        Set<String> fields = SolrIndexer.instance().getFieldList(record, fieldSpec);
+        Iterator<String> fieldsIter = fields.iterator();
+        if (fields != null) {
+            while(fieldsIter.hasNext()) {
+                // Get the current string to work on (and sanitize spaces):
+                String current = fieldsIter.next().replaceAll(" ", "%20");
+                // Filter by file extension
+                if (extension == null || current.endsWith(extension)) {
+                    // Load the parser output for each tag into a string
+                    result = result + harvestWithParser(current, parserSettings);
+                }
+            }
+        }
+        // return string to SolrMarc
+        return result;
+    }
+
+    /**
+     * Extract full-text from the documents referenced in the tags
+     *
+     * @param Record record current MARC record
+     * @param String field spec to search for URLs
+     * @return String The full-text
+     */
+    public String getFulltext(Record record, String fieldSpec) {
+        return getFulltext(record, fieldSpec, null);
+    }
+
+    /**
+     * Extract full-text from the documents referenced in the tags
+     *
+     * @param Record record current MARC record
+     * @return String The full-text
+     */
+    public String getFulltext(Record record) {
+        return getFulltext(record, "856u", null);
+    }
+
+    /**
+     * Clean up XML data generated by Aperture
+     *
+     * @param f file to clean
+     * @return a fixed version of the file
+     */
+    public File sanitizeApertureOutput(File f) throws IOException
+    {
+        //clean up the aperture xml output
+        File tempFile = File.createTempFile("buffer", ".tmp");
+        FileOutputStream fw = new FileOutputStream(tempFile);
+        OutputStreamWriter writer = new OutputStreamWriter(fw, "UTF8");
+
+        //delete this control character from the File and save
+        FileReader fr = new FileReader(f);
+        BufferedReader br = new BufferedReader(fr);
+        while (br.ready()) {
+            writer.write(sanitizeFullText(br.readLine()));
+        }
+        writer.close();
+        br.close();
+        fr.close();
+
+        return tempFile;
+    }
+
+    /**
+     * Clean up bad characters in the full text.
+     *
+     * @param text text to clean
+     * @return cleaned text
+     */
+    public String sanitizeFullText(String text)
+    {
+        String badChars = "[^\\u0009\\u000A\\u000D\\u0020-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]+";
+        return text.replaceAll(badChars, " ");
+    }
+
+    /**
+     * Harvest the contents of a document file (PDF, Word, etc.) using Aperture.
+     * This method will only work if Aperture is properly configured in the
+     * fulltext.ini file.  Without proper configuration, this will simply return an
+     * empty string.
+     *
+     * @param url the url extracted from the MARC tag.
+     * @param aperturePath The path to Aperture
+     * @return full-text extracted from url
+     */
+    public String harvestWithAperture(String url, String aperturePath) {
+        String plainText = "";
+        // Create temp file.
+        File f = null;
+        try {
+            f = File.createTempFile("apt", ".txt");
+        } catch (Throwable e) {
+            dieWithError("Unable to create temporary file for full text harvest.");
+        }
+
+        // Delete temp file when program exits.
+        f.deleteOnExit();
+
+        // Construct the command to call Aperture
+        String cmd = aperturePath + " -o " + f.getAbsolutePath().toString()  + " -x " + url;
+
+        // Call Aperture
+        //System.out.println("Loading fulltext from " + url + ". Please wait ...");
+        try {
+            Process p = Runtime.getRuntime().exec(cmd);
+            
+            // Debugging output
+            /*
+            BufferedReader stdInput = new BufferedReader(new
+                InputStreamReader(p.getInputStream()));
+            String s;
+            while ((s = stdInput.readLine()) != null) {
+                System.out.println(s);
+            }
+            */
+            
+            // Wait for Aperture to finish
+            p.waitFor();
+        } catch (Throwable e) {
+            logger.error("Problem executing Aperture -- " + e.getMessage());
+        }
+
+        // Parse Aperture XML output
+        Document xmlDoc = null;
+        try {
+            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+            DocumentBuilder db = dbf.newDocumentBuilder();
+            File tempFile = sanitizeApertureOutput(f);
+            xmlDoc = db.parse(tempFile);
+            NodeList nl = xmlDoc.getElementsByTagName("plainTextContent");
+            if(nl != null && nl.getLength() > 0) {
+                Node node = nl.item(0);
+                if (node.getNodeType() == Node.ELEMENT_NODE) {
+                    plainText = plainText + node.getTextContent();
+                }
+            }
+
+            // we'll hold onto the temp file if it failed to parse for debugging;
+            // only set it up to be deleted if we've made it this far successfully.
+            tempFile.deleteOnExit();
+        } catch (Throwable e) {
+            logger.error("Problem parsing Aperture XML -- " + e.getMessage());
+        }
+
+        return plainText;
+    }
+
+    /**
+     * Harvest the contents of a document file (PDF, Word, etc.) using Tika.
+     * This method will only work if Tika is properly configured in the fulltext.ini
+     * file.  Without proper configuration, this will simply return an empty string.
+     *
+     * @param url the url extracted from the MARC tag.
+     * @param scraperPath path to Tika
+     * @return the full-text
+     */
+    public String harvestWithTika(String url, String scraperPath) {
+
+        // Construct the command
+        String cmd = "java -jar " + scraperPath + " -t -eUTF8 " + url;
+
+        StringBuilder stringBuilder= new StringBuilder();
+
+        // Call our scraper
+        //System.out.println("Loading fulltext from " + url + ". Please wait ...");
+        try {
+            Process p = Runtime.getRuntime().exec(cmd);
+            BufferedReader stdInput = new BufferedReader(new
+                InputStreamReader(p.getInputStream(), "UTF8"));
+
+            // We'll build the string from the command output
+            String s;
+            while ((s = stdInput.readLine()) != null) {
+                stringBuilder.append(s);
+            }
+        } catch (Throwable e) {
+            logger.error("Problem with Tika -- " + e.getMessage());
+        }
+
+        return sanitizeFullText(stringBuilder.toString());
+    }
+
+    /**
+     * Harvest the contents of a document file (PDF, Word, etc.) using the active parser.
+     *
+     * @param url the URL extracted from the MARC tag.
+     * @param settings configuration settings from {@code getFulltextParserSettings}.
+     * @return the full-text
+     */
+    public String harvestWithParser(String url, String[] settings) {
+        if (settings[0].equals("aperture")) {
+            return harvestWithAperture(url, settings[1]);
+        } else if (settings[0].equals("tika")) {
+            return harvestWithTika(url, settings[1]);
+        }
+        return null;
+    }
+
+    /**
+     * Log an error message and throw a fatal exception.
+     * @param msg message to log
+     */
+    private void dieWithError(String msg)
+    {
+        logger.error(msg);
+        throw new SolrMarcIndexerException(SolrMarcIndexerException.EXIT, msg);
+    }
+}
\ No newline at end of file
diff --git a/import/index_java/src/org/vufind/index/GeoTools.java b/import/index_java/src/org/vufind/index/GeoTools.java
new file mode 100644
index 0000000000000000000000000000000000000000..65d5fe7e7dd78d2bf2bfb8abe896661282f85431
--- /dev/null
+++ b/import/index_java/src/org/vufind/index/GeoTools.java
@@ -0,0 +1,408 @@
+package org.vufind.index;
+/**
+ * Geographic indexing routines.
+ *
+ * This code is designed to get latitude and longitude coordinates.
+ * Records can have multiple coordinates sets of points and/or rectangles.
+ * Points are represented by coordinate sets where N=S E=W.
+ *
+ * code adapted from xrosecky - Moravian Library
+ * https://github.com/moravianlibrary/VuFind-2.x/blob/master/import/index_scripts/geo.bsh
+ *
+ * Copyright (C) Villanova University 2017.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import org.apache.log4j.Logger;
+import org.marc4j.marc.Record;
+import org.marc4j.marc.VariableField;
+import org.marc4j.marc.ControlField;
+import org.marc4j.marc.DataField;
+import org.marc4j.marc.Subfield;
+import java.util.HashMap;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Geographic indexing routines.
+ */
+public class GeoTools
+{
+    private static final Pattern COORDINATES_PATTERN = Pattern.compile("^([eEwWnNsS])(\\d{3})(\\d{2})(\\d{2})");
+    private static final Pattern HDMSHDD_PATTERN = Pattern.compile("^([eEwWnNsS])(\\d+(\\.\\d+)?)");
+    private static final Pattern PMDD_PATTERN = Pattern.compile("^([+-])(\\d+(\\.\\d+)?)");
+
+    // Initialize logging category
+    static Logger logger = Logger.getLogger(GeoTools.class.getName());
+
+    /**
+     * Convert MARC coordinates into long_lat format.
+     *
+     * @param  Record record
+     * @return List   geo_coordinates
+     */
+    public List<String> getAllCoordinates(Record record) {
+        List<String> geo_coordinates = new ArrayList<String>();
+        List<VariableField> list034 = record.getVariableFields("034");
+        if (list034 != null) {
+            for (VariableField vf : list034) {
+                HashMap<Character, String> coords = getCoordinateValues(vf);
+                //DEBUG output
+                //ControlField recID = (ControlField) record.getVariableField("001");
+                //String recNum = recID.getData();
+                //logger.info("Record ID: " + recNum.trim() + " ...Coordinates: [ {" + coords.get('d') + "} {" + coords.get('e') + "} {" + coords.get('f') + "} {" + coords.get('g') + "} ]");
+
+                // Check for null coordinates
+                if (validateCoordinateValues(record, coords)) {
+                    // Check and convert coordinates to +/- decimal degrees
+                    Double west = convertCoordinate(coords.get('d'));
+                    Double east = convertCoordinate(coords.get('e'));
+                    Double north = convertCoordinate(coords.get('f'));
+                    Double south = convertCoordinate(coords.get('g'));
+                    if (validateDDCoordinates(record, west, east, north, south)) {
+                        // New Format for indexing coordinates in Solr 5.0 - minX, maxX, maxY, minY
+                        // Note - storage in Solr follows the WENS order, but display is WSEN order
+                        String result = String.format("ENVELOPE(%s,%s,%s,%s)", new Object[] { west, east, north, south });
+                        geo_coordinates.add(result);
+                    }  else {
+                        logger.error(".......... Not indexing INVALID coordinates: [ {" + coords.get('d') + "} {" + coords.get('e') + "} {" + coords.get('f') + "} {" + coords.get('g') + "} ]");
+                    }
+                } else {
+                    logger.error(".......... Not indexing INVALID coordinates: [ {" + coords.get('d') + "} {" + coords.get('e') + "} {" + coords.get('f') + "} {" + coords.get('g') + "} ]");
+                }
+            }
+        }
+        return geo_coordinates;
+    }
+
+    /**
+     * Get all available coordinates from the record.
+     *
+     * @param  Record record
+     * @return List   geo_coordinates
+     */
+    public List<String> getDisplayCoordinates(Record record) {
+        List<String> geo_coordinates = new ArrayList<String>();
+        List<VariableField> list034 = record.getVariableFields("034");
+        if (list034 != null) {
+            for (VariableField vf : list034) {
+                HashMap<Character, String> coords = getCoordinateValues(vf);
+                // Check for null coordinates
+                if (validateCoordinateValues(record, coords)) {
+                    String result = String.format("%s %s %s %s", new Object[] {  coords.get('d'),  coords.get('e'),  coords.get('f'),  coords.get('g') });
+                    geo_coordinates.add(result);
+                } else {
+                    logger.error(".......... Not indexing INVALID Display coordinates: [ {" + coords.get('d') + "} {" + coords.get('e') + "} {" + coords.get('f') + "} {" + coords.get('g') + "} ]");
+                }
+            }
+        }
+        return geo_coordinates;
+    }
+
+    /**
+     * Get all coordinate values from list034
+     *
+     * @param  VariableField vf
+     * @return HashMap full_coords
+     */
+    protected HashMap<Character, String> getCoordinateValues(VariableField vf) {
+        DataField df = (DataField) vf;
+        HashMap<Character, String> coords = new HashMap();
+        for (char code = 'd'; code <= 'g'; code++) {
+            Subfield subfield = df.getSubfield(code);
+            if (subfield != null) {
+                coords.put(code, subfield.getData());
+            }
+        }
+        // If coordinate set is a point with 2 coordinates, fill the empty values.
+        HashMap<Character, String> full_coords = fillEmptyPointCoordinates(coords);
+        return full_coords;
+    }
+
+    /**
+     * If coordinates are a point, fill empty N/S or E/W coordinate
+     *
+     * @param  HashMap coords
+     * @return HashMap full_coords
+     */
+    protected HashMap<Character, String> fillEmptyPointCoordinates(HashMap coords) {
+        HashMap<Character, String> full_coords = coords;
+        if (coords.containsKey('d') && !coords.containsKey('e') && coords.containsKey('f') && !coords.containsKey('g')) {
+            full_coords.put('e', coords.get('d').toString());
+            full_coords.put('g', coords.get('f').toString());
+        }
+        if (coords.containsKey('e') && !coords.containsKey('d') && coords.containsKey('g') && !coords.containsKey('h')) {
+            full_coords.put('d', coords.get('e').toString());
+            full_coords.put('f', coords.get('g').toString());
+        }
+        return full_coords;
+    }
+
+    /**
+    * Check record coordinates to make sure they do not contain null values.
+    *
+    * @param  Record record
+    * @param  HashMap coords
+    * @return boolean
+    */
+   protected boolean validateCoordinateValues(Record record, HashMap coords) {
+        if (coords.containsKey('d') && coords.containsKey('e') && coords.containsKey('f') && coords.containsKey('g')) {
+            return true;
+        }
+        ControlField recID = (ControlField) record.getVariableField("001");
+        String recNum = recID.getData();
+        logger.error("Record ID: " + recNum.trim() + " - Coordinate values contain null values.");
+        return false;
+    }
+
+    /**
+     * Check coordinate type HDMS HDD or +/-DD.
+     *
+     * @param  String coordinateStr
+     * @return Double coordinate
+     */
+    protected Double convertCoordinate(String coordinateStr) {
+        Double coordinate = Double.NaN;
+        Matcher HDmatcher = HDMSHDD_PATTERN.matcher(coordinateStr);
+        Matcher PMDmatcher = PMDD_PATTERN.matcher(coordinateStr);
+        if (HDmatcher.matches()) {
+            String hemisphere = HDmatcher.group(1).toUpperCase();
+            Double degrees = Double.parseDouble(HDmatcher.group(2));
+            // Check for HDD or HDMS
+            if (hemisphere.equals("N") || hemisphere.equals("S")) {
+                if (degrees > 90) {
+                    String hdmsCoordinate = hemisphere+"0"+HDmatcher.group(2);
+                    coordinate = coordinateToDecimal(hdmsCoordinate);
+                } else {
+                    coordinate = Double.parseDouble(HDmatcher.group(2));
+                    if (hemisphere.equals("S")) {
+                        coordinate *= -1;
+                    }
+                }
+            }
+            if (hemisphere.equals("E") || hemisphere.equals("W")) {
+                if (degrees > 180) {
+                    String hdmsCoordinate = HDmatcher.group(0);
+                    coordinate = coordinateToDecimal(hdmsCoordinate);
+                } else {
+                    coordinate = Double.parseDouble(HDmatcher.group(2));
+                    if (hemisphere.equals("W")) {
+                        coordinate *= -1;
+                    }
+                }
+            }
+            return coordinate;
+        } else if (PMDmatcher.matches()) {
+            String hemisphere = PMDmatcher.group(1);
+            coordinate = Double.parseDouble(PMDmatcher.group(2));
+            if (hemisphere.equals("-")) {
+                coordinate *= -1;
+            }
+            return coordinate;
+        } else {
+            logger.error("Decimal Degree Coordinate Conversion Error:  Poorly formed coordinate: [" + coordinateStr + "] ... Returning null value ... ");
+            return null;
+        }
+    }
+
+    /**
+     * Convert HDMS coordinates to decimal degrees.
+     *
+     * @param  String coordinateStr
+     * @return Double coordinate
+     */
+    protected Double coordinateToDecimal(String coordinateStr) {
+        Matcher matcher = COORDINATES_PATTERN.matcher(coordinateStr);
+        if (matcher.matches()) {
+            String hemisphere = matcher.group(1).toUpperCase();
+            int degrees = Integer.parseInt(matcher.group(2));
+            int minutes = Integer.parseInt(matcher.group(3));
+            int seconds = Integer.parseInt(matcher.group(4));
+            double coordinate = degrees + (minutes / 60.0) + (seconds / 3600.0);
+            if (hemisphere.equals("W") || hemisphere.equals("S")) {
+                coordinate *= -1;
+            }
+            return coordinate;
+        }
+        return null;
+    }
+
+    /**
+     * Check decimal degree coordinates to make sure they are valid.
+     *
+     * @param  Record record
+     * @param  Double west, east, north, south
+     * @return boolean
+     */
+    protected boolean validateDDCoordinates(Record record, Double west, Double east, Double north, Double south) {
+        boolean validValues = true;
+        boolean validLines = true;
+        boolean validExtent = true;
+        boolean validNorthSouth = true;
+        boolean validEastWest = true;
+        boolean validCoordDist = true;
+
+        if (validateValues(record, west, east, north, south)) {
+            validLines = validateLines(record, west, east, north, south);
+            validExtent = validateExtent(record, west, east, north, south);
+            validNorthSouth = validateNorthSouth(record, north, south);
+            validEastWest = validateEastWest(record, east, west);
+            validCoordDist = validateCoordinateDistance(record, west, east, north, south);
+        } else {
+            return false;
+        }
+
+        // Validate all coordinate combinations
+        if (!validLines || !validExtent || !validNorthSouth || !validEastWest || !validCoordDist) {
+            return false;
+        } else {
+            return true;
+        }
+    }
+
+    /**
+    * Check decimal degree coordinates to make sure they do not form a line at the poles.
+    *
+    * @param  Record record
+    * @param  Double west, east, north, south
+    * @return boolean
+    */
+   public boolean validateLines(Record record, Double west, Double east, Double north, Double south) {
+    if ((!west.equals(east) && north.equals(south)) && (north == 90 || south == -90)) {
+        ControlField recID = (ControlField) record.getVariableField("001");
+        String recNum = recID.getData();
+        logger.error("Record ID: " + recNum.trim() + " - Coordinates form a line at the pole");
+        return false;
+    }
+    return true;
+   }
+
+    /**
+    * Check decimal degree coordinates to make sure they do not contain null values.
+    *
+    * @param  Record record
+    * @param  Double west, east, north, south
+    * @return boolean
+    */
+   public boolean validateValues(Record record, Double west, Double east, Double north, Double south) {
+    if (west == null || east == null || north == null || south == null) {
+        ControlField recID = (ControlField) record.getVariableField("001");
+        String recNum = recID.getData();
+        logger.error("Record ID: " + recNum.trim() + " - Decimal Degree coordinates contain null values: [ {" + west + "} {" + east + "} {" + north + "} {" + south + "} ]");
+        return false;
+    }
+    return true;
+   }
+
+    /**
+    * Check decimal degree coordinates to make sure they are within map extent.
+    *
+    * @param  Record record
+    * @param  Double west, east, north, south
+    * @return boolean
+    */
+   public boolean validateExtent(Record record, Double west, Double east, Double north, Double south) {
+    if (west > 180.0 || west < -180.0 || east > 180.0 || east < -180.0) {
+        ControlField recID = (ControlField) record.getVariableField("001");
+        String recNum = recID.getData();
+        logger.error("Record ID: " + recNum.trim() + " - Coordinates exceed map extent.");
+        return false;
+    }
+    if (north > 90.0 || north < -90.0 || south > 90.0 || south < -90.0) {
+        ControlField recID = (ControlField) record.getVariableField("001");
+        String recNum = recID.getData();
+        logger.error("Record ID: " + recNum.trim() + " - Coordinates exceed map extent.");
+        return false;
+    }
+    return true;
+   }
+
+    /**
+    * Check decimal degree coordinates to make sure that north is not less than south.
+    *
+    * @param  Record record
+    * @param  Double north, south
+    * @return boolean
+    */
+   public boolean validateNorthSouth(Record record, Double north, Double south) {
+    if (north < south) {
+        ControlField recID = (ControlField) record.getVariableField("001");
+        String recNum = recID.getData();
+        logger.error("Record ID: " + recNum.trim() + " - North < South.");
+        return false;
+    }
+    return true;
+   }
+
+    /**
+    * Check decimal degree coordinates to make sure that east is not less than west.
+    *
+    * @param  Record record
+    * @param  Double east, west
+    * @return boolean
+    */
+   public boolean validateEastWest(Record record, Double east, Double west) {
+    if (east < west) {
+       // Convert to 360 degree grid
+       if (east < 0) {
+           east = 360 + east;
+       }
+       if (west < 0) {
+           west = 360 + west;
+       }
+       // Check again
+       if (east < west) {
+           ControlField recID = (ControlField) record.getVariableField("001");
+           String recNum = recID.getData();
+           logger.error("Record ID: " + recNum.trim() + " - East < West.");
+           return false;
+       }
+    }
+    return true;
+   }
+
+    /**
+     * Check decimal degree coordinates to make sure they are not too close.
+     * Coordinates too close will cause Solr to run out of memory during indexing.
+     *
+     * @param  Record record
+     * @param  Double west, east, north, south
+     * @return boolean
+     */
+    public boolean validateCoordinateDistance(Record record, Double west, Double east, Double north, Double south) {
+        Double distEW = east - west;
+        Double distNS = north - south;
+
+        //Check for South Pole coordinate distance
+        if ((north == -90 || south == -90) && (distNS > 0 && distNS < 0.167)) {
+            ControlField recID = (ControlField) record.getVariableField("001");
+            String recNum = recID.getData();
+            logger.error("Record ID: " + recNum.trim() + " - Coordinates < 0.167 degrees from South Pole. Coordinate Distance: "+distNS);
+            return false;
+        }
+
+        //Check for East-West coordinate distance
+        if ((west == 0 || east == 0) && (distEW > -2 && distEW <0)) {
+            ControlField recID = (ControlField) record.getVariableField("001");
+            String recNum = recID.getData();
+            logger.error("Record ID: " + recNum.trim() + " - Coordinates within 2 degrees of Prime Meridian. Coordinate Distance: "+distEW);
+            return false;
+        }
+        return true;
+    }
+}
diff --git a/import/index_java/src/org/vufind/index/IllustrationTools.java b/import/index_java/src/org/vufind/index/IllustrationTools.java
new file mode 100644
index 0000000000000000000000000000000000000000..36578eff7df8653ad77581a3147a747932830f97
--- /dev/null
+++ b/import/index_java/src/org/vufind/index/IllustrationTools.java
@@ -0,0 +1,104 @@
+package org.vufind.index;
+/**
+ * Illustration indexing routines.
+ *
+ * Copyright (C) Villanova University 2017.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+import java.util.Iterator;
+import org.marc4j.marc.Record;
+import org.marc4j.marc.VariableField;
+import org.marc4j.marc.ControlField;
+import org.marc4j.marc.DataField;
+import org.marc4j.marc.Subfield;
+import java.util.List;
+
+/**
+ * Illustration indexing routines.
+ */
+public class IllustrationTools
+{
+    /**
+     * Determine if a record is illustrated.
+     *
+     * @param record  current MARC record
+     * @return "Illustrated" or "Not Illustrated"
+     */
+    public String isIllustrated(Record record) {
+        String leader = record.getLeader().toString();
+
+        // Does the leader indicate this is a "language material" that might have extra
+        // illustration details in the fixed fields?
+        if (leader.charAt(6) == 'a') {
+            String currentCode = "";         // for use in loops below
+
+            // List of 008/18-21 codes that indicate illustrations:
+            String illusCodes = "abcdefghijklmop";
+
+            // Check the illustration characters of the 008:
+            ControlField fixedField = (ControlField) record.getVariableField("008");
+            if (fixedField != null) {
+                String fixedFieldText = fixedField.getData().toLowerCase();
+                for (int i = 18; i <= 21; i++) {
+                    if (i < fixedFieldText.length()) {
+                        currentCode = fixedFieldText.substring(i, i + 1);
+                        if (illusCodes.contains(currentCode)) {
+                            return "Illustrated";
+                        }
+                    }
+                }
+            }
+
+            // Now check if any 006 fields apply:
+            List<VariableField> fields = record.getVariableFields("006");
+            Iterator<VariableField> fieldsIter = fields.iterator();
+            if (fields != null) {
+                while(fieldsIter.hasNext()) {
+                    fixedField = (ControlField) fieldsIter.next();
+                    String fixedFieldText = fixedField.getData().toLowerCase();
+                    for (int i = 1; i <= 4; i++) {
+                         if (i < fixedFieldText.length()) {
+                            currentCode = fixedFieldText.substring(i, i + 1);
+                            if (illusCodes.contains(currentCode)) {
+                                return "Illustrated";
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        // Now check for interesting strings in 300 subfield b:
+        List<VariableField> fields = record.getVariableFields("300");
+        Iterator<VariableField> fieldsIter = fields.iterator();
+        if (fields != null) {
+            DataField physical;
+            while(fieldsIter.hasNext()) {
+                physical = (DataField) fieldsIter.next();
+                List<Subfield> subfields = physical.getSubfields('b');
+                for (Subfield sf: subfields) {
+                    String desc = sf.getData().toLowerCase();
+                    if (desc.contains("ill.") || desc.contains("illus.")) {
+                        return "Illustrated";
+                    }
+                }
+            }
+        }
+
+        // If we made it this far, we found no sign of illustrations:
+        return "Not Illustrated";
+    }
+}
\ No newline at end of file
diff --git a/import/index_java/src/org/vufind/index/LccnTools.java b/import/index_java/src/org/vufind/index/LccnTools.java
new file mode 100644
index 0000000000000000000000000000000000000000..65536146eca97e2d4b1ee2191e8f1e4eb7ec3f9b
--- /dev/null
+++ b/import/index_java/src/org/vufind/index/LccnTools.java
@@ -0,0 +1,157 @@
+package org.vufind.index;
+/**
+ * LCCN indexing routines.
+ *
+ * Copyright (C) Villanova University 2017.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+import org.marc4j.marc.Record;
+import org.solrmarc.index.SolrIndexer;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+/**
+ * LCCN indexing routines.
+ */
+public class LccnTools
+{
+    /**
+     * Normalize a single LCCN using the procedure specified at:
+     *      http://www.loc.gov/marc/lccn-namespace.html#normalization
+     * @param lccn
+     * @return Normalized LCCN
+     */
+    public String getNormalizedLCCN(String lccn) {
+        // Remove whitespace:
+        lccn = lccn.replaceAll(" ", "");
+
+        // Chop off anything following a forward slash:
+        String[] parts = lccn.split("/", 2);
+        lccn = parts[0];
+
+        // Normalize any characters following a hyphen to at least six digits:
+        parts = lccn.split("-", 2);
+        if (parts.length > 1) {
+            String secondPart = parts[1];
+            while (secondPart.length() < 6) {
+                secondPart = "0" + secondPart;
+            }
+            lccn = parts[0] + secondPart;
+        }
+
+        // Send back normalized LCCN:
+        return lccn;
+    }
+
+    /**
+     * Extract LCCNs from a record and return them in a normalized format
+     * @param record
+     * @param fieldSpec
+     * @return Set of normalized LCCNs
+     */
+    public Set getNormalizedLCCNs(Record record, String fieldSpec) {
+        // Initialize return value:
+        Set result = new LinkedHashSet();
+
+        // Loop through relevant fields and normalize everything:
+        Set<String> lccns = SolrIndexer.instance().getFieldList(record, fieldSpec);
+        Iterator<String> lccnIter = lccns.iterator();
+        if (lccns != null) {
+            String current;
+            while(lccnIter.hasNext()) {
+                current = getNormalizedLCCN(lccnIter.next());
+                if (current != null && current.length() > 0) {
+                    result.add(current);
+                }
+            }
+        }
+
+        // Send back results:
+        return result;
+    }
+
+    /**
+     * Extract LCCNs from a record and return them in a normalized format
+     * @param record
+     * @return Set of normalized LCCNs
+     */
+    public Set getNormalizedLCCNs(Record record) {
+        // Send in a default fieldSpec if none was provided by the user:
+        return getNormalizedLCCNs(record, "010a");
+    }
+
+    /**
+     * Extract the first valid LCCN from a record and return it in a normalized format
+     * with an optional prefix added (helpful for guaranteeing unique IDs)
+     * @param indexer
+     * @param record
+     * @param fieldSpec
+     * @param prefix
+     * @return Normalized LCCN
+     */
+    public String getFirstNormalizedLCCN(SolrIndexer indexer, 
+        Record record, String fieldSpec, String prefix) {
+        // Loop through relevant fields in search of first valid LCCN:
+        Set<String> lccns = SolrIndexer.instance().getFieldList(record, fieldSpec);
+        Iterator<String> lccnIter = lccns.iterator();
+        if (lccns != null) {
+            String current;
+            while(lccnIter.hasNext()) {
+                current = getNormalizedLCCN(lccnIter.next());
+                if (current != null && current.length() > 0) {
+                    return prefix + current;
+                }
+            }
+        }
+
+        // If we got this far, we couldn't find a valid value:
+        return null;
+    }
+
+    /**
+     * Extract the first valid LCCN from a record and return it in a normalized format
+     * with an optional prefix added (helpful for guaranteeing unique IDs)
+     * @param record
+     * @param fieldSpec
+     * @param prefix
+     * @return Normalized LCCN
+     */
+    public String getFirstNormalizedLCCN(Record record, String fieldSpec, String prefix) {
+        return getFirstNormalizedLCCN(SolrIndexer.instance(), record, fieldSpec, prefix);
+    }
+
+    /**
+     * Extract the first valid LCCN from a record and return it in a normalized format
+     * @param record
+     * @param fieldSpec
+     * @return Normalized LCCN
+     */
+    public String getFirstNormalizedLCCN(Record record, String fieldSpec) {
+        // Send in a default prefix if none was provided by the user:
+        return getFirstNormalizedLCCN(SolrIndexer.instance(), record, fieldSpec, "");
+    }
+
+    /**
+     * Extract the first valid LCCN from a record and return it in a normalized format
+     * @param record
+     * @return Normalized LCCN
+     */
+    public String getFirstNormalizedLCCN(Record record) {
+        // Send in a default fieldSpec/prefix if none were provided by the user:
+        return getFirstNormalizedLCCN(SolrIndexer.instance(), record, "010a", "");
+    }
+}
\ No newline at end of file
diff --git a/import/index_java/src/org/vufind/index/PublisherTools.java b/import/index_java/src/org/vufind/index/PublisherTools.java
new file mode 100644
index 0000000000000000000000000000000000000000..2fe8f2e3c69c4db9fd4f1d08965631c04355ccd2
--- /dev/null
+++ b/import/index_java/src/org/vufind/index/PublisherTools.java
@@ -0,0 +1,91 @@
+package org.vufind.index;
+/**
+ * Publisher indexing routines.
+ *
+ * Copyright (C) Villanova University 2017.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+import org.marc4j.marc.Record;
+import org.marc4j.marc.VariableField;
+import org.marc4j.marc.DataField;
+import org.marc4j.marc.Subfield;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Publisher indexing routines.
+ */
+public class PublisherTools
+{
+    /**
+     * Get all available publishers from the record.
+     *
+     * @param  record MARC record
+     * @return set of publishers
+     */
+    public Set<String> getPublishers(final Record record) {
+        Set<String> publishers = new LinkedHashSet<String>();
+
+        // First check old-style 260b name:
+        List<VariableField> list260 = record.getVariableFields("260");
+        for (VariableField vf : list260)
+        {
+            DataField df = (DataField) vf;
+            String currentString = "";
+            for (Subfield current : df.getSubfields('b')) {
+                currentString = currentString.trim().concat(" " + current.getData()).trim();
+            }
+            if (currentString.length() > 0) {
+                publishers.add(currentString);
+            }
+        }
+
+        // Now track down relevant RDA-style 264b names; we only care about
+        // copyright and publication names (and ignore copyright names if
+        // publication names are present).
+        Set<String> pubNames = new LinkedHashSet<String>();
+        Set<String> copyNames = new LinkedHashSet<String>();
+        List<VariableField> list264 = record.getVariableFields("264");
+        for (VariableField vf : list264)
+        {
+            DataField df = (DataField) vf;
+            String currentString = "";
+            for (Subfield current : df.getSubfields('b')) {
+                currentString = currentString.trim().concat(" " + current.getData()).trim();
+            }
+            if (currentString.length() > 0) {
+                char ind2 = df.getIndicator2();
+                switch (ind2)
+                {
+                    case '1':
+                        pubNames.add(currentString);
+                        break;
+                    case '4':
+                        copyNames.add(currentString);
+                        break;
+                }
+            }
+        }
+        if (pubNames.size() > 0) {
+            publishers.addAll(pubNames);
+        } else if (copyNames.size() > 0) {
+            publishers.addAll(copyNames);
+        }
+
+        return publishers;
+    }
+}
\ No newline at end of file
diff --git a/import/index_java/src/org/vufind/index/PunctuationTools.java b/import/index_java/src/org/vufind/index/PunctuationTools.java
new file mode 100644
index 0000000000000000000000000000000000000000..e71f2b62490913d5b8af3d0a70e2862785e289d0
--- /dev/null
+++ b/import/index_java/src/org/vufind/index/PunctuationTools.java
@@ -0,0 +1,57 @@
+package org.vufind.index;
+/**
+ * Punctuation indexing routines.
+ *
+ * Copyright (C) Villanova University 2017.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+import org.marc4j.marc.Record;
+import java.util.LinkedHashSet;
+import java.util.Set;
+import java.util.regex.Pattern;
+import org.solrmarc.index.SolrIndexer;
+
+/**
+ * Punctuation indexing routines.
+ */
+public class PunctuationTools
+{
+    /**
+     * Normalize trailing punctuation. This mimics the functionality built into VuFind's
+     * textFacet field type, so that you can get equivalent values when indexing into
+     * a string field. (Useful for docValues support).
+     *
+     * Can return null
+     *
+     * @param record current MARC record
+     * @param fieldSpec which MARC fields / subfields need to be analyzed
+     * @return Set containing normalized values
+     */
+    public Set<String> normalizeTrailingPunctuation(Record record, String fieldSpec) {
+        // Initialize our return value:
+        Set<String> result = new LinkedHashSet<String>();
+
+        // Loop through the specified MARC fields:
+        Set<String> input = SolrIndexer.instance().getFieldList(record, fieldSpec);
+        Pattern pattern = Pattern.compile("(?<!\b[A-Z])[.\\s]*$");
+        for (String current: input) {
+            result.add(pattern.matcher(current).replaceAll(""));
+        }
+
+        // If we found no matches, return null; otherwise, return our results:
+        return result.isEmpty() ? null : result;
+    }
+}
\ No newline at end of file
diff --git a/import/index_java/src/org/vufind/index/ReadingProgramTools.java b/import/index_java/src/org/vufind/index/ReadingProgramTools.java
new file mode 100644
index 0000000000000000000000000000000000000000..e342bab130082bded56a9e853b6c60cbcea967f6
--- /dev/null
+++ b/import/index_java/src/org/vufind/index/ReadingProgramTools.java
@@ -0,0 +1,90 @@
+package org.vufind.index;
+/**
+ * Reading program logic courtesy of Chanel Wheeler
+ *
+ * Example usage:
+ *
+ * #### In marc_local.properties, insert this:
+ * arLvel = custom, getARLevel, (pattern_map.level)
+ * rcLevel = custom, getRCLevel, (pattern_map.level)
+ * pattern_map.level.pattern_0 = ([0-9]\\.[0-9]).*=>$1
+ *
+ * #### In solr/vufind/biblio/conf/schema.xml (I'm not aware of any way to localize this),
+ * #### add this in the <types> section:
+ * <fieldType name="tfloat" class="solr.TrieFloatField" precisionStep="8" positionIncrementGap="0"/>
+ *
+ * #### In solr/vufind/biblio/conf/schema.xml, add this in the <fields> section
+ * <field name="arLevel" type="tfloat" indexed="true" stored="true"/>
+ * <field name="rcLevel" type="tfloat" indexed="true" stored="true"/>
+ *
+ * Copyright (C) Villanova University 2017.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+import org.marc4j.marc.Record;
+import org.marc4j.marc.DataField;
+import org.marc4j.marc.VariableField;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Reading program logic courtesy of Chanel Wheeler
+ */
+public class ReadingProgramTools
+{
+    /**
+     * Get reading level for Accelerated Reader items
+     *
+     * @param  record
+     * @return AR level
+     */
+     public String getARLevel(Record record) {
+        List readingprograms = record.getVariableFields("526");
+        if (readingprograms != null) {
+            Iterator<VariableField> rpIter = readingprograms.iterator();
+            while(rpIter.hasNext()) {
+                DataField rp = (DataField) rpIter.next();
+                if (rp.getSubfield('a') != null){
+                    if (rp.getSubfield('a').getData().toLowerCase().contains("accelerated reader")) {
+                        return rp.getSubfield('c').getData();
+                    }
+                }
+            }
+        }
+        return null;
+     }
+
+     /**
+     * Get reading level for Reading Counts items
+     *
+     * @param  record
+     * @return RC level
+     */
+     public String getRCLevel(Record record) {
+        List readingprograms = record.getVariableFields("526");
+        if (readingprograms != null) {
+            Iterator<VariableField> rpIter = readingprograms.iterator();
+            while(rpIter.hasNext()) {
+                DataField rp = (DataField) rpIter.next();
+                if (rp.getSubfield('a') != null){
+                    if (rp.getSubfield('a').getData().toLowerCase().contains("reading counts")) {
+                        return rp.getSubfield('c').getData();
+                    }
+                }
+            }
+        }
+        return null;
+    }
+}
\ No newline at end of file
diff --git a/import/index_java/src/org/vufind/index/RelatorContainer.java b/import/index_java/src/org/vufind/index/RelatorContainer.java
new file mode 100644
index 0000000000000000000000000000000000000000..5d2177e80a35519e466162533de6a767b12921e3
--- /dev/null
+++ b/import/index_java/src/org/vufind/index/RelatorContainer.java
@@ -0,0 +1,57 @@
+package org.vufind.index;
+/**
+ * Singleton for storing relator information.
+ *
+ * Copyright (C) Villanova University 2017.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+import java.util.LinkedHashSet;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Singleton for storing relator information.
+ */
+public class RelatorContainer
+{
+   private static ThreadLocal<RelatorContainer> containerCache = 
+        new ThreadLocal<RelatorContainer>()
+        {
+            @Override
+            protected RelatorContainer initialValue()
+            {
+                return new RelatorContainer();
+            }
+        };
+
+    private ConcurrentHashMap<String, String> relatorSynonymLookup = new ConcurrentHashMap<String, String>();
+    private Set<String> knownRelators = new LinkedHashSet<String>();
+
+    public ConcurrentHashMap<String, String> getSynonymLookup()
+    {
+        return relatorSynonymLookup;
+    }
+
+    public Set<String> getKnownRelators()
+    {
+        return knownRelators;
+    }
+
+    public static RelatorContainer instance()
+    {
+        return containerCache.get();
+    }
+}
\ No newline at end of file
diff --git a/import/index_java/src/org/vufind/index/UpdateDateTools.java b/import/index_java/src/org/vufind/index/UpdateDateTools.java
new file mode 100644
index 0000000000000000000000000000000000000000..e09517266d1ff734f222d6d19801c0673d0107bf
--- /dev/null
+++ b/import/index_java/src/org/vufind/index/UpdateDateTools.java
@@ -0,0 +1,223 @@
+package org.vufind.index;
+/**
+ * Indexing routines using the UpdateDateTracker.
+ *
+ * Copyright (C) Villanova University 2017.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+import java.util.Iterator;
+import java.util.Set;
+import java.text.SimpleDateFormat;
+import org.solrmarc.index.SolrIndexer;
+import org.solrmarc.tools.SolrMarcIndexerException;
+import org.marc4j.marc.Record;
+import org.apache.log4j.Logger;
+
+/**
+ * Indexing routines using the UpdateDateTracker.
+ */
+public class UpdateDateTools
+{
+    // Initialize logging category
+    static Logger logger = Logger.getLogger(UpdateDateTools.class.getName());
+
+    // the SimpleDateFormat class is not Thread-safe the below line were changes to be not static 
+    // which given the rest of the design of SolrMarc will make them work correctly.
+    private SimpleDateFormat marc005date = new SimpleDateFormat("yyyyMMddHHmmss.S");
+    private SimpleDateFormat marc008date = new SimpleDateFormat("yyMMdd");
+
+    /**
+     * Support method for getLatestTransaction.
+     * @return Date extracted from 005 (or very old date, if unavailable)
+     */
+    private java.util.Date normalize005Date(String input)
+    {
+        // Normalize "null" strings to a generic bad value:
+        if (input == null) {
+            input = "null";
+        }
+
+        // Try to parse the date; default to "millisecond 0" (very old date) if we can't
+        // parse the data successfully.
+        java.util.Date retVal;
+        try {
+            retVal = marc005date.parse(input);
+        } catch(java.text.ParseException e) {
+            retVal = new java.util.Date(0);
+        }
+        return retVal;
+    }
+
+    /**
+     * Support method for getLatestTransaction.
+     * @return Date extracted from 008 (or very old date, if unavailable)
+     */
+    private java.util.Date normalize008Date(String input)
+    {
+        // Normalize "null" strings to a generic bad value:
+        if (input == null || input.length() < 6) {
+            input = "null";
+        }
+
+        // Try to parse the date; default to "millisecond 0" (very old date) if we can't
+        // parse the data successfully.
+        java.util.Date retVal;
+        try {
+            retVal = marc008date.parse(input.substring(0, 6));
+        } catch(java.lang.StringIndexOutOfBoundsException e) {
+            retVal = new java.util.Date(0);
+        } catch(java.text.ParseException e) {
+            retVal = new java.util.Date(0);
+        }
+        return retVal;
+    }
+
+    /**
+     * Extract the latest transaction date from the MARC record.  This is useful
+     * for detecting when a record has changed since the last time it was indexed.
+     *
+     * @param record MARC record
+     * @return Latest transaction date.
+     */
+    public java.util.Date getLatestTransaction(Record record) {
+        // First try the 005 -- this is most likely to have a precise transaction date:
+        Set<String> dates = SolrIndexer.instance().getFieldList(record, "005");
+        if (dates != null) {
+            Iterator<String> dateIter = dates.iterator();
+            if (dateIter.hasNext()) {
+                return normalize005Date(dateIter.next());
+            }
+        }
+
+        // No luck with 005?  Try 008 next -- less precise, but better than nothing:
+        dates = SolrIndexer.instance().getFieldList(record, "008");
+        if (dates != null) {
+            Iterator<String> dateIter = dates.iterator();
+            if (dateIter.hasNext()) {
+                return normalize008Date(dateIter.next());
+            }
+        }
+
+        // If we got this far, we couldn't find a valid value; return an arbitrary date:
+        return new java.util.Date(0);
+    }
+
+
+    /**
+     * Update the index date in the database for the specified core/ID pair.  We
+     * maintain a database of "first/last indexed" times separately from Solr to
+     * allow the history of our indexing activity to be stored permanently in a
+     * fashion that can survive even a total Solr rebuild.
+     */
+    public void updateTracker(String core, String id, java.util.Date latestTransaction)
+    {
+        // Update the database (if necessary):
+        try {
+            UpdateDateTracker.instance().index(core, id, latestTransaction);
+        } catch (java.sql.SQLException e) {
+            // If we're in the process of shutting down, an error is expected:
+            if (!DatabaseManager.instance().isShuttingDown()) {
+                dieWithError("Unexpected database error");
+            }
+        }
+    }
+
+    /**
+     * Get the "first indexed" date for the current record.  (This is the first
+     * time that SolrMarc ever encountered this particular record).
+     *
+     * @param record current MARC record
+     * @param fieldSpec fields / subfields to be analyzed
+     * @param core core name
+     * @return ID string
+     */
+    public String getFirstIndexed(Record record, String fieldSpec, String core) {
+        // Update the database, then send back the first indexed date:
+        updateTracker(core, SolrIndexer.instance().getFirstFieldVal(record, fieldSpec), getLatestTransaction(record));
+        return UpdateDateTracker.instance().getFirstIndexed();
+    }
+
+    /**
+     * Get the "first indexed" date for the current record.  (This is the first
+     * time that SolrMarc ever encountered this particular record).
+     *
+     * @param record current MARC record
+     * @param fieldSpec fields / subfields to be analyzed
+     * @return ID string
+     */
+    public String getFirstIndexed(Record record, String fieldSpec) {
+        return getFirstIndexed(record, fieldSpec, "biblio");
+    }
+
+    /**
+     * Get the "first indexed" date for the current record.  (This is the first
+     * time that SolrMarc ever encountered this particular record).
+     *
+     * @param record current MARC record
+     * @return ID string
+     */
+    public String getFirstIndexed(Record record) {
+        return getFirstIndexed(record, "001", "biblio");
+    }
+
+    /**
+     * Get the "last indexed" date for the current record.  (This is the last time
+     * the record changed from SolrMarc's perspective).
+     *
+     * @param record current MARC record
+     * @param fieldSpec fields / subfields to be analyzed
+     * @param core core name
+     * @return ID string
+     */
+    public String getLastIndexed(Record record, String fieldSpec, String core) {
+        // Update the database, then send back the last indexed date:
+        updateTracker(core, SolrIndexer.instance().getFirstFieldVal(record, fieldSpec), getLatestTransaction(record));
+        return UpdateDateTracker.instance().getLastIndexed();
+    }
+
+    /**
+     * Get the "last indexed" date for the current record.  (This is the last time
+     * the record changed from SolrMarc's perspective).
+     *
+     * @param record current MARC record
+     * @param fieldSpec fields / subfields to analyze
+     * @return ID string
+     */
+    public String getLastIndexed(Record record, String fieldSpec) {
+        return getLastIndexed(record, fieldSpec, "biblio");
+    }
+
+    /**
+     * Get the "last indexed" date for the current record.  (This is the last time
+     * the record changed from SolrMarc's perspective).
+     *
+     * @param record current MARC record
+     * @return ID string
+     */
+    public String getLastIndexed(Record record) {
+        return getLastIndexed(record, "001", "biblio");
+    }
+
+    /**
+     * Log an error message and throw a fatal exception.
+     * @param msg message to log
+     */
+    private void dieWithError(String msg)
+    {
+        logger.error(msg);
+        throw new SolrMarcIndexerException(SolrMarcIndexerException.EXIT, msg);
+    }
+}
\ No newline at end of file
diff --git a/import/index_java/src/org/solrmarc/index/UpdateDateTracker.java b/import/index_java/src/org/vufind/index/UpdateDateTracker.java
similarity index 81%
rename from import/index_java/src/org/solrmarc/index/UpdateDateTracker.java
rename to import/index_java/src/org/vufind/index/UpdateDateTracker.java
index ac8c6b796dedbf0dd8b6e8835f118805adc8bebf..c43aa7a4077fb946e55b5a3d45bd36b76e310bb7 100644
--- a/import/index_java/src/org/solrmarc/index/UpdateDateTracker.java
+++ b/import/index_java/src/org/vufind/index/UpdateDateTracker.java
@@ -1,24 +1,29 @@
-package org.solrmarc.index;
+package org.vufind.index;
 /**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
+ * Class for managing record update dates.
  *
- *     http://www.apache.org/licenses/LICENSE-2.0
+ * Copyright (C) Villanova University 2017.
  *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
 import java.sql.*;
 import java.text.SimpleDateFormat;
 
+/**
+ * Class for managing record update dates.
+ */
 public class UpdateDateTracker
 {
     private Connection db;
@@ -35,6 +40,25 @@ public class UpdateDateTracker
     PreparedStatement selectSql;
     PreparedStatement updateSql;
 
+    private static ThreadLocal<UpdateDateTracker> trackerCache = 
+        new ThreadLocal<UpdateDateTracker>()
+        {
+            @Override
+            protected UpdateDateTracker initialValue()
+            {
+                try {
+                    return new UpdateDateTracker(DatabaseManager.instance().getConnection());
+                } catch (SQLException e) {
+                    throw new RuntimeException(e.getMessage());
+                }
+            }
+        };
+
+    public static UpdateDateTracker instance()
+    {
+        return trackerCache.get();
+    }
+
     /* Private support method: create a row in the change_tracker table.
      */
     private void createRow(Timestamp newRecordChange) throws SQLException
diff --git a/import/index_scripts/README_SCRIPTS b/import/index_scripts/README_SCRIPTS
index ee6a073bef2fd04e71afdf40611e3bdd840422f4..69ad62c6d21c5964a59c60c466afd69f0e5d206d 100644
--- a/import/index_scripts/README_SCRIPTS
+++ b/import/index_scripts/README_SCRIPTS
@@ -1 +1,3 @@
-This is the directory in which you should place java-like beanshell scripts for handling custom indexing functions via dynamic scripts.
\ No newline at end of file
+This is the directory in which you should place java-like beanshell scripts for handling custom indexing functions via dynamic scripts.
+
+Note that use of beanshell is discouraged now that java can be dynamically compiled; see the index_java directory instead.
\ No newline at end of file
diff --git a/import/index_scripts/author.bsh b/import/index_scripts/author.bsh
deleted file mode 100644
index 4bbbc395959b8098fada43068f0f57f05ae01739..0000000000000000000000000000000000000000
--- a/import/index_scripts/author.bsh
+++ /dev/null
@@ -1,692 +0,0 @@
-import org.marc4j.marc.Record;
-import org.marc4j.marc.DataField;
-import org.solrmarc.index.UpdateDateTracker;
-import org.ini4j.Ini;
-import java.util.Arrays;
-import java.util.ArrayList;
-import java.util.Map;
-
-// define the base level indexer so that its methods can be called from the script.
-// note that the SolrIndexer code will set this value before the script methods are called.
-org.solrmarc.index.SolrIndexer indexer = null;
-
-HashMap relatorSynonymLookup = new HashMap();
-Set knownRelators = new LinkedHashSet();
-
-/**
- * Extract all valid relator terms from a list of subfields using a whitelist.
- * @param subfields        List of subfields to check
- * @param permittedRoles   Whitelist to check against
- * @param indexRawRelators Should we index relators raw, as found
- * in the MARC (true) or index mapped versions (false)?
- * @return Set of valid relator terms
- */
-public Set getValidRelatorsFromSubfields(List subfields, List permittedRoles, Boolean indexRawRelators)
-{
-    Set relators = new LinkedHashSet();
-    for (int j = 0; j < subfields.size(); j++) {
-        String raw = subfields.get(j).getData();
-        String current = normalizeRelatorString(raw);
-        if (permittedRoles.contains(current)) {
-            relators.add(indexRawRelators ? raw : mapRelatorStringToCode(current));
-        }
-    }
-    return relators;
-}
-
-/**
- * Is this relator term unknown to author-classification.ini?
- * @param current relator to check
- * @return True if unknown
- */
-public Boolean isUnknownRelator(String current)
-{
-    // If we haven't loaded known relators yet, do so now:
-    if (knownRelators.size() == 0) {
-        Map all = indexer.getConfigSection("author-classification.ini", "RelatorSynonyms");
-        for (String key : all.keySet()) {
-            knownRelators.add(normalizeRelatorString(key));
-            for (String synonym: all.get(key).split("\\|")) {
-                knownRelators.add(normalizeRelatorString(synonym));
-            }
-        }
-    }
-    return !knownRelators.contains(normalizeRelatorString(current));
-}
-
-/**
- * Extract all valid relator terms from a list of subfields using a whitelist.
- * @param subfields      List of subfields to check
- * @return Set of valid relator terms
- */
-public Set getUnknownRelatorsFromSubfields(List subfields)
-{
-    Set relators = new LinkedHashSet();
-    for (int j = 0; j < subfields.size(); j++) {
-        String current = subfields.get(j).getData().trim();
-        if (current.length() > 0 && isUnknownRelator(current)) {
-            indexer.getLogger().info("Unknown relator: " + current);
-            relators.add(current);
-        }
-    }
-    return relators;
-}
-
-/**
- * Extract all values that meet the specified relator requirements.
- * @param authorField           Field to analyze
- * @param noRelatorAllowed      Array of tag names which are allowed to be used with
- * no declared relator.
- * @param relatorConfig         The setting in author-classification.ini which
- * defines which relator terms are acceptable (or a colon-delimited list)
- * @param unknownRelatorAllowed Array of tag names whose relators should be indexed
- * even if they are not listed in author-classification.ini.
- * @param indexRawRelators      Set to "true" to index relators raw, as found
- * in the MARC or "false" to index mapped versions.
- * @return Set
- */
-public Set getValidRelators(DataField authorField,
-    String[] noRelatorAllowed, String relatorConfig,
-    String[] unknownRelatorAllowed, String indexRawRelators
-) {
-    // get tag number from Field
-    String tag = authorField.getTag();
-    List subfieldE = authorField.getSubfields('e');
-    List subfield4 = authorField.getSubfields('4');
-
-    Set relators = new LinkedHashSet();
-
-    // if no relator is found, check to see if the current tag is in the "no
-    // relator allowed" list.
-    if (subfieldE.size() == 0 && subfield4.size() == 0) {
-        if (Arrays.asList(noRelatorAllowed).contains(tag)) {
-            relators.add("");
-        }
-    } else {
-        // If we got this far, we need to figure out what type of relation they have
-        List permittedRoles = normalizeRelatorStringList(Arrays.asList(loadRelatorConfig(relatorConfig)));
-        relators.addAll(getValidRelatorsFromSubfields(subfieldE, permittedRoles, indexRawRelators.toLowerCase().equals("true")));
-        relators.addAll(getValidRelatorsFromSubfields(subfield4, permittedRoles, indexRawRelators.toLowerCase().equals("true")));
-        if (Arrays.asList(unknownRelatorAllowed).contains(tag)) {
-            Set unknown = getUnknownRelatorsFromSubfields(subfieldE);
-            if (unknown.size() == 0) {
-                unknown = getUnknownRelatorsFromSubfields(subfield4);
-            }
-            relators.addAll(unknown);
-        }
-    }
-    return relators;
-}
-
-/**
- * Parse a SolrMarc fieldspec into a map of tag name to set of subfield strings
- * (note that we need to map to a set rather than a single string, because the
- * same tag may repeat with different subfields to extract different sections
- * of the same field into distinct values).
- *
- * @param tagList The field specification to parse
- * @return HashMap
- */
-public HashMap getParsedTagList(String tagList)
-{
-    String[] tags = tagList.split(":");//convert string input to array
-    HashMap tagMap = new HashMap();
-    //cut tags array up into key/value pairs in hash map
-    Set currentSet;
-    for(int i = 0; i < tags.length; i++){
-        String tag = tags[i].substring(0, 3);
-        if (!tagMap.containsKey(tag)) {
-            currentSet = new LinkedHashSet();
-            tagMap.put(tag, currentSet);
-        } else {
-            currentSet = tagMap.get(tag);
-        }
-        currentSet.add(tags[i].substring(3));
-    }
-    return tagMap;
-}
-
-/**
- * Filter values retrieved using tagList to include only those whose relator
- * values are acceptable. Used for separating different types of authors.
- *
- * @param record               The record (fed in automatically)
- * @param tagList              The field specification to read
- * @param acceptWithoutRelator Colon-delimited list of tags whose values should
- * be accepted even if no relator subfield is defined
- * @param relatorConfig        The setting in author-classification.ini which
- * defines which relator terms are acceptable (or a colon-delimited list)
- * @param acceptUnknownRelators Colon-delimited list of tags whose relators
- * should be indexed even if they are not listed in author-classification.ini.
- * @param indexRawRelators      Set to "true" to index relators raw, as found
- * in the MARC or "false" to index mapped versions.
- * @param firstOnly            Return first result only?
- * @return List result
- */
-public List getAuthorsFilteredByRelator(Record record, String tagList,
-    String acceptWithoutRelator, String relatorConfig,
-    String acceptUnknownRelators, String indexRawRelators, Boolean firstOnly
-) {
-    List result = new LinkedList();
-    String[] noRelatorAllowed = acceptWithoutRelator.split(":");
-    String[] unknownRelatorAllowed = acceptUnknownRelators.split(":");
-    HashMap parsedTagList = getParsedTagList(tagList);
-    List fields = indexer.getFieldSetMatchingTagList(record, tagList);
-    Iterator fieldsIter = fields.iterator();
-    if (fields != null){
-        DataField authorField;
-        while (fieldsIter.hasNext()){
-            authorField = (DataField) fieldsIter.next();
-            // add all author types to the result set; if we have multiple relators, repeat the authors
-            for (String iterator: getValidRelators(authorField, noRelatorAllowed, relatorConfig, unknownRelatorAllowed, indexRawRelators)) {
-                for (String subfields : parsedTagList.get(authorField.getTag())) {
-                    String current = indexer.getDataFromVariableField(authorField, "["+subfields+"]", " ", false);
-                    // TODO: we may eventually be able to use this line instead,
-                    // but right now it's not handling separation between the
-                    // subfields correctly, so it's commented out until that is
-                    // fixed.
-                    //String current = authorField.getSubfieldsAsString(subfields);
-                    if (null != current) {
-                        result.add(current);
-                        if (firstOnly) {
-                            return result;
-                        }
-                    }
-                }
-            }
-        }
-    }
-    return result;
-}
-
-/**
- * Filter values retrieved using tagList to include only those whose relator
- * values are acceptable. Used for separating different types of authors.
- *
- * @param record               The record (fed in automatically)
- * @param tagList              The field specification to read
- * @param acceptWithoutRelator Colon-delimited list of tags whose values should
- * be accepted even if no relator subfield is defined
- * @param relatorConfig        The setting in author-classification.ini which
- * defines which relator terms are acceptable (or a colon-delimited list)
- * @return List result
- */
-public List getAuthorsFilteredByRelator(Record record, String tagList,
-    String acceptWithoutRelator, String relatorConfig
-) {
-    // default firstOnly to false!
-    return getAuthorsFilteredByRelator(
-        record, tagList, acceptWithoutRelator, relatorConfig,
-        acceptWithoutRelator, "false", false
-    );
-}
-
-/**
- * Filter values retrieved using tagList to include only those whose relator
- * values are acceptable. Used for separating different types of authors.
- *
- * @param record               The record (fed in automatically)
- * @param tagList              The field specification to read
- * @param acceptWithoutRelator Colon-delimited list of tags whose values should
- * be accepted even if no relator subfield is defined
- * @param relatorConfig        The setting in author-classification.ini which
- * defines which relator terms are acceptable (or a colon-delimited list)
- * @return List result
- * @param acceptUnknownRelators Colon-delimited list of tags whose relators
- * should be indexed even if they are not listed in author-classification.ini.
- */
-public List getAuthorsFilteredByRelator(Record record, String tagList,
-    String acceptWithoutRelator, String relatorConfig,
-    String acceptUnknownRelators
-) {
-    // default firstOnly to false!
-    return getAuthorsFilteredByRelator(
-        record, tagList, acceptWithoutRelator, relatorConfig,
-        acceptUnknownRelators, "false", false
-    );
-}
-
-/**
- * Filter values retrieved using tagList to include only those whose relator
- * values are acceptable. Used for separating different types of authors.
- *
- * @param record               The record (fed in automatically)
- * @param tagList              The field specification to read
- * @param acceptWithoutRelator Colon-delimited list of tags whose values should
- * be accepted even if no relator subfield is defined
- * @param relatorConfig        The setting in author-classification.ini which
- * defines which relator terms are acceptable (or a colon-delimited list)
- * @return List result
- * @param acceptUnknownRelators Colon-delimited list of tags whose relators
- * should be indexed even if they are not listed in author-classification.ini.
- * @param indexRawRelators      Set to "true" to index relators raw, as found
- * in the MARC or "false" to index mapped versions.
- */
-public List getAuthorsFilteredByRelator(Record record, String tagList,
-    String acceptWithoutRelator, String relatorConfig,
-    String acceptUnknownRelators, String indexRawRelators
-) {
-    // default firstOnly to false!
-    return getAuthorsFilteredByRelator(
-        record, tagList, acceptWithoutRelator, relatorConfig,
-        acceptUnknownRelators, indexRawRelators, false
-    );
-}
-
-/**
- * If the provided relator is included in the synonym list, convert it back to
- * a code (for better standardization/translation).
- *
- * @param relator Relator code to check
- * @return Code version, if found, or raw string if no match found.
- */
-public String mapRelatorStringToCode(String relator)
-{
-    String normalizedRelator = normalizeRelatorString(relator);
-    return relatorSynonymLookup.containsKey(normalizedRelator)
-        ? relatorSynonymLookup.get(normalizedRelator) : relator;
-}
-
-/**
- * Filter values retrieved using tagList to include only those whose relator
- * values are acceptable. Used for separating different types of authors.
- *
- * @param record                The record (fed in automatically)
- * @param tagList               The field specification to read
- * @param acceptWithoutRelator  Colon-delimited list of tags whose values should
- * be accepted even if no relator subfield is defined
- * @param relatorConfig         The setting in author-classification.ini which
- * defines which relator terms  are acceptable (or a colon-delimited list)
- * @param acceptUnknownRelators Colon-delimited list of tags whose relators
- * should be indexed even if they are not listed in author-classification.ini.
- * @param indexRawRelators      Set to "true" to index relators raw, as found
- * in the MARC or "false" to index mapped versions.
- * @return String
- */
-public String getFirstAuthorFilteredByRelator(Record record, String tagList,
-    String acceptWithoutRelator, String relatorConfig,
-    String acceptUnknownRelators, String indexRawRelators
-) {
-    List result = getAuthorsFilteredByRelator(
-        record, tagList, acceptWithoutRelator, relatorConfig,
-        acceptUnknownRelators, indexRawRelators, true
-    );
-    for (String s : result) {
-        return s;
-    }
-    return null;
-}
-
-/**
- * Filter values retrieved using tagList to include only those whose relator
- * values are acceptable. Used for separating different types of authors.
- *
- * @param record                The record (fed in automatically)
- * @param tagList               The field specification to read
- * @param acceptWithoutRelator  Colon-delimited list of tags whose values should
- * be accepted even if no relator subfield is defined
- * @param relatorConfig         The setting in author-classification.ini which
- * defines which relator terms  are acceptable (or a colon-delimited list)
- * @return String
- */
-public String getFirstAuthorFilteredByRelator(Record record, String tagList,
-    String acceptWithoutRelator, String relatorConfig
-) {
-    return getFirstAuthorFilteredByRelator(
-        record, tagList, acceptWithoutRelator, relatorConfig,
-        acceptWithoutRelator, "false"
-    );
-}
-
-/**
- * Filter values retrieved using tagList to include only those whose relator
- * values are acceptable. Used for separating different types of authors.
- *
- * @param record                The record (fed in automatically)
- * @param tagList               The field specification to read
- * @param acceptWithoutRelator  Colon-delimited list of tags whose values should
- * be accepted even if no relator subfield is defined
- * @param relatorConfig         The setting in author-classification.ini which
- * defines which relator terms  are acceptable (or a colon-delimited list)
- * @param acceptUnknownRelators Colon-delimited list of tags whose relators
- * should be indexed even if they are not listed in author-classification.ini.
- * @return String
- */
-public String getFirstAuthorFilteredByRelator(Record record, String tagList,
-    String acceptWithoutRelator, String relatorConfig,
-    String acceptUnknownRelators
-) {
-    return getFirstAuthorFilteredByRelator(
-        record, tagList, acceptWithoutRelator, relatorConfig,
-        acceptUnknownRelators, "false"
-    );
-}
-
-/**
- * Filter values retrieved using tagList to include only those whose relator
- * values are acceptable. Used for saving relators of authors separated by different
- * types.
- *
- * @param record               The record (fed in automatically)
- * @param tagList              The field specification to read
- * @param acceptWithoutRelator Colon-delimited list of tags whose values should
- * be accepted even if no relator subfield is defined
- * @param relatorConfig        The setting in author-classification.ini which
- * defines which relator terms are acceptable (or a colon-delimited list)
- * @param acceptUnknownRelators Colon-delimited list of tags whose relators
- * should be indexed even if they are not listed in author-classification.ini.
- * @param indexRawRelators      Set to "true" to index relators raw, as found
- * in the MARC or "false" to index mapped versions.
- * @param firstOnly            Return first result only?
- * @return List result
- */
-public List getRelatorsFilteredByRelator(Record record, String tagList,
-    String acceptWithoutRelator, String relatorConfig,
-    String acceptUnknownRelators, String indexRawRelators, Boolean firstOnly
-) {
-    List result = new LinkedList();
-    String[] noRelatorAllowed = acceptWithoutRelator.split(":");
-    String[] unknownRelatorAllowed = acceptUnknownRelators.split(":");
-    HashMap parsedTagList = getParsedTagList(tagList);
-    List fields = indexer.getFieldSetMatchingTagList(record, tagList);
-    Iterator fieldsIter = fields.iterator();
-    if (fields != null){
-        DataField authorField;
-        while (fieldsIter.hasNext()){
-            authorField = (DataField) fieldsIter.next();
-            //add all author types to the result set
-            result.addAll(getValidRelators(authorField, noRelatorAllowed, relatorConfig, unknownRelatorAllowed, indexRawRelators));
-        }
-    }
-    return result;
-}
-
-/**
- * Filter values retrieved using tagList to include only those whose relator
- * values are acceptable. Used for saving relators of authors separated by different
- * types.
- *
- * @param record               The record (fed in automatically)
- * @param tagList              The field specification to read
- * @param acceptWithoutRelator Colon-delimited list of tags whose values should
- * be accepted even if no relator subfield is defined
- * @param relatorConfig        The setting in author-classification.ini which
- * defines which relator terms are acceptable (or a colon-delimited list)
- * @param acceptUnknownRelators Colon-delimited list of tags whose relators
- * should be indexed even if they are not listed in author-classification.ini.
- * @param indexRawRelators      Set to "true" to index relators raw, as found
- * in the MARC or "false" to index mapped versions.
- * @return List result
- */
-public List getRelatorsFilteredByRelator(Record record, String tagList,
-    String acceptWithoutRelator, String relatorConfig,
-    String acceptUnknownRelators, String indexRawRelators
-) {
-    // default firstOnly to false!
-    return getRelatorsFilteredByRelator(
-        record, tagList, acceptWithoutRelator, relatorConfig,
-        acceptUnknownRelators, indexRawRelators, false
-    );
-}
-
-/**
- * Filter values retrieved using tagList to include only those whose relator
- * values are acceptable. Used for saving relators of authors separated by different
- * types.
- *
- * @param record               The record (fed in automatically)
- * @param tagList              The field specification to read
- * @param acceptWithoutRelator Colon-delimited list of tags whose values should
- * be accepted even if no relator subfield is defined
- * @param relatorConfig        The setting in author-classification.ini which
- * defines which relator terms are acceptable (or a colon-delimited list)
- * @param acceptUnknownRelators Colon-delimited list of tags whose relators
- * should be indexed even if they are not listed in author-classification.ini.
- * @return List result
- */
-public List getRelatorsFilteredByRelator(Record record, String tagList,
-    String acceptWithoutRelator, String relatorConfig,
-    String acceptUnknownRelators
-) {
-    // default firstOnly to false!
-    return getRelatorsFilteredByRelator(
-        record, tagList, acceptWithoutRelator, relatorConfig,
-        acceptUnknownRelators, "false", false
-    );
-}
-
-/**
- * Filter values retrieved using tagList to include only those whose relator
- * values are acceptable. Used for saving relators of authors separated by different
- * types.
- *
- * @param record               The record (fed in automatically)
- * @param tagList              The field specification to read
- * @param acceptWithoutRelator Colon-delimited list of tags whose values should
- * be accepted even if no relator subfield is defined
- * @param relatorConfig        The setting in author-classification.ini which
- * defines which relator terms are acceptable (or a colon-delimited list)
- * @return List result
- */
-public List getRelatorsFilteredByRelator(Record record, String tagList,
-    String acceptWithoutRelator, String relatorConfig
-) {
-    // default firstOnly to false!
-    return getRelatorsFilteredByRelator(
-        record, tagList, acceptWithoutRelator, relatorConfig,
-        acceptWithoutRelator, "false", false
-    );
-}
-
-/**
- * This method fetches relator definitions from ini file and casts them to an
- * array. If a colon-delimited string is passed in, this will be directly parsed
- * instead of resorting to .ini loading.
- *
- * @param setting Setting to load from .ini or colon-delimited list.
- * @return String[]
- */
-public String[] loadRelatorConfig(String setting){
-    StringBuilder relators = new StringBuilder();
-
-    // check for pipe-delimited string
-    String[] relatorSettings = setting.split("\\|");
-    for (String relatorSetting: relatorSettings) {
-        // check for colon-delimited string
-        String[] relatorArray = relatorSetting.split(":");
-        if (relatorArray.length > 1) {
-            for (int i = 0; i < relatorArray.length; i++) {
-                relators.append(relatorArray[i]).append(",");
-            }
-        } else {
-            relators.append(indexer.getConfigSetting(
-                "author-classification.ini", "AuthorRoles", relatorSetting
-            )).append(",");
-        }
-    }
-
-    return relators.toString().split(",");
-}
-
-/**
- * Normalizes a relator string and returns a list containing the normalized
- * relator plus any configured synonyms.
- *
- * @param relator Relator term to normalize
- * @return List of strings
- */
-public List normalizeRelatorAndAddSynonyms(String relator)
-{
-    List newList = new ArrayList();
-    String normalized = normalizeRelatorString(relator);
-    newList.add(normalized);
-    String synonyms = indexer.getConfigSetting(
-        "author-classification.ini", "RelatorSynonyms", relator
-    );
-    if (null != synonyms && synonyms.length() > 0) {
-        for (String synonym: synonyms.split("\\|")) {
-            String normalizedSynonym = normalizeRelatorString(synonym);
-            relatorSynonymLookup.put(normalizedSynonym, relator);
-            newList.add(normalizedSynonym);
-        }
-    }
-    return newList;
-}
-
-/**
- * Normalizes the strings in a list.
- *
- * @param stringList List of strings to be normalized
- * @return Normalized List of strings 
- */
-public List normalizeRelatorStringList(List stringList)
-{
-    List newList = new ArrayList();
-    for (String relator: stringList) {
-        newList.addAll(normalizeRelatorAndAddSynonyms(relator));
-    }
-    return newList;
-}
-
-/**
- * Normalizes a string
- *
- * @param string String to be normalized
- * @return string
- */
-public String normalizeRelatorString(String string)
-{
-    return string
-        .trim()
-        .toLowerCase()
-        .replaceAll("\\p{Punct}+", "");    //POSIX character class Punctuation: One of !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~
-}
-
-/**
- * Filter values retrieved using tagList to include only those whose relator
- * values are acceptable. Used for separating different types of authors.
- *
- * @param record               The record (fed in automatically)
- * @param tagList              The field specification to read
- * @param acceptWithoutRelator Colon-delimited list of tags whose values should
- * be accepted even if no relator subfield is defined
- * @param relatorConfig        The setting in author-classification.ini which
- * defines which relator terms are acceptable (or a colon-delimited list)
- * @param acceptUnknownRelators Colon-delimited list of tags whose relators
- * should be indexed even if they are not listed in author-classification.ini.
- * @param indexRawRelators      Set to "true" to index relators raw, as found
- * in the MARC or "false" to index mapped versions.
- * @return List result
- */
-public List getAuthorInitialsFilteredByRelator(Record record,
-    String tagList, String acceptWithoutRelator, String relatorConfig,
-    String acceptUnknownRelators, String indexRawRelators
-) {
-    List authors = getAuthorsFilteredByRelator(
-        record, tagList, acceptWithoutRelator, relatorConfig,
-        acceptUnknownRelators, indexRawRelators
-    );
-    List result = new LinkedList();
-    for (String author : authors) {
-        result.add(processInitials(author));
-    }
-    return result;
-}
-
-/**
- * Filter values retrieved using tagList to include only those whose relator
- * values are acceptable. Used for separating different types of authors.
- *
- * @param record               The record (fed in automatically)
- * @param tagList              The field specification to read
- * @param acceptWithoutRelator Colon-delimited list of tags whose values should
- * be accepted even if no relator subfield is defined
- * @param relatorConfig        The setting in author-classification.ini which
- * defines which relator terms are acceptable (or a colon-delimited list)
- * @return List result
- */
-public List getAuthorInitialsFilteredByRelator(Record record,
-    String tagList, String acceptWithoutRelator, String relatorConfig
-) {
-    return getAuthorInitialsFilteredByRelator(
-        record, tagList, acceptWithoutRelator, relatorConfig,
-        acceptWithoutRelator, "false"
-    );
-}
-
-/**
- * Filter values retrieved using tagList to include only those whose relator
- * values are acceptable. Used for separating different types of authors.
- *
- * @param record               The record (fed in automatically)
- * @param tagList              The field specification to read
- * @param acceptWithoutRelator Colon-delimited list of tags whose values should
- * be accepted even if no relator subfield is defined
- * @param relatorConfig        The setting in author-classification.ini which
- * defines which relator terms are acceptable (or a colon-delimited list)
- * @param acceptUnknownRelators Colon-delimited list of tags whose relators
- * should be indexed even if they are not listed in author-classification.ini.
- * @return List result
- */
-public List getAuthorInitialsFilteredByRelator(Record record,
-    String tagList, String acceptWithoutRelator, String relatorConfig,
-    String acceptUnknownRelators
-) {
-    return getAuthorInitialsFilteredByRelator(
-        record, tagList, acceptWithoutRelator, relatorConfig,
-        acceptUnknownRelators, "false"
-    );
-}
-
-/**
- * Takes a name and cuts it into initials
- * @param authorName e.g. Yeats, William Butler
- * @return initials e.g. w b y wb
- */
-public String processInitials(String authorName) {
-    Boolean isPersonalName = false;
-    // we guess that if there is a comma before the end - this is a personal name
-    if ((authorName.indexOf(',') > 0) 
-        && (authorName.indexOf(',') < authorName.length()-1)) {
-        isPersonalName = true;
-    }
-    // get rid of non-alphabet chars but keep hyphens and accents 
-    authorName = authorName.replaceAll("[^\\p{L} -]", "").toLowerCase();
-    String[] names = authorName.split(" "); //split into tokens on spaces
-    // if this is a personal name we'll reorganise to put lastname at the end
-    String result = "";
-    if (isPersonalName) {
-        String lastName = names[0]; 
-        for (int i = 0; i < names.length-1; i++) {
-            names[i] = names[i+1];
-        }
-        names[names.length-1] = lastName;
-    }
-    // put all the initials together in a space separated string
-    for (String name : names) {
-        if (name.length() > 0) {
-            String initial = name.substring(0,1);
-            // if there is a hyphenated name, use both initials
-            int pos = name.indexOf('-');
-            if (pos > 0 && pos < name.length() - 1) {
-                String extra = name.substring(pos+1, pos+2);
-                initial = initial + " " + extra;
-            }
-            result += " " + initial; 
-        }
-    }
-    // grab all initials and stick them together
-    String smushAll = result.replaceAll(" ", "");
-    // if it's a long personal name, get all but the last initials as well
-    // e.g. wb for william butler yeats
-    if (names.length > 2 && isPersonalName) {
-        String smushPers = result.substring(0,result.length()-1).replaceAll(" ","");
-        result = result + " " + smushPers;
-    }
-    // now we have initials separate and together
-    if (!result.trim().equals(smushAll)) {
-        result += " " + smushAll; 
-    }
-    result = result.trim();
-    return result;
-}
diff --git a/import/index_scripts/callnumber.bsh b/import/index_scripts/callnumber.bsh
deleted file mode 100644
index fa87d608ffe9dedc1e86b48a938254832d08ce79..0000000000000000000000000000000000000000
--- a/import/index_scripts/callnumber.bsh
+++ /dev/null
@@ -1,142 +0,0 @@
-/**
- * Custom call number script.
- *
- * This can be used to override built-in SolrMarc custom functions.  If you change
- * this script, you will need to activate it in import/marc_local.properties before
- * it will be applied during indexing.
- */
-import org.marc4j.marc.Record;
-import org.solrmarc.callnum.LCCallNumber;
-import org.solrmarc.index.SolrIndexer;
-
-
-// define the base level indexer so that its methods can be called from the script.
-// note that the SolrIndexer code will set this value before the script methods are called.
-org.solrmarc.index.SolrIndexer indexer = null;
-
-    /**
-     * Extract the full call number from a record, stripped of spaces
-     * @param record MARC record
-     * @return Call number label
-     * @deprecated Obsolete as of VuFind 2.4.
-     *          This method exists only to support the VuFind call number search, version <= 2.3.
-     *          As of VuFind 2.4, the munging for call number search in handled entirely in Solr.
-     */
-    public String getFullCallNumber(Record record) {
-
-        return(getFullCallNumber(record, "099ab:090ab:050ab"));
-    }
-
-    /**
-     * Extract the full call number from a record, stripped of spaces
-     * @param record MARC record
-     * @param fieldSpec taglist for call number fields
-     * @return Call number label
-     * @deprecated Obsolete as of VuFind 2.4.
-     *          This method exists only to support the VuFind call number search, version <= 2.3.
-     *          As of VuFind 2.4, the munging for call number search in handled entirely in Solr.
-     */
-    public String getFullCallNumber(Record record, String fieldSpec) {
-
-        String val = SolrIndexer.getFirstFieldVal(record, fieldSpec);
-
-        if (val != null) {
-            return val.toUpperCase().replaceAll(" ", "");
-        } else {
-            return val;
-        }
-    }
-
-
-    /**
-     * Extract the call number label from a record
-     * @param record MARC record
-     * @return Call number label
-     */
-    public String getCallNumberLabel(Record record) {
-
-        return getCallNumberLabel(record, "090a:050a");
-    }
-
-    /**
-     * Extract the call number label from a record
-     * @param record MARC record
-     * @param fieldSpec taglist for call number fields
-     * @return Call number label
-     */
-    public String getCallNumberLabel(Record record, String fieldSpec) {
-
-        String val = SolrIndexer.getFirstFieldVal(record, fieldSpec);
-
-        if (val != null) {
-            int dotPos = val.indexOf(".");
-            if (dotPos > 0) {
-                val = val.substring(0, dotPos);
-            }
-            return val.toUpperCase();
-        } else {
-            return val;
-        }
-    }
-
-    /**
-     * Extract the subject component of the call number
-     *
-     * Can return null
-     *
-     * @param record MARC record
-     * @return Call number subject letters
-     */
-    public String getCallNumberSubject(Record record) {
-
-        return(getCallNumberSubject(record, "090a:050a"));
-    }
-
-    /**
-     * Extract the subject component of the call number
-     *
-     * Can return null
-     *
-     * @param record current MARC record
-     * @return Call number subject letters
-     */
-    public String getCallNumberSubject(Record record, String fieldSpec) {
-
-        String val = SolrIndexer.getFirstFieldVal(record, fieldSpec);
-
-        if (val != null) {
-            String [] callNumberSubject = val.toUpperCase().split("[^A-Z]+");
-            if (callNumberSubject.length > 0)
-            {
-                return callNumberSubject[0];
-            }
-        }
-        return(null);
-    }
-
-    /**
-     * Normalize a single LC call number
-     * @param record current MARC record
-     * @return String Normalized LCCN
-     */
-    public String getFullCallNumberNormalized(Record record) {
-
-        return(getFullCallNumberNormalized(record, "099ab:090ab:050ab"));
-    }
-
-    /**
-     * Normalize a single LC call number
-     * @param record current MARC record
-     * @param fieldSpec which MARC fields / subfields need to be analyzed
-     * @return String Normalized LC call number
-     */
-    public String getFullCallNumberNormalized(Record record, String fieldSpec) {
-
-        // TODO: is the null fieldSpec still an issue?
-        if (fieldSpec != null) {
-            String cn = SolrIndexer.getFirstFieldVal(record, fieldSpec);
-            return (new LCCallNumber(cn)).getShelfKey();
-        }
-        // If we got this far, we couldn't find a valid value:
-        return null;
-    }
diff --git a/import/index_scripts/dewey.bsh b/import/index_scripts/dewey.bsh
deleted file mode 100644
index 50edb41552ab3c45c591f290400b40cc7c909247..0000000000000000000000000000000000000000
--- a/import/index_scripts/dewey.bsh
+++ /dev/null
@@ -1,201 +0,0 @@
-/**
- * Custom Dewey call number script.
- *
- * This can be used to override built-in SolrMarc custom functions.  If you change
- * this script, you will need to activate it in import/marc_local.properties before
- * it will be applied during indexing.
- */
-import org.marc4j.marc.Record;
-import org.solrmarc.callnum.DeweyCallNumber;
-import org.solrmarc.index.SolrIndexer;
-import org.solrmarc.tools.CallNumUtils;
-
-// The beanshell script class will initialize this variable to pointer to the singleton SolrIndexer class.
-SolrIndexer indexer;
-
-/**
- * Extract a numeric portion of the Dewey decimal call number
- *
- * Can return null
- *
- * @param record current MARC record
- * @param fieldSpec which MARC fields / subfields need to be analyzed
- * @param precisionStr a decimal number (represented in string format) showing the
- *  desired precision of the returned number; i.e. 100 to round to nearest hundred,
- *  10 to round to nearest ten, 0.1 to round to nearest tenth, etc.
- * @return Set containing requested numeric portions of Dewey decimal call numbers
- */
-public Set getDeweyNumber(Record record, String fieldSpec, String precisionStr) {
-    // Initialize our return value:
-    Set result = new LinkedHashSet();
-
-    // Precision comes in as a string, but we need to convert it to a float:
-    float precision = Float.parseFloat(precisionStr);
-
-    // Loop through the specified MARC fields:
-    Set input = indexer.getFieldList(record, fieldSpec);
-    for (String current: input) {
-        DeweyCallNumber callNum = new DeweyCallNumber(current);
-        if (callNum.isValid()) {
-            // Convert the numeric portion of the call number into a float:
-            float currentVal = Float.parseFloat(callNum.getClassification());
-            
-            // Round the call number value to the specified precision:
-            Float finalVal = new Float(Math.floor(currentVal / precision) * precision);
-            
-            // Convert the rounded value back to a string (with leading zeros) and save it:
-            // TODO: Provide different conversion to remove CallNumUtils dependency
-            result.add(CallNumUtils.normalizeFloat(finalVal.toString(), 3, -1));
-        }
-    }
-
-    // If we found no call number matches, return null; otherwise, return our results:
-    if (result.isEmpty())
-        return null;
-    return result;
-}
-
-/**
- * Normalize Dewey numbers for searching purposes (uppercase/stripped spaces)
- *
- * Can return null
- *
- * @param record current MARC record
- * @param fieldSpec which MARC fields / subfields need to be analyzed
- * @return Set containing normalized Dewey numbers extracted from specified fields.
- */
-public Set getDeweySearchable(Record record, String fieldSpec) {
-    // Initialize our return value:
-    Set result = new LinkedHashSet();
-
-    // Loop through the specified MARC fields:
-    Set input = indexer.getFieldList(record, fieldSpec);
-    Iterator iter = input.iterator();
-    while (iter.hasNext()) {
-        // Get the current string to work on:
-        String current = iter.next();
-
-        // Add valid strings to the set, normalizing them to be all uppercase
-        // and free from whitespace.
-        DeweyCallNumber callNum = new DeweyCallNumber(current);
-        if (callNum.isValid()) {
-            result.add(callNum.toString().toUpperCase().replaceAll(" ", ""));
-        }
-    }
-
-    // If we found no call numbers, return null; otherwise, return our results:
-    if (result.isEmpty())
-        return null;
-    return result;
-}
-
-/**
- * Normalize Dewey numbers for sorting purposes (use only the first valid number!)
- *
- * Can return null
- *
- * @param record current MARC record
- * @param fieldSpec which MARC fields / subfields need to be analyzed
- * @return String containing the first valid Dewey number encountered, normalized
- *         for sorting purposes.
- */
-public String getDeweySortable(Record record, String fieldSpec) {
-    // Loop through the specified MARC fields:
-    Set input = indexer.getFieldList(record, fieldSpec);
-    Iterator iter = input.iterator();
-    while (iter.hasNext()) {
-        // Get the current string to work on:
-        String current = iter.next();
-
-        // If this is a valid Dewey number, return the sortable shelf key:
-        DeweyCallNumber callNum = new DeweyCallNumber(current);
-        if (callNum.isValid()) {
-            return callNum.getShelfKey();
-        }
-    }
-
-    // If we made it this far, we didn't find a valid sortable Dewey number:
-    return null;
-}
-
-/**
- * Get sort key for first Dewey call number, identified by call type.
- * 
- * <p>{@code fieldSpec} is of form {@literal 098abc:099ab}, does not accept subfield ranges.
- *
- *
- * @param record  current MARC record
- * @param fieldSpec  which MARC fields / subfields need to be analyzed
- * @param callTypeSf  subfield containing call number type, single character only
- * @param callType  literal call number code
- * @return sort key for first identified Dewey call number
- */
-public static String getDeweySortableByType(
-        Record record, String fieldSpec, String callTypeSf, String callType) {
-    String sortKey = null;
-    for (String tag : fieldSpec.split(":")) {
-        // Check to ensure tag length is at least 3 characters
-        if (tag.length() < 3) {
-            //TODO: Should this go to a log? Better message for a bad tag in a field spec?
-            System.err.println("Invalid tag specified: " + tag);
-            continue;
-        }
-        String dfTag = tag.substring(0, 3);
-        String sfSpec = null;
-        if (tag.length() > 3) {
-                sfSpec = tag.substring(3);
-        }
-
-        // do all fields for this tag
-        for (VariableField vf : record.getVariableFields(dfTag)) {
-            // Assume tag represents a DataField
-            DataField df = (DataField) vf;
-            boolean callTypeMatch = false;
-            
-            // Assume call type subfield could repeat
-            for (Subfield typeSf : df.getSubfields(callTypeSf)) {
-                if (callTypeSf.indexOf(typeSf.getCode()) != -1 && typeSf.getData().equals(callType)) {
-                    callTypeMatch = true;
-                }
-            }
-            // take the first call number coded as Dewey
-            if (callTypeMatch) {
-                sortKey = new DeweyCallNumber(df.getSubfieldsAsString(sfSpec)).getShelfKey();
-                break;
-            }
-        } // end loop over variable fields
-    } // end loop over fieldSpec
-    return sortKey;
-}
-
-
-/**
- * Normalize Dewey numbers for AlphaBrowse sorting purposes (use all numbers!)
- *
- * Can return null
- *
- * @param record current MARC record
- * @param fieldSpec which MARC fields / subfields need to be analyzed
- * @return List containing normalized Dewey numbers extracted from specified fields.
- */
-public List getDeweySortables(Record record, String fieldSpec) {
-    // Initialize our return value:
-    List result = new LinkedList();
-
-    // Loop through the specified MARC fields:
-    Set input = indexer.getFieldList(record, fieldSpec);
-    Iterator iter = input.iterator();
-    while (iter.hasNext()) {
-        // Get the current string to work on:
-        String current = iter.next();
-
-        // gather all sort keys, even if number is not valid
-        DeweyCallNumber callNum = new DeweyCallNumber(current);
-        result.add(callNum.getShelfKey());
-    }
-
-    // If we found no call numbers, return null; otherwise, return our results:
-    if (result.isEmpty())
-        return null;
-    return result;
-}
diff --git a/import/index_scripts/format.bsh b/import/index_scripts/format.bsh
deleted file mode 100644
index 863e167722c1f29e73bb1c67495553bc2b1f4e78..0000000000000000000000000000000000000000
--- a/import/index_scripts/format.bsh
+++ /dev/null
@@ -1,302 +0,0 @@
-/**
- * Custom format determination script.
- *
- * This can be used to override built-in SolrMarc custom functions.  If you change
- * this script, you will need to activate it in import/marc_local.properties before
- * it will be applied during indexing.
- */
-import org.marc4j.marc.Record;
-import org.marc4j.marc.ControlField;
-import org.marc4j.marc.DataField;
-
-/**
- * Determine Record Format(s)
- *
- * @param  Record          record
- * @return Set     format of record
- */
-public Set getFormat(Record record){
-    Set result = new LinkedHashSet();
-    String leader = record.getLeader().toString();
-    char leaderBit;
-    ControlField fixedField = (ControlField) record.getVariableField("008");
-    DataField title = (DataField) record.getVariableField("245");
-    String formatString;
-    char formatCode = ' ';
-    char formatCode2 = ' ';
-    char formatCode4 = ' ';
-
-    // check if there's an h in the 245
-    if (title != null) {
-        if (title.getSubfield('h') != null){
-            if (title.getSubfield('h').getData().toLowerCase().contains("[electronic resource]")) {
-                result.add("Electronic");
-                return result;
-            }
-        }
-    }
-
-    // check the 007 - this is a repeating field
-    List fields = record.getVariableFields("007");
-    Iterator fieldsIter = fields.iterator();
-    if (fields != null) {
-        ControlField formatField;
-        while(fieldsIter.hasNext()) {
-            formatField = (ControlField) fieldsIter.next();
-            formatString = formatField.getData().toUpperCase();
-            formatCode = formatString.length() > 0 ? formatString.charAt(0) : ' ';
-            formatCode2 = formatString.length() > 1 ? formatString.charAt(1) : ' ';
-            formatCode4 = formatString.length() > 4 ? formatString.charAt(4) : ' ';
-            switch (formatCode) {
-                case 'A':
-                    switch(formatCode2) {
-                        case 'D':
-                            result.add("Atlas");
-                            break;
-                        default:
-                            result.add("Map");
-                            break;
-                    }
-                    break;
-                case 'C':
-                    switch(formatCode2) {
-                        case 'A':
-                            result.add("TapeCartridge");
-                            break;
-                        case 'B':
-                            result.add("ChipCartridge");
-                            break;
-                        case 'C':
-                            result.add("DiscCartridge");
-                            break;
-                        case 'F':
-                            result.add("TapeCassette");
-                            break;
-                        case 'H':
-                            result.add("TapeReel");
-                            break;
-                        case 'J':
-                            result.add("FloppyDisk");
-                            break;
-                        case 'M':
-                        case 'O':
-                            result.add("CDROM");
-                            break;
-                        case 'R':
-                            // Do not return - this will cause anything with an
-                            // 856 field to be labeled as "Electronic"
-                            break;
-                        default:
-                            result.add("Software");
-                            break;
-                    }
-                    break;
-                case 'D':
-                    result.add("Globe");
-                    break;
-                case 'F':
-                    result.add("Braille");
-                    break;
-                case 'G':
-                    switch(formatCode2) {
-                        case 'C':
-                        case 'D':
-                            result.add("Filmstrip");
-                            break;
-                        case 'T':
-                            result.add("Transparency");
-                            break;
-                        default:
-                            result.add("Slide");
-                            break;
-                    }
-                    break;
-                case 'H':
-                    result.add("Microfilm");
-                    break;
-                case 'K':
-                    switch(formatCode2) {
-                        case 'C':
-                            result.add("Collage");
-                            break;
-                        case 'D':
-                            result.add("Drawing");
-                            break;
-                        case 'E':
-                            result.add("Painting");
-                            break;
-                        case 'F':
-                            result.add("Print");
-                            break;
-                        case 'G':
-                            result.add("Photonegative");
-                            break;
-                        case 'J':
-                            result.add("Print");
-                            break;
-                        case 'L':
-                            result.add("Drawing");
-                            break;
-                        case 'O':
-                            result.add("FlashCard");
-                            break;
-                        case 'N':
-                            result.add("Chart");
-                            break;
-                        default:
-                            result.add("Photo");
-                            break;
-                    }
-                    break;
-                case 'M':
-                    switch(formatCode2) {
-                        case 'F':
-                            result.add("VideoCassette");
-                            break;
-                        case 'R':
-                            result.add("Filmstrip");
-                            break;
-                        default:
-                            result.add("MotionPicture");
-                            break;
-                    }
-                    break;
-                case 'O':
-                    result.add("Kit");
-                    break;
-                case 'Q':
-                    result.add("MusicalScore");
-                    break;
-                case 'R':
-                    result.add("SensorImage");
-                    break;
-                case 'S':
-                    switch(formatCode2) {
-                        case 'D':
-                            result.add("SoundDisc");
-                            break;
-                        case 'S':
-                            result.add("SoundCassette");
-                            break;
-                        default:
-                            result.add("SoundRecording");
-                            break;
-                    }
-                    break;
-                case 'V':
-                    switch(formatCode2) {
-                        case 'C':
-                            result.add("VideoCartridge");
-                            break;
-                        case 'D':
-                            switch(formatCode4) {
-                                case 'S':
-                                    result.add("BRDisc");
-                                    break;
-                                case 'V':
-                                default:
-                                    result.add("VideoDisc");
-                                    break;
-                            }
-                            break;
-                        case 'F':
-                            result.add("VideoCassette");
-                            break;
-                        case 'R':
-                            result.add("VideoReel");
-                            break;
-                        default:
-                            result.add("Video");
-                            break;
-                    }
-                    break;
-            }
-        }
-        if (!result.isEmpty()) {
-            return result;
-        }
-    }
-
-    // check the Leader at position 6
-    leaderBit = leader.charAt(6);
-    switch (Character.toUpperCase(leaderBit)) {
-        case 'C':
-        case 'D':
-            result.add("MusicalScore");
-            break;
-        case 'E':
-        case 'F':
-            result.add("Map");
-            break;
-        case 'G':
-            result.add("Slide");
-            break;
-        case 'I':
-            result.add("SoundRecording");
-            break;
-        case 'J':
-            result.add("MusicRecording");
-            break;
-        case 'K':
-            result.add("Photo");
-            break;
-        case 'M':
-            result.add("Electronic");
-            break;
-        case 'O':
-        case 'P':
-            result.add("Kit");
-            break;
-        case 'R':
-            result.add("PhysicalObject");
-            break;
-        case 'T':
-            result.add("Manuscript");
-            break;
-    }
-    if (!result.isEmpty()) {
-        return result;
-    }
-
-    // check the Leader at position 7
-    leaderBit = leader.charAt(7);
-    switch (Character.toUpperCase(leaderBit)) {
-        // Monograph
-        case 'M':
-            if (formatCode == 'C') {
-                result.add("eBook");
-            } else {
-                result.add("Book");
-            }
-            break;
-        // Component parts
-        case 'A':
-            result.add("BookComponentPart");
-            break;
-        case 'B':
-            result.add("SerialComponentPart");
-            break;
-        // Serial
-        case 'S':
-            // Look in 008 to determine what type of Continuing Resource
-            formatCode = fixedField.getData().toUpperCase().charAt(21);
-            switch (formatCode) {
-                case 'N':
-                    result.add("Newspaper");
-                    break;
-                case 'P':
-                    result.add("Journal");
-                    break;
-                default:
-                    result.add("Serial");
-                    break;
-            }
-    }
-
-    // Nothing worked!
-    if (result.isEmpty()) {
-        result.add("Unknown");
-    }
-    
-    return result;
-}
diff --git a/import/index_scripts/getFirstNormalizedLCCN.bsh b/import/index_scripts/getFirstNormalizedLCCN.bsh
deleted file mode 100644
index e4b00be6ae5cb5f67d1c116f254e514105511ecc..0000000000000000000000000000000000000000
--- a/import/index_scripts/getFirstNormalizedLCCN.bsh
+++ /dev/null
@@ -1,75 +0,0 @@
-import org.marc4j.marc.Record;
-
-// Give ourselves the ability to import other BeanShell scripts
-String vufindHome = System.getenv("VUFIND_HOME");
-String vufindLocal = System.getenv("VUFIND_LOCAL_DIR");
-addClassPath(vufindHome + "/import");
-if (vufindLocal != null) {
-    addClassPath(vufindLocal + "/import");
-}
-importCommands("index_scripts");
-
-// define the base level indexer so that its methods can be called from the script.
-// note that the SolrIndexer code will set this value before the script methods are called.
-org.solrmarc.index.SolrIndexer indexer = null;
-
-/**
- * Extract the first valid LCCN from a record and return it in a normalized format
- * with an optional prefix added (helpful for guaranteeing unique IDs)
- * @param indexer
- * @param record
- * @param fieldSpec
- * @param prefix
- * @return Normalized LCCN
- */
-public String getFirstNormalizedLCCN(org.solrmarc.index.SolrIndexer indexer, 
-    Record record, String fieldSpec, String prefix) {
-    // Loop through relevant fields in search of first valid LCCN:
-    Set lccns = indexer.getFieldList(record, fieldSpec);
-    Iterator lccnIter = lccns.iterator();
-    if (lccns != null) {
-        String current;
-        while(lccnIter.hasNext()) {
-            current = getNormalizedLCCN(lccnIter.next());
-            if (current != null && current != false && current.length() > 0) {
-                return prefix + current;
-            }
-        }
-    }
-
-    // If we got this far, we couldn't find a valid value:
-    return null;
-}
-
-/**
- * Extract the first valid LCCN from a record and return it in a normalized format
- * with an optional prefix added (helpful for guaranteeing unique IDs)
- * @param record
- * @param fieldSpec
- * @param prefix
- * @return Normalized LCCN
- */
-public String getFirstNormalizedLCCN(Record record, String fieldSpec, String prefix) {
-    return getFirstNormalizedLCCN(indexer, record, fieldSpec, prefix);
-}
-
-/**
- * Extract the first valid LCCN from a record and return it in a normalized format
- * @param record
- * @param fieldSpec
- * @return Normalized LCCN
- */
-public String getFirstNormalizedLCCN(Record record, String fieldSpec) {
-    // Send in a default prefix if none was provided by the user:
-    return getFirstNormalizedLCCN(indexer, record, fieldSpec, "");
-}
-
-/**
- * Extract the first valid LCCN from a record and return it in a normalized format
- * @param record
- * @return Normalized LCCN
- */
-public String getFirstNormalizedLCCN(Record record) {
-    // Send in a default fieldSpec/prefix if none were provided by the user:
-    return getFirstNormalizedLCCN(indexer, record, "010a", "");
-}
diff --git a/import/index_scripts/getFulltext.bsh b/import/index_scripts/getFulltext.bsh
deleted file mode 100644
index 6385c8640b4a21ef68add7ee431ae1f51bcedb91..0000000000000000000000000000000000000000
--- a/import/index_scripts/getFulltext.bsh
+++ /dev/null
@@ -1,260 +0,0 @@
-/**
- * Custom full text retrieval script.
- *
- * This can be used to override built-in SolrMarc custom functions.  If you change
- * this script, you will need to activate it in import/marc_local.properties before
- * it will be applied during indexing.
- */
-import org.marc4j.marc.Record;
-import org.marc4j.marc.DataField;
-import java.util.regex.Pattern;
-import java.io.*;
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-
-// define the base level indexer so that its methods can be called from the script.
-// note that the SolrIndexer code will set this value before the script methods are called.
-org.solrmarc.index.SolrIndexer indexer = null;
-
-/**
- * Load configurations for the full text parser.  Return an array containing the
- * parser type in the first element and the parser configuration in the second
- * element.
- *
- * @return String[]
- */
-public String[] getFulltextParserSettings()
-{
-    String parserType = indexer.getConfigSetting(
-        "fulltext.ini", "General", "parser"
-    );
-    if (null != parserType) {
-        parserType = parserType.toLowerCase();
-    }
-
-    // Is Aperture active?
-    String aperturePath = indexer.getConfigSetting(
-        "fulltext.ini", "Aperture", "webcrawler"
-    );
-    if ((null == parserType && null != aperturePath)
-        || (null != parserType && parserType.equals("aperture"))
-    ) {
-        String[] array = { "aperture", aperturePath };
-        return array;
-    }
-
-    // Is Tika active?
-    String tikaPath = indexer.getConfigSetting(
-        "fulltext.ini", "Tika", "path"
-    );
-    if ((null == parserType && null != tikaPath)
-        || (null != parserType && parserType.equals("tika"))
-    ) {
-        String[] array = { "tika", tikaPath };
-        return array;
-    }
-
-    // No recognized parser found:
-    String[] array = { "none", null };
-    return array;
-}
-
-/**
- * Extract full-text from the documents referenced in the tags
- *
- * @param Record record
- * @param String field spec to search for URLs
- * @param String only harvest files matching this extension (null for all)
- * @return String The full-text
- */
-public String getFulltext(Record record, String fieldSpec, String extension) {
-    String result = "";
-
-    // Get the web crawler settings (and return no text if it is unavailable)
-    String[] parserSettings = getFulltextParserSettings();
-    if (parserSettings[0].equals("none")) {
-        return null;
-    }
-
-    // Loop through the specified MARC fields:
-    Set fields = indexer.getFieldList(record, fieldSpec);
-    Iterator fieldsIter = fields.iterator();
-    if (fields != null) {
-        while(fieldsIter.hasNext()) {
-            // Get the current string to work on (and sanitize spaces):
-            String current = fieldsIter.next().replaceAll(" ", "%20");
-            // Filter by file extension
-            if (extension == null || current.endsWith(extension)) {
-                // Load the parser output for each tag into a string
-                result = result + harvestWithParser(current, parserSettings);
-            }
-        }
-    }
-    // return string to SolrMarc
-    return result;
-}
-
-/**
- * Extract full-text from the documents referenced in the tags
- *
- * @param Record record
- * @param String field spec to search for URLs
- * @return String The full-text
- */
-public String getFulltext(Record record, String fieldSpec) {
-    return getFulltext(record, fieldSpec, null);
-}
-
-/**
- * Extract full-text from the documents referenced in the tags
- *
- * @param Record record
- * @return String The full-text
- */
-public String getFulltext(Record record) {
-    return getFulltext(record, "856u", null);
-}
-
-/**
- * Clean up XML data generated by Aperture
- *
- * @param File The file to clean
- * @return File A fixed version of the file
- */
-public File sanitizeApertureOutput(File f)
-{
-    //clean up the aperture xml output
-    File tempFile = File.createTempFile("buffer", ".tmp");
-    FileOutputStream fw = new FileOutputStream(tempFile);
-    Writer writer = new OutputStreamWriter(fw, "UTF8");
-
-    //delete this control character from the File and save
-    Reader fr = new FileReader(f);
-    BufferedReader br = new BufferedReader(fr);
-    while (br.ready()) {
-        writer.write(sanitizeFullText(br.readLine()));
-    }
-    writer.close();
-    br.close();
-    fr.close();
-
-    return tempFile;
-}
-
-/**
- * Clean up bad characters in the full text.
- *
- * @param String Text to clean
- * @return String Cleaned text
- */
-public String sanitizeFullText(text)
-{
-    String badChars = "[^\\u0009\\u000A\\u000D\\u0020-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFFF]+";
-    return text.replaceAll(badChars, " ");
-}
-
-/**
- * Harvest the contents of a document file (PDF, Word, etc.) using Aperture.
- * This method will only work if Aperture is properly configured in the
- * fulltext.ini file.  Without proper configuration, this will simply return an
- * empty string.
- *
- * @param String The url extracted from the MARC tag.
- * @param String The path to Aperture
- * @return String The full-text
- */
-public String harvestWithAperture(url, aperturePath) {
-    String plainText = "";
-    // Create temp file.
-    File f = File.createTempFile("apt", ".txt");
-
-    // Delete temp file when program exits.
-    f.deleteOnExit();
-
-    // Construct the command to call Aperture
-    String cmd = aperturePath + " -o " + f.getAbsolutePath().toString()  + " -x " + url;
-
-    // Call Aperture
-    //System.out.println("Loading fulltext from " + url + ". Please wait ...");
-    Process p = Runtime.getRuntime().exec(cmd);
-    BufferedReader stdInput = new BufferedReader(new
-        InputStreamReader(p.getInputStream()));
-    while ((s = stdInput.readLine()) != null) {
-        //System.out.println(s);
-    }
-    // Wait for Aperture to finish
-    p.waitFor();
-
-    // Parse Aperture XML output
-    try {
-        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
-        DocumentBuilder db = dbf.newDocumentBuilder();
-        File tempFile = sanitizeApertureOutput(f);
-        Document xmlDoc = db.parse(tempFile);
-        NodeList nl = xmlDoc.getElementsByTagName("plainTextContent");
-        if(nl != null && nl.getLength() > 0) {
-            Node node = nl.item(0);
-            if (node.getNodeType() == Node.ELEMENT_NODE) {
-                plainText = plainText + node.getTextContent();
-            }
-        }
-
-        // we'll hold onto the temp file if it failed to parse for debugging;
-        // only set it up to be deleted if we've made it this far successfully.
-        tempFile.deleteOnExit();
-    } catch (Exception e) {
-        indexer.getLogger().error("Error encountered parsing XML Document: " + e);
-    }
-
-    return plainText;
-}
-
-/**
- * Harvest the contents of a document file (PDF, Word, etc.) using Tika.
- * This method will only work if Tika is properly configured in the fulltext.ini
- * file.  Without proper configuration, this will simply return an empty string.
- *
- * @param String The url extracted from the MARC tag.
- * @param String The path to Tika
- * @return String The full-text
- */
-public String harvestWithTika(url, scraperPath) {
-    String plainText = "";
-
-    // Construct the command
-    String cmd = "java -jar " + scraperPath + " -t -eUTF8 " + url;
-
-    // Call our scraper
-    //System.out.println("Loading fulltext from " + url + ". Please wait ...");
-    Process p = Runtime.getRuntime().exec(cmd);
-    BufferedReader stdInput = new BufferedReader(new
-        InputStreamReader(p.getInputStream(), "UTF8"));
-
-    // We'll build the string from the command output
-    StringBuilder stringBuilder= new StringBuilder();
-    while ((s = stdInput.readLine()) != null) {
-        stringBuilder.append(s);
-    }
-
-    return sanitizeFullText(stringBuilder.toString());
-}
-
-/**
- * Harvest the contents of a document file (PDF, Word, etc.) using the active parser.
- *
- * @param String The url extracted from the MARC tag.
- * @param String[] Configuration settings from getFulltextParserSettings.
- * @return String The full-text
- */
-public String harvestWithParser(url, settings) {
-    if (settings[0].equals("aperture")) {
-        return harvestWithAperture(url, settings[1]);
-    } else if (settings[0].equals("tika")) {
-        return harvestWithTika(url, settings[1]);
-    }
-    return null;
-}
diff --git a/import/index_scripts/getNormalizedLCCN.bsh b/import/index_scripts/getNormalizedLCCN.bsh
deleted file mode 100644
index 8f5d9182e7780d79ec983607604f176c639b3234..0000000000000000000000000000000000000000
--- a/import/index_scripts/getNormalizedLCCN.bsh
+++ /dev/null
@@ -1,27 +0,0 @@
-/**
- * Normalize a single LCCN using the procedure specified at:
- *      http://www.loc.gov/marc/lccn-namespace.html#normalization
- * @param lccn
- * @return Normalized LCCN
- */
-public String getNormalizedLCCN(String lccn) {
-    // Remove whitespace:
-    lccn = lccn.replaceAll(" ", "");
-
-    // Chop off anything following a forward slash:
-    String[] parts = lccn.split("/", 2);
-    lccn = parts[0];
-
-    // Normalize any characters following a hyphen to at least six digits:
-    parts = lccn.split("-", 2);
-    if (parts.length > 1) {
-        String secondPart = parts[1];
-        while (secondPart.length() < 6) {
-            secondPart = "0" + secondPart;
-        }
-        lccn = parts[0] + secondPart;
-    }
-
-    // Send back normalized LCCN:
-    return lccn;
-}
diff --git a/import/index_scripts/getNormalizedLCCNs.bsh b/import/index_scripts/getNormalizedLCCNs.bsh
deleted file mode 100644
index b5ca263e5550d1379737f2f59e25511e07d5c945..0000000000000000000000000000000000000000
--- a/import/index_scripts/getNormalizedLCCNs.bsh
+++ /dev/null
@@ -1,51 +0,0 @@
-import org.marc4j.marc.Record;
-
-// Give ourselves the ability to import other BeanShell scripts
-String vufindHome = System.getenv("VUFIND_HOME");
-String vufindLocal = System.getenv("VUFIND_LOCAL_DIR");
-addClassPath(vufindHome + "/import");
-if (vufindLocal != null) {
-    addClassPath(vufindLocal + "/import");
-}
-importCommands("index_scripts");
-
-// define the base level indexer so that its methods can be called from the script.
-// note that the SolrIndexer code will set this value before the script methods are called.
-org.solrmarc.index.SolrIndexer indexer = null;
-
-/**
- * Extract LCCNs from a record and return them in a normalized format
- * @param record
- * @param fieldSpec
- * @return Set of normalized LCCNs
- */
-public Set getNormalizedLCCNs(Record record, String fieldSpec) {
-    // Initialize return value:
-    Set result = new LinkedHashSet();
-
-    // Loop through relevant fields and normalize everything:
-    Set lccns = indexer.getFieldList(record, fieldSpec);
-    Iterator lccnIter = lccns.iterator();
-    if (lccns != null) {
-        String current;
-        while(lccnIter.hasNext()) {
-            current = getNormalizedLCCN(lccnIter.next());
-            if (current != null && current != false && current.length() > 0) {
-                result.add(current);
-            }
-        }
-    }
-
-    // Send back results:
-    return result;
-}
-
-/**
- * Extract LCCNs from a record and return them in a normalized format
- * @param record
- * @return Set of normalized LCCNs
- */
-public Set getNormalizedLCCNs(Record record) {
-    // Send in a default fieldSpec if none was provided by the user:
-    return getNormalizedLCCNs(record, "010a");
-}
diff --git a/import/index_scripts/getdate.bsh b/import/index_scripts/getdate.bsh
deleted file mode 100644
index 0a8186b4d5bc8414c0bfbe6f478d772cefa20b87..0000000000000000000000000000000000000000
--- a/import/index_scripts/getdate.bsh
+++ /dev/null
@@ -1,198 +0,0 @@
-/**
- * Custom date script.
- *
- * This can be used to override built-in SolrMarc custom functions.  If you change
- * this script, you will need to activate it in import/marc_local.properties before
- * it will be applied during indexing.
- */
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import org.apache.log4j.Logger;
-import org.marc4j.marc.*;
-import org.solrmarc.marc.MarcImporter;
-import org.solrmarc.tools.Utils;
-import org.solrmarc.index.SolrIndexer;
-
-private final static Pattern FOUR_DIGIT_PATTERN_BRACES = Pattern.compile("\\[[12]\\d{3,3}\\]");
-private final static Pattern FOUR_DIGIT_PATTERN_ONE_BRACE = Pattern.compile("\\[[12]\\d{3,3}");
-private final static Pattern FOUR_DIGIT_PATTERN_STARTING_WITH_1_2 = Pattern.compile("(20|19|18|17|16|15)[0-9][0-9]");
-private final static Pattern FOUR_DIGIT_PATTERN_OTHER_1 = Pattern.compile("l\\d{3,3}");
-private final static Pattern FOUR_DIGIT_PATTERN_OTHER_2 = Pattern.compile("\\[19\\]\\d{2,2}");
-private final static Pattern FOUR_DIGIT_PATTERN_OTHER_3 = Pattern.compile("(20|19|18|17|16|15)[0-9][-?0-9]");
-private final static Pattern FOUR_DIGIT_PATTERN_OTHER_4 = Pattern.compile("i.e. (20|19|18|17|16|15)[0-9][0-9]");
-private final static Pattern BC_DATE_PATTERN = Pattern.compile("[0-9]+ [Bb][.]?[Cc][.]?");
-private final static Pattern FOUR_DIGIT_PATTERN = Pattern.compile("\\d{4,4}");
-private static Matcher matcher;
-private static Matcher matcher_braces;
-private static Matcher matcher_one_brace;
-private static Matcher matcher_start_with_1_2;
-private static Matcher matcher_l_plus_three_digits;
-private static Matcher matcher_bracket_19_plus_two_digits;
-private static Matcher matcher_ie_date;
-private static Matcher matcher_bc_date;
-private static Matcher matcher_three_digits_plus_unk;
-protected static Logger logger = Logger.getLogger(Utils.class.getName());
-
-/**
- * Cleans non-digits from a String
- * @param date String to parse
- * @return Numeric part of date String (or null)
- */
-public String cleanDate(String date)
-{
-    matcher_braces = FOUR_DIGIT_PATTERN_BRACES.matcher(date);
-    matcher_one_brace = FOUR_DIGIT_PATTERN_ONE_BRACE.matcher(date);
-    matcher_start_with_1_2 = FOUR_DIGIT_PATTERN_STARTING_WITH_1_2.matcher(date);
-    matcher_l_plus_three_digits = FOUR_DIGIT_PATTERN_OTHER_1.matcher(date);
-    matcher_bracket_19_plus_two_digits = FOUR_DIGIT_PATTERN_OTHER_2.matcher(date);
-    matcher_three_digits_plus_unk = FOUR_DIGIT_PATTERN_OTHER_3.matcher(date);
-    matcher_ie_date = FOUR_DIGIT_PATTERN_OTHER_4.matcher(date);
-    matcher = FOUR_DIGIT_PATTERN.matcher(date);
-    matcher_bc_date = BC_DATE_PATTERN.matcher(date);
-    
-    String cleanDate = null; // raises DD-anomaly
-    
-    if(matcher_braces.find())
-    {   
-        cleanDate = matcher_braces.group();
-        cleanDate = Utils.removeOuterBrackets(cleanDate);
-        if (matcher.find())
-        {
-            String tmp = matcher.group();
-            if (!tmp.equals(cleanDate))
-            {
-                tmp = "" + tmp;
-            }
-        }
-    } 
-    else if (matcher_ie_date.find())
-    {
-        cleanDate = matcher_ie_date.group().replaceAll("i.e. ", "");
-    }
-    else if(matcher_one_brace.find())
-    {   
-        cleanDate = matcher_one_brace.group();
-        cleanDate = Utils.removeOuterBrackets(cleanDate);
-        if (matcher.find())
-        {
-            String tmp = matcher.group();
-            if (!tmp.equals(cleanDate))
-            {
-                tmp = "" + tmp;
-            }
-        }
-    }
-    else if(matcher_bc_date.find())
-    {   
-        cleanDate = null;
-    } 
-    else if(matcher_start_with_1_2.find())
-    {   
-        cleanDate = matcher_start_with_1_2.group();
-    } 
-    else if(matcher_l_plus_three_digits.find())
-    {   
-        cleanDate = matcher_l_plus_three_digits.group().replaceAll("l", "1");
-    } 
-    else if(matcher_bracket_19_plus_two_digits.find())
-    {   
-        cleanDate = matcher_bracket_19_plus_two_digits.group().replaceAll("\\[", "").replaceAll("\\]", "");
-    } 
-    else if(matcher_three_digits_plus_unk.find())
-    {   
-        cleanDate = matcher_three_digits_plus_unk.group().replaceAll("[-?]", "0");
-    } 
-    if (cleanDate != null)
-    {
-        logger.debug("Date : "+ date + " mapped to : "+ cleanDate);            
-    }
-    else
-    {
-        logger.debug("No Date match: "+ date);
-    }
-    return cleanDate;
-}
-
-/**
- * Return the date in 260c as a string
- * @param record - the marc record object
- * @return 260c, "cleaned" per org.solrmarc.tools.Utils.cleanDate()
- */
-public String getDate(Record record)
-{
-    Set result = SolrIndexer.getFieldList(record, "260c");
-    String date = org.solrmarc.tools.Utils.join(result, ", ");
-    if (date == null || date.length() == 0)
-        return (null);
-    return cleanDate(date);
-}
-
-/**
- * Get all available dates from the record.
- *
- * @param  Record          record
- * @return Set             dates
- */
-public Set getDates(Record record) {
-    Set dates = new LinkedHashSet();
-
-    // First check old-style 260c date:
-    List list260 = record.getVariableFields("260");
-    for (VariableField vf : list260) {
-        DataField df = (DataField) vf;
-        List currentDates = df.getSubfields('c');
-        for (Subfield sf : currentDates) {
-            String currentDateStr = cleanDate(sf.getData());
-            dates.add(currentDateStr);
-        }
-    }
-    // Now track down relevant RDA-style 264c dates; we only care about
-    // copyright and publication dates (and ignore copyright dates if
-    // publication dates are present).
-    Set pubDates = new LinkedHashSet();
-    Set copyDates = new LinkedHashSet();
-    List list264 = record.getVariableFields("264");
-    for (VariableField vf : list264) {
-        DataField df = (DataField) vf;
-        List currentDates = df.getSubfields('c');
-        for (Subfield sf : currentDates) {
-            String currentDateStr = cleanDate(sf.getData());
-            char ind2 = df.getIndicator2();
-            switch (ind2)
-            {
-                case '1':
-                    pubDates.add(currentDateStr);
-                    break;
-                case '4':
-                    copyDates.add(currentDateStr);
-                    break;
-            }
-        }
-    }
-    if (pubDates.size() > 0) {
-        dates.addAll(pubDates);
-    } else if (copyDates.size() > 0) {
-        dates.addAll(copyDates);
-    }
-
-    return dates;
-}
-
-/**
- * Get the earliest publication date from the record.
- *
- * @param  Record          record
- * @return String          earliest date
- */
-public String getFirstDate(Record record) {
-    String result = null;
-    Set dates = getDates(record);
-    Iterator datesIter = dates.iterator();
-    while (datesIter.hasNext()) {
-        String current = datesIter.next();
-        if (result == null || Integer.parseInt(current) < Integer.parseInt(result)) {
-            result = current;
-        }
-    }
-    return result;
-}
\ No newline at end of file
diff --git a/import/index_scripts/getpublishers.bsh b/import/index_scripts/getpublishers.bsh
deleted file mode 100644
index 465909590cc0c19f044c0486796eb47c3f0fa1eb..0000000000000000000000000000000000000000
--- a/import/index_scripts/getpublishers.bsh
+++ /dev/null
@@ -1,66 +0,0 @@
-/**
- * Custom date script.
- *
- * This can be used to override built-in SolrMarc custom functions.  If you change
- * this script, you will need to activate it in import/marc_local.properties before
- * it will be applied during indexing.
- */
-import org.marc4j.marc.*;
-
-/**
- * Get all available publishers from the record.
- *
- * @param  Record          record
- * @return Set             publishers
- */
-public Set getPublishers(Record record) {
-    Set publishers = new LinkedHashSet();
-
-    // First check old-style 260b name:
-    List list260 = record.getVariableFields("260");
-    for (VariableField vf : list260)
-    {
-        DataField df = (DataField) vf;
-        String currentString = "";
-        for (Subfield current : df.getSubfields('b')) {
-            currentString = currentString.trim().concat(" " + current.getData()).trim();
-        }
-        if (currentString.length() > 0) {
-            publishers.add(currentString);
-        }
-    }
-
-    // Now track down relevant RDA-style 264b names; we only care about
-    // copyright and publication names (and ignore copyright names if
-    // publication names are present).
-    Set pubNames = new LinkedHashSet();
-    Set copyNames = new LinkedHashSet();
-    List list264 = record.getVariableFields("264");
-    for (VariableField vf : list264)
-    {
-        DataField df = (DataField) vf;
-        String currentString = "";
-        for (Subfield current : df.getSubfields('b')) {
-            currentString = currentString.trim().concat(" " + current.getData()).trim();
-        }
-        if (currentString.length() > 0) {
-            char ind2 = df.getIndicator2();
-            switch (ind2)
-            {
-                case '1':
-                    pubNames.add(currentString);
-                    break;
-                case '4':
-                    copyNames.add(currentString);
-                    break;
-            }
-        }
-    }
-    if (pubNames.size() > 0) {
-        publishers.addAll(pubNames);
-    } else if (copyNames.size() > 0) {
-        publishers.addAll(copyNames);
-    }
-
-    return publishers;
-}
\ No newline at end of file
diff --git a/import/index_scripts/illustrated.bsh b/import/index_scripts/illustrated.bsh
deleted file mode 100644
index 3733630e7a4c00e9f40e51703b02931e183fcaa3..0000000000000000000000000000000000000000
--- a/import/index_scripts/illustrated.bsh
+++ /dev/null
@@ -1,86 +0,0 @@
-/**
- * Custom isIllustrated() script.
- *
- * This can be used to override built-in SolrMarc custom functions.  If you change
- * this script, you will need to activate it in import/marc_local.properties before
- * it will be applied during indexing.
- */
-import org.marc4j.marc.Record;
-import org.marc4j.marc.ControlField;
-import org.marc4j.marc.DataField;
-
-/**
- * Determine if a record is illustrated.
- *
- * @param  Record          record
- * @return String   "Illustrated" or "Not Illustrated"
- */
-public String isIllustrated(Record record) {
-    String leader = record.getLeader().toString();
-    
-    // Does the leader indicate this is a "language material" that might have extra
-    // illustration details in the fixed fields?
-    if (leader.charAt(6) == 'a') {
-        String currentCode = "";         // for use in loops below
-        
-        // List of 008/18-21 codes that indicate illustrations:
-        String illusCodes = "abcdefghijklmop";
-        
-        // Check the illustration characters of the 008:
-        ControlField fixedField = (ControlField) record.getVariableField("008");
-        if (fixedField != null) {
-            String fixedFieldText = fixedField.getData().toLowerCase();
-            for (int i = 18; i <= 21; i++) {
-                if (i < fixedFieldText.length()) {
-                    currentCode = fixedFieldText.substring(i, i + 1);
-                    if (illusCodes.contains(currentCode)) {
-                        return "Illustrated";
-                    }
-                }
-            }
-        }
-        
-        // Now check if any 006 fields apply:
-        List fields = record.getVariableFields("006");
-        Iterator fieldsIter = fields.iterator();
-        if (fields != null) {
-            ControlField formatField;
-            while(fieldsIter.hasNext()) {
-                fixedField = (ControlField) fieldsIter.next();
-                String fixedFieldText = fixedField.getData().toLowerCase();
-                for (int i = 1; i <= 4; i++) {
-                     if (i < fixedFieldText.length()) {
-                        currentCode = fixedFieldText.substring(i, i + 1);
-                        if (illusCodes.contains(currentCode)) {
-                            return "Illustrated";
-                        }
-                    }
-                }
-            }
-        }
-    }
-    
-    // Now check for interesting strings in 300 subfield b:
-    List fields = record.getVariableFields("300");
-    Iterator fieldsIter = fields.iterator();
-    if (fields != null) {
-        DataField physical;
-        while(fieldsIter.hasNext()) {
-            physical = (DataField) fieldsIter.next();
-            List subfields = physical.getSubfields('b');
-            Iterator subfieldsIter = subfields.iterator();
-            if (subfields != null) {
-                String desc;
-                while (subfieldsIter.hasNext()) {
-                    desc = subfieldsIter.next().getData().toLowerCase();
-                    if (desc.contains("ill.") || desc.contains("illus.")) {
-                        return "Illustrated";
-                    }
-                }
-            }
-        }
-    }
-
-    // If we made it this far, we found no sign of illustrations:
-    return "Not Illustrated";
-}
diff --git a/import/index_scripts/lcnaf.bsh b/import/index_scripts/lcnaf.bsh
deleted file mode 100644
index 563593afedec1d13a3e1ddd30f2940ec48fc2e94..0000000000000000000000000000000000000000
--- a/import/index_scripts/lcnaf.bsh
+++ /dev/null
@@ -1,94 +0,0 @@
-import org.marc4j.marc.Record;
-import org.marc4j.marc.DataField;
-import org.solrmarc.index.UpdateDateTracker;
-
-// define the base level indexer so that its methods can be called from the script.
-// note that the SolrIndexer code will set this value before the script methods are called.
-org.solrmarc.index.SolrIndexer indexer = null;
-
-// Give ourselves the ability to import other BeanShell scripts
-String vufindHome = System.getenv("VUFIND_HOME");
-String vufindLocal = System.getenv("VUFIND_LOCAL_DIR");
-addClassPath(vufindHome + "/import");
-if (vufindLocal != null) {
-    addClassPath(vufindLocal + "/import");
-}
-importCommands("index_scripts");
-
-/**
- * Get the unique identifier for the current LCNAF record.
- * @param record
- * @return ID string
- */
-public String getLCNAFID(Record record) {
-    return getFirstNormalizedLCCN(indexer, record, "010a", "lcnaf-");
-}
-
-/**
- * Determine the type of the current authority record.
- * @param record
- * @return Record type string
- */
-public String getLCNAFRecordType(Record record) {
-    String recordType;
-
-    // Try to identify the record type using the main heading:
-    DataField heading = null;
-    if ((heading = (DataField) record.getVariableField("100")) != null) {
-        recordType = "Personal Name";
-    } else if ((heading = (DataField) record.getVariableField("110")) != null) {
-        recordType = "Corporate Name";
-    } else if ((heading = (DataField) record.getVariableField("111")) != null) {
-        recordType = "Meeting Name";
-    } else if ((heading = (DataField) record.getVariableField("130")) != null) {
-        recordType = "Uniform Title";
-    } else if ((heading = (DataField) record.getVariableField("150")) != null) {
-        recordType = "Topical Term";
-    } else if ((heading = (DataField) record.getVariableField("151")) != null) {
-        recordType = "Geographic Name";
-    } else if ((heading = (DataField) record.getVariableField("155")) != null) {
-        recordType = "Heading - Genre/Form Term";
-    } else if ((heading = (DataField) record.getVariableField("180")) != null) {
-        recordType = "Heading - General Subdivision";
-    } else if ((heading = (DataField) record.getVariableField("181")) != null) {
-        recordType = "Heading - Geographic Subdivision";
-    } else if ((heading = (DataField) record.getVariableField("182")) != null) {
-        recordType = "Heading - Chronological Subdivision";
-    } else if ((heading = (DataField) record.getVariableField("185")) != null) {
-        recordType = "Heading - Form Subdivision";
-    } else {
-        // No recognized heading field found:
-        return "Unknown";
-    }
-
-    // If we got this far, we found a main heading; let's see if it has
-    // a title subfield!
-    if (heading.getSubfield('t') != null) {
-        recordType += " / Title";
-    }
-
-    return recordType;
-}
-
-/**
- * Get the "first indexed" date for the current record.
- * @param record
- * @return ID string
- */
-public String getLCNAFFirstIndexed(Record record) {
-    UpdateDateTracker tracker = indexer.updateTracker("authority",
-        getLCNAFID(record), indexer.getLatestTransaction(record));
-    return tracker.getFirstIndexed();
-}
-
-/**
- * Get the "last indexed" date for the current record.
- * @param record
- * @return ID string
- */
-public String getLCNAFLastIndexed(Record record) {
-    UpdateDateTracker tracker = indexer.updateTracker("authority",
-        getLCNAFID(record), indexer.getLatestTransaction(record));
-    return tracker.getLastIndexed();
-}
-
diff --git a/import/index_scripts/location.bsh b/import/index_scripts/location.bsh
deleted file mode 100644
index 9787855982e204f06e26ba59b8c63746b5b1e757..0000000000000000000000000000000000000000
--- a/import/index_scripts/location.bsh
+++ /dev/null
@@ -1,271 +0,0 @@
-/**
- * Custom script to get latitude and longitude coordinates.
- * Records can have multiple coordinates sets
- * of points and/or rectangles.
- * Points are represented by coordinate sets where N=S E=W.
- *
- * code adapted from xrosecky - Moravian Library
- * https://github.com/moravianlibrary/VuFind-2.x/blob/master/import/index_scripts/geo.bsh
- * and incorporates VuFind location.bsh functionality for GoogleMap display.
- *
- */
-
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import org.marc4j.marc.*;
-
-private static final Pattern COORDINATES_PATTERN = Pattern.compile("^([eEwWnNsS])(\\d{3})(\\d{2})(\\d{2})");
-private static final Pattern HDMSHDD_PATTERN = Pattern.compile("^([eEwWnNsS])(\\d+(\\.\\d+)?)");
-private static final Pattern PMDD_PATTERN = Pattern.compile("^([+-])(\\d+(\\.\\d+)?)");
-
-/**
- * Convert MARC coordinates into location_geo format.
- *
- * @param  Record record
- * @return List   geo_coordinates
- */
-public List getAllCoordinates(Record record) {
-    List geo_coordinates = new ArrayList();
-    List list034 = record.getVariableFields("034");
-    if (list034 != null) {
-        for (VariableField vf : list034) {
-            DataField df = (DataField) vf;
-            String d = df.getSubfield('d').getData();
-            String e = df.getSubfield('e').getData();
-            String f = df.getSubfield('f').getData();
-            String g = df.getSubfield('g').getData();
-            //System.out.println("raw Coords: "+d+" "+e+" "+f+" "+g);
-
-            // Check to see if there are only 2 coordinates
-            // If so, copy them into the corresponding coordinate fields
-            if ((d !=null && (e == null || e.trim().equals(""))) && (f != null && (g==null || g.trim().equals("")))) {
-                e = d;
-                g = f;
-            }
-            if ((e !=null && (d == null || d.trim().equals(""))) && (g != null && (f==null || f.trim().equals("")))) {
-                d = e;
-                f = g;
-            }
-
-            // Check and convert coordinates to +/- decimal degrees
-            Double west = convertCoordinate(d);
-            Double east = convertCoordinate(e);
-            Double north = convertCoordinate(f);
-            Double south = convertCoordinate(g);
-
-            // New Format for indexing coordinates in Solr 5.0 - minX, maxX, maxY, minY
-            // Note - storage in Solr follows the WENS order, but display is WSEN order
-            String result = String.format("ENVELOPE(%s,%s,%s,%s)", new Object[] { west, east, north, south });
-
-            if (validateCoordinates(west, east, north, south)) {
-                    geo_coordinates.add(result);
-            }
-        }
-    }
-    return geo_coordinates;
-}
-
-/**
- * Get point coordinates for GoogleMap display.
- *
- * @param  Record record
- * @return List   coordinates
- */
-public List getPointCoordinates(Record record) {
-    List coordinates = new ArrayList();
-    List list034 = record.getVariableFields("034");
-    if (list034 != null) {
-        for (VariableField vf : list034) {
-            DataField df = (DataField) vf;
-            String d = df.getSubfield('d').getData();
-            String e = df.getSubfield('e').getData();
-            String f = df.getSubfield('f').getData();
-            String g = df.getSubfield('g').getData();
-
-            // Check to see if there are only 2 coordinates
-            if ((d !=null && (e == null || e.trim().equals(""))) && (f != null && (g==null || g.trim().equals("")))) {
-                Double long_val = convertCoordinate(d);
-                Double lat_val = convertCoordinate(f);
-                String longlatCoordinate = Double.toString(long_val) + ',' + Double.toString(lat_val);
-                coordinates.add(longlatCoordinate);
-            }
-            if ((e !=null && (d == null || d.trim().equals(""))) && (g != null && (f==null || f.trim().equals("")))) {
-                Double long_val = convertCoordinate(e);
-                Double lat_val = convertCoordinate(g);
-                String longlatCoordinate = Double.toString(long_val) + ',' + Double.toString(lat_val);
-                coordinates.add(longlatCoordinate);
-            }
-            // Check if N=S and E=W
-            if (d.equals(e) && f.equals(g)) {
-                Double long_val = convertCoordinate(d);
-                Double lat_val = convertCoordinate(f);
-                String longlatCoordinate = Double.toString(long_val) + ',' + Double.toString(lat_val);
-                coordinates.add(longlatCoordinate);
-            }
-        }
-    }
-    return coordinates;
-}
-
-/**
- * Get all available coordinates from the record.
- *
- * @param  Record record
- * @return List   geo_coordinates
- */
-public List getDisplayCoordinates(Record record) {
-    List geo_coordinates = new ArrayList();
-    List list034 = record.getVariableFields("034");
-    if (list034 != null) {
-        for (VariableField vf : list034) {
-            DataField df = (DataField) vf;
-            String west = df.getSubfield('d').getData();
-            String east = df.getSubfield('e').getData();
-            String north = df.getSubfield('f').getData();
-            String south = df.getSubfield('g').getData();
-            String result = String.format("%s %s %s %s", new Object[] { west, east, north, south });
-            if (west != null || east != null || north != null || south != null) {
-                geo_coordinates.add(result);
-            }
-        }
-    }
-    return geo_coordinates;
-}
-
-/**
- * Check coordinate type HDMS HDD or +/-DD.
- *
- * @param  String coordinateStr
- * @return Double coordinate
- */
-public Double convertCoordinate(String coordinateStr) {
-    Double coordinate = Double.NaN;
-    Matcher HDmatcher = HDMSHDD_PATTERN.matcher(coordinateStr);
-    Matcher PMDmatcher = PMDD_PATTERN.matcher(coordinateStr);
-    if (HDmatcher.matches()) {
-        String hemisphere = HDmatcher.group(1).toUpperCase();
-        Double degrees = Double.parseDouble(HDmatcher.group(2));
-        // Check for HDD or HDMS
-        if (hemisphere.equals("N") || hemisphere.equals("S")) {
-            if (degrees > 90) {
-                String hdmsCoordinate = hemisphere+"0"+HDmatcher.group(2);
-                coordinate = coordinateToDecimal(hdmsCoordinate);
-            } else {
-                coordinate = Double.parseDouble(HDmatcher.group(2));
-                if (hemisphere.equals("S")) {
-                    coordinate *= -1;
-                }
-            }
-        }
-        if (hemisphere.equals("E") || hemisphere.equals("W")) {
-            if (degrees > 180) {
-                String hdmsCoordinate = HDmatcher.group(0);
-                coordinate = coordinateToDecimal(hdmsCoordinate);
-            } else {
-                coordinate = Double.parseDouble(HDmatcher.group(2));
-                if (hemisphere.equals("W")) {
-                    coordinate *= -1;
-                }
-            }
-        }
-        return coordinate;
-    } else if (PMDmatcher.matches()) {
-        String hemisphere = PMDmatcher.group(1);
-        coordinate = Double.parseDouble(PMDmatcher.group(2));
-        if (hemisphere.equals("-")) {
-            coordinate *= -1;
-        }
-        return coordinate;
-    } else {
-        return null;
-    }
-}
-
-/**
- * Convert HDMS coordinates to decimal degrees.
- *
- * @param  String coordinateStr
- * @return Double coordinate
- */
-public Double coordinateToDecimal(String coordinateStr) {
-    Matcher matcher = COORDINATES_PATTERN.matcher(coordinateStr);
-    if (matcher.matches()) {
-        String hemisphere = matcher.group(1).toUpperCase();
-        int degrees = Integer.parseInt(matcher.group(2));
-        int minutes = Integer.parseInt(matcher.group(3));
-        int seconds = Integer.parseInt(matcher.group(4));
-        double coordinate = degrees + (minutes / 60.0) + (seconds / 3600.0);
-        if (hemisphere.equals("W") || hemisphere.equals("S")) {
-            coordinate *= -1;
-        }
-        return coordinate;
-    }
-    return null;
-}
-
-/**
- * Check decimal degree coordinates to make sure they are valid.
- *
- * @param  Double west, east, north, south
- * @return boolean
- */
-public boolean validateCoordinates(Double west, Double east, Double north, Double south) {
-    if (west == null || east == null || north == null || south == null) {
-        return false;
-    }
-    if (west > 180.0 || west < -180.0 || east > 180.0 || east < -180.0) {
-        return false;
-    }
-    if (north > 90.0 || north < -90.0 || south > 90.0 || south < -90.0) {
-        return false;
-    }
-    if (north < south || west > east) {
-        return false;
-    }
-    return true;
-}
-
-/**
- * THIS FUNCTION HAS BEEN DEPRECATED.
- * Determine the longitude and latitude of the items location.
- *
- * @param  Record    record
- * @return String    "longitude, latitude"
- */
-public String getLongLat(Record record) {
-    // Check 034 subfield d and f
-    List fields = record.getVariableFields("034");
-    Iterator fieldsIter = fields.iterator();
-    if (fields != null) {
-        DataField physical;
-        while(fieldsIter.hasNext()) {
-            physical = (DataField) fieldsIter.next();
-            String val;
-
-            List subfields_d = physical.getSubfields('d');
-            Iterator subfieldsIter_d = subfields_d.iterator();
-            if (subfields_d != null) {
-                while (subfieldsIter_d.hasNext()) {
-                    val = subfieldsIter_d.next().getData().trim();
-                    if (!val.matches("-?\\d+(.\\d+)?")) {
-                        return null;
-                    }
-                }
-            }
-            List subfields_f = physical.getSubfields('f');
-            Iterator subfieldsIter_f = subfields_f.iterator();
-            if (subfields_f != null) {
-                while (subfieldsIter_f.hasNext()) {
-                    String val2 = subfieldsIter_f.next().getData().trim();
-                    if (!val2.matches("-?\\d+(.\\d+)?")) {
-                        return null;
-                    }
-                    val = val + ',' + val2;
-                }
-            }
-            return val;
-        }
-    }
-    //otherwise return null
-    return null;
-}
\ No newline at end of file
diff --git a/import/index_scripts/readingprograms.bsh b/import/index_scripts/readingprograms.bsh
deleted file mode 100644
index 053fb299609d46965c29541cfcffbc89172a3677..0000000000000000000000000000000000000000
--- a/import/index_scripts/readingprograms.bsh
+++ /dev/null
@@ -1,66 +0,0 @@
-/**
- * Reading program scripts courtesy of Chanel Wheeler
- *
- * Example usage:
- *
- * #### In marc_local.properties, insert this:
- * arLvel = script(readingprograms.bsh), getARLevel, (pattern_map.level)
- * rcLevel = script(readingprograms.bsh), getRCLevel, (pattern_map.level)
- * pattern_map.level.pattern_0 = ([0-9]\\.[0-9]).*=>$1
- *
- * #### In solr/biblio/conf/schema.xml (I'm not aware of any way to localize this),
- * #### add this in the <types> section:
- * <fieldType name="tfloat" class="solr.TrieFloatField" precisionStep="8" positionIncrementGap="0"/>
- *
- * #### In solr/biblio/conf/schema.xml, add this in the <fields> section
- * <field name="arLevel" type="tfloat" indexed="true" stored="true"/>
- * <field name="rcLevel" type="tfloat" indexed="true" stored="true"/>
- */
-import org.marc4j.marc.Record;
-import org.marc4j.marc.DataField;
-
-org.solrmarc.index.SolrIndexer indexer = null;
-
-/**
- * Get reading level for Accelerated Reader items
- *
- * @param  Record          record
- * @return String           AR level
- */
- public String getARLevel(Record record) {
-    List readingprograms = record.getVariableFields("526");
-    if (readingprograms != null) {
-        Iterator rpIter = readingprograms.iterator();
-        while(rpIter.hasNext()) {
-            DataField rp = (DataField) rpIter.next();
-            if (rp.getSubfield('a') != null){
-                if (rp.getSubfield('a').getData().toLowerCase().contains("accelerated reader")) {
-                    return rp.getSubfield('c').getData();
-                }
-            }
-        }
-    }
-    return null;
- }
-
- /**
- * Get reading level for Reading Counts items
- *
- * @param  Record          record
- * @return String           RC level
- */
- public String getRCLevel(Record record) {
-    List readingprograms = record.getVariableFields("526");
-    if (readingprograms != null) {
-        Iterator rpIter = readingprograms.iterator();
-        while(rpIter.hasNext()) {
-            DataField rp = (DataField) rpIter.next();
-            if (rp.getSubfield('a') != null){
-                if (rp.getSubfield('a').getData().toLowerCase().contains("reading counts")) {
-                    return rp.getSubfield('c').getData();
-                }
-            }
-        }
-    }
-    return null;
-}
\ No newline at end of file
diff --git a/import/marc.properties b/import/marc.properties
index b743ac762026721b50db21b6e022c67539937077..e061dae9f6e615bc1b2f39ddc57262a8447bd0a6 100644
--- a/import/marc.properties
+++ b/import/marc.properties
@@ -46,10 +46,10 @@ author                = custom, getAuthorsFilteredByRelator(100abcd:700abcd,100,
 author_variant        = custom, getAuthorInitialsFilteredByRelator(100a:700a,100,firstAuthorRoles)
 author_fuller         = custom, getAuthorsFilteredByRelator(100q:700q,100,firstAuthorRoles)
 author_role           = custom, getRelatorsFilteredByRelator(100abcd:700abcd,100,firstAuthorRoles)
-author2               = custom, getAuthorsFilteredByRelator(700abcd,700,secondAuthorRoles)
-author2_variant       = custom, getAuthorInitialsFilteredByRelator(700a,700,secondAuthorRoles)
-author2_fuller        = custom, getAuthorsFilteredByRelator(700q,700,secondAuthorRoles)
-author2_role          = custom, getRelatorsFilteredByRelator(700abcd,700,secondAuthorRoles)
+author2               = custom, getAuthorsFilteredByRelator(100abcd:700abcd,700,secondAuthorRoles)
+author2_variant       = custom, getAuthorInitialsFilteredByRelator(100a:700a,700,secondAuthorRoles)
+author2_fuller        = custom, getAuthorsFilteredByRelator(100q:700q,700,secondAuthorRoles)
+author2_role          = custom, getRelatorsFilteredByRelator(100abcd:700abcd,700,secondAuthorRoles)
 author_corporate      = custom, getAuthorsFilteredByRelator(110ab:111abc:710ab:711ab,110:111:710:711,firstAuthorRoles|secondAuthorRoles)
 author_corporate_role = custom, getRelatorsFilteredByRelator(110ab:111abc:710ab:711ab,110:111:710:711,firstAuthorRoles|secondAuthorRoles)
 author_sort           = custom, getFirstAuthorFilteredByRelator(100abcd:110ab:111abc:700abcd,100:110:111:700,firstAuthorRoles)
diff --git a/import/marc_auth.properties b/import/marc_auth.properties
index 0513aeb8a416d94ecdc1f78ef2c381e660e72d2a..5ef540dee66792ca334980924be27811c04929c6 100644
--- a/import/marc_auth.properties
+++ b/import/marc_auth.properties
@@ -3,11 +3,11 @@
 #                         marc.properties for the more commonly changed       #
 #                         bibliographic settings.                             #
 ###############################################################################
-id = script(getFirstNormalizedLCCN.bsh), getFirstNormalizedLCCN("010a")
-lccn = script(getNormalizedLCCNs.bsh), getNormalizedLCCNs("010a")
+id = custom, getFirstNormalizedLCCN("010a")
+lccn = custom, getNormalizedLCCNs("010a")
 
 # These values should be overridden in a second properties file (for example,
-# see marc_lcnaf.properties).  This allows the basic authority mappings to
+# see marc_auth_fast_*.properties). This allows the basic authority mappings to
 # be used for multiple sources/types of authority records.
 source = "Unknown"
 record_type = "Unknown"
diff --git a/import/marc_lcnaf.properties b/import/marc_lcnaf.properties
deleted file mode 100644
index c938822fc3db2ba0f4bfe2c683566fe4e579d53c..0000000000000000000000000000000000000000
--- a/import/marc_lcnaf.properties
+++ /dev/null
@@ -1,18 +0,0 @@
-###############################################################################
-# marc_lcnaf.properties -- VuFind MARC authority override settings for        #
-#                          Library of Congress Name Authority File.           #
-###############################################################################
-id = script(lcnaf.bsh), getLCNAFID
-source = "Library of Congress Name Authority File"
-record_type = script(lcnaf.bsh), getLCNAFRecordType
-
-heading = 100abcdegjqt:110abcdegjqt:111abcdegjqt:130abcdegjqt:150abvxyz:151avxyz:155avxyz:180vxyz:181vxyz:182vxyz:185vxyz
-use_for = 400abcdegjqt:410abcdegjqt:411abcdegjqt:430abcdegjqt:450abvxyz:451avxyz:455avxyz:480vxyz:481vxyz:482vxyz:485vxyz
-see_also = 500abcdegjqt:510abcdegjqt:511abcdegjqt:530abcdegjqt:550abvxyz:551avxyz:555avxyz:580vxyz:581vxyz:582vxyz:585vxyz
-form_facet_str_mv = 150v:151v:155v:180v:181v:182v:185v
-general_facet_str_mv = 150x:151x:155x:180x:181x:182x:185x
-chronological_facet_str_mv = 150y:151y:155y:180y:181y:182y:185y
-geographic_facet_str_mv = 150z:151z:155z:180z:181z:182z:185z
-
-first_indexed = script(lcnaf.bsh), getLCNAFFirstIndexed
-last_indexed = script(lcnaf.bsh), getLCNAFLastIndexed
\ No newline at end of file
diff --git a/import/marc_local.properties b/import/marc_local.properties
index a5bc4cdf01687bbb60a9bd16916041d5a4cd50e6..82a9654b9034a7fe2a89c9bac99611b6a6a55fa3 100644
--- a/import/marc_local.properties
+++ b/import/marc_local.properties
@@ -9,33 +9,6 @@
 #institution = "MyInstitution"
 #building = "Library A"
 
-# Uncomment the following settings to use the .bsh scripts in import/scripts/
-# instead of the built-in SolrMarc functionality found in the .jar file.
-# (by default, the scripts have the same behavior as the built-in functions,
-# but the external scripts are easier to customize to your needs).
-#format = script(format.bsh), getFormat, format_map.properties
-#author                = script(author.bsh), getAuthorsFilteredByRelator(100abcd:700abcd,100,firstAuthorRoles)
-#author_variant        = script(author.bsh), getAuthorInitialsFilteredByRelator(100a:700a,100,firstAuthorRoles)
-#author_fuller         = script(author.bsh), getAuthorsFilteredByRelator(100q:700q,100,firstAuthorRoles)
-#author_role           = script(author.bsh), getRelatorsFilteredByRelator(100abcd:700abcd,100,firstAuthorRoles)
-#author2               = script(author.bsh), getAuthorsFilteredByRelator(700abcd,700,secondAuthorRoles)
-#author2_variant       = script(author.bsh), getAuthorInitialsFilteredByRelator(700a,700,secondAuthorRoles)
-#author2_fuller        = script(author.bsh), getAuthorsFilteredByRelator(700q,700,secondAuthorRoles)
-#author2_role          = script(author.bsh), getRelatorsFilteredByRelator(700abcd,700,secondAuthorRoles)
-#author_corporate      = script(author.bsh), getAuthorsFilteredByRelator(110ab:111abc:710ab:711ab,110:111:710:711,firstAuthorRoles|secondAuthorRoles)
-#author_corporate_role = script(author.bsh), getRelatorsFilteredByRelator(110ab:111abc:710ab:711ab,110:111:710:711,firstAuthorRoles|secondAuthorRoles)
-#author_sort           = script(author.bsh), getFirstAuthorFilteredByRelator(100abcd:110ab:111abc:700abcd,100:110:111:700,firstAuthorRoles)
-#callnumber-subject = script(callnumber.bsh), getCallNumberSubject(090a:050a), callnumber_subject_map.properties
-#callnumber-label = script(callnumber.bsh), getCallNumberLabel(090a:050a)
-#publisher = script(getpublishers.bsh), getPublishers
-#publishDate = script(getdate.bsh), getDates
-#illustrated = script(illustrated.bsh), isIllustrated
-#dewey-hundreds = script(dewey.bsh), getDeweyNumber(082a:083a, 100), ddc22_map.properties(hundreds)
-#dewey-tens = script(dewey.bsh), getDeweyNumber(082a:083a, 10), ddc22_map.properties(tens)
-#dewey-ones = script(dewey.bsh), getDeweyNumber(082a:083a, 1), ddc22_map.properties(ones)
-#dewey-full = script(dewey.bsh), getDeweySearchable(082a:083a)
-#dewey-sort = script(dewey.bsh), getDeweySortable(082a:083a)
-
 # Uncomment the following lines to track history of indexing times for RSS feeds,
 # OAI-PMH server and other updates.  The parameter to these functions must be the
 # same fieldspec as the id setting above!
@@ -55,15 +28,13 @@
 #fulltext = custom, getFulltext(856u, pdf)
 
 # Uncomment the following if you want to use the OpenLayers3 Geographic Search
-# and Google Map or OpenLayers3 Geo-Display functionality
+# and OpenLayers3 Geo-Display functionality
 # See searches.ini for configuration options for Geographic Searching.
 # See config.ini for configuration options for Geo-Display.
-#location_geo = custom, getAllCoordinates
-#long_lat = custom, getPointCoordinates
+#long_lat = custom, getAllCoordinates
 #long_lat_display = custom, getDisplayCoordinates
 #long_lat_label = 034z
 
-
 # Uncomment the following lines if you are indexing journal article data that uses
 # the 773 field to describe the journal containing the article.  These settings
 # assume the records have been formatted according to recommendation 4.1 found at:
diff --git a/import/translation_maps/language_map.properties b/import/translation_maps/language_map.properties
index 1d20a51b236e483cf470dd65e651fb873b9f63e8..399fcfbca90062dc675abebb5fd0766890f9f3e3 100644
--- a/import/translation_maps/language_map.properties
+++ b/import/translation_maps/language_map.properties
@@ -1,4 +1,5 @@
 aar = Afar
+aav = Austro-Asiatic
 abk = Abkhazian
 ace = Achinese
 ach = Acoli
@@ -14,10 +15,13 @@ alb = Albanian
 ale = Aleut
 alg = Algonquian
 alt = Southern Altai
+alv = Atlantic-Congo
 amh = Amharic
 ang = Old English
 anp = Angika
 apa = Apache
+aqa = Alacalufan
+aql = Algic
 ara = Arabic
 arc = Aramaic
 arg = Aragonese
@@ -29,11 +33,14 @@ arw = Arawak
 asm = Assamese
 ast = Asturian
 ath = Athapascan
+auf = Arauan
 aus = Australian
 ava = Avaric
 ave = Avestan
 awa = Awadhi
+awd = Arawakan
 aym = Aymara
+azc = Uto-Aztecan
 aze = Azerbaijani
 bad = Banda
 bai = Bamileke
@@ -70,6 +77,11 @@ cai = Central American Indian
 car = Galibi Carib
 cat = Catalan
 cau = Caucasian
+cba = Chibchan
+ccn = North Caucasian
+ccs = South Caucasian
+cdc = Chadic
+cdd = Caddoan
 ceb = Cebuano
 cel = Celtic
 cha = Chamorro
@@ -97,6 +109,7 @@ cre = Cree
 crh = Crimean Tatar
 crp = Creoles
 csb = Kashubian
+csu = Central Sudanic
 cus = Cushitic
 cze = Czech
 dak = Dakota
@@ -108,6 +121,7 @@ den = Slave
 dgr = Dogrib
 din = Dinka
 div = Divehi
+dmn = Mande
 doi = Dogri
 dra = Dravidian
 dsb = Lower Sorbian
@@ -117,6 +131,7 @@ dut = Dutch
 dyu = Dyula
 dzo = Dzongkha
 efi = Efik
+egx = Egyptian
 egy = Ancient Egyptian
 eka = Ekajuk
 elx = Elamite
@@ -124,6 +139,8 @@ eng = English
 enm = Middle English
 epo = Esperanto
 est = Estonian
+esx = Eskimo-Aleut
+euq = Basque
 ewe = Ewe
 ewo = Ewondo
 fan = Fang
@@ -134,6 +151,7 @@ fil = Filipino
 fin = Finnish
 fiu = Finno-Ugrian
 fon = Fon
+fox = Formosan
 fre = French
 frm = Middle French
 fro = Old French
@@ -154,7 +172,10 @@ gla = Gaelic
 gle = Irish
 glg = Galician
 glv = Manx
+gme = East Germanic
 gmh = Middle High German
+gmq = North Germanic
+gmw = West Germanic
 goh = Old High German
 gon = Gondi
 gor = Gorontalo
@@ -162,6 +183,7 @@ got = Gothic
 grb = Grebo
 grc = Ancient Greek
 gre = Greek
+grk = Greek
 grn = Guarani
 gsw = Swiss German
 guj = Gujarati
@@ -178,14 +200,19 @@ hin = Hindi
 hit = Hittite
 hmn = Hmong
 hmo = Hiri Motu
+hmx = Hmong-Mien
+hok = Hokan
+hrv = Croatian
 hsb = Upper Sorbian
 hun = Hungarian
 hup = Hupa
+hyx = Armenian
 iba = Iban
 ibo = Igbo
 ice = Icelandic
 ido = Ido
 iii = Sichuan Yi
+iir = Indo-Iranian
 ijo = Ijo
 iku = Inuktitut
 ile = Interlingue
@@ -199,10 +226,12 @@ ipk = Inupiaq
 ira = Iranian
 iro = Iroquoian
 ita = Italian
+itc = Italic
 jav = Javanese
 jbo = Lojban
 jpn = Japanese
 jpr = Judeo-Persian
+jpx = Japanese
 jrb = Judeo-Arabic
 kaa = Kara-Kalpak
 kab = Kabyle
@@ -216,6 +245,7 @@ kau = Kanuri
 kaw = Kawi
 kaz = Kazakh
 kbd = Kabardian
+kdo = Kordofanian
 kha = Khasi
 khi = Khoisan
 khm = Central Khmer
@@ -304,6 +334,7 @@ ndo = Ndonga
 nds = Low German
 nep = Nepali
 new = Nepal Bhasa
+ngf = Trans-New Guinea
 nia = Nias
 nic = Niger-Kordofanian
 niu = Niuean
@@ -323,6 +354,8 @@ nyo = Nyoro
 nzi = Nzima
 oci = Occitan
 oji = Ojibwa
+omq = Oto-Manguean
+omv = Omotic
 ori = Oriya
 orm = Oromo
 osa = Osage
@@ -340,17 +373,23 @@ peo = Old Persian
 per = Persian
 phi = Philippine
 phn = Phoenician
+plf = Central Malayo-Polynesian
 pli = Pali
 pol = Polish
 pon = Pohnpeian
 por = Portuguese
+poz = Malayo-Polynesian
+pqe = Eastern Malayo-Polynesian
+pqw = Western Malayo-Polynesian
 pra = Prakrit languages
 pro = Old Provençal
 pus = Pushto
 que = Quechua
+qwe = Quechuan
 raj = Rajasthani
 rap = Rapanui
 rar = Rarotongan
+rcf = Reunionese, Reunion Creole
 roa = Romance
 roh = Romansh
 rom = Romany
@@ -371,6 +410,7 @@ scc = Serbian
 scn = Sicilian
 sco = Scots
 scr = Croatian
+sdv = Eastern Sudanic
 sel = Selkup
 sem = Semitic
 sga = Old Irish
@@ -398,6 +438,7 @@ som = Somali
 son = Songhai
 sot = Southern Sotho
 spa = Spanish
+sqi = Albanian
 srd = Sardinian
 srn = Sranan Tongo
 srr = Serer
@@ -410,11 +451,13 @@ sux = Sumerian
 swa = Swahili
 swe = Swedish
 syc = Classical Syriac
+syd = Samoyedic
 syr = Syriac
 tah = Tahitian
 tai = Tai
 tam = Tamil
 tat = Tatar
+tbq = Tibeto-Burman
 tel = Telugu
 tem = Timne
 ter = Tereno
@@ -433,6 +476,7 @@ tmh = Tamashek
 tog = Tonga
 ton = Tonga
 tpi = Tok
+trk = Turkic
 tsi = Tsimshian
 tsn = Tswana
 tso = Tsonga
@@ -441,6 +485,7 @@ tum = Tumbuka
 tup = Tupi
 tur = Turkish
 tut = Altaic
+tuw = Tungus
 tvl = Tuvalu
 twi = Twi
 tyv = Tuvinian
@@ -451,6 +496,7 @@ ukr = Ukrainian
 umb = Umbundu
 und = Undetermined
 urd = Urdu
+urj = Uralic
 uzb = Uzbek
 vai = Vai
 ven = Venda
@@ -466,7 +512,9 @@ wen = Sorbian
 wln = Walloon
 wol = Wolof
 xal = Kalmyk
+xgn = Mongolian
 xho = Xhosa
+xnd = Na-Dene
 yao = Yao
 yap = Yapese
 yid = Yiddish
@@ -475,7 +523,12 @@ ypk = Yupik
 zap = Zapotec
 zbl = Blissymbols
 zen = Zenaga
+zgh = Tamazight
 zha = Zhuang
+zhx = Chinese
+zle = East Slavic
+zls = South Slavic
+zlw = West Slavic
 znd = Zande
 zul = Zulu
 zun = Zuni
@@ -483,4 +536,4 @@ zza = Zaza
 zxx = No linguistic content
 ??? = Unknown
 mul = Multiple
-mis = Unknown
\ No newline at end of file
+mis = Unknown
diff --git a/import/webcrawl.php b/import/webcrawl.php
index 24857961c8ab76bf9a16fadac73d3df26c7e347e..f7e4e53f0da3d3de2975696580f057b421605f50 100644
--- a/import/webcrawl.php
+++ b/import/webcrawl.php
@@ -27,7 +27,7 @@
  * @link     https://vufind.org/wiki/indexing Wiki
  */
 
-// Load the Zend framework -- this will automatically trigger the appropriate
-// controller action based on directory and file names
-define('CLI_DIR', __DIR__);     // save directory name of current script
+// Manipulate command line to load correct route, then load Zend Framework:
+array_unshift($_SERVER['argv'], array_shift($_SERVER['argv']), 'import', 'webcrawl');
+$_SERVER['argc'] += 2;
 require_once __DIR__ . '/../public/index.php';
diff --git a/import/xsl/doaj.xsl b/import/xsl/doaj.xsl
index 611bf64f45a6ff17f4b635aa3486c455c013def5..615de066bf03aaa8fd458d218725c9eb2369c4d9 100644
--- a/import/xsl/doaj.xsl
+++ b/import/xsl/doaj.xsl
@@ -3,17 +3,17 @@
     xmlns:php="http://php.net/xsl"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xmlns:xlink="http://www.w3.org/2001/XMLSchema-instance"
-    xmlns:doaj="http://www.doaj.org/schemas/">
+    xmlns:oai_doaj="http://doaj.org/features/oai_doaj/1.0/">
     <xsl:output method="xml" indent="yes" encoding="utf-8"/>
-    <xsl:param name="institution">My University</xsl:param>
+    <xsl:param name="institution">Directory of Open Access Journals</xsl:param>
     <xsl:param name="collection">DOAJ</xsl:param>
-    <xsl:template match="doaj:record">
+    <xsl:template match="oai_doaj:doajArticle">
         <add>
             <doc>
                 <!-- ID -->
                 <!-- Important: This relies on an <identifier> tag being injected by the OAI-PMH harvester. -->
                 <field name="id">
-                    <xsl:value-of select="//doaj:doajIdentifier"/>
+                    <xsl:value-of select="//identifier"/>
                 </field>
 
                 <!-- RECORDTYPE -->
@@ -22,13 +22,13 @@
                 <!-- FULLRECORD -->
                 <!-- disabled for now; records are so large that they cause memory problems!
                 <field name="fullrecord">
-                    <xsl:copy-of select="php:function('VuFind::xmlAsText', /doaj:record)"/>
+                    <xsl:copy-of select="php:function('VuFind::xmlAsText', /oai_doaj:record)"/>
                 </field>
                   -->
 
                 <!-- ALLFIELDS -->
                 <field name="allfields">
-                    <xsl:value-of select="normalize-space(string(/doaj:record))"/>
+                    <xsl:value-of select="normalize-space(string(/oai_doaj:doajArticle))"/>
                 </field>
 
                 <!-- INSTITUTION -->
@@ -42,16 +42,11 @@
                 </field>
 
                 <!-- LANGUAGE -->
-                <!-- TODO: add language support; in practice, there don't seem to be
-                     many records with <language> tags in them.  If we encounter any,
-                     the code below is partially complete, but we probably need to
-                     build a new language map for ISO 639-2b, which is the standard
-                     specified by the DOAJ XML schema.
-                <xsl:if test="/doaj:record/doaj:language">
-                    <xsl:for-each select="/doaj:record/doaj:language">
+                <xsl:if test="/oai_doaj:doajArticle/oai_doaj:language">
+                    <xsl:for-each select="/oai_doaj:doajArticle/oai_doaj:language">
                         <xsl:if test="string-length() > 0">
                             <field name="language">
-                                <xsl:value-of select="php:function('VuFind::mapString', normalize-space(string(.)), 'language_map_iso639-1.properties')"/>
+                                <xsl:value-of select="php:function('VuFind::mapString', normalize-space(string(.)), 'language_map.properties')"/>
                             </field>
                         </xsl:if>
                     </xsl:for-each>
@@ -62,8 +57,8 @@
                 <field name="format">Article</field>
 
                 <!-- AUTHOR -->
-                <xsl:if test="//doaj:authors/doaj:author/doaj:name">
-                    <xsl:for-each select="//doaj:authors/doaj:author/doaj:name">
+                <xsl:if test="//oai_doaj:authors/oai_doaj:author/oai_doaj:name">
+                    <xsl:for-each select="//oai_doaj:authors/oai_doaj:author/oai_doaj:name">
                         <xsl:if test="normalize-space()">
                             <field name="author">
                                 <xsl:value-of select="normalize-space()"/>
@@ -79,69 +74,69 @@
                 </xsl:if>
 
                 <!-- TITLE -->
-                <xsl:if test="//doaj:title[normalize-space()]">
+                <xsl:if test="//oai_doaj:title[normalize-space()]">
                     <field name="title">
-                        <xsl:value-of select="//doaj:title[normalize-space()]"/>
+                        <xsl:value-of select="//oai_doaj:title[normalize-space()]"/>
                     </field>
                     <field name="title_short">
-                        <xsl:value-of select="//doaj:title[normalize-space()]"/>
+                        <xsl:value-of select="//oai_doaj:title[normalize-space()]"/>
                     </field>
                     <field name="title_full">
-                        <xsl:value-of select="//doaj:title[normalize-space()]"/>
+                        <xsl:value-of select="//oai_doaj:title[normalize-space()]"/>
                     </field>
                     <field name="title_sort">
-                        <xsl:value-of select="php:function('VuFind::stripArticles', string(//doaj:title[normalize-space()]))"/>
+                        <xsl:value-of select="php:function('VuFind::stripArticles', string(//oai_doaj:title[normalize-space()]))"/>
                     </field>
                 </xsl:if>
 
                 <!-- PUBLISHER -->
-                <xsl:if test="//doaj:publisher[normalize-space()]">
+                <xsl:if test="//oai_doaj:publisher[normalize-space()]">
                     <field name="publisher">
-                        <xsl:value-of select="//doaj:publisher[normalize-space()]"/>
+                        <xsl:value-of select="//oai_doaj:publisher[normalize-space()]"/>
                     </field>
                 </xsl:if>
 
                  <!-- SERIES -->
-                <xsl:if test="//doaj:journalTitle[normalize-space()]">
+                <xsl:if test="//oai_doaj:journalTitle[normalize-space()]">
                     <field name="series">
-                        <xsl:value-of select="//doaj:journalTitle[normalize-space()]"/>
+                        <xsl:value-of select="//oai_doaj:journalTitle[normalize-space()]"/>
                     </field>
                 </xsl:if>
 
                  <!-- ISSN  -->
-                <xsl:if test="//doaj:issn[normalize-space()]">
+                <xsl:if test="//oai_doaj:issn[normalize-space()]">
                     <field name="issn">
-                        <xsl:value-of select="//doaj:issn[normalize-space()]"/>
+                        <xsl:value-of select="//oai_doaj:issn[normalize-space()]"/>
                     </field>
                 </xsl:if>
 
                 <!-- ISSN  -->
-                <xsl:if test="//doaj:eissn[normalize-space()]">
+                <xsl:if test="//oai_doaj:eissn[normalize-space()]">
                     <field name="issn">
-                        <xsl:value-of select="//doaj:eissn[normalize-space()]"/>
+                        <xsl:value-of select="//oai_doaj:eissn[normalize-space()]"/>
                     </field>
                 </xsl:if>
 
                 <!-- PUBLISHDATE -->
-                <xsl:if test="//doaj:publicationDate">
+                <xsl:if test="//oai_doaj:publicationDate">
                     <field name="publishDate">
-                        <xsl:value-of select="//doaj:publicationDate"/>
+                        <xsl:value-of select="//oai_doaj:publicationDate"/>
                     </field>
                     <field name="publishDateSort">
-                        <xsl:value-of select="//doaj:publicationDate"/>
+                        <xsl:value-of select="//oai_doaj:publicationDate"/>
                     </field>
                 </xsl:if>
 
                 <!-- DESCRIPTION -->
-                <xsl:if test="//doaj:abstract">
+                <xsl:if test="//oai_doaj:abstract">
                     <field name="description">
-                        <xsl:value-of select="//doaj:abstract" />
+                        <xsl:value-of select="//oai_doaj:abstract" />
                     </field>
                 </xsl:if>
 
                 <!-- SUBJECT -->
-                <xsl:if test="//doaj:keywords">
-                    <xsl:for-each select="//doaj:keywords/doaj:keyword">
+                <xsl:if test="//oai_doaj:keywords">
+                    <xsl:for-each select="//oai_doaj:keywords/oai_doaj:keyword">
                         <xsl:if test="string-length() > 0">
                             <field name="topic">
                                 <xsl:value-of select="normalize-space()"/>
@@ -151,13 +146,13 @@
                 </xsl:if>
 
                 <!-- URL -->
-                <xsl:if test="//doaj:fullTextUrl">
+                <xsl:if test="//oai_doaj:fullTextUrl">
                     <xsl:choose>
-                        <xsl:when test="contains(//doaj:fullTextUrl, '://')">
-                            <field name="url"><xsl:value-of select="//doaj:fullTextUrl[normalize-space()]"/></field>
+                        <xsl:when test="contains(//oai_doaj:fullTextUrl, '://')">
+                            <field name="url"><xsl:value-of select="//oai_doaj:fullTextUrl[normalize-space()]"/></field>
                         </xsl:when>
                         <xsl:otherwise>
-                            <field name="url">http://<xsl:value-of select="//doaj:fullTextUrl[normalize-space()]"/></field>
+                            <field name="url">http://<xsl:value-of select="//oai_doaj:fullTextUrl[normalize-space()]"/></field>
                         </xsl:otherwise>
                     </xsl:choose>
                 </xsl:if> 
diff --git a/install.php b/install.php
index 78ffaaaec0041bb813d029cc5673666be356e927..d6aa2e344a2f206b7fbb4f30509c6decde416f00 100644
--- a/install.php
+++ b/install.php
@@ -43,26 +43,26 @@ $basePath = '/vufind';
 try {
     $opts = new Getopt(
         array(
-        'use-defaults' => 
+        'use-defaults' =>
            'Use VuFind Defaults to Configure (ignores any other arguments passed)',
-        'overridedir=s' => 
+        'overridedir=s' =>
            "Where would you like to store your local settings? [{$baseDir}/local]",
-        'module-name=s' => 
+        'module-name=s' =>
            'What module name would you like to use? Use disabled, to not use',
-        'basepath=s' => 
+        'basepath=s' =>
            'What base path should be used in VuFind\'s URL? [/vufind]',
-        'multisite-w' => 
+        'multisite-w' =>
            'Specify we are going to setup a multisite. Options: directory and host',
-        'hostname=s' => 
+        'hostname=s' =>
             'Specify the hostname for the VuFind Site, When multisite=host',
         'non-interactive' =>
             'Use settings if provided via arguments, otherwise use defaults',
       )
     );
-
     $opts->parse();
 } catch (Exception $e) {
-    echo $e->getUsageMessage();
+    echo is_callable([$e, 'getUsageMessage'])
+        ? $e->getUsageMessage() : $e->getMessage() . "\n";
     exit;
 }
 
diff --git a/languages/CreatorRoles/ca.ini b/languages/CreatorRoles/ca.ini
index 0a7a50c0cf2b78048ee892aecdf1265b7446b36d..402dd163c300dbbc318f9ff72c8f20cee605e610 100644
--- a/languages/CreatorRoles/ca.ini
+++ b/languages/CreatorRoles/ca.ini
@@ -1,63 +1,261 @@
+abr = "Abridger"
+acp = "Copista d'art"
+act = "Actor"
 adi = "director d’art"
+adp = "Adaptador"
+Adressat = "Destinatari"
+adressat = "Destinatari"
+animation = "Animació"
 anl = "Analista"
+anm = "Animador"
+ann = "Anotador"
+ape = "Appellee"
+apl = "Appellant"
 app = "Candidat"
 arc = "Arquitecte"
+ard = "Director artístic"
+arr = "Arranjador"
 art = "Artista"
+asg = "Assignat"
+asn = "Nom associat"
+ato = "Autògraf"
+att = "Nom atribuït"
+auc = "Subhastador"
+aud = "Autor del diàleg"
+Auftraggeber = "Client"
+aui = "Autor d'introducció, etc."
+aus = "Guionista"
 aut = "Autor"
+Bearb = "Editor"
+bearb = "Editor"
+Begr = "Fundador"
+begr = "Fundador"
 Beiträger = "Col·laborador"
+beiträger = "Contribució literària"
+beiträger k = "Col·laborador artístic"
+beiträger m = "Col·laborador musical"
+bnd = "Binder"
+bpd = "Dissenyador de llibretes"
+brd = "Emissora"
 bsl = "Llibreter"
+bühnenbild = "Establir dissenyador"
+cas = "Caster"
+ccp = "Conceptor"
+choreogr = "Coreògraf"
 chr = "Coreògraf"
+clb = "Col·laborador"
+cli = "Client"
+cll = "Calligrapher"
+clr = "Colorista"
+clt = "Collotyper"
+cmm = "Comentarista"
+cmp = "Compositor"
+cmt = "Compositor"
+cnd = "Conductor"
+cng = "Cinematògraf"
+cns = "Censor"
+coe = "Contestant-appellee"
+col = "Col·leccionista"
+com = "Compilador"
 con = "Conservador"
+cor = "Collection registrar"
+cos = "Concursant"
+cot = "Contestant-appellant"
+cov = "Dissenyador de cobertes"
+cpe = "Complainant-appellee"
+cpl = "Reclamant"
+cpt = "Complainant-appellant"
+cre = "Creador"
+crp = "Corresponsal"
+crr = "Corrector"
 csl = "Consultor"
+csp = "Consultor d'un projecte"
+cst = "Dissenyador de vestuari"
 ctb = "Col·laborador"
+cte = "Contestee-appellee"
 ctg = "Cartògraf"
+ctr = "Contractista"
+cts = "Contestee"
+ctt = "Contestee-appellant"
 cur = "Preservador"
+darst = "Intèrpret"
+dbp = "Lloc de distribució"
+dfd = "Defendant"
+dfe = "Defendant-appellee"
+dft = "Defendant-appellant"
+dir = "Conductor"
+dis = "Dissertant"
+dln = "Delineant"
 dnc = "Ballarí"
+dnr = "Donant"
+dpc = "Representat"
+dpt = "Dipositari"
+drehbuch = "Guionista"
+drm = "Dibuixant"
+drt = "Director"
+dsr = "Dissenyador"
+dst = "Distribuïdor"
+dte = "Dedicat"
+dtm = "Administrador de dades"
+dto = "Dedicat"
+edt = "Editor"
+egr = "Gravador"
 elg = "Electricista"
+elt = "Electrotyper"
 eng = "Ingenier"
+etr = "Etcher"
+evp = "Lloc de l'esdeveniment"
+exp = "Expert"
+fac = "Facsimilista"
+fds = "Distribuïdor de pel·lícules"
+fld = "Director de camp"
+flm = "Editor de pel·lícules"
+fmd = "Director de pel·lícules"
+fmk = "Cineasta"
+fmo = "Antic propietari"
+fmp = "Productor de pel·lícules"
+fnd = "Fundador"
+Forts = "Continuació"
+fotogr = "Fotògraf"
+fpy = "Primera festa"
+frg = "Forger"
+gis = "Especialista en informació geogràfica"
+grt = "Tècnic gràfic"
 hg = "Editor"
+his = "Institució amfitriona"
+hnr = "Honora"
 Hrsg = "Editor"
 hrsg = "Editor"
 Ill = "Illustrador"
 ill = "Illustrador"
+ilu = "Il·luminador"
+ins = "Inscriptor"
+interpr = "Intèrpret"
+interpret = "Intèrpret"
+interviewer = "Entrevistador"
+interviewter = "Entrevistat"
+inv = "Inventor"
+itr = "Instrumentalista"
+ive = "Entrevistador"
 ivr = "Entrevistador"
 jud = "Jutge"
+kamera = "Càmera"
+kartograph = "Cartògraf"
 komm = "Commentarista"
 Komment = "Commentarista"
 Komp = "Compositor"
 komp = "Compositor"
+Korresp = "Corresponsal"
+kostüm = "Dissenyador de vestuari"
 lbr = "Laboratori"
+lbt = "Libretista"
+ldr = "Director de laboratori"
+lee = "Libelee-appellee"
+lel = "Libelee"
+len = "Prestador"
+let = "Libelee-appellant"
+lie = "Libelant-appellee"
+lil = "Libelant"
+lit = "Libelant-appellant"
 lse = "Llicenciat"
+lso = "Llicenciador"
+ltg = "Lithographer"
+lyr = "Lletrista"
+mfp = "Lloc de fabricació"
+mfr = "Fabricant"
+mitarb = "CCol·laborador"
 mod = "Moderador"
+mrb = "Marbler"
+msd = "Director musical"
 mus = "Músic"
 nrt = "Narrador"
 opn = "Oponent"
+org = "Organitzador"
+orm = "Organitzador"
 oth = "Altre"
 own = "Propietari"
+pan = "Panelista"
 pat = "Usuari"
+pbd = "Director editorial"
 pbl = "Editor"
+pdr = "Director del projecte"
+pfr = "Proofreader"
+pht = "Fotògraf"
+plt = "Platemaker"
+pmn = "Director de producció"
+ppm = "Papermaker"
+ppt = "Puppeteer"
+pra = "Praeses"
+prd = "Personal de producció"
+pre = "Presentador"
+prf = "Intèrpret"
+prg = "Programador"
+prm = "impressor"
 pro = "Productor"
 prod = "Productor"
+prp = "Lloc de producció"
+prt = "Impressora"
+prv = "Proveïdor"
+präses = "Praeses"
+pta = "Sol·licitant de patents"
+pte = "Plaintiff-appellee"
+ptf = "Plaintiff"
+ptt = "Plaintiff-appellant"
+rbr = "Rectificador"
+rcd = "Enregistrador"
+rce = "Enginyer de gravació"
+rcp = "Destinatari"
+rdd = "Director de ràdio"
+Red = "Redactor"
+red = "Redactor"
+regie = "Director"
+ren = "Renderitzador"
+reporter = "Periodista"
 res = "Investigador"
+resp = "Respondent"
 rev = "Revisor"
+rpc = "Productor de ràdio"
 rps = "Repositori"
+rpt = "Periodista"
+rpy = "Responsable"
+rse = "Respondent-appellee"
+rsg = "Restager"
+rsp = "Respondent"
+rsr = "Restorationist"
+rst = "Respondent-appellant"
 sad = "Assesor científic"
+Sammler = "Col·leccionista"
+sammler = "Col·leccionista"
+sce = "Scenarist"
+Schreiber = "Escriptor"
 scl = "Escultor"
+sds = "Dissenyador de so"
 sec = "Secretari"
+sgd = "Director d'escena"
 sgn = "Signant"
 sll = "Venedor"
 sng = "Cantant"
 spn = "Patroncinador"
+srv = "Agrimensor"
+stecher = "Gravador"
 stl = "Conta contes"
+str = "Estereotip"
+tcd = "Director tècnic"
 tch = "Professor"
 textverf = "Autor"
+trc = "Transcriber"
 trl = "Traductor"
+tyg = "Typographer"
 tänzer = "Ballarí"
 vac = "Doblador"
+vdg = "Videògraf"
 Verstorb = "Mort"
 verstorb = "Mort"
 voc = "Vocalista"
 vorl = "Esborrany"
+widmungsempfänger = "Dedicat"
 wit = "Testimoni"
+zeichner = "Dibuixant"
+zensor = "Censor"
 Ãœbers = "Traductor"
 übers = "Traductor"
diff --git a/languages/CreatorRoles/de.ini b/languages/CreatorRoles/de.ini
index 4322814697b6a9d8e9c7a406411fc6fd2d66784d..3da8a5216faa6926931bf4a8eb5d6fb44cdaf5e3 100644
--- a/languages/CreatorRoles/de.ini
+++ b/languages/CreatorRoles/de.ini
@@ -193,10 +193,14 @@ lbr = "Labor"
 lbt = "LibrettistIn"
 ldr = "Laborleitung"
 led = "Führung"
+lee = "Libelee-appellee"
 lel = "BeklagteR im Seerecht/Kirchenrecht"
 len = "LeihgeberIn"
+let = "Libelee-appellant"
 lgd = "LichtgestalterIn"
+lie = "Libelant-appellee"
 lil = "KlägerIn im Seerecht/Kirchenrecht"
+lit = "Libelant-appellant"
 lsa = "LandschaftsarchitektIn"
 lse = "LizenznehmerIn"
 lso = "LizenzgeberIn"
diff --git a/languages/CreatorRoles/fr.ini b/languages/CreatorRoles/fr.ini
index 960a443840cfd0120058fc534860ab6ac4e947d6..bacf75fcf8bb35655c737a110ec7364bb214a992 100644
--- a/languages/CreatorRoles/fr.ini
+++ b/languages/CreatorRoles/fr.ini
@@ -76,6 +76,7 @@ con = "Conservateur"
 cor = "Déspositaire de la collection"
 cos = "Contestant"
 cot = "Contestant-appelant"
+cou = "Tribunal compétent"
 cov = "Concepteur de pages couvertures"
 cpc = "Demandeur du droit d'auteur"
 cpe = "Plaignant-intimé"
@@ -85,6 +86,7 @@ cpt = "Plaignant-appelant"
 cre = "Créateur"
 crp = "Correspondant"
 crr = "Réviseur"
+crt = "Sténographe de justice"
 csl = "Expert-conseil"
 csp = "Consultant sur le projet"
 cst = "Costumier"
@@ -140,6 +142,7 @@ fmk = "Réalisateur"
 fmo = "Ancien propriétaire"
 fmp = "Producteur de film"
 fnd = "Bailleur de fonds"
+Forts = "Continuation"
 fotogr = "Photographe"
 fpy = "Première partie"
 frg = "Faussaire"
@@ -166,6 +169,7 @@ itr = "Instrumentiste"
 ive = "Personne interrogée"
 ivr = "Interviewer"
 jud = "Juge"
+jug = "Juridiction compétente"
 kad = "Auteur cadentiel"
 kamera = "Caméraman"
 kartograph = "Cartographe"
@@ -201,6 +205,7 @@ mitarb = "Collaborateur"
 mod = "Animateur de débat"
 moderation = "Modérateur"
 mon = "Moniteur"
+mrb = "Marbreur"
 mrk = "Éditeur de balisage"
 msd = "Directeur musical"
 mte = "Graveur sur métal"
@@ -254,6 +259,7 @@ ptf = "Demandeur"
 pth = "Titulaire de brevet"
 ptt = "Demandeur-appelant"
 pup = "Lieur d'édition"
+rbr = "Auteur de rubriques"
 rcd = "Enregistreur"
 rce = "Ingénieur du son"
 rcp = "Destinataire"
diff --git a/languages/ar.ini b/languages/ar.ini
index a34366ca8c82cbdd822560d6a45e8c73cb15566b..b010a51ca0905fa4a7d08bd8b6208e1a3e6fc072 100644
--- a/languages/ar.ini
+++ b/languages/ar.ini
@@ -5,29 +5,28 @@ Abstract = "مستخلص"
 Access = "وصول"
 Access URL = "URL الوصول"
 access_denied = "تم رفض الوصول."
-Accession Number = "رقم الأكسشن"
+Accession Number = "رقم الانضمام"
 Account = "حساب"
-Add = "إضافة"
+account_block_options_missing = "تمت إزالة بعض الخيارات نظرا لوجود حظر على حسابك. التفاصيل: %%details%%"
 Add a Library Card = "أضف بطاقة مكتبة"
 Add a Note = "إضافة ملاحظة"
 Add Tag = "إضافة وسم"
 Add Tags = "إضافة وسوم"
 Add to another list = "أضف إلى قائمة أخرى"
-Add to Book Bag = "أضق إلى سلة الكتب"
+Add to Book Bag = "أضف إلى سلة الكتب"
 Add to favorites = "أضف إلى المفضلة"
 Add your comment = "أضف تعليقك"
 add_comment_fail_blank = "لا يمكن أن يكون التعليق خاليا."
 add_comment_success = "تمت إضافة التعليق."
 add_favorite_fail = "خطأ: التسجيلة غير محفوظة"
-add_favorite_prefix = "إضافة"
-add_favorite_suffix = "إلى المفضلة"
 add_list_fail = "خطأ: لم يتم إنشاء القائمة"
 add_other_libraries = "إدراج المقالات من مكتبات أخرى"
 add_search = "إضافة حقل بحث"
 add_search_group = "إضافة مجموعة بحث"
 add_tag_error = "خطأ: لا يمكن حفظ الوسوم"
-add_tag_note = "ستقوم المسافات بفضل الوسوم. استخدم الأقواس للوسوم المكونة من أكثر من كلمة."
+add_tag_note = "ستقوم المسافات بفصل الوسوم. استخدم الأقواس للوسوم المكونة من أكثر من كلمة."
 add_tag_success = "تم حفظ الوسوم"
+add_to_favorites_html = "إضافة <em>%%title%%</em> إلى المفضلة"
 Address = "العنوان"
 adv_search_all = "كل الحقول"
 adv_search_author = "المؤلف"
@@ -48,7 +47,7 @@ Advanced Search = "بحث متقدم"
 advSearchError_noRights = "عذراً، لكنك لا تملك صلاحية تحرير هذا البحث. ربما انتهت جلسة متصفحك ؟"
 advSearchError_notAdvanced = "البحث الذي طلبت تحريره ليس بحثا متقدماً."
 advSearchError_notFound = "لم يتم العثور على البحث الذي طلبته."
-ajaxview_label_information = "نعلومات"
+ajaxview_label_information = "معلومات"
 ajaxview_label_tools = "أدوات"
 All = "الكل"
 All Fields = "كل الحقول"
@@ -140,7 +139,7 @@ browse_topic = "الموضوع"
 bulk_email_success = "تم إرسال موادك بالبريد الالكتروني"
 bulk_email_title = "مواد فهرس المكتبة"
 bulk_error_missing = "بعض البيانات مفقودة. لم ينجح طلبك."
-bulk_export_not_supported = "التسجيلة (التسجيلات) التي قمت بتحديدها لا تدعم التصدير الضخم."
+bulk_export_not_supported = "التسجيلة (التسجيلات) التي قمت بتحديدها لا تدعم التصدير الكمي."
 bulk_fail = "عذراً، حدث خطأ. يرجى إعادة المحاولة."
 bulk_noitems_advice = "لم يتم تحديد مواد. يرجى النقر على مربع التحديد الموجود بجانب المادة وإعادة المحاولة."
 bulk_save_error = "بعض البيانات مفقودة. لم يتم حفظ موادك."
@@ -173,6 +172,11 @@ Catalog Results = "نتائج الفهرس"
 catalog_login_desc = "أدخل اعتمادات فهرس مكتبتك."
 CD = "قرص مضغوط"
 Change Password = "تغيير كلمة المرور"
+channel_add_more = "أضف المزيد من القنوات هكذا"
+channel_expand = "اكتشف القنوات ذات الصلة"
+channel_explore = "اكتشف القنوات"
+channel_search = "عرض المواد كنتائج بحث"
+channel_searchbox_label = "البحث عن المزيد من القنوات:"
 Check Hold = "تحديد الحجز"
 Check Recall = "تحديد الاستدعاء"
 Checked Out = "معار"
@@ -222,8 +226,7 @@ confirm_ill_request_cancel_all_text = "هل ترغب في إلغاء كل طلب
 confirm_ill_request_cancel_selected_text = "هل ترغب في الغاء طلبات استعاراتك بين المكتبات المحددة؟"
 confirm_new_password = "تأكيد كلمة المرور الجديدة"
 confirm_storage_retrieval_request_cancel_all_text = "هل ترغب في إلغاء كل طلبات استعادة مخزونك الحالية؟"
-confirm_storage_retrieval_request_cancel_selected_text = "هل ترغب غي إلغاء طلبات استعادة مخزونك المحددة؟"
-conjunction_or = "أو"
+confirm_storage_retrieval_request_cancel_selected_text = "هل ترغب في إلغاء طلبات استعادة مخزونك المحددة؟"
 Contents = "المحتويات"
 Contributing Source = "المصدر المساهم"
 Contributors = "المساهمون"
@@ -235,7 +238,7 @@ Corporate Authors = "مؤلفون مشاركون"
 Country = "البلد"
 Course = "الكورس"
 Course Reserves = "الحجز الأكاديمي"
-course_reserves_empty_list = "لم يتم العثور على احتياطي أكاديمي مطابق."
+course_reserves_empty_list = "لم يتم العثور على حجز أكاديمي مطابق."
 Cover Image = "صورة الغلاف"
 Create a List = "إنشاء قائمة"
 Create New Account = "إنشاء حساب جديد"
@@ -273,19 +276,21 @@ Displaying the top = "عرض الأعلى"
 Document Inspector = "فاحص الوثائق"
 Document Type = "نوع الوثيقة"
 DOI = "DOI"
-Draw Search Box = "أرسم صندوق البحث"
+doi_detected_html = "يبدو أن بحثك يحتوي على معرف كيان رقمي. انقر هنا للتحقق من توافر المواد: <a href="%%url%%">%%doi%%</a>"
+Draw Search Box = "مربع بحث الرسم"
 Due = "مستحق"
 Due Date = "تاريخ الاستحقاق"
 DVD = "قرص فيديو رقمي"
 eBook = "كتاب الكتروني"
 Edit = "تحرير"
-Edit Library Card = "حرّر بطاةق المكتبة"
+Edit Library Card = "حرّر بطاقة المكتبة"
 Edit this Advanced Search = "تحرير هذا البحث المتقدم"
 edit_list = "تحرير القائمة"
 edit_list_fail = "عذرا، ليس لديك صلاحية تحرير هذه القائمة"
 edit_list_success = "تم تحديث القائمة بنجاح."
 Edition = "الطبعة"
 eds_expander_fulltext = "ابحث أيضا في النص الكامل للمقالات"
+eds_expander_relatedsubjects = "تطبيق موضوعات مماثلة "
 eds_expander_thesaurus = "قم بتطبيق الكلمات ذات الصلة"
 eds_limiter_FC = "الفهرس فقط"
 eds_limiter_FC1 = "المستودع المؤسسي فقط"
@@ -346,6 +351,10 @@ export_selected = "تصدير المحدد"
 export_selected_favorites = "تصدير المفضلة المحددة"
 export_success = "اكتمل التصدير"
 export_unsupported_format = "تنسيق تصدير غير مدعوم"
+external_auth_heading = "الوصول إلى المادة المرخصة"
+external_auth_login_message = "تسجيل الدخول للوصول إلى المادة المرخصة "
+external_auth_unauthorized = "غير مصرح لك بالوصول إلى المادة المرخصة"
+external_auth_unauthorized_desc = "لا توفر طريقة تسجيل دخولك وصولا إلى المادة المرخصة. يرجى تسجيل الخروج ثم إعادة تسجيل الدخول بطريقة أخرى."
 FAQs = "الأسئلة الشائعة"
 fav_delete = "حذف المفضلة المحددة"
 fav_delete_deleting = "تم حذف مفضلتك."
@@ -378,12 +387,11 @@ fine_limit_patron = "لقد وصلت للحد الأقصى للغرامات ول
 Fines = "الغرامات"
 First = "الأول"
 First Name = "الاسم الأول"
-fix_metadata = "أجل، قم بإصلاح الميتاداتا؛سأنتظر"
+fix_metadata = "أجل، قم بإصلاح واصفات البيانات؛سأنتظر"
 for search = "نتيجة بحث عن"
 Forgot Password = "نسيت كلمة المرور"
 Form Submitted! = "تم تقديم النموذج !"
 Format = "التنسيق"
-found = "تم العثور على"
 From = "من"
 Full description = "وصف كامل"
 Full text is not displayed to guests = "لا يتم عرض النص الكامل للضيوف."
@@ -435,7 +443,7 @@ hold_cancel_all = "إلغاء كل الحجوزات"
 hold_cancel_fail = "لم يتم إلغاء طلبك. يرجى الاتصال بمكتب الإعارة للمزيد من المساعدة"
 hold_cancel_selected = "إلغاء الحجوزات المحددة"
 hold_cancel_success = "تم إلغاء طلبك بنجاح"
-hold_cancel_success_items = "تم الغاء طلبك بنجاح"
+hold_cancel_success_items = "%%count%% تم الغاء طلبك بنجاح"
 hold_date_invalid = "يرجى إدخال تاريخ صحيح"
 hold_date_past = "يرجى إدخال تاريخ في المستقبل"
 hold_empty_selection = "لم يتم تحديد حجوزات"
@@ -443,19 +451,21 @@ hold_error_blocked = "لا يوجد لديك امتيازات كافية لوض
 hold_error_fail = "لقد فشل طلبك. يرجى الإتصال بمكتب الإعارة للمزيد من المساعدة"
 hold_invalid_pickup = "تم إدخال موقع التقاط غير صحيح. يرجى إعادة المحاولة"
 hold_invalid_request_group = "تم إدخال مجموعة طلبات حجز غير صحيحة. يرجى إعادة المحاولة"
-hold_login = "لمعلومات الحجز والاستدعاء"
+hold_items_available = "لا يمكن وضع حجز لأن المواد متاحة."
+hold_login = "تسجيل الدخول لمعلومات الحجز والاستدعاء"
 hold_place = "وضع طلب"
 hold_place_fail_missing = "لقد فشل طلبك. بعض البيانات مفقودة. يرجى الاتصال بمكتب الاستعارة للمزيد من المساعدة"
 hold_place_success_html = "لقد نجح طلبك. <a href="%%url%%">حجوزاتك واستدعاءاتك</a>."
 hold_profile_html = "لمعلومات الحجز والاستدعاء، يرجى إنشاء <a href="%%url%%">ملف فهرس مكتبك</a>."
 hold_queue_position = "وضع الصف"
+hold_record_already_on_loan = "التسجيلة معارة لك بالفعل"
 hold_request_group = "طلب من"
 hold_requested_group = "مطلوب من"
 hold_required_by = "غير مطلوب بعد"
 hold_success = "كان طلبك ناجحا"
 Holdings = "المقتنيات"
 Holdings at Other Libraries = "المقتنيات في مكتبات أخرى"
-Holdings details from = "تفاصيل المقتنيات من"
+holdings_details_from = "تفاصيل المقتنيات من %%location%%"
 Holdings_notes = "ملاحظات"
 Holds = "الحجوزات"
 Holds and Recalls = "الحجوزات والاستدعاءات"
@@ -469,7 +479,7 @@ ill_request_cancel_all = "الغاء طلبات الاستعارة بين الم
 ill_request_cancel_fail = "لم يتم إلغاء طليك. يرجى الاتصال بمكتب الإعارة للمزيد من المساعدة"
 ill_request_cancel_selected = "إلغاء طلبات الاستعارة بين المكتبات المحددة"
 ill_request_cancel_success = "تم إلغاء طلبك بنجاح"
-ill_request_cancel_success_items = "تم إلغاء الطلب بنجاح"
+ill_request_cancel_success_items = "%%count%% تم إلغاء الطلب بنجاح"
 ill_request_canceled = "تم الغاء"
 ill_request_check_text = "التحقق من طلب الاستعارة بين المكتبات"
 ill_request_comments = "التعليقات"
@@ -483,7 +493,7 @@ ill_request_error_unknown_patron_source = "مكتبة المستفيد غير م
 ill_request_invalid_pickup = "تم إدخال موقع التقاط غير صحيح. يرجى إعادة المحاولة"
 ill_request_pick_up_library = "مكتبة الالتقاط"
 ill_request_pick_up_location = "موقع الالتقاط"
-ill_request_place_fail_missing = "لقد فشل طبيك. بعض البيامات مفقودة. يرجى الاتصال بمكتب الإعارة للمزيد من المساعدة"
+ill_request_place_fail_missing = "لقد فشل طلبك. بعض البيانات مفقودة. يرجى الاتصال بمكتب الإعارة للمزيد من المساعدة"
 ill_request_place_success = "كان طلبك ناجحا"
 ill_request_place_success_html = "كان طلبك ناجحا <a href="%%url%%">طلبات الاستعارة بين المكتبات</a>."
 ill_request_place_text = "وضع طلب استعارة بين المكتبات"
@@ -498,7 +508,6 @@ ils_offline_login_message = "تفاصيل حسابك ستكون غير متاح
 ils_offline_status = "نظام إدارة مكتبتنا قيد الصيانة حاليا."
 ils_offline_title = "النظام قيد الصيانة"
 Import Record = "استيراد تسجيلة"
-Import to = "استيراد إلى"
 in = "في"
 In This Collection = "في هذه المجموعة"
 in_collection_label = "في المجموعة :"
@@ -526,8 +535,8 @@ Item removed from favorites = "تم حذف المادة من المفضلة"
 Item removed from list = "تم حذف المادة من القائمة"
 Items = "مواد"
 items = "مواد"
-items_added_to_bookbag = "تمت إضافة المادة إلى سلة كتبك"
-items_already_in_bookbag = "إما أن المادة موجودة بالفعل في سلة كتبك أو لا يمكن إضافتها"
+items_added_to_bookbag = "%%count%% تمت إضافة المادة إلى سلة كتبك"
+items_already_in_bookbag = "%%count%% إما أن المادة موجودة بالفعل في سلة كتبك أو لا يمكن إضافتها"
 Journal = "دورية"
 Journal Articles = "مقالات الدورية"
 Journal Info = "بيانات الدورية"
@@ -544,15 +553,15 @@ Last = "آخر"
 Last Modified = "آخر تعديل"
 Last Name = "الاسم الأخير"
 less = "أقل"
-libphonenumber_invalid = "رقم التلفون غير صحيح"
+libphonenumber_invalid = "رقم الهاتف غير صحيح"
 libphonenumber_invalidcountry = "رمز البلد في المكالمة غير صحيح"
 libphonenumber_invalidregion = "رقم المنطقة غير صحيح:"
-libphonenumber_notanumber = "رقم التلفون الذي تم تزويده لا يبدو انه صحيح"
-libphonenumber_toolong = "رقم التلفون الذي تم تزويده يبدو انه أطول من المتوقع"
-libphonenumber_tooshort = "رقم التلفون الذي تم تزويده يبدو أنه أقصر من المتوقع"
-libphonenumber_tooshortidd = "رقم التلفون أقصر من المتوقع بعد IDD"
+libphonenumber_notanumber = "رقم الهاتف الذي تم تقديمه لا يبدو أنه صحيح"
+libphonenumber_toolong = "رقم الهاتف الذي تم تقديمه يبدو أطول من المتوقع"
+libphonenumber_tooshort = "رقم الهاتف الذي تم تقديمه يبدو  أقصر من المتوقع"
+libphonenumber_tooshortidd = "رقم الهاتف أقصر من المتوقع بعد IDD"
 Library = "المكتبة"
-Library Card = "كرت المكتبة"
+Library Card = "بطاقة المكتبة"
 Library Card Deleted = "تم حذف بطاقة المكتبة"
 Library Card Name = "اسم بطاقة المكتبة"
 Library Cards = "بطاقات المكتبة"
@@ -596,15 +605,15 @@ medium = "وسيط"
 MeSH Terms = "مواضيع طبية MeSH"
 Message = "رسالة"
 Message From Sender = "رسالة من المرسل"
-Metadata Prefix = "بادئة الميتاداتا"
+Metadata Prefix = "بادئة واصفات البيانات"
 Microfilm = "مكروفيلم"
 MLA Citation = "MLA استشهاد"
 mobile_link = "يبدو أنك تستخدم جهاز محمول ؛ هل تريد التحويل إلى عرض الهاتف المحمول؟"
 Monograph Title = "عنوان موحد"
 more = "المزيد"
-More catalog results = "المزيد من نتائج الفهرس"
+More catalog results = "المزيد من نتائج بحث الفهرس"
 More options = "المزيد من الخيارات"
-More Summon results = "المزيد من استدعاء النتائج"
+More Summon results = "استدعاء المزيد من النتائج"
 More Topics = "المزيد من الموضوعات"
 more_authors_abbrev = "وآخرون"
 more_info_toggle = "عرض/إخفاء المزيد من المعلومات"
@@ -644,12 +653,11 @@ nohit_active_filters = "أحد مرشحات الواجهة أو أكثر تم ت
 nohit_change_tab = "لقد كنت تبحث في تبويب  "%%activeTab%%" . يمكنك العثور على شيء ما في أحد التبويبات الأخرى :"
 nohit_filters = "المرشحات المطبقة حاليا على هذا البحث :"
 nohit_heading = "لا توجد نتائج!"
+nohit_lookfor_html = "بحثك - <strong>%%lookfor%%</strong> - لم يطابق أي من المصادر."
 nohit_no_filters = "لم يتم تطبيق أي مرشحات على هذا البحث."
 nohit_parse_error = "يبدو أن هناك مشكلة في استعلام بحثك. يرجى التحقق من التركيب. إذا لم تكن تحاول استخدام خواص متقدمة، قد يساعدك وضع الاستعلام بين قوسين مزدوجين."
-nohit_prefix = "بحثك"
 nohit_query_without_filters = "حذف كل المرشحات من هذا البحث."
 nohit_spelling = "ربما يجب عليك تجربة بعض المتغيرات الهجائية"
-nohit_suffix = "لم يطابق أي من المصادر."
 nohit_suggest = "يمكنك مراجعة عبارة بحثك عن طريق حذف بعض الكلمات أو مراجعة الهجاء."
 NOT = "غير"
 Not Illustrated = "غير موضح"
@@ -667,10 +675,10 @@ note_774 = "وحدة مكونة"
 note_775 = "طبعة أخرى متاحة"
 note_776 = "نموذج إضافي"
 note_777 = "تم إصداره بـ"
-note_780_0 = "يستمر"
-note_780_1 = "يستمر جزئيا"
-note_780_2 = "يلغي"
-note_780_3 = "يلغي جزئيا"
+note_780_0 = "مستمر"
+note_780_1 = "مستمر جزئيا"
+note_780_2 = "ملغي"
+note_780_3 = "ملغي جزئيا"
 note_780_4 = "مكون بواسطة"
 note_780_5 = "بيانات النشر"
 note_780_6 = "منشور جزئيا"
@@ -691,7 +699,7 @@ number_decimal_point = "."
 number_thousands_separator = ","
 OAI Server = "OAI خادم"
 Occupation = "الوظيفة"
-of = "من"
+of_num_results = "#%%position%% من %%total%% نتائج"
 old_password = "كلمة المرور القديمة"
 On Reserve = "في الحجز"
 On Reserve - Ask at Circulation Desk = "في الحجز - اسأل في مكتب الإعارة"
@@ -699,6 +707,7 @@ on_reserve = "الحجز - اسأل في الإعارة"
 on_topic = "%%count%% مواد حول الموضوع"
 Online Access = "الوصول للمادة أونلاين"
 online_resources = "نص كامل"
+open_access_limit = "قصر على محتوى الوصول الحر"
 operator_contains = "يحتوي على"
 operator_exact = "هو (بالضبط)"
 OR = "أو"
@@ -731,14 +740,12 @@ Physical Object = "كيان مادي"
 pick_up_location = "موقع الالتقاط"
 Place a Hold = "أحجز النسخة"
 Place of birth = "مكان الميلاد"
-Place of death = "مكان الوفاه"
+Place of death = "مكان الوفاة"
 Playing Time = "وقت التشغيل"
 Please check back soon = "يرجى التحقق مرة أخرى قريبا"
 Please contact the Library Reference Department for assistance = "يرجى الاتصال بقسم مرجعية المكتبة للمساعدة"
 Please enable JavaScript. = "الرجاء تفعيل JavaScript."
 Please upgrade your browser. = "الرجاء ترقية متصفحك."
-Posted by = "منشور بواسطة"
-posted_on = "في"
 Preferences = "مفضلات"
 Preferred Library = "المكتبة المفضلة"
 Prev = "السابق"
@@ -874,13 +881,18 @@ Sensor Image = "صورة المجس"
 Serial = "دورية"
 Series = "سلاسل"
 Set = "ضبط"
-Showing = "يعرض"
-sidebar_close = "أقفل الشريط الجانبي"
-sidebar_expand = "أفتح الشريط الجانبي"
+showing_items_html = "يعرض <strong>%%start%% - %%end%%</strong> مواد"
+showing_items_of_html = "يعرض <strong>%%start%% - %%end%%</strong> من <strong>%%total%%</strong> مواد"
+showing_results_for_html = "يعرض <strong>%%start%% - %%end%%</strong> نتائج نتيجة بحث عن '<strong>%%lookfor%%</strong>'"
+showing_results_html = "يعرض <strong>%%start%% - %%end%%</strong> نتائج"
+showing_results_of_for_html = "يعرض <strong>%%start%% - %%end%%</strong> نتائج من <strong>%%total%%</strong> نتيجة بحث عن '<strong>%%lookfor%%</strong>'"
+showing_results_of_html = "يعرض <strong>%%start%% - %%end%%</strong> نتائج من <strong>%%total%%</strong>"
+sidebar_close = "إغلاق الشريط الجانبي"
+sidebar_expand = "فتح الشريط الجانبي"
 Similar Items = "مواد مشابهة"
 Skip to content = "تخطي إلى المحتوى"
 skip_confirm = "هل أنت متأكد من أنك تريد تخطي هذه الخطوة؟"
-skip_fix_metadata = "لا تصلح الميتاداتا في الوقت الحالي."
+skip_fix_metadata = "لا تصلح واصفات البيانات في الوقت الحالي."
 skip_step = "تخطي هذه الخطوة"
 Slide = "شريحة"
 sms_failure = "خطأ! لا يمكن إرسال الرسالة."
@@ -918,7 +930,7 @@ storage_retrieval_request_cancel_all = "إلغاء كل طلبات استرجا
 storage_retrieval_request_cancel_fail = "لم يتم الغاء طلبك. يرجى الاتصال بمكتب الإعارة للمزيد من المساعدة"
 storage_retrieval_request_cancel_selected = "إلغاء طلبات استرجاع المخزون المحددة"
 storage_retrieval_request_cancel_success = "تم الغاء طلبك بنجاح"
-storage_retrieval_request_cancel_success_items = "تم إلغاء الطلب بنجاح"
+storage_retrieval_request_cancel_success_items = "%%count%% تم إلغاء الطلب بنجاح"
 storage_retrieval_request_canceled = "ملغي"
 storage_retrieval_request_check_text = "التحقق من طلب استرجاع التخزين"
 storage_retrieval_request_comments = "التعليقات"
@@ -952,11 +964,11 @@ Submit = "تقديم"
 Submitting = "تقديم"
 Suggested Topics = "الموضوعات المستخلصة"
 Summary = "الملخص"
-Summon Results = "نتائج صامون"
-summon_database_recommendations = "متقرحات من قواعد صمون:"
+Summon Results = "استدعاء النتائج"
+summon_database_recommendations = "استدعاء مقترحات من قواعد البيانات:"
 Supplements = "ملاحق"
 Supplied by Amazon = "مقدم بواسطة Amazon"
-Switch view to = "تبديل العرض إلى"
+switch_view = "تبديل العرض إلى %%view%%"
 switchquery_fuzzy = "إجراء بحث ضبابي قد يستعيد مصطلحات ذات تهجئة مشابهة "
 switchquery_intro = "يمكنك الحصول على المزيد من النتائج عن طريق تعديل استعلام بحثك."
 switchquery_lowercasebools = "إذا كنت تحاول استخدام المعاملات البوليانية، يجب أن تكون جميعها حروفا كبيرة"
@@ -998,8 +1010,7 @@ Too Many Email Recipients = "متلقي البريد الالكتروني أكث
 too_many_favorites = "هذه القائمة كبيرة جدا لا يمكن عرضها كلها مرة واحدة. حاول إعادة ترتيب مفضلاتك إلى المزيد من القوائم أو تحديد استخدام الوسوم."
 too_many_new_items = "يوجد الكثير جدا من المواد لعرضها في قائمة واحدة. حاول تحديد بحثك"
 too_many_reserves = "يوجد الكثير جدا من الاحتياطي الأكاديمي لعرضه في قائمة واحدة. حاول تحديد بحثك."
-top_facet_additional_prefix = "إضافي"
-top_facet_suffix = "... من بحثك."
+top_facet_label = "%%label%% من بحثك."
 Topic = "موضوع"
 Topics = "موضوعات"
 Total Balance Due = "إجمالي الرصيد المستحق"
@@ -1028,7 +1039,6 @@ VHS = "VHS"
 Video = "الفيديو"
 Video Clips = "مقاطع الفيديو"
 Videos = "الفيديوهات"
-view already selected = "عرض المحدد بالفعل"
 View Book Bag = "عرض سلة الكتب"
 View Full Collection = "عرض المجموعة كاملة"
 View Full Record = "عرض التسجيلة الكاملة"
@@ -1037,11 +1047,12 @@ View online: Full view Book Preview from the Hathi Trust = "عرض على أون
 View Record = "عرض التسجيلة"
 View Records = "عرض التسجيلات"
 View this record in EBSCOhost = "عرض هذه التسجيلة في EBSCOhost"
+view_already_selected = "%%current%% عرض المحدد بالفعل"
 visual_facet_parent = "من"
 Volume = "المجلد"
 Volume Holdings = "مقتنيات المجلد"
-VuFind Configuration = "VuFind تهيئة"
-vufind_upgrade_fail = "لا يمكننا ترقية VuFind في الوقت الحالي"
+VuFind Configuration = "تهيئة فيوفايند"
+vufind_upgrade_fail = "لا يمكننا ترقية فيوفايند في الوقت الحالي"
 Warning: These citations may not always be 100% accurate = "تحذير: قد لا تكون هذه الاستشهادات دائما دقيقة بنسبة 100%"
 wcterms_broader = "موضوعات أوسع"
 wcterms_exact = "موضوعات ذات صلة"
diff --git a/languages/bn.ini b/languages/bn.ini
index 38c56a834286bb503071ef118ed6d5f6ad323d54..19dcb7fc7efc74f092757c6d1181db41165decab 100644
--- a/languages/bn.ini
+++ b/languages/bn.ini
@@ -8,7 +8,7 @@ Access URL = "URL ব্যবহার করুন"
 access_denied = "পরিষেবা বন্ধ।"
 Accession Number = "পরিগ্রহন সংখ্যা"
 Account = "অ্যাকাউন্ট"
-Add = "যুক্ত করুন"
+account_block_options_missing = "আপনার অ্যাকাউন্ট ব্লক করার জন্য কিছু সুবিধা প্রত্যাহার করা হয়েছে । বিশদে জানুন : %%details%%"
 Add a Library Card = "গ্রন্থাগার কার্ড যুক্ত করুন"
 Add a Note = "টীকা যুক্ত করুন"
 Add Tag = "ট্যাগ যুক্ত করুন"
@@ -20,8 +20,6 @@ Add your comment = "মন্তব্য করুন"
 add_comment_fail_blank = "মন্তব্য স্থান শূন্য থাকবে না।"
 add_comment_success = "মন্তব্য যুক্ত হয়েছে।"
 add_favorite_fail = "ত্রুটি: রেকর্ড ভুক্তিকরন হয়নি"
-add_favorite_prefix = "যুক্ত করুন"
-add_favorite_suffix = "পছন্দ তালিকা"
 add_list_fail = "ত্রুটি: তালিকা তৈরি হয়নি"
 add_other_libraries = "অন্যান্য গ্রন্থাগারে নিবন্ধ অন্তর্ভুক্ত করুন"
 add_search = "অনুসন্ধান ক্ষেত্র যোগ করুন"
@@ -29,6 +27,7 @@ add_search_group = "অনুসন্ধান দল যোগ করুন"
 add_tag_error = "ত্রুটি: ট্যাগ  সংরক্ষণ করা যায়নি"
 add_tag_note = "শূন্যস্থানের ট্যাগ আলাদা হবে। শব্দাবলী ট্যাগের জন্য কোট ব্যবহার করুন"
 add_tag_success = "ট্যাগ  সংরক্ষিত"
+add_to_favorites_html = "যুক্ত করুন <em>%%title%%</em> পছন্দ তালিকা"
 Address = "ঠিকানা"
 adv_search_all = "সমস্ত ক্ষেত্রসমূহ "
 adv_search_author = "লেখক"
@@ -174,6 +173,10 @@ Catalog Results = "গ্রন্থ তালিকা অনুসন্ধ
 catalog_login_desc = "আপনার গ্রন্থাগার ক্যাটালগে পরিচয়পত্র লিখুন"
 CD = "সি ডি"
 Change Password = "পাসওয়ার্ড পরিবর্তন করুন "
+channel_add_more = "এই ধরণের আরো চ্যানেল যোগ করুন"
+channel_expand = "সমধর্মী চ্যানেল অন্বেষণ করুন"
+channel_explore = "চ্যানেল অন্বেষণ করুন"
+channel_search = "অনুসন্ধানে প্রলেখ প্রদর্শন করুন"
 Check Hold = "গ্রন্থ রিজার্ভ করার জন্য চেক করুন"
 Check Recall = "গ্রন্থ তলব করুন"
 Checked Out = "গ্রন্থ প্রদান হয়েছে"
@@ -224,7 +227,6 @@ confirm_ill_request_cancel_selected_text = "আপনি কি আপনার
 confirm_new_password = "নতুন পাসওয়ার্ড নিশ্চিত করুন"
 confirm_storage_retrieval_request_cancel_all_text = "আপনি কি আপনার সমস্ত সঞ্চয়ন তথ্যোদ্ধার অনুরোধ বাতিল করতে চান?"
 confirm_storage_retrieval_request_cancel_selected_text = "আপনি কি আপনার নির্বাচিত সঞ্চয়ন তথ্যোদ্ধার অনুরোধ বাতিল করতে চান?"
-conjunction_or = "অথবা"
 Contents = "সামগ্রীগুলি"
 Contributing Source = "সংগ্রহের অবদান"
 Contributors = "অবদানকারীরা"
@@ -274,6 +276,7 @@ Displaying the top = "শীর্ষে প্রদর্শিত"
 Document Inspector = "প্রলেখ পরিদর্শক"
 Document Type = "প্রলেখের ধরণ"
 DOI = "ডিওআই"
+doi_detected_html = "প্রদর্শিত প্রলেখে DOI রয়েছে। প্রলেখ উপলব্ধ করার জন্য এখানে ক্লিক করুন: <a href="%%url%%">%%doi%%</a>"
 Draw Search Box = "অনুসন্ধান ক্ষেত্র সংযোজন করুন"
 Due = "বাকি"
 Due Date = "তারিখ বাকি আছে"
@@ -347,6 +350,10 @@ export_selected = "নির্বাচিত ফাইলটি এক্স
 export_selected_favorites = "নির্বাচিত পছন্দ তালিকাগুলি এক্সপোর্ট করুন"
 export_success = "এক্সপোর্ট সম্পূর্ন হয়েছে"
 export_unsupported_format = "অসমর্থিত এক্সপোর্ট বিন্যাস"
+external_auth_heading = "সাবস্ক্রাইব করা গ্রন্থাগার সম্পদের ব্যবহার করুন"
+external_auth_login_message = "লগ ইন করুন : সাবস্ক্রাইব করা গ্রন্থাগার সম্পদের ব্যবহার করুন"
+external_auth_unauthorized = "সাবস্ক্রাইব করা গ্রন্থাগার সম্পদের ব্যবহার করার জন্য আপনার প্রয়োজনীয় অনুমোদন নেই"
+external_auth_unauthorized_desc = "আপনার বর্তমান লগ ইন পদ্ধতি সাবস্ক্রাইব করা গ্রন্থাগার সম্পদের ব্যবহার করার জন্য প্রয়োজনীয় অনুমোদন প্রদান করছে না । লগ আউট করে অন্য লগ ইন পদ্ধতি ব্যবহার করুন "
 FAQs = "জিজ্ঞাসিত প্রশ্নাবলী"
 fav_delete = "নির্বাচিত পছন্দ তালিকাগুলি মুছুন"
 fav_delete_deleting = "আপনার প্রিয় পছন্দ তালিকাগুলি মোছা হয়েছে।"
@@ -384,7 +391,6 @@ for search = "অনুসন্ধানের জন্য"
 Forgot Password = "পাসওয়ার্ড ভুলে গেছেন"
 Form Submitted! = "ফর্ম দাখিল হয়েছে!"
 Format = "বিন্যাস"
-found = "পাওয়া গেছে"
 From = "থেকে"
 Full description = "সম্পূর্ণ বিবরণ"
 Full text is not displayed to guests = "সম্পূর্ণ পাঠ অতিথি ব্যবহারকারীকে প্রদর্শন করা হয় না।"
@@ -436,7 +442,7 @@ hold_cancel_all = "সমস্ত হোল্ড বাতিল করা হ
 hold_cancel_fail = "আপনার অনুরোধ বাতিল করা হয় নি। আরও সহায়তার জন্য সঞ্চারন ডেস্কে যোগাযোগ করুন"
 hold_cancel_selected = "নির্বাচিত হোল্ডগুলি বাতিল করা হয়েছে"
 hold_cancel_success = "আপনার অনুরোধ সম্পূর্নরূপে বাতিল করা হয়েছে"
-hold_cancel_success_items = "আপনার অনুরোধগুলি সম্পূর্নরূপে বাতিল করা হয়েছে"
+hold_cancel_success_items = "%%count%% আপনার অনুরোধগুলি সম্পূর্নরূপে বাতিল করা হয়েছে"
 hold_date_invalid = "অনুগ্রহ করে একটি বৈধ তারিখ লিখুন"
 hold_date_past = "অনুগ্রহ করে একটি ভবিষ্যত তারিখ লিখুন"
 hold_empty_selection = "কোন হোল্ড নির্বাচন করে রাখা নেই"
@@ -444,19 +450,21 @@ hold_error_blocked = "এই উপাদানটি হোল্ড করে
 hold_error_fail = "আপনার অনুরোধ পূরণ করতে ব্যর্থ। আরও সহায়তার জন্য সঞ্চারন ডেস্কে যোগাযোগ করুন"
 hold_invalid_pickup = "একটি অবৈধ পিকআপের স্থান লেখা হয়েছে। অনুগ্রহ করে আবার চেষ্টা করুন"
 hold_invalid_request_group = "আপনি একটি অবৈধ পিকআপ হোল্ড অনুরোধ দলে লিখেছেন। অনুগ্রহ করে আবার চেষ্টা করুন"
-hold_login = "তলব তথ্য এবং হোল্ড করার জন্য"
+hold_items_available = "প্রলেখ উপলব্ধ আছে, সংরক্ষণ (হোল্ড) করা যাবে না"
+hold_login = "লগ ইন করুন তলব তথ্য এবং হোল্ড করার জন্য"
 hold_place = "স্থানের জন্য অনুরোধ"
 hold_place_fail_missing = "আপনার অণুরোধ ব্যর্থ। কিছু ডাটা পাওয়া যাচ্ছে না। আরও সহায়তার জন্য সঞ্চারন ডেস্কে যোগাযোগ করুন"
 hold_place_success_html = "আপনার আনুরোধটি সফল হয়েছে। <a href="%%url%%">Your Holds and Reclls</a>."
 hold_profile_html = "তলব তথ্য এবং হোল্ড করার জন্য, অনুগ্রহ করে স্থাপন করুন <a href="%%url%%">Library Catalog Profile</a>."
 hold_queue_position = "লাইনের অবস্থান"
+hold_record_already_on_loan = "যে প্রলেখটি  সংরক্ষণ (হোল্ড) করতে চাইছেন সেটি ইতিমধ্যে আপনাকে প্রদান করা হয়েছে "
 hold_request_group = "অনুরোধে"
 hold_requested_group = "আনুরোধ থেকে"
 hold_required_by = "পরে অপ্রয়োজন"
 hold_success = "আপনার আনুরোধটি সফল হয়েছে"
 Holdings = "হোল্ডিংস"
 Holdings at Other Libraries = "অন্যান্য গ্রন্থাগারে হোল্ডিংসগুলি"
-Holdings details from = "হোল্ডিংসের বিবরণ"
+holdings_details_from = "হোল্ডিংসের বিবরণ %%location%%"
 Holdings_notes = "হোল্ডিং টীকা"
 Holds = "হোল্ড করুন"
 Holds and Recalls = "তলব তথ্য এবং হোল্ড গুলি"
@@ -470,7 +478,7 @@ ill_request_cancel_all = "সমস্ত আন্তঃগ্রন্থা
 ill_request_cancel_fail = "আপনার অনুরোধ বাতিল করা হয় নি। আরও সহায়তার জন্য সঞ্চারন ডেস্কে যোগাযোগ করুন"
 ill_request_cancel_selected = "নির্বাচিত আন্তঃগ্রন্থাগার ঋণের অনুরোধ বাতিল"
 ill_request_cancel_success = "আপনার অনুরোধটি সম্পূর্ন বাতিল করা হয়েছে"
-ill_request_cancel_success_items = "আপনার অনুরোধগুলো সম্পূর্নরূপে বাতিল করা হয়েছে"
+ill_request_cancel_success_items = "%%count%% আপনার অনুরোধগুলো সম্পূর্নরূপে বাতিল করা হয়েছে"
 ill_request_canceled = "বাতিল করা হয়েছে"
 ill_request_check_text = "আন্তঃগ্রন্থাগার ঋণের অনুরোধটি পরীক্ষা করুন"
 ill_request_comments = "মন্তব্য করুন"
@@ -499,7 +507,6 @@ ils_offline_login_message = "আপনার অ্যাকাউন্টে
 ils_offline_status = "বর্তমানে আমাদের গ্রন্থাগার ব্যবস্থাপনা পদ্ধতিটি রক্ষণাবেক্ষণের অধীনে।"
 ils_offline_title = "পদ্ধতিটি  রক্ষণাবেক্ষণের অধীনে"
 Import Record = "সংগ্রহীত তথ্য"
-Import to = "সংগ্রহ করুন"
 in = "মধ্যে"
 In This Collection = "এই সংগ্রহের মধ্যে"
 in_collection_label = "সংগ্রহের মধ্যে"
@@ -527,8 +534,8 @@ Item removed from favorites = "পছন্দের তালিকা থে
 Item removed from list = "তালিকা থেকে উপাদানটি বাদ দিন"
 Items = "উপাদানগুলি"
 items = "উপাদানগুলি"
-items_added_to_bookbag = "আপনার গ্রন্থসম্ভারে উপাদানগুলো যোগ করুন"
-items_already_in_bookbag = "উপাদানগুলি হয়তো আপনার গ্রন্থসম্ভারে ইতিমধ্যে আছে আথবা যোগ করা হয়নি"
+items_added_to_bookbag = "%%count%% আপনার গ্রন্থসম্ভারে উপাদানগুলো যোগ করুন"
+items_already_in_bookbag = "%%count%% উপাদানগুলি হয়তো আপনার গ্রন্থসম্ভারে ইতিমধ্যে আছে আথবা যোগ করা হয়নি"
 Journal = "পত্রিকা"
 Journal Articles = "পত্রিকা প্রবন্ধ"
 Journal Info = "পত্রিকা তথ্য"
@@ -645,12 +652,11 @@ nohit_active_filters = "এক বা একাধিক ফিল্টার 
 nohit_change_tab = "আপনার অনুসন্ধানটি "%%activeTab%%" ট্যাবে সীমিত আছে। প্রলেখ সংখ্যা বেশি পেতে অন্যান্য ট্যাব ব্যবহার করুন।"
 nohit_filters = "এই অনুসন্ধানের জন্য ফিল্টার প্রয়োগ করুন:"
 nohit_heading = "ফলাফল নেই!"
+nohit_lookfor_html = "অনুসন্ধানের সাথে সম্পর্ক যুক্ত  - <strong>%%lookfor%%</strong> - কোনো প্রলেখ নেই।"
 nohit_no_filters = "কোন ফিল্টার এই অনুসন্ধানে প্রয়োগ করা হয় নি"
 nohit_parse_error = "আপনার অনুসন্ধানের প্রশ্নটি একটি সমস্যা করবে বলে মনে হয়। বাক্য-গঠন চেক করুন। যদি আপনি বিস্তৃত বৈশিষ্ট্য প্রয়োগ করার চেষ্টা না করেন, তাহলে উদ্ধারচিহ্নের ভিতরে প্রশ্নটি করলে সাহায্য পেতে পারেন"
-nohit_prefix = "অনুসন্ধানের সাথে সম্পর্ক যুক্ত "
 nohit_query_without_filters = "এই অনুসন্ধান থেকে সমস্ত ফিল্টার গুলি মুছুন।"
 nohit_spelling = "সম্ভবত আপনার কিছু বানান বৈচিত্র প্রয়োগ চেষ্টা করা উচিত"
-nohit_suffix = "কোনো প্রলেখ নেই।"
 nohit_suggest = "আপনি কিছু শব্দ মুছে ফেলে আপনার  অনুসন্ধান ফ্রেজ পরিমার্জন করুন বা আপনার বানান পরীক্ষা করার চেষ্টা করতে পারেন."
 NOT = "না"
 Not Illustrated = "ছবিযুক্ত নয়"
@@ -692,7 +698,7 @@ number_decimal_point = "."
 number_thousands_separator = ","
 OAI Server = "ওএআই সার্ভার"
 Occupation = "পেশা"
-of = "এর"
+of_num_results = "#%%position%% এর %%total%% ফলাফল"
 old_password = "পুরোনো পাসওয়ার্ড"
 On Reserve = "আরক্ষিত"
 On Reserve - Ask at Circulation Desk = "আরক্ষিত - সঞ্চারন ডেস্কে যোগাযোগ করুন"
@@ -700,6 +706,7 @@ on_reserve = "আরক্ষিত - সঞ্চারন ডেস্কে 
 on_topic = "%%count%% item(s) on this topic"
 Online Access = "অনলাইন ব্যবহার করুন"
 online_resources = "সম্পূর্ন পাঠ"
+open_access_limit = "শুধুমাত্র মুক্ত তথ্যসম্ভারে (ওপেন এক্সেস) অনুসন্ধান সীমিত রাখুন"
 operator_contains = "ধারণ"
 operator_exact = "রয়েছে (একদম ঠিক)"
 OR = "অথবা"
@@ -738,8 +745,6 @@ Please check back soon = "শীঘ্রই আবার চেক করুন
 Please contact the Library Reference Department for assistance = "সহায়তার জন্য গ্রন্থাগার রেফারেন্স বিভাগের সাথে যোগাযোগ করুন"
 Please enable JavaScript. = "জাভাস্ক্রিপ্ট সচল করুন।"
 Please upgrade your browser. = "আপনার ব্রাউজার আপগ্রেড করুন।"
-Posted by = "এর দ্বারা পোস্ট করুন"
-posted_on = "চালু"
 Preferences = "পছন্দসমূহ"
 Preferred Library = "পছন্দের গ্রন্থাগার"
 Prev = "প্রাকদর্শন"
@@ -875,7 +880,12 @@ Sensor Image = "সেন্সর চিত্র"
 Serial = "সাময়িক পত্র"
 Series = "মালা"
 Set = "সেট"
-Showing = "প্রদর্শন"
+showing_items_html = "প্রদর্শন <strong>%%start%% - %%end%%</strong> উপাদানগুলি"
+showing_items_of_html = "প্রদর্শন <strong>%%start%% - %%end%%</strong> এর <strong>%%total%%</strong> উপাদানগুলি"
+showing_results_for_html = "প্রদর্শন <strong>%%start%% - %%end%%</strong> ফলাফল অনুসন্ধানের জন্য '<strong>%%lookfor%%</strong>'"
+showing_results_html = "প্রদর্শন <strong>%%start%% - %%end%%</strong> ফলাফল"
+showing_results_of_for_html = "প্রদর্শন <strong>%%start%% - %%end%%</strong> ফলাফল এর <strong>%%total%%</strong> অনুসন্ধানের জন্য '<strong>%%lookfor%%</strong>'"
+showing_results_of_html = "প্রদর্শন <strong>%%start%% - %%end%%</strong> ফলাফল এর <strong>%%total%%</strong>"
 sidebar_close = "সাইডবার সংকোচন"
 sidebar_expand = "সাইডবার প্রসারণ"
 Similar Items = "অনুরূপ উপাদানগুলি"
@@ -919,7 +929,7 @@ storage_retrieval_request_cancel_all = "সমস্ত সঞ্চিত ত
 storage_retrieval_request_cancel_fail = "আপনার অনুরোধ বাতিল করা হয় নি। আরও সহায়তার জন্য সঞ্চারন ডেস্কে যোগাযোগ করুন"
 storage_retrieval_request_cancel_selected = "নির্বাচিত সঞ্চিত তথ্যোদ্ধার অণুরোধ বাতিল করা হয়েছে"
 storage_retrieval_request_cancel_success = "আপনার অনুরোধ সম্পূর্নরূপে বাতিল করা হয়েছে"
-storage_retrieval_request_cancel_success_items = "অনুরোধগুলি সম্পূর্নরূপে বাতিল করা হয়েছে"
+storage_retrieval_request_cancel_success_items = "%%count%% অনুরোধগুলি সম্পূর্নরূপে বাতিল করা হয়েছে"
 storage_retrieval_request_canceled = "বাতিল করা হয়েছে"
 storage_retrieval_request_check_text = "সঞ্চিত তথ্যোদ্ধার অণুরোধটি চেক করুন"
 storage_retrieval_request_comments = "মন্তব্য করুন"
@@ -957,7 +967,7 @@ Summon Results = "Summon এর ফলাফল"
 summon_database_recommendations = "এখানে আপনি অতিরিক্ত সম্পদের উৎসটি খুঁজে পেতে পারেন"
 Supplements = "সম্পূরক অংশ"
 Supplied by Amazon = "অ্যামাজন দ্বারা সরবরাহকৃত"
-Switch view to = "অন্যটিতে গিয়ে দেখুন"
+switch_view = "অন্যটিতে গিয়ে দেখুন %%view%%"
 switchquery_fuzzy = "ফাজি (fuzzy) অনুসন্ধানের প্রয়োগ একই বানানের অন্যান্য শব্দ গুলি প্রদর্শন করবে"
 switchquery_intro = "আপনি আপনার অনুসন্ধান জিজ্ঞাসাগুলি সমন্বয়ের মাধ্যমে আরও ফলাফল পেতে পারেন"
 switchquery_lowercasebools = "আপনি যদি বুলিয়ান অপারেটর ব্যবহার করেন, তাহলে অবশ্যয় বড় হরফ ব্যবহার করুন"
@@ -999,8 +1009,7 @@ Too Many Email Recipients = "অত্যধিক ইমেল প্রাপ
 too_many_favorites = "এই তালিকাটি একবারে সমস্ত কিছু প্রদর্শনের জন্য অত্যন্ত বড়। আরো তালিকার মধ্যে আপনার পছন্দতালিকাগুলি সাজান বা ট্যাগগুলির ব্যবহার সীমিত করার চেষ্টা করুন"।"
 too_many_new_items = "একটি একক তালিকায় অনেকগুলি নতুন উপাদান প্রদর্শন করা হয়েছে। আপনার অনুসন্ধান সীমিত করার চেষ্টা করুন"
 too_many_reserves = "একটি একক তালিকায় অনেকগুলি কোর্স মজুদ করে প্রদর্শন করা হয়েছে। আপনার অনুসন্ধান সীমিত করার চেষ্টা করুন"
-top_facet_additional_prefix = "অতিরিক্ত"
-top_facet_suffix = "আপনার সার্চের মধ্যে"
+top_facet_label = "%%label%% আপনার সার্চের মধ্যে"
 Topic = "বিষয়"
 Topics = "বিষয় গুলি"
 Total Balance Due = "মোট ব্যালেন্স বাকি আছে"
@@ -1029,7 +1038,6 @@ VHS = "ভিএইচএস"
 Video = "ভিডিও"
 Video Clips = "ভিডিও ক্লিপস"
 Videos = "ভিডিও"
-view already selected = "দৃশ্যগুলো ইতিমধ্যে নির্বাচিত"
 View Book Bag = "গ্রন্থসম্ভার দেখুন"
 View Full Collection = "সম্পূর্ণ সংগ্রহ দেখুন"
 View Full Record = "সম্পূর্ণ নথি দেখুন"
@@ -1038,6 +1046,7 @@ View online: Full view Book Preview from the Hathi Trust = "অনলাইন
 View Record = "নথি দেখুন"
 View Records = "নথিগুলো দেখুন"
 View this record in EBSCOhost = "নথিগুলো EBSCOhost এ দেখুন"
+view_already_selected = "%%current%% দৃশ্যগুলো ইতিমধ্যে নির্বাচিত"
 visual_facet_parent = "থেকে"
 Volume = "খণ্ড"
 Volume Holdings = "খণ্ড সংগ্রহ"
diff --git a/languages/ca.ini b/languages/ca.ini
index 5e26cd72314aa0290b0b00a1c55debcdf6a6ee98..3995a658b90f93daf7fb8af28f0d45bf110a8023 100644
--- a/languages/ca.ini
+++ b/languages/ca.ini
@@ -18,7 +18,7 @@ Access URL = "URL d'accés"
 access_denied = "Accés no autoritzat."
 Accession Number = "Número de registre"
 Account = "Compte"
-Add = "Afegir"
+account_block_options_missing = "Algunes opcions s'han eliminat a causa d'un bloqueig del compte. Detalls:: %%details%%"
 Add a Library Card = "Afegir un nou carnet"
 Add a Note = "Afegir una nota"
 Add Tag = "Afegir etiqueta"
@@ -30,8 +30,6 @@ Add your comment = "Afegir el teu comentari"
 add_comment_fail_blank = "No ha afegit cap comentari."
 add_comment_success = "Comentari afegit."
 add_favorite_fail = "Error: Registre no guardat"
-add_favorite_prefix = "Afegir"
-add_favorite_suffix = "a favorits"
 add_list_fail = "Error: Llista no creada"
 add_other_libraries = "Inclou articles a altres biblioteques"
 add_search = "Afegir camp de cerca"
@@ -39,6 +37,7 @@ add_search_group = "Afegir grup de cerca"
 add_tag_error = "Error: no es poden guardar les etiquetes"
 add_tag_note = "Els espais separen etiquetes. Utilitzeu cometes per etiquetes de diverses paraules."
 add_tag_success = "Etiquetes guardades"
+add_to_favorites_html = "Afegir <em>%%title%%</em> a favorits"
 Address = "Adressa"
 adv_search_all = "Tots els camps"
 adv_search_author = "Autor"
@@ -184,6 +183,10 @@ Catalog Results = "Resultats al catàleg"
 catalog_login_desc = "Enter your library catalog credentials."
 CD = "CD"
 Change Password = "Canviar contrasenya"
+channel_add_more = "Afegeix més canals com aquest"
+channel_expand = "Explora canals relacionats"
+channel_explore = "Explora canals"
+channel_search = "Mostrar elements com a resultats de cerca"
 Check Hold = "Comprovar fons"
 Check Recall = "Comprovar recordatoris"
 Checked Out = "Retirat"
@@ -234,7 +237,6 @@ confirm_ill_request_cancel_selected_text = "Vols cancelar la selecció de petiti
 confirm_new_password = "Confirma "la nova contrasenya"
 confirm_storage_retrieval_request_cancel_all_text = "Vols cancelar les teves peticions?"
 confirm_storage_retrieval_request_cancel_selected_text = "Vols canceler la teva selecció de peticions?"
-conjunction_or = "O"
 Contents = "Continguts"
 Contributing Source = "Contributing Source"
 Contributors = "Col·laboradors"
@@ -284,6 +286,8 @@ Displaying the top = "Visualitzant la part superior"
 Document Inspector = "Document Inspector"
 Document Type = "Tipus de document"
 DOI = "DOI"
+doi_detected_html = "La vostra cerca sembla que conté un DOI. Feu clic aquí per consultar la disponibilitat del recurs: <a href="%%url%%">%%doi%%</a>"
+Draw Search Box = "Dibuixar quadre de cerca"
 Due = "Venciment"
 Due Date = "Data de venciment"
 DVD = "DVD"
@@ -356,6 +360,10 @@ export_selected = "Exportar seleccionats"
 export_selected_favorites = "Exportar favorits seleccionats"
 export_success = "Exportació completada"
 export_unsupported_format = "Format d’exportació no suportat"
+external_auth_heading = "Dibuixar quadre de cerca"
+external_auth_login_message = "Accedir per accedir a material amb llicència"
+external_auth_unauthorized = "No tens autorització per accedir a material amb llicència"
+external_auth_unauthorized_desc = "El vostre mètode d'inici de sessió no proporciona accés a material amb llicència. Tanqueu la sessió i, a continuació, inicieu sessió mitjançant un altre mètode."
 FAQs = "FAQs"
 fav_delete = "Eliminar favorits seleccionats"
 fav_delete_deleting = "El(s) vostre(s) favorit(s) s’està(-an) eliminant."
@@ -393,7 +401,6 @@ for search = "per cerca"
 Forgot Password = "S'ha oblidat la contrasenya?"
 Form Submitted! = "Formulari enviat!"
 Format = "Format"
-found = "trobat"
 From = "Des de"
 Full description = "Descripció completa"
 Full text is not displayed to guests = "Text complet no disponible per a convidats."
@@ -445,7 +452,7 @@ hold_cancel_all = "Cancel·lar totes les reserves"
 hold_cancel_fail = "La petició no es pot cancel·lar. Si us plau, contacteu amb el taulell de préstec."
 hold_cancel_selected = "Cancel·lar reserves seleccionades"
 hold_cancel_success = "La vostra petició s’ha cancel·lat correctament"
-hold_cancel_success_items = "petició(ns) s’han cancel·lat correctament"
+hold_cancel_success_items = "%%count%% petició(ns) s’han cancel·lat correctament"
 hold_date_invalid = "Introduïu una data vàlida"
 hold_date_past = "Introduïu una data futura"
 hold_empty_selection = "No hi ha reserves seleccionades"
@@ -453,19 +460,21 @@ hold_error_blocked = "NO teniu permisos suficients per fer una reserva d’aques
 hold_error_fail = "Ha fallat la vostra petició. Contacteu amb el taulell de préstec per sol·licitar ajuda"
 hold_invalid_pickup = "Heu introduït una localització de recollida no vàlida. Torneu-ho a intentar"
 hold_invalid_request_group = "La petició de reserva no es vàlida. S"i us plau torni a provar-ho"
-hold_login = "informació per reserva"
+hold_items_available = "No es pot col·locar perquè els elements estan disponibles."
+hold_login = "Iniciar sessió informació per reserva"
 hold_place = "Solicitar lloc"
 hold_place_fail_missing = "Ha fallat la vostra petició. Algunes dades s’han perdut. Contacteu amb el taulell de circulació per sol·licitar ajuda."
 hold_place_success_html = "Petició correcta. <a href="%%url%%">Reserves</a>."
 hold_profile_html = "Per accedir a informació dels fons en temps real, si us plau configureu el seur <a href="%%url%%">Perfil del Catàleg de la Biblioteca</a>."
 hold_queue_position = "Posició a la cua"
+hold_record_already_on_loan = "Ja teniu el registre a préstec"
 hold_request_group = "Demanar a"
 hold_requested_group = "Demanat desde"
 hold_required_by = "No sol·licitat més enllà de"
 hold_success = "Petició correcta"
 Holdings = "Fons"
 Holdings at Other Libraries = "Fons a altres biblioteques"
-Holdings details from = "Detall dels fons de"
+holdings_details_from = "Detall dels fons de %%location%%"
 Holdings_notes = "Notes"
 Holds = "Reserves"
 Holds and Recalls = "Reserves i reclamacions"
@@ -479,7 +488,7 @@ ill_request_cancel_all = "Cancelar totes les peticions de prèstec interbibliote
 ill_request_cancel_fail = "La petició no es pot cancel·lar. Si us plau, contacteu amb el taulell de préstec."
 ill_request_cancel_selected = "Cancelar les peticions seleccionades de prèstec interbibliotecari"
 ill_request_cancel_success = "La vostra petició s’ha cancel·lat correctament"
-ill_request_cancel_success_items = "petició(ns) s’han cancel·lat correctament"
+ill_request_cancel_success_items = "%%count%% petició(ns) s’han cancel·lat correctament"
 ill_request_canceled = "Cancelat"
 ill_request_check_text = "Comprovar les peticions de prèstec interbibliotecari"
 ill_request_comments = "Observacions"
@@ -508,7 +517,6 @@ ils_offline_login_message = "El seu compte i la informació dels exemplars no es
 ils_offline_status = "El catàleg està fora de servei temporalment per tasques de manteniment"
 ils_offline_title = "Sistema fora de servei per tasques de manteniment"
 Import Record = "Importar registre"
-Import to = "Importar a "
 in = "a"
 In This Collection = "En aquesta col·lecció"
 in_collection_label = "En la col·lecció:"
@@ -536,8 +544,8 @@ Item removed from favorites = "Exemplars esborrats de favorits"
 Item removed from list = "Exemplar esborrat de la llista"
 Items = "Exemplars"
 items = "ítems"
-items_added_to_bookbag = "ítem(s) afegit a la cistella de llibres"
-items_already_in_bookbag = "ítem(s) ja estan a la vostra cistella de llibres o no es poden afegir"
+items_added_to_bookbag = "%%count%% ítem(s) afegit a la cistella de llibres"
+items_already_in_bookbag = "%%count%% ítem(s) ja estan a la vostra cistella de llibres o no es poden afegir"
 Journal = "Revista"
 Journal Articles = "Articles de revista"
 Journal Info = "Informació de la publicació"
@@ -654,12 +662,11 @@ nohit_active_filters = "Una o más facetas s’han aplicar a apuesta cerca. Si e
 nohit_change_tab = "Has estar cercana a "%%activeTab%%". Jauría de cerca en altera pestañees per obtener más resultaste:"
 nohit_filters = "Filtres aplicats a aquesta cerca:"
 nohit_heading = "Sense resultats!"
+nohit_lookfor_html = "La vostra cerca - <strong>%%lookfor%%</strong> - no coincideix cap recurs."
 nohit_no_filters = "No s’han aplicat filtres a aquesta cerca."
 nohit_parse_error = "Sembla haver-hi un problema amb la petició de cerca. Comproveu la sintaxi. Si no voleu utilitzar funcions avançades, posar la cerca entre cometes podria ajudar-vos."
-nohit_prefix = "La vostra cerca"
 nohit_query_without_filters = "Treure toas les filtres de la cerca."
 nohit_spelling = "Potser podríeu intentar variants ortogràfiques"
-nohit_suffix = "no coincideix cap recurs."
 nohit_suggest = "Podríeu intentar revisar l’ecuació de cerca eliminant algunes paraules o comprovant la ortografia"
 NOT = "NOT"
 Not Illustrated = "Sense il·lustracions"
@@ -701,7 +708,7 @@ number_decimal_point = "."
 number_thousands_separator = ","
 OAI Server = "Servidor OAI"
 Occupation = "Ocupació"
-of = "de"
+of_num_results = "#%%position%% de %%total%% resultats"
 old_password = "Constrasenya antiga"
 On Reserve = "Reservat"
 On Reserve - Ask at Circulation Desk = "Reservat - Pregunteu al taulell de circulació"
@@ -709,6 +716,7 @@ on_reserve = "Reserves - Pregunteu a préstec"
 on_topic = "%%count%% item(s) d'aquesta matèria"
 Online Access = "Accés en línia"
 online_resources = "Text complete"
+open_access_limit = "Limitar el contingut d'accés obert"
 operator_contains = "conté"
 operator_exact = "es (exacte)"
 OR = "OR"
@@ -747,8 +755,6 @@ Please check back soon = "Si us plau, retorneu aviat el préstec"
 Please contact the Library Reference Department for assistance = "Si us plau, per rebre ajuda contacteu amb el Departament de Referència de la Biblioteca"
 Please enable JavaScript. = "Si us plau activa el JavaScript."
 Please upgrade your browser. = "Si us plau actualitza el teu navegador."
-Posted by = "Publicat per"
-posted_on = "a"
 Preferences = "Preferències"
 Preferred Library = "Biblioteca de referència"
 Prev = "Prev"
@@ -833,6 +839,7 @@ Requests = "Peticions"
 Reserves = "Reserves"
 Reserves Search = "Cerca de reserves"
 Reserves Search Results = "Resultats de la cerca de reserves"
+result_count = "%%count%% results"
 Results = "Resultats"
 results = "resultats"
 Results for = "Resultats per"
@@ -883,7 +890,12 @@ Sensor Image = "Imatge del sensor"
 Serial = "Publicació Periòdica"
 Series = "Periòdiques"
 Set = "Conjunt"
-Showing = "Mostrar"
+showing_items_html = "Mostrar <strong>%%start%% - %%end%%</strong> Exemplars"
+showing_items_of_html = "Mostrar <strong>%%start%% - %%end%%</strong> de <strong>%%total%%</strong> Exemplars"
+showing_results_for_html = "Mostrar <strong>%%start%% - %%end%%</strong> resultats per cerca '<strong>%%lookfor%%</strong>'"
+showing_results_html = "Mostrar <strong>%%start%% - %%end%%</strong> resultats"
+showing_results_of_for_html = "Mostrar <strong>%%start%% - %%end%%</strong> resultats de <strong>%%total%%</strong> per cerca '<strong>%%lookfor%%</strong>'"
+showing_results_of_html = "Mostrar <strong>%%start%% - %%end%%</strong> resultats de <strong>%%total%%</strong>"
 sidebar_close = "Amagar lateral"
 sidebar_expand = "Expanish literal"
 Similar Items = "Ítems similars"
@@ -927,7 +939,7 @@ storage_retrieval_request_cancel_all = "Cancelar totes les peticions al magatzem
 storage_retrieval_request_cancel_fail = "La petició no es pot cancel·lar. Si us plau, contacteu amb el taulell de préstec."
 storage_retrieval_request_cancel_selected = "Cancelar les peticions seleccionades al magatzem"
 storage_retrieval_request_cancel_success = "La vostra petició s’ha cancel·lat correctament"
-storage_retrieval_request_cancel_success_items = "petició(ns) s’han cancel·lat correctament"
+storage_retrieval_request_cancel_success_items = "%%count%% petició(ns) s’han cancel·lat correctament"
 storage_retrieval_request_canceled = "Cancelat"
 storage_retrieval_request_check_text = "Comprovar peticions al magatzem"
 storage_retrieval_request_comments = "Comentaris"
@@ -965,7 +977,7 @@ Summon Results = "Resultats a Summon"
 summon_database_recommendations = "Podríeu trobar més recursos aquí:"
 Supplements = "Suplements"
 Supplied by Amazon = "Proporcionat per Amazon"
-Switch view to = "Canviar visualització a"
+switch_view = "Canviar visualització a %%view%%"
 switchquery_fuzzy = "Executant una cerca difusa por obtener resultaste amo pararles similares"
 switchquery_intro = "Pot obtenir més resultats si ajusta la seva cerca."
 switchquery_lowercasebools = "Si vols fer servir operadors booleans, han d'estar en majúscules"
@@ -1007,8 +1019,7 @@ Too Many Email Recipients = "Massa destinataris de correus-e"
 too_many_favorites = "Aquesta llista és massa llarga per visualitzar-la de cop. Intenteu reconfigurar els favorits en més llistes o limitar l’ús d’etiquetes."
 too_many_new_items = "Hi ha massa ítems nous per visualitzar-los en una única llista. Intenteu limitar la cerca."
 too_many_reserves = "Hi ha massa bibliografia recomanada per visualitzar-la en una única llista. Intenteu limitar la cerca."
-top_facet_additional_prefix = "Adicional "
-top_facet_suffix = "... dins de la cerca"
+top_facet_label = "%%label%% dins de la cerca"
 Topic = "Tema"
 Topics = "Temes"
 Total Balance Due = "Total pendent"
@@ -1037,7 +1048,6 @@ VHS = "VHS"
 Video = "Video"
 Video Clips = "Video Clips"
 Videos = "Videos"
-view already selected = "veure ja seleccionats"
 View Book Bag = "Veure la cistella de llibres"
 View Full Collection = "Veure col·leccio completa"
 View Full Record = "Veure Registre complet"
@@ -1046,6 +1056,7 @@ View online: Full view Book Preview from the Hathi Trust = "Veure en línia: Pre
 View Record = "Veure Registre"
 View Records = "Veure la cistella de registres"
 View this record in EBSCOhost = "Veure aquest registre a EBSCOhost"
+view_already_selected = "%%current%% veure ja seleccionats"
 visual_facet_parent = "Des de"
 Volume = "Volum"
 Volume Holdings = "Fons del volum"
diff --git a/languages/cs.ini b/languages/cs.ini
index b125da83c07d4623c5ab08dfef2707eac33a0d7c..464eaba001cc00486d4acd00dd8de4b2f6a0adaf 100644
--- a/languages/cs.ini
+++ b/languages/cs.ini
@@ -5,7 +5,7 @@ Access URL = "Přístupová URL adresa"
 access_denied = "Přístup odepřen."
 Accession Number = "Přístupové číslo"
 Account = "Účet"
-Add = "Přidat"
+account_block_options_missing = "Některé možnosti ovládání čtenářského konta byly omezeny, protože je vaše konto zablokováno: %%details%%"
 Add a Library Card = "Připojit další účet"
 Add a Note = "Přidat poznámku"
 Add Tag = "Přidat tag"
@@ -17,8 +17,6 @@ Add your comment = "Přidat komentář"
 add_comment_fail_blank = "Komentář musí obsahovat text."
 add_comment_success = "Komentář vložen."
 add_favorite_fail = "Chyba: záznam nebyl uložen"
-add_favorite_prefix = "Přidat"
-add_favorite_suffix = "do oblíbených"
 add_list_fail = "Chyba: seznam nebyl vytvořen"
 add_other_libraries = "Včetně článků z jiných knihoven"
 add_search = "Přidat vyhledávací pole"
@@ -26,6 +24,7 @@ add_search_group = "Přidat vyhledávací skupinu"
 add_tag_error = "Při tagování došlo k chybě"
 add_tag_note = "Tagy oddělte mezerami. Víceslovné tagy uzavřete do uvozovek."
 add_tag_success = "Tagy byly úspěšně uloženy"
+add_to_favorites_html = "Přidat <em>%%title%%</em> do oblíbených"
 Address = "Adresa"
 adv_search_all = "VÅ¡echna pole"
 adv_search_author = "Autor"
@@ -171,6 +170,10 @@ Catalog Results = "Výsledky z katalogu"
 catalog_login_desc = "Vložte přístupové údaje do katalogu knihovny."
 CD = "CD"
 Change Password = "Změnit heslo"
+channel_add_more = "Přidat další podobné pohledy"
+channel_expand = "Zobrazit související pohledy"
+channel_explore = "Grafické procházení katalogu"
+channel_search = "Zobrazit jako výsledek vyhledávání"
 Check Hold = "Zjistit stav rezervací"
 Check Recall = "Zjistit stav objednávek"
 Checked Out = "Vypůjčeno"
@@ -221,7 +224,6 @@ confirm_ill_request_cancel_selected_text = "Opravdu chcete zrušit vybrané pož
 confirm_new_password = "Nové heslo (pro potvrzení)"
 confirm_storage_retrieval_request_cancel_all_text = "Opravdu chcete zrušit všechny požadavky na dokumenty ze skladu?"
 confirm_storage_retrieval_request_cancel_selected_text = "Opravdu chcete zrušit vybrané požadavky na dokumenty ze skladu?"
-conjunction_or = "nebo"
 Contents = "Obsah"
 Contributing Source = "Přispívající zdroj"
 Contributors = "Přispěvatelé"
@@ -271,6 +273,7 @@ Displaying the top = "Zobrazuji nejrelevantnější výsledky"
 Document Inspector = "Inspekce dokumentu"
 Document Type = "Druh dokumentu"
 DOI = "DOI"
+doi_detected_html = "Zdá se, že Váš vyhledávací dotaz obsahuje DOI. Pokud chcete ověřit dostupnost odpovídajícího digitálního dokumentu, klikněte zde: <a href="%%url%%">%%doi%%</a>"
 Draw Search Box = "Zobrazit vyhledávací pole"
 Due = "do"
 Due Date = "Půjčeno do"
@@ -344,6 +347,10 @@ export_selected = "Exportovat vybrané"
 export_selected_favorites = "Exportovat vybrané oblíbené položky"
 export_success = "Export byl úspěšný"
 export_unsupported_format = "Nepodporovaný exportní formát."
+external_auth_heading = "Přístup k licencovaným zdrojům"
+external_auth_login_message = "Pro přístup k licencovaným zdrojům se přihlaste"
+external_auth_unauthorized = "Nemáte oprávnění pro přístup k licencovaným zdrojům"
+external_auth_unauthorized_desc = "Tento způsob přihlášneí nelze využít k ověření přístupu k licencovaným zdrojům. Odhlašte se a použijte jiný způsob přihlášení."
 FAQs = "Často kladené otázky"
 fav_delete = "Smazat vybrané oblíbené položky"
 fav_delete_deleting = "Vaše oblíbené budou smazány."
@@ -369,7 +376,7 @@ filter_tags = "Filtrovat tagy"
 filter_wildcard = "Libovolný"
 Find = "Hledat"
 Find More = "Objevte více"
-Find New Items = "Najít nové jednotky"
+Find New Items = "Vyhledávat v nových titulech"
 Finding Aid = "Pomůcka pro vyhledávání"
 Fine = "Upomínka"
 fine_limit_patron = "Dosáhli jste Vašeho limitu upomínek, vaše výpůjčky proto nelze prodloužit."
@@ -381,7 +388,6 @@ for search = "pro vyhledávání"
 Forgot Password = "Zapomenuté heslo"
 Form Submitted! = "Formulář byl odeslán!"
 Format = "Médium"
-found = "nalezeno"
 From = "Od"
 Full description = "Celý popis"
 Full text is not displayed to guests = "Nepřihlášeným uživatelům se plný text nezobrazuje"
@@ -428,32 +434,34 @@ history_saved_searches = "Uložená vyhledávání"
 history_search = "Vyhledávací dotaz"
 history_time = "Datum a čas"
 hold_available = "Připraveno k vyzvednutí"
-hold_cancel = "Smazat požadavek"
-hold_cancel_all = "Smazat všechny požadavky"
-hold_cancel_fail = "Váš požadavek nebyl smazán. Kontaktujte obsluhu pro další informace."
-hold_cancel_selected = "Smazat vybrané požadavky."
-hold_cancel_success = "Váš požadavek byl úspěšně smazán."
-hold_cancel_success_items = "požadavků bylo smazáno"
+hold_cancel = "Zrušit požadavek"
+hold_cancel_all = "Zrušit všechny požadavky"
+hold_cancel_fail = "Váš požadavek se nepodařilo zrušit. Kontaktujte pracovníky knihovny pro další informace."
+hold_cancel_selected = "Zrušit vybrané požadavky."
+hold_cancel_success = "Váš požadavek byl úspěšně zrušen."
+hold_cancel_success_items = "Bylo zrušeno %%count%% požadavků"
 hold_date_invalid = "Zadejte platné datum"
 hold_date_past = "Zadejte datum v budoucnosti"
 hold_empty_selection = "Nebyly vybrány žádné požadavky"
-hold_error_blocked = "Nemáte dostatečná práva k zadání požadavku na tento exemplář."
-hold_error_fail = "Váš požadavek selhal. Kontaktujte obsluhu pro další informace."
-hold_invalid_pickup = "Neplatné místo vyzvednutí. Zkuste to znova."
+hold_error_blocked = "Nemáte dostatečné oprávnění k zadání požadavku na tento dokument."
+hold_error_fail = "Váš požadavek selhal. Kontaktujte pracovníky knihovny pro další informace."
+hold_invalid_pickup = "Neplatné místo vyzvednutí. Zkuste to znovu."
 hold_invalid_request_group = "Byla vybrána neplatná skupina požadavků. Zkuste to znovu, prosím"
-hold_login = "Přihlaste se"
+hold_items_available = "Nelze vytvořit požadavek na dokument, který je k dispozici."
+hold_login = "Přihláste se"
 hold_place = "Zadat požadavek"
-hold_place_fail_missing = "Váš požadavek selhal. Chybí některé údaje. Kontaktujte obsluhu pro další informace."
+hold_place_fail_missing = "Váš požadavek selhal. Chybí některé údaje. Kontaktujte pracovníky knihovny pro další informace."
 hold_place_success_html = "Váš požadavek byl úspěšně vložen. <a href="%%url%%">Vaše rezervace a objednávky</a>."
 hold_profile_html = "Pro informace o rezervacích a objednávkách musíte mít vytvořený <a href="%%url%%">účet v katalogu</a>."
 hold_queue_position = "Vaše pořadí ve frontě"
+hold_record_already_on_loan = "Tento dokument již máte rezervován."
 hold_request_group = "Požadavek z"
 hold_requested_group = "Požadováno z"
 hold_required_by = "Požadováno do"
 hold_success = "Váš požadavek byl úspěšný"
 Holdings = "Jednotky"
 Holdings at Other Libraries = "Exampláře v jiných knihovnách"
-Holdings details from = "Informace o exemplářích z"
+holdings_details_from = "Informace o exemplářích z: %%location%%"
 Holdings_notes = "Poznámky"
 Holds = "Výpůjčky"
 Holds and Recalls = "Rezervace a objednávky"
@@ -464,10 +472,10 @@ Identifier = "Identifikátor"
 ill_request_available = "Připraveno k vyzvednutí"
 ill_request_cancel = "Zrušit požadavek na meziknihovní výpůjčku"
 ill_request_cancel_all = "Zrušit všechny požadavky na meziknihovní výpůjčky"
-ill_request_cancel_fail = "Váš požadavek nebyl smazán. Kontaktujte obsluhu pro další informace."
+ill_request_cancel_fail = "Váš požadavek se nepodařilo zrušit . Kontaktujte pracovníky knihovny pro další informace."
 ill_request_cancel_selected = "Zrušit vybrané požadavky na meziknihovní výpůjčky"
-ill_request_cancel_success = "Váš požadavek byl úspěšně smazán."
-ill_request_cancel_success_items = "požadavků bylo smazáno"
+ill_request_cancel_success = "Váš požadavek byl úspěšně zrušen."
+ill_request_cancel_success_items = "Bylo zrušeno %%count%% požadavků"
 ill_request_canceled = "Zrušeno"
 ill_request_check_text = "Ověření požadavku na meziknihovní výpůjčku"
 ill_request_comments = "Poznámky"
@@ -475,13 +483,13 @@ ill_request_date_invalid = "Zadejte platné datum"
 ill_request_date_past = "Zadejte datum v budoucnosti"
 ill_request_empty_selection = "Nebyly vybrány žádné požadavky"
 ill_request_error_blocked = "Nemáte oprávnění pro vytvoření požadavku na meziknihovní výpůjčku tohoto dokumentu"
-ill_request_error_fail = "Váš požadavek selhal. Kontaktujte obsluhu pro další informace."
+ill_request_error_fail = "Váš požadavek selhal. Kontaktujte pracovníky knihovny pro další informace."
 ill_request_error_technical = "Vytvoření požadavku z technických důvodů selhalo. Prosím, kontaktujte knihovnu."
 ill_request_error_unknown_patron_source = "Při zpracování požadavku se nepodařilo identifikovat domovskou knihovnu čtenáře."
-ill_request_invalid_pickup = "Neplatné místo vyzvednutí. Zkuste to znova."
+ill_request_invalid_pickup = "Neplatné místo vyzvednutí. Zkuste to znovu."
 ill_request_pick_up_library = "Vyzvednout v knihovnÄ›"
 ill_request_pick_up_location = "Vyzvednout na oddělení"
-ill_request_place_fail_missing = "Váš požadavek selhal. Chybí některé údaje. Kontaktujte obsluhu pro další informace."
+ill_request_place_fail_missing = "Váš požadavek selhal. Chybí některé údaje. Kontaktujte pracovníky knihovny pro další informace."
 ill_request_place_success = "Váš požadavek byl úspěšně vložen."
 ill_request_place_success_html = "Váš požadavek byl úspěšně vložen. <a href="%%url%%">Požadavky na meziknihovní výpůjčky</a>."
 ill_request_place_text = "Objednat MVS"
@@ -496,7 +504,6 @@ ils_offline_login_message = "V současné době nelze zobrazit údaje z Vašeho
 ils_offline_status = "Právě probíhá údržba knihovního systému."
 ils_offline_title = "Právě probíhá údržba systému"
 Import Record = "Importovat záznam"
-Import to = "Importovat do"
 in = "v poli"
 In This Collection = "Zúžit v rámci této sbírky"
 in_collection_label = "Sbírka:"
@@ -524,11 +531,11 @@ Item removed from favorites = "Jednotka byla odstraněna z oblíbených"
 Item removed from list = "Jednotka byla odstraněna ze seznamu"
 Items = "Jednotky"
 items = "položek"
-items_added_to_bookbag = "položek vloženo do košíku"
-items_already_in_bookbag = "položka(y) již máte v košíku nebo je nelze z nějakého jiného důvodu vložit."
+items_added_to_bookbag = "Do košíku bylo vloženo %%count%% položek"
+items_already_in_bookbag = "%%count%% položek již máte v košíku nebo je nelze z nějakého jiného důvodu vložit."
 Journal = "ÄŒasopis"
 Journal Articles = "Články z časopisů"
-Journal Info = "Info o časopise"
+Journal Info = "Informace o časopise"
 Journal Title = "Název časopisu"
 Journals = "ÄŒasopisy"
 Jump to = "Přejít na"
@@ -618,11 +625,11 @@ My Profile = "Profil"
 Narrow Search = "Upřesnit hledání"
 navigate_back = "Zpět"
 Need Help? = "Hledáte pomoc?"
-New Item Feed = "Nové knihy"
-New Item Search = "Hledání v nových knihách"
-New Item Search Results = "Výsledky vyhledávání v nových knihách"
-New Items = "Nové položky"
-New Title = "Nové název"
+New Item Feed = "Nové tituly v katalogu"
+New Item Search = "Hledání v novinkách"
+New Item Search Results = "Výsledky vyhledávání v novinkách"
+New Items = "Nové tituly v katalogu"
+New Title = "Nový název"
 new_password = "Nové heslo"
 new_password_success = "Vaše heslo bylo úspěšně změněno"
 Newspaper = "Noviny"
@@ -642,12 +649,11 @@ nohit_active_filters = "Použili jste funkci upřesnění výsledků. Pokud tato
 nohit_change_tab = "Hledali jste v sekci "%%activeTab%%". Zkuste také další sekce, třeba budete úspěšní tam:"
 nohit_filters = "Filtry použité pro toto hledání:"
 nohit_heading = "Žádné výsledky!"
-nohit_no_filters = "Žádné filtry nejsou použité pro toto hledání."
+nohit_lookfor_html = "Pro váš dotaz - <strong>%%lookfor%%</strong> - nebyl nalezen žádný výsledek."
+nohit_no_filters = "Pro toto hledání nebyly použity žádné filtry."
 nohit_parse_error = "Vypadá to, že je nějaký problém s vaším vyhledávacím dotazem. Zkuste zkontrolovat, je-li zapsán správně, nebo uzavřete hledaný výraz do uvozovek."
-nohit_prefix = "Vaše hledání"
 nohit_query_without_filters = "Odstranit všechna upřesnění výsledků."
 nohit_spelling = "Můžete zkusit použít některé podobné tvary:"
-nohit_suffix = "nebyl nalezen žádný výskyt."
 nohit_suggest = "Můžete se pokusit upravit váš vyhledávací dotaz vynecháním některých slov. Zkontrolujte také zda-li jste nenapsali nějaký překlep."
 NOT = "NOT"
 Not Illustrated = "Bez ilustrací"
@@ -689,7 +695,7 @@ number_decimal_point = ","
 number_thousands_separator = " "
 OAI Server = "OAI Server"
 Occupation = "Povolání"
-of = "z"
+of_num_results = "č. %%position%% z %%total%% výsledků"
 old_password = "Staré heslo"
 On Reserve = "Rezervováno"
 On Reserve - Ask at Circulation Desk = "Rezervováno. Bližší informace získáte u knihovníka."
@@ -697,6 +703,7 @@ on_reserve = "Rezervováno"
 on_topic = "%%count%% záznamů k tomuto tématu"
 Online Access = "On-line přístup"
 online_resources = "Plný text"
+open_access_limit = "Omezit na obsah dostupný jako Open Access"
 operator_contains = "obsahuje"
 operator_exact = "rovná se"
 OR = "OR"
@@ -718,7 +725,7 @@ password_minimum_length = "Heslo musí být dlouhé alespoň %%minlength%% znak
 password_only_alphanumeric = "Pouze čísla a písmena A-Z"
 password_only_numeric = "Pouze čísla"
 Passwords do not match = "Hesla se neshodují"
-Past = "Minulost"
+Past = "Za posledních"
 PDF Full Text = "Plný text ve formátu PDF"
 peer_reviewed = "Recenzováno"
 peer_reviewed_limit = "Omezit na články z recenzovaných časopisů"
@@ -735,8 +742,6 @@ Please check back soon = "Prosím, zkuste to znovu později"
 Please contact the Library Reference Department for assistance = "Pro pomoc se obraťte na pracovníky knihovny:"
 Please enable JavaScript. = "Pro správnou funkci je třeba mít zapnutý JavaScript."
 Please upgrade your browser. = "Prosím, aktualizujte svůj prohlížeč."
-Posted by = "Od"
-posted_on = "dne"
 Preferences = "Nastavení"
 Preferred Library = "Preferovaná knihovna"
 Prev = "Předchozí"
@@ -769,7 +774,7 @@ qrcode_hide = "Skrýt QR kód"
 qrcode_show = "Zobrazit QR kód"
 query time = "doba hledání"
 random_recommendation_title = "Náhodné výsledky"
-Range = "Rozmezí"
+Range = "Přidané v období"
 Range slider = "Výběr rozsahu"
 Read the full review online... = "Přečíst celou recenzi online..."
 Recall This = "Rezervovat"
@@ -872,7 +877,12 @@ Sensor Image = "Sensor Image"
 Serial = "Seriál"
 Series = "Edice"
 Set = "Nastavit"
-Showing = "Zobrazuji"
+showing_items_html = "Zobrazuji položky <strong>%%start%% - %%end%%</strong>"
+showing_items_of_html = "Zobrazuji položky <strong>%%start%% - %%end%%</strong> z <strong>%%total%%</strong>"
+showing_results_for_html = "Zobrazuji výsledky <strong>%%start%% - %%end%%</strong> pro vyhledávání '<strong>%%lookfor%%</strong>'"
+showing_results_html = "Zobrazuji výsledky <strong>%%start%% - %%end%%</strong>"
+showing_results_of_for_html = "Zobrazuji výsledky <strong>%%start%% - %%end%%</strong> z <strong>%%total%%</strong> pro vyhledávání '<strong>%%lookfor%%</strong>'"
+showing_results_of_html = "Zobrazuji výsledky <strong>%%start%% - %%end%%</strong> z <strong>%%total%%</strong>"
 sidebar_close = "Skrýt možnosti"
 sidebar_expand = "Zobrazit možnosti"
 Similar Items = "Podobné jednotky"
@@ -913,10 +923,10 @@ Storage Retrieval Requests = "Požadavky na vyzvednutí ze skladu"
 storage_retrieval_request_available = "Připraveno k vyzvednutí"
 storage_retrieval_request_cancel = "Zrušit požadavek na vyzvednutí ze skladu"
 storage_retrieval_request_cancel_all = "Zrušit všechny požadavky na vyzvednutí ze skladu"
-storage_retrieval_request_cancel_fail = "Váš požadavek nebyl smazán. Kontaktujte obsluhu pro další informace."
+storage_retrieval_request_cancel_fail = "Váš požadavek se nepodařilo zrušit. Kontaktujte pracovníky knihovny pro další informace."
 storage_retrieval_request_cancel_selected = "Zrušit vybrané požadavky na vyzvednutí ze skladu"
-storage_retrieval_request_cancel_success = "Váš požadavek byl úspěšně smazán."
-storage_retrieval_request_cancel_success_items = "požadavků bylo smazáno"
+storage_retrieval_request_cancel_success = "Váš požadavek byl úspěšně zrušen."
+storage_retrieval_request_cancel_success_items = "Bylo zrušeno %%count%% požadavků"
 storage_retrieval_request_canceled = "Zrušeno"
 storage_retrieval_request_check_text = "Ověřit požadavek na vyzvednutí ze skladu"
 storage_retrieval_request_comments = "Komentáře"
@@ -924,10 +934,10 @@ storage_retrieval_request_date_invalid = "Zadejte platné datum"
 storage_retrieval_request_date_past = "Zadejte datum v budoucnosti"
 storage_retrieval_request_empty_selection = "Nebyly vybrány žádné požadavky"
 storage_retrieval_request_error_blocked = "Nemáte nastavena dostatečná oprávnění pro zadání požadavku na vyzvednutí dokumentu ze skladu."
-storage_retrieval_request_error_fail = "Váš požadavek selhal. Kontaktujte obsluhu pro další informace."
-storage_retrieval_request_invalid_pickup = "Neplatné místo vyzvednutí. Zkuste to znova."
+storage_retrieval_request_error_fail = "Váš požadavek selhal. Kontaktujte pracovníky knihovny pro další informace."
+storage_retrieval_request_invalid_pickup = "Neplatné místo vyzvednutí. Zkuste to znovu."
 storage_retrieval_request_issue = "Datum"
-storage_retrieval_request_place_fail_missing = "Váš požadavek selhal. Chybí některé údaje. Kontaktujte obsluhu pro další informace."
+storage_retrieval_request_place_fail_missing = "Váš požadavek selhal. Chybí některé údaje. Kontaktujte pracovníky knihovny pro další informace."
 storage_retrieval_request_place_success = "Váš požadavek byl úspěšný"
 storage_retrieval_request_place_success_html = "Váš požadavek byl úspěšně vložen. <a href="%%url%%">Požadavky na vyzvednutí ze skladu</a>."
 storage_retrieval_request_place_text = "Zadat požadavek na vyzvednutí ze skladu"
@@ -954,7 +964,7 @@ Summon Results = "Výsledky hledání v systému Summon"
 summon_database_recommendations = "Další zdroje můžete nalézt zde:"
 Supplements = "Přílohy"
 Supplied by Amazon = "Získáno z Amazon.com"
-Switch view to = "Přepnout na"
+switch_view = "Přepnout na %%view%%"
 switchquery_fuzzy = "Vyhledávání s použitím zástupných znaků ('*', '?') může vrátit více výsledků (fuzzy vyhledávání)."
 switchquery_intro = "Více výsledků můžete získat úpravou Vašeho dotazu."
 switchquery_lowercasebools = "Boolovské operátory je třeba zapisovat VELKÝMI PÍSMENY"
@@ -996,8 +1006,7 @@ Too Many Email Recipients = "Bylo vloženo příliš mnoho příjemců zprávy"
 too_many_favorites = "Tento seznam obsahuje příliš mnoho položek. Zkuste rozdělit oblíbené položky do více seznamů, případně omezte počet tagů."
 too_many_new_items = "V jednom seznamu nelze zobrazit tolik položek. Zkuste upřesnit parametry vašeho hledání."
 too_many_reserves = "V jednom seznamu nelze zobrazit tolik kurzů. Zkuste upřesnit parametry vašeho hledání."
-top_facet_additional_prefix = "Doplňující "
-top_facet_suffix = " mezi výsledky hledání:"
+top_facet_label = "%%label%% ve výsledcích tohoto hledání:"
 Topic = "Téma"
 Topics = "Témata"
 Total Balance Due = "Celkový stav ke dni"
@@ -1026,7 +1035,6 @@ VHS = "VHS"
 Video = "Video"
 Video Clips = "Video klipy"
 Videos = "Videa"
-view already selected = "tento typ zobrazení je již vybrán"
 View Book Bag = "Prohlédnout obsah košíku"
 View Full Collection = "Zobrazit celou sbírku"
 View Full Record = "Zobrazit úplný záznam"
@@ -1035,6 +1043,7 @@ View online: Full view Book Preview from the Hathi Trust = "Prohlédnout online:
 View Record = "Prohlédnou záznam"
 View Records = "Prohlédnout záznamy"
 View this record in EBSCOhost = "Zobrazit záznam v databázi EBSCOhost"
+view_already_selected = "Typ zobrazení %%current%% je již vybrán"
 visual_facet_parent = "Od"
 Volume = "Část"
 Volume Holdings = "Jednotky"
@@ -1051,7 +1060,7 @@ wiki_link = "Získáno z Wikipedie"
 with filters = "S omezeními"
 with_selected = "Vybrané"
 Year of Publication = "Rok vydání"
-Yesterday = "Včera"
+Yesterday = "Od včerejška"
 You do not have any fines = "Nemáte žádné upomínky"
 You do not have any holds or recalls placed = "Nemáte žádné rezervace ani objednávky"
 You do not have any interlibrary loan requests placed = "Nemáte žádné nevyřízené požadavky na meziknihovní výpůjčky"
diff --git a/languages/cy.ini b/languages/cy.ini
index a2e7b917ffe6111087f5c7136957d26b0a9cf530..1b7addf864cf1a1ef6ea2c1edb0a12d569ef8b55 100644
--- a/languages/cy.ini
+++ b/languages/cy.ini
@@ -7,7 +7,7 @@ Access URL = "URL mynediad"
 access_denied = "Mynediad wedi'i wrthod."
 Accession Number = "Cyfeirnod"
 Account = "Cyfrif"
-Add = "Ychwanegu"
+account_block_options_missing = "Mae rhai o'r dewisiadau wedi'u tynnu'n ôl o ganlyniad i rwystr ar eich cyfrif. Manylion: %%details%%"
 Add a Library Card = "Ychwanegu Cerdyn Llyfrgell"
 Add a Note = "Ychwanegu Nodyn"
 Add Tag = "Ychwanegu Tag"
@@ -19,8 +19,6 @@ Add your comment = "Ychwnegu eich sylwadau"
 add_comment_fail_blank = "Ni chaniateir gadael y sylw'n wag"
 add_comment_success = "Ychwanegwyd Sylw"
 add_favorite_fail = "Gwall: Ni gadwyd y Cyfnod"
-add_favorite_prefix = "Ychwanegu"
-add_favorite_suffix = "at ffefrynnau"
 add_list_fail = "Gwall: Ni grëwyd y rhestr"
 add_other_libraries = "Cynnwys erthyglau mewn llyfrgelloedd eraill"
 add_search = "Ychwanegu Maes Chwilio"
@@ -28,6 +26,7 @@ add_search_group = "Ychwanegu Grŵp Chwilio"
 add_tag_error = "Gwall: Ni Ellir Cadw'r Tagiau"
 add_tag_note = "Bydd bylchau yn gwahanu tagiau. Defnyddiwch ddyfyniadau ar gyfer tagiau aml air"
 add_tag_success = "Tagiau wedi'u cadw"
+add_to_favorites_html = "Ychwanegu <em>%%title%%</em> at ffefrynnau"
 Address = "Cyfeiriad"
 adv_search_all = "Pob Maes"
 adv_search_author = "Awdur"
@@ -173,6 +172,10 @@ Catalog Results = "Canlyniadau Catalog"
 catalog_login_desc = "Rhowch eich manylion catalog llyfrgell."
 CD = "CD"
 Change Password = "Newid Cyfrinair"
+channel_add_more = "Ychwanegwch ragor o sianeli fel hyn"
+channel_expand = "Archwiliwch sianeli cysylltiedig"
+channel_explore = "Archwiliwch Sianeli"
+channel_search = "Dangoswch eitemau fel canlyniadau chwilio"
 Check Hold = "Gwirio os ydyw ar Gadw"
 Check Recall = "Gwirio am Adalw"
 Checked Out = "Ar Fenthyg"
@@ -223,7 +226,6 @@ confirm_ill_request_cancel_selected_text = "Ydych chi'n dymuno canslo'r ceisiada
 confirm_new_password = "Cadarnhau Cyfrinair Newydd"
 confirm_storage_retrieval_request_cancel_all_text = "Ydych chi'n dymuno canslo'ch holl geisiadau cyfredol ar gyfer tynnu eitemau o'r storfa?"
 confirm_storage_retrieval_request_cancel_selected_text = "Ydych chi'n dymuno canslo'r ceisiadau ar gyfer tynnu eitemau o'r storfa sydd wedi'u dewis?"
-conjunction_or = "neu"
 Contents = "Cynnwys"
 Contributing Source = "Ffynhonnell"
 Contributors = "Cyfranwyr"
@@ -273,6 +275,7 @@ Displaying the top = "Arddangos y brig"
 Document Inspector = "Archwilydd Dogfen"
 Document Type = "Math o Ddogfen"
 DOI = "DOI"
+doi_detected_html = "Ymddengys bod eich chwiliad yn cynnwys DOI. Cliciwch yma i weld argaeledd yr adnodd:<a href="%%url%%">%%doi%%</a>"
 Draw Search Box = "Llunio Blwch Chwilio"
 Due = "Erbyn"
 Due Date = "Dyddiad Cau"
@@ -346,6 +349,10 @@ export_selected = "Allfudo'r detholiad"
 export_selected_favorites = "Allfudo Ffefrynnau Dethol"
 export_success = "Allfudo'n Llwyddiannus"
 export_unsupported_format = "Fformat Allfudo na Chefnogwyd"
+external_auth_heading = "Mynediad i ddeunydd trwyddedig"
+external_auth_login_message = "Mewngofnodwch i gael mynediad i ddeunydd trwyddedig"
+external_auth_unauthorized = "Nid ydych wedi'ch awdurdodi i gael mynediad i ddeunydd trwyddedig"
+external_auth_unauthorized_desc = "Nid yw'ch dull mewngofnodi yn rhoi mynediad i ddeunydd trwyddedig. Allgofnodwch yna menwgofnodwch gan ddefnyddio dull arall."
 FAQs = "Cwestiynau Cyffredin"
 fav_delete = "Dileu Ffefrynnau Dethol"
 fav_delete_deleting = "Mae eich ffefryn(nau) yn cael eu dileu."
@@ -383,7 +390,6 @@ for search = "ar gyfer chwilio"
 Forgot Password = "Wedi anghofio'r cyfrinair"
 Form Submitted! = "Ffurflen wedi'i Chyflwyno!"
 Format = "Fformat"
-found = "wedi'i ganfod"
 From = "o"
 Full description = "Disgrifiad llawn"
 Full text is not displayed to guests = "Ni ddangosir y testun llawn i westeion."
@@ -435,7 +441,7 @@ hold_cancel_all = "Canslo'r Holl Ddaliadau"
 hold_cancel_fail = "Ni chanslwyd eich cais. Cysylltwch â'r ddesg fenthyca am gymorth pellach"
 hold_cancel_selected = "Canslo'r Daliadau Dewisol"
 hold_cancel_success = "Canslwyd eich cais yn llwyddiannus"
-hold_cancel_success_items = "Canslwyd y cais/ceisiadau yn llwyddiannus"
+hold_cancel_success_items = "%%count%% Canslwyd y cais/ceisiadau yn llwyddiannus"
 hold_date_invalid = "Rhowch ddyddiad dilys os gwelwch yn dda"
 hold_date_past = "Rhowch ddyddiad yn y dyfodol os gwelwch yn dda"
 hold_empty_selection = "Ni ddewiswyd unrhyw ddaliadau"
@@ -443,19 +449,21 @@ hold_error_blocked = "Nid oes digon o freintiau gennych i osod daliad ar yr eite
 hold_error_fail = "Mae eich cais wedi methu. Cysylltwch â'r ddesg fenthyca am gymorth pellach"
 hold_invalid_pickup = "Rhoddwyd lleoliad casglu annilys. Rhowch gynnig eto"
 hold_invalid_request_group = "Rhoddwyd grŵp cais dal anghywir. Rhowch gynnig eto"
-hold_login = "am wybodaeth ynghylch daliadau ac adalw"
+hold_items_available = "Nid oes modd ei roi ar gadw am fod eitemau ar gael. "
+hold_login = "Mewngofnodi am wybodaeth ynghylch daliadau ac adalw"
 hold_place = "Gosod Cais"
 hold_place_fail_missing = "Mae eich cais wedi methu. Roedd peth data ar goll. Cysylltwch â'r ddesg fenthyca am gymorth pellach"
 hold_place_success_html = "Roedd eich cais yn llwyddiannus. <a href="%%url%%">Daliadau ac Adalwadau</a>."
 hold_profile_html = "Am wybodaeth dal a galw'n ôl, rhaid i chi sefydlu <a href=%%url%%">Proffeil Catalog Llyfrgell</a>.""
 hold_queue_position = "Safle yn y Ciw"
+hold_record_already_on_loan = "Mae'r record eisoes ar fenthyg gennych chi "
 hold_request_group = "Cais oddi wrth"
 hold_requested_group = "Ceisiwyd oddi wrth"
 hold_required_by = "Nid oes angen bellach ar ôl"
 hold_success = " Roedd eich cais yn llwyddiannus"
 Holdings = "Daliadau"
 Holdings at Other Libraries = "Daliadau mewn Llyfrgelloedd Eraill"
-Holdings details from = "Manylion daliadau o"
+holdings_details_from = "Manylion daliadau o %%location%%"
 Holdings_notes = "Nodiadau"
 Holds = "Daliadau"
 Holds and Recalls = "Daliadau ac Adalwadau"
@@ -469,7 +477,7 @@ ill_request_cancel_all = "Canslo Bob Cais am Fenthyciad Rhwnglyfrgellol"
 ill_request_cancel_fail = "Ni chanslwyd eich cais. Cysylltwch â'r ddesg fenthyca am gymorth pellach"
 ill_request_cancel_selected = "Canslo'r Ceisiadau Benthyciad Rhwnglyfrgellol a Ddewiswyd"
 ill_request_cancel_success = "Canslwyd eich cais yn llwyddiannus"
-ill_request_cancel_success_items = "Canslwyd y cais/ceisiadau yn llwyddiannus"
+ill_request_cancel_success_items = "%%count%% Canslwyd y cais/ceisiadau yn llwyddiannus"
 ill_request_canceled = "Canslwyd"
 ill_request_check_text = "Gwirio Cais am Fenthyciad Rhwnglyfrgellol"
 ill_request_comments = "Sylwadau"
@@ -498,7 +506,6 @@ ils_offline_login_message = "Ni fydd manylion eich cyfrif ar gael yn ystod y cyf
 ils_offline_status = "Rydym yn gwneud gwaith cynnal a chadw ar ein System Rheoli'r Llyfrgell ar hyn o bryd"
 ils_offline_title = "Gwaith Cynnal a Chadw ar y Gweill"
 Import Record = "Mewnforio Cofnod"
-Import to = "Mewnforio i"
 in = "mewn"
 In This Collection = "Yn y Casgliad Hwn"
 in_collection_label = "Yng Nghasgliad:"
@@ -526,8 +533,8 @@ Item removed from favorites = "Dilëwyd yr Eitem o'r Ffefrynnau"
 Item removed from list = "Dilëwyd yr Eitem o'r Rhestr"
 Items = "Eitemau"
 items = "eitemau"
-items_added_to_bookbag = "eitem(au) wedi ei/eu hychwanegu i'ch Bag Llyfrau"
-items_already_in_bookbag = "Eitem(au) naill ai yn eich Bag Llyfrau yn barod neu ni fedrwyd ei/eu hychwanegu"
+items_added_to_bookbag = "%%count%% eitem(au) wedi ei/eu hychwanegu i'ch Bag Llyfrau"
+items_already_in_bookbag = "%%count%% Eitem(au) naill ai yn eich Bag Llyfrau yn barod neu ni fedrwyd ei/eu hychwanegu"
 Journal = "Cylchgrawn"
 Journal Articles = "Erthyglau Cylchgrawn"
 Journal Info = "Gwybodaeth am Gyfnodolyn"
@@ -644,12 +651,11 @@ nohit_active_filters = "Mae un neu fwy o hidlwyr ffasedau wedi'u cymhwyso i'r ch
 nohit_change_tab = "Rydych wedi bod yn chwilio yn y tab "%%activeTab%%". Efallai y dewch o hyd i rywbeth yn un o'r tabiau eraill:"
 nohit_filters = "Hidlwyr sydd wedi'u gosod i'r chwiliad hwn:"
 nohit_heading = "Dim Canlyniadau!"
+nohit_lookfor_html = "Eich chwiliad - <strong>%%lookfor%%</strong> - ddim yn cyfateb ag unrhyw adnoddau"
 nohit_no_filters = "Ni osodwyd unrhyw hidlwyr i'r chwiliad hwn"
 nohit_parse_error = "Mae'n ymddangos fod problem gyda'ch ymholiad chwilio. Gwiriwch y gystrawen. Os nad ydych yn ceisio defnyddio'r nodweddion uwch, gall gosod yr ymholiad ar wahân mewn dyfynodau dwbl helpu."
-nohit_prefix = "Eich chwiliad"
 nohit_query_without_filters = "Tynnu pob hidlydd o'r chwiliad hwn."
 nohit_spelling = "Efallai y dylech gynnig rhai amrywiadau sillafu"
-nohit_suffix = "ddim yn cyfateb ag unrhyw adnoddau"
 nohit_suggest = "Mae'n bosib y byddwch am adolygu eich brawddeg chwilio drwy gael gwared ar rai o'r geiriau neu wirio'r sillafu."
 NOT = "NOT"
 Not Illustrated = "Heb ei Ddarlunio"
@@ -691,7 +697,7 @@ number_decimal_point = "."
 number_thousands_separator = ","
 OAI Server = "Gweinydd OAI"
 Occupation = "Galwedigaeth"
-of = "o"
+of_num_results = "#%%position%% o %%total%% canlyniadau"
 old_password = "Hen Gyfrinair"
 On Reserve = "Ar Gadw"
 On Reserve - Ask at Circulation Desk = "Ar Gadw – Gofynnwch wrth y Ddesg Fenthyca"
@@ -699,6 +705,7 @@ on_reserve = "Ar gadw – Gofynnwch wrth y Ddesg Fenthyca"
 on_topic = "%%count%% eitem ar y pwnc hwn"
 Online Access = "Mynediad Ar-lein"
 online_resources = "Testun Llawn"
+open_access_limit = "Cynnwys Mynediad Agored wedi'i gyfyngu"
 operator_contains = "sy'n cynnwys"
 operator_exact = "yn (yn union)"
 OR = "OR"
@@ -737,8 +744,6 @@ Please check back soon = "Gwiriwch eto yn fuan"
 Please contact the Library Reference Department for assistance = "Cysylltwch â'r Ddesg Fenthyca am gymorth"
 Please enable JavaScript. = "Galluogwch JavaScript."
 Please upgrade your browser. = "Uwchraddiwch eich porwr."
-Posted by = "Postiwyd gan"
-posted_on = "ar"
 Preferences = "Dewisiadau"
 Preferred Library = "Hoff Lyfrgell"
 Prev = "Blaenorol"
@@ -874,7 +879,12 @@ Sensor Image = "Delwedd y Synhwyrydd"
 Serial = "Cyfresol"
 Series = "Cyfres"
 Set = "Set"
-Showing = "Dangos"
+showing_items_html = "Dangos <strong>%%start%% - %%end%%</strong> Eitemau"
+showing_items_of_html = "Dangos <strong>%%start%% - %%end%%</strong> o <strong>%%total%%</strong> Eitemau"
+showing_results_for_html = "Dangos <strong>%%start%% - %%end%%</strong> canlyniadau ar gyfer chwilio '<strong>%%lookfor%%</strong>'"
+showing_results_html = "Dangos <strong>%%start%% - %%end%%</strong> canlyniadau"
+showing_results_of_for_html = "Dangos <strong>%%start%% - %%end%%</strong> canlyniadau o <strong>%%total%%</strong> ar gyfer chwilio '<strong>%%lookfor%%</strong>'"
+showing_results_of_html = "Dangos <strong>%%start%% - %%end%%</strong> canlyniadau o <strong>%%total%%</strong>"
 sidebar_close = "Cwympo bar ochr"
 sidebar_expand = "Ehangu bar ochr"
 Similar Items = "Eitemau Tebyg"
@@ -918,7 +928,7 @@ storage_retrieval_request_cancel_all = "Canslo Pob Cais am Dynnu Eitemau o'r Sto
 storage_retrieval_request_cancel_fail = "Ni chanslwyd eich cais. Cysylltwch â'r ddesg fenthyca am gymorth pellach"
 storage_retrieval_request_cancel_selected = "Canslo'r Ceisiadau a Ddewiswyd am Dynnu Eitemau o'r Storfa"
 storage_retrieval_request_cancel_success = "Canslwyd eich cais yn llwyddiannus"
-storage_retrieval_request_cancel_success_items = "Canslwyd y cais/ceisiadau yn llwyddiannus"
+storage_retrieval_request_cancel_success_items = "%%count%% Canslwyd y cais/ceisiadau yn llwyddiannus"
 storage_retrieval_request_canceled = "Canslwyd"
 storage_retrieval_request_check_text = "Gwirio Cais am Dynnu Eitem o'r Storfa"
 storage_retrieval_request_comments = "Sylwadau"
@@ -956,7 +966,7 @@ Summon Results = "Galw Summon"
 summon_database_recommendations = "Gallwch ddod o hyd i adnoddau ychwanegol yma:"
 Supplements = "Atodiadau"
 Supplied by Amazon = "Cyflenwyd gan Amazon"
-Switch view to = "Newid golwg i"
+switch_view = "Newid golwg i %%view%%"
 switchquery_fuzzy = "Cynnal chwiliad niwlog a allai adalw termau sydd wedi'u sillafu'n debyg"
 switchquery_intro = "Efallai y cewch fwy o ganlyniadau drwy addasu'ch ymholiad chwilio."
 switchquery_lowercasebools = "Os ydych yn ceisio defnyddio gweithredwyr Boolean, rhaid defnyddio PRIFLYTHRENNAU"
@@ -998,8 +1008,7 @@ Too Many Email Recipients = "Gormod o dderbynwyr e-bost"
 too_many_favorites = "Mae'r rhestr hon yn rhy fawr i'w harddangos ar unwaith. Ceisiwch aildrefnu eich ffefrynnau yn rhagor o restri neu peidiwch â defnyddio cymaint o dagiau."
 too_many_new_items = "Mae gormod o eitemau newydd i'w harddangos mewn rhestr unigol. Ceisiwch gyfyngu eich chwiliad."
 too_many_reserves = "Mae gormod o gyrsiau a gedwir i'w harddangos mewn rhestr unigol. Ceisiwch gyfyngu eich chwiliad."
-top_facet_additional_prefix = "Ychwanegol"
-top_facet_suffix = "... O fewn eich chwiliad"
+top_facet_label = "%%label%% O fewn eich chwiliad"
 Topic = "Pwnc"
 Topics = "Pynciau"
 Total Balance Due = "Cyfanswm Balans sy'n Ddyledus"
@@ -1028,7 +1037,6 @@ VHS = "VHS"
 Video = "Fideo"
 Video Clips = "Clipiau Fideo"
 Videos = "Fideos"
-view already selected = "gweld yr hyn a ddewiswyd yn barod"
 View Book Bag = "Dangos Bag Llyfrau"
 View Full Collection = "Gweld yr Holl Gasgliad"
 View Full Record = "Gweld y Cofnod Llawn"
@@ -1037,6 +1045,7 @@ View online: Full view Book Preview from the Hathi Trust = "Dangos ar-lein: Rhag
 View Record = "Gweld Cofnod"
 View Records = "Dangos Cofnodion"
 View this record in EBSCOhost = "Gweld y cofnod hwn mewn EBSCOhost"
+view_already_selected = "%%current%% gweld yr hyn a ddewiswyd yn barod"
 visual_facet_parent = "o"
 Volume = "Sain"
 Volume Holdings = "Daliadau Sain"
diff --git a/languages/da.ini b/languages/da.ini
index 614aba3980b5803b54713f895ac65d5edfbc9add..670886a811e5665f30769e39b545bcb2ebed83dc 100644
--- a/languages/da.ini
+++ b/languages/da.ini
@@ -17,7 +17,6 @@
 ;note_785_7 = "Sammenføjet med" ; incomplete translation (en.ini was later revised)
 Access = "Adgang"
 Account = "Konto"
-Add = "Tilføj"
 Add a Note = "Tilføj en kommentar"
 Add Tag = "Tilføj Tag"
 Add Tags = "Tilføj Tags"
@@ -25,8 +24,6 @@ Add to Book Bag = "Tilføj til Bogkurv"
 Add to favorites = "Føj til favoritter"
 Add your comment = "Tilføj din kommentar"
 add_favorite_fail = "Fejl: posten er ikke gemt"
-add_favorite_prefix = "Tilføj favorit præfix"
-add_favorite_suffix = "Tilføj favorit suffix”"
 add_list_fail = "Fejl: Listen blev ikke oprettet"
 add_other_libraries = "Inkluder artikler fra andre biblioteker"
 add_search = "Tilføj søgefelt"
@@ -34,6 +31,7 @@ add_search_group = "Tilføj søgegruppe"
 add_tag_error = "Fejl: kunne ikke gemme tag"
 add_tag_note = "Mellemrum vil separere tags. Brug anførselstegn til tags med flere ord"
 add_tag_success = "Tags gemt"
+add_to_favorites_html = "Tilføj favorit præfix <em>%%title%%</em> Tilføj favorit suffix”"
 Address = "Addresse"
 adv_search_all = "Alle felter"
 adv_search_author = "Forfatter”"
@@ -267,7 +265,6 @@ Fines = "Bøder"
 First Name = "Fornavn"
 for search = "til søgning"
 Format = "Format"
-found = "fundet"
 From = "Fra"
 Full description = "Fuld beskrivelse"
 fulltext_limit = "Afgræns til artikler med fuldtekst”"
@@ -305,14 +302,14 @@ hold_cancel_all = "Afbestil alle reservationer"
 hold_cancel_fail = "Din forespørgsel blev aflyst. Kontakt venligst udlånsskranken for yderligere assistance"
 hold_cancel_selected = "Afbestil valgte reservationer"
 hold_cancel_success = "Din forespørgsel blev aflyst"
-hold_cancel_success_items = "Dine forespørgsler blev aflyst"
+hold_cancel_success_items = "%%count%% Dine forespørgsler blev aflyst"
 hold_date_invalid = "Vær venlig at tilføje en gyldig dato"
 hold_date_past = "Vær venlig at tilføje en fremtidig dato"
 hold_empty_selection = "Ingen reservationer valgt”"
 hold_error_blocked = "Du har ikke rettigheder til at reservere dette emne"
 hold_error_fail = "Din forespørgsel kunne ikke gennemføres. Kontakt venligst udlånsskranken for yderligere assistance"
 hold_invalid_pickup = "Afhentningslokation ugyldig. Prøv venligst igen"
-hold_login = "Til information omkring lån og hjemkaldelser"
+hold_login = "Login Til information omkring lån og hjemkaldelser"
 hold_place = "Lav forespørgsel"
 hold_place_fail_missing = "Din forespørgsel kunne ikke gennemføres pga. en fejl. Kontakt venligst udlånsskranken for yderligere assistance”"
 hold_place_success_html = "Din forespørgsel blev godkendt. <a href="%%url%%">Dine lån og hjemkaldelser</a>."
@@ -321,7 +318,7 @@ hold_required_by = "ønskes ikke længere efter"
 hold_success = "Din forespørgsel blev godkendt"
 Holdings = "Beholdninger"
 Holdings at Other Libraries = "Beholdninger på andre biblioteker"
-Holdings details from = "Detaljer om beholdninger fra"
+holdings_details_from = "Detaljer om beholdninger fra %%location%%"
 Holdings_notes = "Kommentarer"
 Holds = "LÃ¥n"
 Holds and Recalls = "LÃ¥n og hjemkaldelser"
@@ -330,7 +327,7 @@ home_browse = "Gennemse"
 ill_request_available = "Kan afhentes"
 ill_request_cancel_fail = "Din forespørgsel blev aflyst. Kontakt venligst udlånsskranken for yderligere assistance"
 ill_request_cancel_success = "Din forespørgsel blev aflyst"
-ill_request_cancel_success_items = "Dine forespørgsler blev aflyst"
+ill_request_cancel_success_items = "%%count%% Dine forespørgsler blev aflyst"
 ill_request_date_invalid = "Vær venlig at tilføje en gyldig dato"
 ill_request_date_past = "Vær venlig at tilføje en fremtidig dato"
 ill_request_error_fail = "Din forespørgsel kunne ikke gennemføres. Kontakt venligst udlånsskranken for yderligere assistance"
@@ -339,7 +336,6 @@ ill_request_place_fail_missing = "Din forespørgsel kunne ikke gennemføres pga.
 ill_request_place_success = "Din forespørgsel blev godkendt"
 Illustrated = "Illustreret"
 Import Record = "Importér poster"
-Import to = "Importér til"
 in = "i"
 Institution = "Institution"
 Institutional Login = "KB Login"
@@ -355,8 +351,8 @@ Issue = "Eksemplar"
 Item Description = "Emne beskrivelse"
 Item Notes = "Kommentarer"
 items = "emner"
-items_added_to_bookbag = "emne(r) tilføjet din bogkurv"
-items_already_in_bookbag = "emne(r) findes allerede i din bogkurv eller kunne ikke tilføjes”"
+items_added_to_bookbag = "%%count%% emne(r) tilføjet din bogkurv"
+items_already_in_bookbag = "%%count%% emne(r) findes allerede i din bogkurv eller kunne ikke tilføjes”"
 Journal = "Tidsskrift"
 Journal Articles = "Tidsskriftsartikler"
 Journal Title = "Tidsskriftstitel"
@@ -428,11 +424,10 @@ no_description = "Ingen beskrivelse tilgængelig."
 no_items_selected = "Ingen emner valgt"
 nohit_filters = "Anvendte filter på denne søgning:"
 nohit_heading = "Ingen resultater!"
+nohit_lookfor_html = "Din søgning - <strong>%%lookfor%%</strong> - ingen ressourcematch."
 nohit_no_filters = "Ingen filter blev anvendt på denne søgning."
 nohit_parse_error = "Der forekommer at være et problem med din søgning. Check venligst syntaksen."
-nohit_prefix = "Din søgning"
 nohit_spelling = "Prøv at variere din stavemåde"
-nohit_suffix = "ingen ressourcematch."
 nohit_suggest = "Revidér din søgesætning ved at fjerne ord eller checke stavning."
 NOT = "IKKE"
 Not Illustrated = "Ikke Illustreret"
@@ -453,7 +448,6 @@ note_780_5 = "Inkluderet"
 note_785_0 = "Fortsat af"
 Notes = "Kommentarer"
 Number = "Nummer"
-of = "af"
 On Reserve = "Kan reserveres"
 On Reserve - Ask at Circulation Desk = "Kan reserveres - Spørg i udlånsskranken"
 on_reserve = "Reservationer ø spørg i udlånsskranken"
@@ -478,8 +472,6 @@ Place a Hold = "Reservér”"
 Playing Time = "Spilletid"
 Please check back soon = "Kom snart tilbage"
 Please contact the Library Reference Department for assistance = "Kontakt venligst afdelingen for Digital Services, University and Regional Library of Tyrol, Austria for assistance"
-Posted by = "Indsat af"
-posted_on = "på"
 Prev = "Forrige"
 Previous Title = "Forrige titel"
 Print = "Udskriv"
@@ -561,7 +553,6 @@ Sensor Image = "Sensor Image"
 Serial = "Serial"
 Series = "Serier"
 Set = "Sæt"
-Showing = "viser"
 Similar Items = "Lignende værker"
 Slide = "Slide"
 sms_failure = "Fejl! Kunne ikke sende besked."
@@ -591,7 +582,7 @@ Status = "Status"
 storage_retrieval_request_available = "Kan afhentes"
 storage_retrieval_request_cancel_fail = "Din forespørgsel blev aflyst. Kontakt venligst udlånsskranken for yderligere assistance"
 storage_retrieval_request_cancel_success = "Din forespørgsel blev aflyst"
-storage_retrieval_request_cancel_success_items = "Dine forespørgsler blev aflyst"
+storage_retrieval_request_cancel_success_items = "%%count%% Dine forespørgsler blev aflyst"
 storage_retrieval_request_comments = "Kommentar"
 storage_retrieval_request_date_invalid = "Vær venlig at tilføje en gyldig dato"
 storage_retrieval_request_date_past = "Vær venlig at tilføje en fremtidig dato"
@@ -611,7 +602,7 @@ Summary = "Summary"
 Summon Results = "Summon Resultater"
 summon_database_recommendations = "Yderligere materiale kan finds her:”"
 Supplied by Amazon = "Leveret af Amazon"
-Switch view to = "Skift til"
+switch_view = "Skift til %%view%%"
 System Unavailable = "Systemet er utilgængeligt"
 Table of Contents = "Indholdsfortegnelse"
 Table of Contents unavailable = "Indholdsfortegnelse utilgængelig"
@@ -632,8 +623,7 @@ To = "Til"
 too_many_favorites = "Denne liste er for omfattende til at blive vist på Én gang. Prøv at flytte dine favoritter til flere lister eller begræns brugen af tags.”"
 too_many_new_items = "Der er for mange nye emner for en enkelt liste. Prøv at begrænse din søgning."
 too_many_reserves = "Der er for mange kursusreservationer for en enkelt liste. Prøv at begrænse din søgning ø"
-top_facet_additional_prefix = "Yderligere"
-top_facet_suffix = "... i din søgning."
+top_facet_label = "%%label%% i din søgning."
 Topic = "Emne"
 Topics = "Emner"
 University Library = "Universitetsbibliotek"
@@ -647,10 +637,10 @@ VHS = "VHS"
 Video = "Video"
 Video Clips = "Videoklip"
 Videos = "Videoer"
-view already selected = "visning allerede valgt"
 View Book Bag = "Se bogkurv"
 View online: Full view Book Preview from the Hathi Trust = "Se online: Fuldt preview fra Hathi Trust"
 View Records = "Se poster"
+view_already_selected = "%%current%% visning allerede valgt"
 visual_facet_parent = "Fra"
 Volume = "Bind"
 Volume Holdings = "Bindbeholdninger"
diff --git a/languages/de.ini b/languages/de.ini
index 37b3e5b7c8ff46376cd6b7516a92455b6337641d..101adba656db02f812032138002a8f84331f0b84 100644
--- a/languages/de.ini
+++ b/languages/de.ini
@@ -1,12 +1,12 @@
-; For future reference:
-;German = Deutsch
+; For future reference:
+;German = Deutsch
 Abstract = "Abstract"
 Access = "Zugangseinschränkungen"
 Access URL = "Zugangs-URL"
 access_denied = "Zugriff nicht erlaubt."
 Accession Number = "Dokumentencode"
 Account = "Konto"
-Add = "Hinzufügen"
+account_block_options_missing = "Einige Selektionen wurden aufgrund von Einschränkungen Ihres Benutzerkontos entfernt. Details: %%details%%"
 Add a Library Card = "Bibliotheksausweis hinzufügen"
 Add a Note = "Bemerkung hinzufügen"
 Add Tag = "Tag hinzufügen"
@@ -18,8 +18,6 @@ Add your comment = "Kommentar einfügen"
 add_comment_fail_blank = "Kommentar darf nicht leer sein."
 add_comment_success = "Kommentar hinzugefügt."
 add_favorite_fail = "Fehler: Datensatz wurde nicht gespeichert"
-add_favorite_prefix = ""
-add_favorite_suffix = "zu den Favoriten hinzufügen"
 add_list_fail = "Fehler: Liste wurde nicht erstellt"
 add_other_libraries = "Datensätze anderer Bibliotheken berücksichtigen"
 add_search = "Suchfeld hinzufügen"
@@ -27,6 +25,7 @@ add_search_group = "Suchgruppe hinzufügen"
 add_tag_error = "Fehler: Tags wurden nicht gespeichert"
 add_tag_note = "Leerschläge bewirken einen neuen Tag. Verwenden Sie Anführungszeichen für Begriffe mit mehreren Wörtern."
 add_tag_success = "Tags gespeichert"
+add_to_favorites_html = " <em>%%title%%</em> zu den Favoriten hinzufügen"
 Address = "Anschrift"
 adv_search_all = "Alle Felder"
 adv_search_author = "Verfasser"
@@ -172,6 +171,10 @@ Catalog Results = "Katalogtreffer"
 catalog_login_desc = "Geben Sie die Anmeldeinformationen ihres Bibliothekskontos an."
 CD = "CD"
 Change Password = "Passwort ändern"
+channel_add_more = "Weitere ähnliche Inhalte hinzufügen"
+channel_expand = "Ähnliche Inhalte erkunden"
+channel_explore = "Inhalte erkunden"
+channel_search = "Inhalte in den Suchergebnissen anzeigen"
 Check Hold = "Bestellbarkeit prüfen"
 Check Recall = "Möglichkeit einer Vormerkung prüfen"
 Checked Out = "Ausgeliehen"
@@ -222,7 +225,6 @@ confirm_ill_request_cancel_selected_text = "Möchten Sie die ausgewählten Fernl
 confirm_new_password = "Neues Passwort bestätigen"
 confirm_storage_retrieval_request_cancel_all_text = "Möchten Sie alle ihre Magazinbestellungen widerrufen?"
 confirm_storage_retrieval_request_cancel_selected_text = "Möchten Sie die ausgewählten Magazinbestellungen widerrufen?"
-conjunction_or = "oder"
 Contents = "Inhalte"
 Contributing Source = "Originalquelle"
 Contributors = "Weitere Verfasser"
@@ -272,6 +274,7 @@ Displaying the top = "Angezeigt werden die ersten"
 Document Inspector = "Dokumentprüfer"
 Document Type = "Publikationsart"
 DOI = "DOI"
+doi_detected_html = "Ihre Suche scheint eine DOI zu enthalten. Prüfen Sie die Online-Verfügbarkeit hier: <a href="%%url%%">%%doi%%</a>"
 Draw Search Box = "Suchbereich definieren"
 Due = "Rückgabe bis"
 Due Date = "Rückgabedatum"
@@ -285,6 +288,7 @@ edit_list_fail = "Sie sind leider nicht berechtigt, diese Liste zu bearbeiten"
 edit_list_success = "Liste erfolgreich bearbeitet."
 Edition = "Ausgabe"
 eds_expander_fulltext = "Auf Suche im Volltext innerhalb der Artikel ausweiten"
+eds_expander_relatedsubjects = "Auf verwandte Schlagworte ausweiten"
 eds_expander_thesaurus = "Auf verwandte Wörter ausweiten"
 eds_limiter_FC = "Nur Bibliothekskatalog"
 eds_limiter_FC1 = "Nur institutionelles Repository"
@@ -345,6 +349,10 @@ export_selected = "Auswahl exportieren"
 export_selected_favorites = "Ausgewählte Favoriten exportieren"
 export_success = "Export abgeschlossen"
 export_unsupported_format = "Nichtunterstütztes Exportformat"
+external_auth_heading = "Zugriff auf lizenzpflichtige Inhalte"
+external_auth_login_message = "Melden Sie sich an, um auf lizenzpflichtige Inhalte zuzugreifen"
+external_auth_unauthorized = "Sie haben keinen Zugriff auf lizenzpflichtige Inhalte"
+external_auth_unauthorized_desc = "Ihr aktuelles Login erlaubt keinen Zugriff auf lizenzpflichtige Inhalte. Bitte melden Sie sich ab und verwenden Sie eine andere Art der Anmeldung."
 FAQs = "Häufig gestellte Fragen"
 fav_delete = "Ausgewählte Favoriten löschen"
 fav_delete_deleting = "Ihre ausgewählten Favoriten werden gelöscht."
@@ -382,7 +390,6 @@ for search = "für Suche"
 Forgot Password = "Passwort vergessen"
 Form Submitted! = "Formular abgeschickt!"
 Format = "Format"
-found = "gefundenen"
 From = "Von"
 Full description = "Ausführliche Beschreibung"
 Full text is not displayed to guests = "Volltext ist im Gastzugang nicht verfügbar."
@@ -434,7 +441,7 @@ hold_cancel_all = "Alle Bestellungen annullieren"
 hold_cancel_fail = "Ihre Bestellung konnte nicht annulliert werden. Bitte kontaktieren Sie ihre Bibliothek für weitere Hilfe"
 hold_cancel_selected = "Ausgewählte Bestellungen annullieren"
 hold_cancel_success = "Ihre Bestellung wurde erfolgreich annulliert"
-hold_cancel_success_items = "Bestellung(en) wurden erfolgreich annulliert"
+hold_cancel_success_items = "%%count%% Bestellung(en) wurden erfolgreich annulliert"
 hold_date_invalid = "Bitte geben Sie ein gültiges Datum ein"
 hold_date_past = "Bitte geben Sie ein Datum in der Zukunft an"
 hold_empty_selection = "Keine Bestellungen ausgewählt"
@@ -442,19 +449,21 @@ hold_error_blocked = "Sie haben keine genügende Berechtigung um diese Medium zu
 hold_error_fail = "Ihre Bestellung ist fehlgeschlagen. Bitte kontaktieren Sie ihre Bibliothek für weitere Hilfe"
 hold_invalid_pickup = "Es wurde ein ungültiger Abholort eingegeben. Bitte versuchen Sie es erneut"
 hold_invalid_request_group = "Es wurde eine ungültige Abholstelle angegeben. Bitte versuchen Sie es erneut"
-hold_login = "für die Nachverfolgung von Bestellungen und Vormerkungen"
+hold_items_available = "Reservation nicht möglich, es stehen Exemplare zur Verfügung."
+hold_login = "Login für die Nachverfolgung von Bestellungen und Vormerkungen"
 hold_place = "Bestellen"
 hold_place_fail_missing = "Ihre Bestellung ist fehlgeschlagen. Es fehlen Angaben. Bitte kontaktieren Sie ihre Bibliothek für weitere Hilfe"
 hold_place_success_html = "Ihre Bestellung war erfolgreich. <a href="%%url%%">Ihre offenen Bestellungen und Vormerkungen</a>."
 hold_profile_html = "Für Angaben zu Bestellungen und Vormerkungen, erstellen Sie bitte ein persönliches <a href="%%url%%">Bibliothekskatalog Login</a>."
 hold_queue_position = "Position in der Warteschlange"
+hold_record_already_on_loan = "Das Exemplar ist bereits von Ihnen ausgeliehen"
 hold_request_group = "Anfrage von"
 hold_requested_group = "Angefragt von"
 hold_required_by = "Nicht mehr benötigt nach"
 hold_success = "Ihre Bestellung war erfolgreich"
 Holdings = "Exemplare"
 Holdings at Other Libraries = "Exemplare in anderen Bibliotheken"
-Holdings details from = "Bestandesangaben von"
+holdings_details_from = "Bestandesangaben von %%location%%"
 Holdings_notes = "Anmerkungen"
 Holds = "Bestellungen"
 Holds and Recalls = "Bestellungen/Vormerkungen"
@@ -468,7 +477,7 @@ ill_request_cancel_all = "Alle Fernleihanfragen widerrufen"
 ill_request_cancel_fail = "Ihre Bestellung konnte nicht annulliert werden. Bitte kontaktieren Sie ihre Bibliothek für weitere Hilfe"
 ill_request_cancel_selected = "Ausgewählte Fernleihanfragen widerrufen"
 ill_request_cancel_success = "Ihre Bestellung wurde erfolgreich annulliert"
-ill_request_cancel_success_items = "Bestellung(en) wurden erfolgreich annulliert"
+ill_request_cancel_success_items = "%%count%% Bestellung(en) wurden erfolgreich annulliert"
 ill_request_canceled = "Widerrufen"
 ill_request_check_text = "Fernleihanfrage prüfen"
 ill_request_comments = "Bemerkungen"
@@ -497,7 +506,6 @@ ils_offline_login_message = "Ihr persönliches Konto steht während dieser Zeit
 ils_offline_status = "Unser Bibliotheksverwaltungssystem ist momentan wegen Wartungsarbeiten nicht verfügbar."
 ils_offline_title = "Wegen Wartungsarbeiten nicht verfügbar"
 Import Record = "Datensatz importieren"
-Import to = "Importieren nach "
 in = "in"
 In This Collection = "In diesem Bestand"
 in_collection_label = "In Bestand:"
@@ -525,8 +533,8 @@ Item removed from favorites = "Datensatz aus den Favoriten entfernt"
 Item removed from list = "Datensatz aus der Liste entfernt"
 Items = "Datensätze"
 items = "in der Auswahl"
-items_added_to_bookbag = "Datensatz/Datensätze der Zwischenablage hinzugefügt"
-items_already_in_bookbag = "Datensatz/Datensätze bereits in der Zwischenablage vorhanden und/oder konnte(n) nicht hinzugefügt werden"
+items_added_to_bookbag = "%%count%% Datensatz/Datensätze der Zwischenablage hinzugefügt"
+items_already_in_bookbag = "%%count%% Datensatz/Datensätze bereits in der Zwischenablage vorhanden und/oder konnte(n) nicht hinzugefügt werden"
 Journal = "Zeitschrift"
 Journal Articles = "Zeitschriftenartikel"
 Journal Info = "Info zur Zeitschrift"
@@ -644,12 +652,11 @@ nohit_active_filters = "Es wurden Suchfilter/Facetten verwendet. Ohne Filter kan
 nohit_change_tab = "Sie haben im Reiter %%activeTab%% gesucht. Möglicherweise finden Sie etwas in einem anderen Reiter:"
 nohit_filters = "Verwendete Suchfilter."
 nohit_heading = "Keine Ergebnisse!"
+nohit_lookfor_html = "Für Ihre Suchanfrage - <strong>%%lookfor%%</strong> - wurde keine Übereinstimmung gefunden."
 nohit_no_filters = "Es wurden keine Filter für diese Suche verwendet."
 nohit_parse_error = "Es ist ein Problem bei ihrer Suche aufgetreten. Bitte prüfen Sie die Suchsyntax. Falls Sie nicht komplexe Suchfunktionen verwenden, versuchen Sie die Suchparameter in Anführungszeichen zu setzen."
-nohit_prefix = "Für Ihre Suchanfrage"
 nohit_query_without_filters = "Suche ohne Filter wiederholen."
 nohit_spelling = "Vielleicht sollten Sie eine andere Schreibweise verwenden."
-nohit_suffix = "wurde keine Ãœbereinstimmung gefunden."
 nohit_suggest = "Ev. können Sie ihre Suchanfrage verbessern, indem Sie Wörter entfernen oder die Rechtschreibung überprüfen."
 NOT = "NICHT"
 Not Illustrated = "Ohne Abbildungen"
@@ -691,7 +698,7 @@ number_decimal_point = ","
 number_thousands_separator = "."
 OAI Server = "OAI-Server"
 Occupation = "Beruf"
-of = "von"
+of_num_results = "#%%position%% von %%total%% Treffer"
 old_password = "Bisheriges Passwort"
 On Reserve = "Vorgemerkt"
 On Reserve - Ask at Circulation Desk = "Vorgemerkt - Fragen Sie in ihrer Bibliothek nach"
@@ -699,6 +706,7 @@ on_reserve = "Vormerkungen - Fragen Sie in Ihrer Bibliothek nach"
 on_topic = "%%count%% Treffer zu diesem Thema"
 Online Access = "Online Zugang"
 online_resources = "Volltext"
+open_access_limit = "Eingrenzen auf Open Access"
 operator_contains = "enthält"
 operator_exact = "ist gleich"
 OR = "ODER"
@@ -737,8 +745,6 @@ Please check back soon = "Bitte versuchen Sie es bald nocheinmal"
 Please contact the Library Reference Department for assistance = "Bitte kontaktieren Sie ihre Bibliothek für weitere Hilfe"
 Please enable JavaScript. = "Bitte aktivieren Sie JavaScript."
 Please upgrade your browser. = "Bitte aktualisieren Sie ihren Browser."
-Posted by = "Verfasst von"
-posted_on = "am"
 Preferences = "Voreinstellungen"
 Preferred Library = "Stammbibliothek"
 Prev = "Vorheriger"
@@ -874,7 +880,12 @@ Sensor Image = "Fernerkundungsbilder"
 Serial = "Schriftenreihe"
 Series = "Schriftenreihe"
 Set = "Wechseln"
-Showing = "Treffer"
+showing_items_html = "Treffer <strong>%%start%% - %%end%%</strong> Datensätze"
+showing_items_of_html = "Treffer <strong>%%start%% - %%end%%</strong> von <strong>%%total%%</strong> Datensätze"
+showing_results_for_html = "Treffer <strong>%%start%% - %%end%%</strong> Treffer für Suche '<strong>%%lookfor%%</strong>'"
+showing_results_html = "Treffer <strong>%%start%% - %%end%%</strong> Treffer"
+showing_results_of_for_html = "Treffer <strong>%%start%% - %%end%%</strong> Treffer von <strong>%%total%%</strong> für Suche '<strong>%%lookfor%%</strong>'"
+showing_results_of_html = "Treffer <strong>%%start%% - %%end%%</strong> Treffer von <strong>%%total%%</strong>"
 sidebar_close = "Seitenleiste ausblenden"
 sidebar_expand = "Seitenleiste einblenden"
 Similar Items = "Ähnliche Einträge"
@@ -918,7 +929,7 @@ storage_retrieval_request_cancel_all = "Alle Magazinbestellungen widerrufen"
 storage_retrieval_request_cancel_fail = "Ihre Bestellung konnte nicht annulliert werden. Bitte kontaktieren Sie ihre Bibliothek für weitere Hilfe"
 storage_retrieval_request_cancel_selected = "Ausgewählte Magazinbestellungen widerrufen"
 storage_retrieval_request_cancel_success = "Ihre Bestellung wurde erfolgreich annulliert"
-storage_retrieval_request_cancel_success_items = "Bestellung(en) wurden erfolgreich annulliert"
+storage_retrieval_request_cancel_success_items = "%%count%% Bestellung(en) wurden erfolgreich annulliert"
 storage_retrieval_request_canceled = "Widerrufen"
 storage_retrieval_request_check_text = "Magazinbestellung prüfen"
 storage_retrieval_request_comments = "Kommentare"
@@ -956,7 +967,7 @@ Summon Results = "Zitate"
 summon_database_recommendations = "Weitere mögliche Ressourcen:"
 Supplements = "Supplemente"
 Supplied by Amazon = "Von Amazon zur Verfügung gestellt"
-Switch view to = "Ansicht wechseln nach"
+switch_view = "Ansicht wechseln nach %%view%%"
 switchquery_fuzzy = "Eine Fuzzy-Suche kann Ergebnisse für Wörter mit ähnlicher Schreibweise liefern"
 switchquery_intro = "Erweitern Sie die Ergebnisse, indem Sie die Suche verändern."
 switchquery_lowercasebools = "Falls Sie Boolsche Suchoperatoren verwenden, müssen sie GROSS GESCHRIEBEN werden"
@@ -998,8 +1009,7 @@ Too Many Email Recipients = "Zu viele E-Mail-Adressen"
 too_many_favorites = "Diese Liste ist zu gross um auf einmal angezeigt zu werden. Versuchen Sie Ihre Favoriten in weitere Listen zu unterteilen oder mittels Tags einzuschränken."
 too_many_new_items = "Es gibt zu viele Einträge um in einer einzigen Liste angezeigt zu werden. Versuchen Sie Ihre Suche weiter einzuschränken."
 too_many_reserves = "Es gibt zu viele Vormerkungen um in einer einzigen Liste angezeigt zu werden. Versuchen Sie Ihre Suche weiter einzuschränken."
-top_facet_additional_prefix = "Zusätzlich "
-top_facet_suffix = "... innerhalb Ihrer Suche."
+top_facet_label = "%%label%% innerhalb Ihrer Suche."
 Topic = "Thema"
 Topics = "Themen"
 Total Balance Due = "Total offener Betrag"
@@ -1028,7 +1038,6 @@ VHS = "VHS"
 Video = "Video"
 Video Clips = "Videoclips"
 Videos = "Videos"
-view already selected = "Ansicht bereits ausgewählt"
 View Book Bag = "Zwischenablage ansehen"
 View Full Collection = "Vollständiger Bestand ansehen"
 View Full Record = "Vollständigen Datensatz ansehen"
@@ -1037,6 +1046,7 @@ View online: Full view Book Preview from the Hathi Trust = "Online: vollständig
 View Record = "Datensatz ansehen"
 View Records = "Datensätze ansehen"
 View this record in EBSCOhost = "Diesen Datensatz in EBSCOhost ansehen"
+view_already_selected = "%%current%% Ansicht bereits ausgewählt"
 visual_facet_parent = "Von"
 Volume = "Jahrgang"
 Volume Holdings = "Bandangaben"
diff --git a/languages/el.ini b/languages/el.ini
index fe78601d270129777828b53b750a234fd08fc3cb..eeb9ba9fff91bf2e4b33bd173acc7db1f67d6c04 100644
--- a/languages/el.ini
+++ b/languages/el.ini
@@ -7,20 +7,18 @@ Access URL = "Σύνδεσμος πρόσβασης"
 access_denied = "Δεν επιτρέπεται η πρόσβαση."
 Accession Number = "Αριθμός Καταχώρησης"
 Account = "Λογαριασμός"
-Add = "Προσθήκη"
+account_block_options_missing = "Μερικές επιλογές δεν εμφανίζονται λόγω περιορισμών στον λογαριασμό σας. Λεπτομέρειες: %%details%%"
 Add a Library Card = "Προσθήκη κάρτας βιβλιοθήκης"
 Add a Note = "Προσθήκη σημείωσης"
 Add Tag = "Προσθήκη ετικέτας"
 Add Tags = "Προσθήκη ετικετών"
 Add to another list = "Προσθήκη σε άλλη λίστα"
 Add to Book Bag = "Προσθήκη στο καλάθι"
-Add to favorites = "Στα αγαπημένα"
+Add to favorites = "Προσθήκη στα αγαπημένα"
 Add your comment = "Προσθήκη σχολίου"
 add_comment_fail_blank = "Το σχόλιο δεν μπορεί να είναι άδειο."
-add_comment_success = "Το σχόλιο προστέθηκε."
+add_comment_success = "Το σχόλιο προστέθηκε επιτυχώς"
 add_favorite_fail = "Σφάλμα. Η εγγραφή δεν αποθηκεύτηκε"
-add_favorite_prefix = "Προσθήκη"
-add_favorite_suffix = "στα αγαπημένα"
 add_list_fail = "Σφάλμα. Η λίστα δεν δημιουργήθηκε"
 add_other_libraries = "Να περιλαμβάνονται αποτελέσματα άλλων βιβλιοθηκών"
 add_search = " Προσθήκη πεδίου αναζήτησης"
@@ -28,6 +26,7 @@ add_search_group = "Πρόσθήκη ομάδας πεδίων"
 add_tag_error = "Σφάλμα. Η ετικέτα δεν αποθηκεύτηκε"
 add_tag_note = "Διαχωρίστε τις ετικέτες με κενά. Χρησιμοποιήστε εισαγωγικά για φράσεις."
 add_tag_success = "Οι ετικέτες αποθηκεύτηκαν"
+add_to_favorites_html = "Προσθήκη <em>%%title%%</em> στα αγαπημένα"
 Address = "Διεύθυνση"
 adv_search_all = "Όλα τα πεδία"
 adv_search_author = "Συγγραφέα"
@@ -145,23 +144,23 @@ bulk_fail = "Παρουσιάστηκε σφάλμα. Παρακαλώ προσ
 bulk_noitems_advice = "Δεν έχετε επιλέξει τεκμήρια. Επιλέξτε κάποιο τεκμήριο και προσπαθήστε ξανά."
 bulk_save_error = "Ελλιπή στοιχεία. Η αποθήκευση των τεκμηρίων απέτυχε"
 bulk_save_success = "Η αποθήκευση των τεκμηρίων έγινε επιτυχώς"
-By = "Από"
-by = "από"
+By = "Ανά"
+by = "ανά"
 By Alphabetical = "αλφαβητικά"
-By Author = "με συγγραφέα"
-By Call Number = "με ταξινομικό αριθμό"
-By Course = "με μάθημα"
-By Department = "με τμήμα"
-By Era = "με εποχή "
-By Genre = "με είδος"
-By Instructor = "με διδάσκοντα"
-By Popularity = "με δημοφιλία"
-By Recent = "με παλαιότητα"
-By Region = "με περιοχή"
-By Title = "με τίτλο"
-By Topic = "με θέμα"
-Call Number = "Ταξινομικός #"
-callnumber_abbrev = "Ταξινομικός #"
+By Author = "ανά συγγραφέα"
+By Call Number = "ανά ταξιθετικό αριθμό"
+By Course = "ανά μάθημα"
+By Department = "ανά τμήμα"
+By Era = "ανά Χρονική Περίοδο"
+By Genre = "ανά Κειμενικό Είδος"
+By Instructor = "ανά Διδάσκοντα"
+By Popularity = "ανά Δημοτικότητα"
+By Recent = "ανά Παλαιότητα"
+By Region = "ανά Θεματική Περιοχή"
+By Title = "ανά Τίτλο"
+By Topic = "ανά Θέμα"
+Call Number = "Ταξιθετικός Αριθμός"
+callnumber_abbrev = "Ταξιθετικός Αριθμός"
 Cannot find record = "Δε βρέθηκε"
 Cannot find similar records = "Δε βρέθηκαν παρόμοια αρχεία"
 Cassette = "Κασέτα"
@@ -173,6 +172,10 @@ Catalog Results = "Αποτελέσματα καταλόγου"
 catalog_login_desc = "Εισάγετε τα στοιχεία εισόδου για τον κατάλογο."
 CD = "CD"
 Change Password = "Αλλαγή κωδικού"
+channel_add_more = "Προσθέστε παρόμοια κανάλια"
+channel_expand = "Βρείτε σχετικά κανάλια"
+channel_explore = "Ανακαλύψτε κανάλια"
+channel_search = "Εμφάνιση τεκμηρίων ως αποτελεσμάτων αναζήτησης"
 Check Hold = "Επιλογή κρατημένων"
 Check Recall = "Επιλογή ανακληθέντων"
 Checked Out = "Μη διαθέσιμο"
@@ -194,7 +197,7 @@ City = "Πόλη"
 Clear = "Καθαρισμός"
 clear_tag_filter = "Καθαρισμός φίλτρων"
 close = "κλείσιμο"
-Code = "Κώδικας"
+Code = "Κωδικός"
 Collection = "Συλλογή"
 Collection Browse = "Περιήγηση σε συλλογή"
 Collection Items = "Τεκμήρια συλλογής"
@@ -223,15 +226,14 @@ confirm_ill_request_cancel_selected_text = "Θέλετε να ακυρώσετε
 confirm_new_password = "Επιβεβαίωση νέου κωδικού"
 confirm_storage_retrieval_request_cancel_all_text = "Θέλετε να ακυρώσετε όλα τα τρέχοντα αιτήματα ανάκτησης από αποθήκη;"
 confirm_storage_retrieval_request_cancel_selected_text = "Θέλετε να ακυρώσετε τα επιλεγμένα τρέχοντα αιτήματα ανάκτησης από αποθήκη;"
-conjunction_or = "ή"
 Contents = "Περιεχόμενα"
 Contributing Source = "Πηγή συνεισφοράς"
 Contributors = "Συνεισφορές"
 Copies = "Αντίγραφα"
 Copy = "Αντίγραφο"
 Copyright = "Copyright"
-Corporate Author = "Corporate συγγραφέας"
-Corporate Authors = "Συλλογικά Όργανα"
+Corporate Author = "Συγγραφή απο Οργανισμό/Αρχή"
+Corporate Authors = "Συλλογικό Έργο"
 Country = "Χώρα"
 Course = "Μάθημα"
 Course Reserves = "Δεσμευμένα για μαθήματα"
@@ -241,12 +243,12 @@ Create a List = "Δημιουργία λίστας"
 Create New Account = "Δημιουργία λογαριασμού"
 Create New Password = "Δημιουργία νέου κωδικού"
 Created = "Δημιουργήθηκε"
-Database = "Βάση δεδομένων"
+Database = "Βάση Δεδομένων"
 Date = "Ημερομηνία"
-Date of birth = "Ημερομηνία γέννησης"
-Date of death = "Ημερομηνία θανάτου"
+Date of birth = "Ημερομηνία Γέννησης"
+Date of death = "Ημερομηνία Θανάτου"
 date_day_placeholder = "Η"
-date_from = "Από"
+date_from = "από"
 date_month_placeholder = "Μ"
 date_to = "έως"
 date_year_placeholder = "Ε"
@@ -273,6 +275,7 @@ Displaying the top = "Εμφανίζονται τα πρώτα"
 Document Inspector = "Επισκόπηση εγγράφου"
 Document Type = "Τύπος εγγράφου"
 DOI = "DOI"
+doi_detected_html = "Η αναζήτησή σας φαίνεται να περιέχει DOI. κάντε κλικ εδώ για να ελέγξετε τη διαθεσιμότητα της πηγής: <a href="%%url%%">%%doi%%</a>"
 Draw Search Box = "Σχεδιάστε την περιοχή αναζήτησης"
 Due = "Επιστροφή"
 Due Date = "Ημερομηνία επιστροφής"
@@ -301,9 +304,9 @@ eds_mode_smart = "Αναζήτηση SmartText"
 eds_modes_and_expanders = "Επιλογές αναζήτησης"
 Electronic = "Ηλεκτρονική πηγή"
 Email = "Ηλεκτρονικό ταχυδρομείο"
-Email Address = "Email διεύθυνση"
+Email Address = "διεύθυνση Email"
 Email address is invalid = "Η διεύθυνση email δεν είναι έγκυρη"
-Email Record = "Email αρχείο"
+Email Record = "αρχείο Email"
 Email this = "Αποστολή με email"
 Email this Search = "Αποστολή αναζήτησης με email"
 email_failure = "Σφάλμα - το μήνυμα δε στάλθηκε"
@@ -312,14 +315,14 @@ email_maximum_recipients_note = "Ο επιτρεπόμενος μέγιστος
 email_multiple_recipients_note = "Μπορείτε να ορίσετε πολλαπλούς παραλήπτες διαχωρίζοντάς τους με κόμμα."
 email_selected = "Αποστολή επιλεγμένων με email"
 email_selected_favorites = "Αποστολή επιλεγμένων αγαπημένων με email"
-email_sending = "Αποστολή μυνήματος..."
+email_sending = "Αποστολή μήνυματος..."
 email_subject = "Θέμα"
 email_success = "Το μήνυμα στάλθηκε"
 Empty = "Άδειο"
 Empty Book Bag = "Άδειασμα καλαθιού"
 Enable Auto Config = "Ενεργοποίηση αυτόματης παραμετροποίησης"
 End Page = "Τέλος σελίδας"
-Era = "Ιστορική περίοδος"
+Era = "Χρονική Περίοδος"
 error_inconsistent_parameters = "Παρουσιάστηκε σφάλμα. Κάποια παράμετρος είναι λάθος."
 error_page_parameter_list_heading = "Παράμετροι αιτήματος"
 Exception = "Εξαίρεση"
@@ -345,7 +348,11 @@ export_save = "Αποθήκευση αρχείου"
 export_selected = "Εξαγωγή επιλεγμένων"
 export_selected_favorites = "Εξαγωγή επιλεγμένων αγαπημένων"
 export_success = "Η εξαγωγή ολοκληρώθηκε"
-export_unsupported_format = "Αυτός ο τύπος εξαγωγής δεν υποστηρίζεται"
+export_unsupported_format = "Αυτός ο τύπος αρχείου δεν υποστηρίζεται για εξαγωγή"
+external_auth_heading = "Πρόσβαση σε αδειοδοτημένο υλικό"
+external_auth_login_message = "Συνδεθείτε για να έχετε πρόσβαση σε αδειοδοτημένο υλικό"
+external_auth_unauthorized = "Δεν έχετε δικαίωμα πρόσβασης σε αδειοδοτημένο υλικό"
+external_auth_unauthorized_desc = "Ο τρέχων λογαριασμός δεν έχει δικαίωμα πρόσβασης σε αδειοδοτημένο υλικό. Αποσυνδεθείτε και συνδεθείτε με τον κατάλληλο λογαριασμό."
 FAQs = "Ρωτήστε μας"
 fav_delete = "Διαγραφή επιλεγμένων αγαπημένων"
 fav_delete_deleting = "Διαγραφή των αγαπημένων σας"
@@ -355,14 +362,14 @@ fav_delete_success = "Τα αγαπημένα σας διαγράφηκαν"
 fav_delete_warn = "Πρόκειται να διαγράψετε αυτά τα αγαπημένα από όλες τις λίστες σας - Αν θέλετε να διαγράψετε τα αγαπημένα μόνο από μια λίστα παρακαλώ επιλέξτε τη λίστα πριν επιλέξετε διαγραφή."
 fav_email_fail = "Παρουσιάστηκε σφάλμα. Τα αγαπημένα σας δεν στάλθηκαν."
 fav_email_missing = "Ελλιπή στοιχεία. Τα αγαπημένα σας δεν στάλθηκαν."
-fav_email_success = " Τα αγαπημένα σας στάλθηκαν"
+fav_email_success = "Τα αγαπημένα σας στάλθηκαν"
 fav_export = "Εξαγωγή αγαπημένων"
 fav_list_delete = "Η λίστα αγαπημένων διαγράφηκε"
 fav_list_delete_cancel = "Η λίστα δεν διαγράφηκε"
 fav_list_delete_fail = "Παρουσιάστηκε σφάλμα. Η λίστα δεν διαγράφηκε"
 Favorites = "Αγαπημένα"
 Fee = "Χρέωση"
-Feedback = "σχόλιά"
+Feedback = "Σχόλιά"
 feedback_name = "Όνομα"
 Field of activity = "Πεδίο δραστηριότητας"
 File Description = "Περιγραφή αρχείου"
@@ -383,19 +390,18 @@ for search = "για την αναζήτηση"
 Forgot Password = "Ανάκτηση κωδικού"
 Form Submitted! = "Η φόρμα υποβλήθηκε!"
 Format = "Μορφή"
-found = "βρέθηκε"
 From = "από"
 Full description = "Πλήρης περιγραφή"
 Full text is not displayed to guests = "Οι επισκέπτες δεν έχουν πρόσβαση στο πλήρες κείμενο."
-fulltext_limit = "Μόνο τα άρθρα με πλήρες κείμενο"
-Gender = "Γένος"
+fulltext_limit = "Μόνο άρθρα με πλήρες κείμενο"
+Gender = "Φύλο"
 Genre = "Είδος"
 Geographic Search = "Γεωγραφική αναζήτηση"
 Geographic Terms = "Γεωγραφικοί όροι"
 Geography = "Γεωγραφία"
 Get full text = "Λήψη πλήρους κειμένου"
 Get RSS Feed = "Λήψη RSS"
-Globe = "Ουράνια σφαίρα"
+Globe = "Εμφάνιση Υδρογείου"
 Go = "Έναρξη"
 Go to Standard View = "Κανονική προβολή"
 go_to_list = "Μετάβαση στη λίστα"
@@ -406,7 +412,7 @@ Group = "Κατηγορία"
 group_AND = "Όλες οι ομάδες"
 group_OR = "Οποιαδήποτε ομάδα"
 Has Illustrations = "Ναι"
-Help = "Βοήθεια για την έρευνά μου"
+Help = "Βοήθεια για την αναζήτηση μου"
 Help with Advanced Search = "Βοήθεια για τη σύνθετη αναζήτηση"
 Help with Search Operators = "Βοήθεια για τους τελεστές αναζήτησης"
 help_page_missing = "Η σελίδα βοήθειας που ζητήσατε δεν υπάρχει."
@@ -416,26 +422,26 @@ hierarchy_tree = "Κατάταξη"
 hierarchy_tree_error = " Δεν ήταν δυνατή η εμφάνιση της κατάταξης"
 hierarchy_view_context = "Εμφάνιση κατάταξης"
 History = "Ιστορικό"
-history_delete = "Διαγραφή;"
-history_delete_link = "Διαγραφή"
+history_delete = "Διαγραφή Ιστορικόυ;"
+history_delete_link = "Διαγραφή Συνδέσμου"
 history_empty_search = "Οτιδήποτε (κενή αναζήτηση)"
 history_limits = "Φίλτρα"
 history_no_searches = "Δεν βρέθηκαν αναζητήσεις στο ιστορικό."
 history_purge = "Καθαρισμός αναζητήσεων"
 history_recent_searches = "Πρόσφατες αναζητήσεις"
 history_results = "Αποτελέσματα"
-history_save = "Αποθήκευση;"
-history_save_link = "Αποθήκευση"
-history_saved_searches = "Αποθηκευμένες αναζητήσεις"
-history_search = "Αναζήτηση"
-history_time = "Πότε"
+history_save = "Αποθήκευση Ιστορικού;"
+history_save_link = "Αποθήκευση Σύνδεσμου Ιστορικού"
+history_saved_searches = "Αποθηκευμένες Αναζητήσεις Ιστορικού"
+history_search = "Αναζήτηση Ιστορικού"
+history_time = "Ώρα Ιστορικού"
 hold_available = "Διαθέσιμο"
 hold_cancel = "Ακύρωση κράτησης"
 hold_cancel_all = "Ακύρωση όλων των κρατήσεων"
 hold_cancel_fail = "Το αίτημά σας δεν ακυρώθηκε. Απευθυνθείτε στην εξυπηρέτηση για βοήθεια"
 hold_cancel_selected = "Ακύρωση επιλεγμένων κρατήσεων"
 hold_cancel_success = "Το αίτημά σας ακυρώθηκε με επιτυχία"
-hold_cancel_success_items = "Τα αιτήματά σας ακυρώθηκαν με επιτυχία"
+hold_cancel_success_items = "%%count%% Τα αιτήματά σας ακυρώθηκαν με επιτυχία"
 hold_date_invalid = "Παρακαλώ εισάγετε έγκυρη ημερομηνία"
 hold_date_past = "Παρακαλώ εισάγετε μελλοντική ημερομηνία"
 hold_empty_selection = "Δεν επιλέχτηκαν κρατήσεις"
@@ -443,19 +449,21 @@ hold_error_blocked = "Δεν έχετε δικαίωμα να υποβάλετε
 hold_error_fail = "Το αίτημά σας απέτυχε. Απευθυνθείτε στην εξυπηρέτηση για βοήθεια"
 hold_invalid_pickup = "Η βιβλιοθήκη παραλαβής δεν είναι έγκυρη. Παρακαλώ εισάγετε άλλη"
 hold_invalid_request_group = "Μη έγκυρο αίτημα. Δοκιμάστε ξανά."
-hold_login = "για πληροφορίες κράτησης και ανάκλησης"
+hold_items_available = "Δεν μπορεί να γίνει κράτηση γιατί υπάρχουν ήδη διαθέσιμα τεκμήρια."
+hold_login = "Είσοδος για πληροφορίες κράτησης και ανάκλησης"
 hold_place = "Αίτημα κράτησης"
 hold_place_fail_missing = "Το αίτημά σας απέτυχε. Ελλιπή στοιχεία. Απευθυνθείτε στην εξυπηρέτηση για βοήθεια "
 hold_place_success_html = "Το αίτημά σας καταχωρήθηκε. <a href="%%url%%">Αιτήματα κράτησης και ανάκλησης</a>."
 hold_profile_html = "Για πληροφορίες κράτησης / ανάκλησης χρησιμοποιήστε τον <a href"
 hold_queue_position = "Θέση στην ουρά"
+hold_record_already_on_loan = "Έχετε ήδη δανειστεί αυτόν τον τίτλο"
 hold_request_group = "Αίτημα προς"
 hold_requested_group = "Υποβλήθηκε αίτημα προς"
-hold_required_by = "Αίτημα κράτησης άκυρο από "
+hold_required_by = "Αίτημα κράτησης άκυρο από"
 hold_success = "Το αίτημά σας καταχωρήθηκε"
 Holdings = "Τεκμήρια"
 Holdings at Other Libraries = "Τεκμήρια σε άλλες βιβλιοθήκες"
-Holdings details from = "Λεπτομέρειες τεκμηρίων από"
+holdings_details_from = "Λεπτομέρειες τεκμηρίων από %%location%%"
 Holdings_notes = "Σημειώσεις"
 Holds = "Κρατήσεις"
 Holds and Recalls = "Κρατήσεις και ανακλήσεις"
@@ -469,7 +477,7 @@ ill_request_cancel_all = "Ακύρωση όλων των αιτημάτων δι
 ill_request_cancel_fail = "Το αίτημά σας δεν ακυρώθηκε. Απευθυνθείτε στην εξυπηρέτηση για βοήθεια"
 ill_request_cancel_selected = "Ακύρωση των επιλεγμένων αιτημάτων διαδανεισμού"
 ill_request_cancel_success = "Το αίτημά σας ακυρώθηκε με επιτυχία"
-ill_request_cancel_success_items = "Τα αιτήματά σας ακυρώθηκαν με επιτυχία"
+ill_request_cancel_success_items = "%%count%% Τα αιτήματά σας ακυρώθηκαν με επιτυχία"
 ill_request_canceled = "Ακυρώθηκε"
 ill_request_check_text = "Έλεγχος αιτήματος διαδανεισμού"
 ill_request_comments = "Σχόλια"
@@ -498,7 +506,6 @@ ils_offline_login_message = "Τα στοιχεία του λογαριασμού
 ils_offline_status = "Ο κατάλογος της βιβλιοθήκης βρίσκεται σε κατάσταση συντήρησης."
 ils_offline_title = "Σύστημα σε κατάσταση συντήρησης"
 Import Record = "Εισαγωγή εγγραφής"
-Import to = "Εισαγωγή σε "
 in = "σε"
 In This Collection = "Σε αυτή τη συλλογή"
 in_collection_label = "Στη συλλογή:"
@@ -506,7 +513,7 @@ include_synonyms = "Συμπερίληψη αποτελεσμάτων από σ
 Index Terms = "Όροι ευρετηρίου"
 Indexes = "Ευρετήρια"
 information = "Πληροφορίες"
-Institution = "Πηγή"
+Institution = "Ίδρυμα"
 Institutional Login = "Ιδρυματικός λογαριασμός"
 institutional_login_desc = "Εισάγετε τα στοιχεία εισόδου του ιδρυματικού σας λογαριασμού."
 Instructor = "Διδάσκων"
@@ -526,25 +533,25 @@ Item removed from favorites = "Το τεκμήριο αφαιρέθηκε από
 Item removed from list = "Το τεκμήριο αφαιρέθηκε από τη λίστα"
 Items = "Τεκμήρια"
 items = "τεκμήρια"
-items_added_to_bookbag = "τεκμήρια προστέθηκαν στο καλάθι σας"
-items_already_in_bookbag = "τεκμήρια ήδη περιέχονται στο καλάθι σας ή δεν είναι δυνατό να προστεθούν"
+items_added_to_bookbag = "%%count%% τεκμήρια προστέθηκαν στο καλάθι σας"
+items_already_in_bookbag = "%%count%% τεκμήρια ήδη περιέχονται στο καλάθι σας ή δεν είναι δυνατό να προστεθούν"
 Journal = "Επιστημονικό περιοδικό"
 Journal Articles = "Άρθρα περιοδικού"
 Journal Info = "Στοιχεία περιοδικού"
 Journal Title = "Τίτλος περιοδικού"
 Journals = "Επιστημονικά περιοδικά"
 Jump to = "Μετάβαση σε"
-just_cataloged = "Μόλις καταλογογραφήθηκε"
-Keyword = " λέξη-κλειδί "
-Keyword Filter = "Περιορισμός με λέξη-κλειδί"
-Kit = "Κιτ"
+just_cataloged = "Μόλις εγγράφηκε στον καταλογο"
+Keyword = "Λέξη-Κλειδί "
+Keyword Filter = "Περιορισμός με Λέξη-Κλειδί"
+Kit = "Εργαλειοθήκη"
 Language = "Γλώσσα"
 large = "Μεγάλο μέγεθος"
 Last = "Τελευταία"
 Last Modified = "Τελευταία τροποποίηση"
 Last Name = "Επώνυμο"
 less = "λιγότερα"
-libphonenumber_invalid = "Άκυρος τηλφεωνικός αριθμός"
+libphonenumber_invalid = "Άκυρος τηλεφωνικός αριθμός"
 libphonenumber_invalidcountry = "Άκυρο πρόθεμα χώρας"
 libphonenumber_invalidregion = "Άκυρο πρόθεμα περιοχής"
 libphonenumber_notanumber = "Τηλεφωνικός αριθμός με ακατάλληλους χαρακτήρες"
@@ -591,8 +598,8 @@ Map = "Χάρτης"
 Map View = "Προβολή χάρτη"
 map_results_label = "Σε αυτή την τοποθεσία:"
 Maps = "Χάρτες"
-Media Format = "Μορφή μέσου"
-medium = " Μέτριο μέγεθος "
+Media Format = "Μορφή Μέσου"
+medium = "Μέτριο μέγεθος"
 MeSH Terms = "Ιατρικοί όροι (MeSH)"
 Message = "Μήνυμα"
 Message From Sender = "Μήνυμα από αποστολέα"
@@ -607,10 +614,10 @@ More options = "Περισσότερες επιλογές"
 More Summon results = "Περισσότερα αποτελέσματα (Summon)"
 More Topics = "Περισσότερα θέματα"
 more_authors_abbrev = "κ.ά."
-more_info_toggle = "Εμφάνιση / απόκρυψη περισσότερων πληροφοριών."
+more_info_toggle = "Εμφάνιση/απόκρυψη περισσότερων πληροφοριών."
 more_topics = "%%count%% περισσότερα θέματα"
 Most Recent Received Issues = "πιο πρόσφατα τεύχη"
-Multiple Call Numbers = "Πολλαπλοί ταξινομικοί αριθμοί"
+Multiple Call Numbers = "Πολλαπλοί ταξιθετικοί αριθμοί"
 Multiple Locations = "Πολλαπλές τοποθεσίες"
 Musical Score = "Παρτιτούρα"
 My Favorites = "Τα αγαπημένα μου"
@@ -644,12 +651,11 @@ nohit_active_filters = "Ένα ή περισσότερα φίλτρα έχουν
 nohit_change_tab = "Κάνετε αναζήτηση στην καρτέλα "%%activeTab%%". Μπορεί να βρείτε σχετικά αποτελέσματα σε μια από τις άλλες καρτέλες:"
 nohit_filters = "Ενεργά φίλτρα αναζήτησης:"
 nohit_heading = "Κανένα αποτέλεσμα!"
+nohit_lookfor_html = "Για την αναζήτησή σας - <strong>%%lookfor%%</strong> - δε βρέθηκαν αποτελέσματα"
 nohit_no_filters = "Δεν υπάρχουν ενεργά φίλτρα για την αναζήτηση."
 nohit_parse_error = "Δεν βρέθηκαν αποτελέσματα. Ελέγξτε τη σύνταξη ή βάλτε τη φράση αναζήτησης σε εισαγωγικά"
-nohit_prefix = "Για την αναζήτησή σας"
 nohit_query_without_filters = "Αφαίρεση όλων των φίλτρων αναζήτησης."
 nohit_spelling = "Ελέγξτε την ορθογραφία"
-nohit_suffix = "δε βρέθηκαν αποτελέσματα"
 nohit_suggest = "Δοκιμάστε εναλλακτική αναζήτηση με λιγότερες λέξεις ή ελέγξτε την ορθογραφία"
 NOT = "NOT"
 Not Illustrated = "Όχι"
@@ -691,7 +697,7 @@ number_decimal_point = ","
 number_thousands_separator = "."
 OAI Server = "Εξυπηρετητής OAI"
 Occupation = "Επάγγελμα"
-of = "από"
+of_num_results = "#%%position%% από %%total%% Αποτελέσματα"
 old_password = "Τρέχων κωδικός"
 On Reserve = "Δεσμευμένο"
 On Reserve - Ask at Circulation Desk = "Δεσμευμένο - Απευθυνθείτε στο προσωπικό"
@@ -699,6 +705,7 @@ on_reserve = "Δεσμευμένο - Απευθυνθείτε στο τμήμα
 on_topic = "%%count%% τεκμήριο(α) για αυτό το θέμα"
 Online Access = "Διαθέσιμο Online"
 online_resources = "Πλήρες κείμενο"
+open_access_limit = "Περιορισμός σε περιεχόμενο ανοιχτής πρόσβασης"
 operator_contains = "περιλαμβάνει"
 operator_exact = "είναι (ακριβώς)"
 OR = "OR"
@@ -737,8 +744,6 @@ Please check back soon = "Ελέγξτε πάλι αργότερα"
 Please contact the Library Reference Department for assistance = "Απευθυνθείτε στο προσωπικό της βιβλιοθήκης για βοήθεια"
 Please enable JavaScript. = "Πρέπει να ενεργοποιήσετε το JavaScript."
 Please upgrade your browser. = "Αναβαθμίστε τον φυλλομετρητή σας."
-Posted by = "Αποστολέας"
-posted_on = "στις"
 Preferences = "Επιλογές"
 Preferred Library = "Προεπιλεγμένη βιβλιοθήκη"
 Prev = "Προηγούμενα"
@@ -763,7 +768,7 @@ Publication Year = "Έτος έκδοσης"
 Publication_Place = "Τόπος έκδοσης"
 Published = "Έκδοση"
 Published in = "Τόπος έκδοσης"
-Publisher = "εκδότη"
+Publisher = "Εκδότης"
 Publisher Information = "Στοιχεία εκδότη"
 Publisher Permissions = "Άδειες εκδότη"
 QR Code = "Κώδικας QR"
@@ -820,12 +825,12 @@ request_in_transit = "Σε μεταφορά προς την τοποθεσία 
 request_place_text = "Δημιουργία αιτήματος"
 request_submit_text = "Υποβολή αιτήματος"
 Requests = "Αιτήσεις"
-Reserves = "Καρατήσεις"
+Reserves = "Κρατήσεις"
 Reserves Search = "Αναζήτηση κρατήσεων"
 Reserves Search Results = "Αποτελέσματα αναζήτησης κρατήσεων"
 result_count = "%%count%% αποτελέσματα"
 Results = "Αποτελέσματα"
-results = "Αποτελέσματα"
+results = "αποτελέσματα"
 Results for = "Αποτελέσματα για"
 Results per page = "Αποτελέσματα ανά σελίδα"
 Resumption Token = "Αναγνωριστικό ανάκτησης"
@@ -837,7 +842,7 @@ save_search = "Αποθήκευση αναζήτησης"
 save_search_remove = "Κατάργηση αποθηκευμένης αναζήτησης"
 Saved in = "Αποθηκεύτηκε σε"
 scholarly_limit = "Περιορισμός σε άρθρα επιστημονικών περιοδικών"
-Scroll to Load More = "Κυλήστε προς τα κάτω για να εμφανιστούν περισσότερα"
+Scroll to Load More = "Εμφάνιση περισσοτέρων προς τα κάτω"
 Search = "Αναζήτηση"
 Search For = "Αναζήτηση για"
 Search For Items on Reserve = "Αναζήτηση σε δεσμευμένα τεκμήρια"
@@ -874,9 +879,14 @@ Sensor Image = "Εικόνα αισθητήρα"
 Serial = "Περιοδική έκδοση"
 Series = "Σειρά"
 Set = "Εφαρμογή"
-Showing = "Εμφανίζονται"
-sidebar_close = "Σύμπτυξη πλαϊνής μπάρας"
-sidebar_expand = "Ανάπτυξη πλαϊνής μπάρας"
+showing_items_html = "Εμφανίζονται <strong>%%start%% - %%end%%</strong> Τεκμήρια"
+showing_items_of_html = "Εμφανίζονται <strong>%%start%% - %%end%%</strong> από <strong>%%total%%</strong> Τεκμήρια"
+showing_results_for_html = "Εμφανίζονται <strong>%%start%% - %%end%%</strong> Αποτελέσματα για την αναζήτηση '<strong>%%lookfor%%</strong>'"
+showing_results_html = "Εμφανίζονται <strong>%%start%% - %%end%%</strong> Αποτελέσματα"
+showing_results_of_for_html = "Εμφανίζονται <strong>%%start%% - %%end%%</strong> Αποτελέσματα από <strong>%%total%%</strong> για την αναζήτηση '<strong>%%lookfor%%</strong>'"
+showing_results_of_html = "Εμφανίζονται <strong>%%start%% - %%end%%</strong> Αποτελέσματα από <strong>%%total%%</strong>"
+sidebar_close = "Σύμπτυξη πλευρικής μπάρας"
+sidebar_expand = "Ανάπτυξη πλευρικής μπάρας"
 Similar Items = "Παρόμοια τεκμήρια"
 Skip to content = "Μετάβαση στο περιεχόμενο"
 skip_confirm = "Σίγουρα θέλετε να παραλείψετε αυτό το βήμα;"
@@ -884,22 +894,22 @@ skip_fix_metadata = "Να μην επιδιορθωθούν τα μεταδεδ
 skip_step = "Παράλειψη βήματος"
 Slide = "Διαφάνειες"
 sms_failure = "Σφάλμα. Αδυναμία αποστολής μυνήματος"
-sms_phone_number = "10-ψήφιος αριθμός τηλεφώνου"
-sms_sending = "Αποστολή μυνήματος"
-sms_success = "Αποστολή μυνήματος επιτυχής"
+sms_phone_number = "Αριθμός τηλεφώνου για Αποστολή SMS"
+sms_sending = "Αποστολή μηνύματος SMS"
+sms_success = "Αποστολή μηνύματος SMS επιτυχής"
 Software = "Λογισμικό"
 Sorry, but the help you requested is unavailable in your language. = "Το θέμα της βοήθειας που ψάχνετε δεν είναι διαθέσιμο για τη γλώσσα σας."
 Sort = "Ταξινόμηση"
 sort_alphabetic = "Αλφαβητικά"
-sort_author = "Με συγγραφέα"
+sort_author = "Ανά συγγραφέα"
 sort_author_author = "Αλφαβητικά"
-sort_author_relevance = "Με δημοφιλία"
-sort_callnumber = "Με ταξινομικό"
-sort_count = "Σύνολο αποτελεσμάτων"??"
-sort_relevance = "Με σχετικότητα"
-sort_title = "Με τίτλο"
-sort_year = "Με ημερομηνία (φθ.)"
-sort_year asc = "Με ημερομηνία (αυξ.)"
+sort_author_relevance = "Ανά δημοτικότητα"
+sort_callnumber = "Ανα Ταξιθετικό Αριθμό"
+sort_count = "Αριθμός αποτελεσμάτων"
+sort_relevance = "Ανά σχετικότητα"
+sort_title = "Ανά Τίτλο"
+sort_year = "Ανά Ημερομηνία (φθιν.)"
+sort_year asc = "Ανά Ημερομηνία (αυξ.)"
 Source = "Πηγή"
 Source Title = "Τίτλος πηγής"
 spell_expand_alt = "Επέκταση αναζήτησης"
@@ -918,7 +928,7 @@ storage_retrieval_request_cancel_all = "Ακύρωση όλων των αιτη
 storage_retrieval_request_cancel_fail = "Το αίτημά σας δεν ακυρώθηκε. Απευθυνθείτε στην εξυπηρέτηση για βοήθεια"
 storage_retrieval_request_cancel_selected = "Ακύρωση των επιλεγμένων αιτημάτων ανάκτησης από αποθήκη"
 storage_retrieval_request_cancel_success = "Το αίτημά σας ακυρώθηκε με επιτυχία"
-storage_retrieval_request_cancel_success_items = "Τα αιτήματά σας ακυρώθηκαν με επιτυχία"
+storage_retrieval_request_cancel_success_items = "%%count%% Τα αιτήματά σας ακυρώθηκαν με επιτυχία"
 storage_retrieval_request_canceled = "Ακυρώθηκε"
 storage_retrieval_request_check_text = "Έλεγχος αιτήματος ανάκτησης από αποθήκη"
 storage_retrieval_request_comments = "Σχόλια"
@@ -949,14 +959,14 @@ Subject Terms = "Θεματικοί όροι"
 Subject(s) = "Θέμα(τα)"
 Subjects = "Θέματα"
 Submit = "Υποβολή"
-Submitting = "Υποβολή"
+Submitting = "Προς Υποβολή"
 Suggested Topics = "Προτεινόμενα θέματα"
 Summary = "Περίληψη"
 Summon Results = "Αποτελέσματα (Summon)"
 summon_database_recommendations = "Πρόσθετες πηγές:"
 Supplements = "Παραρτήματα"
 Supplied by Amazon = "Παρέχεται από το Amazon"
-Switch view to = "Αλλαγή προβολής σε"
+switch_view = "Αλλαγή προβολής σε %%view%%"
 switchquery_fuzzy = "Εκτελώντας μια ασαφή αναζήτηση (fuzzy search) μπορείτε να βρείτε όρους με συναφή ορθογραφία"
 switchquery_intro = "Η τροποποίηση των όρων αναζήτησης μπορεί να δώσει περισσότερα αποτελέσματα."
 switchquery_lowercasebools = "Για να χρησιμοποιήσετε λογικούς τελεστές θα πρέπει να τους εισάγετε με κεφαλαία"
@@ -977,7 +987,7 @@ tags_deleted = "%count% ετικέτες διαγράφηκαν"
 test_fail = "Αποτυχία"
 test_fix = "Επιδιόρθωση"
 test_ok = "OK"
-Text this = "Αποστολή με sms"
+Text this = "Αποστολή με SMS"
 Thank you for your feedback. = "Σας ευχαριστούμε για τον σχολιασμό."
 That email address is already used = "Το email χρησιμοποιείται ήδη"
 That username is already taken = "Το όνομα χρήστη χρησιμοποιείται ήδη"
@@ -998,8 +1008,7 @@ Too Many Email Recipients = "Πάρα πολλοί παραλήπτες email"
 too_many_favorites = "Η λίστα είναι πολύ μεγάλη για να προβληθεί. κάντε ανακατανομή των αγαπημένων σας σε περισσότερες λίστες ή βάλτε περιορισμούς χρησιμοποιώντας ετικέτες."
 too_many_new_items = "Τα τεκμήρια είναι πάρα πολλά για να εμφανιστούν σε μια λίστα. Περιορίστε την αναζήτησή σας."
 too_many_reserves = "Τα δεσμευμένα τεκμήρια είναι πάρα πολλά για να εμφανιστούν σε μια λίστα. Περιορίστε την αναζήτησή σας."
-top_facet_additional_prefix = "Περισσότερα "
-top_facet_suffix = " σχετικά με την αναζήτησή σας."
+top_facet_label = "%%label%% σχετικά με την αναζήτησή σας."
 Topic = "Θέμα"
 Topics = "Θέματα"
 Total Balance Due = "Σύνολο χρεώσεων"
@@ -1009,16 +1018,16 @@ total_resources = "Σύνολο στοιχείων"
 total_saved_items = "Σύνολο αποθηκευμένων"
 total_tags = "Σύνολο ετικετών"
 total_users = "Σύνολο χρηστών"
-Transliterated Title = "Μεταγραφείς τίτλος"
+Transliterated Title = "Μεταγλωττισμένος Τίτλος"
 tree_search_limit_reached_html = "Η αναζήτηση επέστρεψε πάρα πολλά αποτελέσματα. Εμφανίζονται μόνο τα πρώτα <b>%%limit%%</b>. Δείτε όλα τα αποτελέσματα <a id"
 unique_tags = "Μοναδικές ετικέτες"
-University Library = "Πανεπιστημιακή βιβλιοθήκη"
+University Library = "Πανεπιστημιακή Βιβλιοθήκη"
 Unknown = "Άγνωστο"
 unrecognized_facet_label = "Άλλο"
 Upgrade VuFind = "Αναβάθμιση VuFind"
 upgrade_description = "Αν αναβαθμίζετε από προηγούμενη έκδοση του VuFind, μπορείτε να εισάγετε τις παλιές σας ρυθμίσεις με αυτό το εργαλείο."
 URL = "Σύνδεσμος"
-Use for = "Use for"
+Use for = "Χρήση για"
 Use instead = "Εναλλακτικά χρησιμοποιήστε"
 User Account = "Λογαριασμός χρήστη"
 Username = "Όνομα χρήστη"
@@ -1028,15 +1037,15 @@ VHS = "VHS"
 Video = "Βίντεο"
 Video Clips = "Βιντεοκλιπ"
 Videos = "Βίντεο"
-view already selected = "Προβολή ήδη επιλεγμένων"
 View Book Bag = "Προβολή καλαθιού"
 View Full Collection = "Εμφάνιση ολόκληρης της συλλογής"
 View Full Record = "Εμφάνιση ολόκληρης της εγγραφής"
-View in EDS = "προβολή σε EDS"
+View in EDS = "Προβολή σε EDS"
 View online: Full view Book Preview from the Hathi Trust = "Δείτε online: Το βιβλίο παρέχεται από το Hathi Trust"
 View Record = "Εμφάνιση εγγραφής"
 View Records = "προβολή εγγραφών"
 View this record in EBSCOhost = "Προβολή αυτής της εγγραφής στο EBSCOhost"
+view_already_selected = "%%current%% Προβολή ήδη επιλεγμένων"
 visual_facet_parent = "από"
 Volume = "Τόμος"
 Volume Holdings = "Τεκμήρια τόμου"
diff --git a/languages/en-gb.ini b/languages/en-gb.ini
index a6287be75929a2ff9e7a986d7f08f66c8fa78764..2db8ed142743162dd09e7b06730153cabcbd2dec 100644
--- a/languages/en-gb.ini
+++ b/languages/en-gb.ini
@@ -1,8 +1,7 @@
 ; For future reference:
 ;English = English
 @parent_ini = "en.ini"
-Add to favorites = "Add to Favourites"
-add_favorite_suffix = "to favourites"
+add_to_favorites_html = "Add <em>%%title%%</em> to favourites"
 adv_search_callnumber = "Classmarks"
 Browse the Catalog = "Browse the Catalogue"
 browse_dewey = "Classmark (Dewey)"
@@ -18,6 +17,7 @@ delete_selected_favorites = "Delete Selected Favourites"
 email_selected_favorites = "Email Selected Favourites"
 Export Favorites = "Export Favourites"
 export_selected_favorites = "Export Selected Favourites"
+external_auth_unauthorized = "You are not authorised to access licensed material"
 fav_delete = "Delete Selected Favourites"
 fav_delete_deleting = "Your favourite(s) are being deleted."
 fav_delete_fail = "Sorry, an error has occurred. Your favourite(s) were not deleted."
@@ -32,7 +32,7 @@ Favorites = "Favourites"
 hold_available = "Available for Collection"
 hold_cancel_fail = "Your request was not cancelled. Please contact the issue desk for further assistance"
 hold_cancel_success = "Your request was successfully cancelled"
-hold_cancel_success_items = "request(s) were successfully cancelled"
+hold_cancel_success_items = "%%count%% request(s) were successfully cancelled"
 hold_error_fail = "Your request failed. Please contact the issue desk for further assistance"
 hold_place_fail_missing = "Your request failed. Some data was missing. Please contact the issue desk for further assistance"
 ill_request_available = "Available for Collection"
diff --git a/languages/en.ini b/languages/en.ini
index 7e22da36c5a8f686673a9b0a3d2037c485def840..336887603b204ea51b5c04e7622e01811afb0963 100644
--- a/languages/en.ini
+++ b/languages/en.ini
@@ -6,7 +6,7 @@ Access URL = "Access URL"
 access_denied = "Access denied."
 Accession Number = "Accession Number"
 Account = "Account"
-Add = "Add"
+account_block_options_missing = "Some choices have been removed due to a block on your account. Details: %%details%%"
 Add a Library Card = "Add a Library Card"
 Add a Note = "Add a Note"
 Add Tag = "Add Tag"
@@ -18,8 +18,6 @@ Add your comment = "Add your comment"
 add_comment_fail_blank = "Comment cannot be blank."
 add_comment_success = "Comment added."
 add_favorite_fail = "Error: Record not saved"
-add_favorite_prefix = "Add"
-add_favorite_suffix = "to favorites"
 add_list_fail = "Error: List not created"
 add_other_libraries = "Include articles at other libraries"
 add_search = "Add Search Field"
@@ -27,6 +25,7 @@ add_search_group = "Add Search Group"
 add_tag_error = "Error: Could Not Save Tags"
 add_tag_note = "Spaces will separate tags. Use quotes for multi-word tags."
 add_tag_success = "Tags Saved"
+add_to_favorites_html = "Add <em>%%title%%</em> to favorites"
 Address = "Address"
 adv_search_all = "All Fields"
 adv_search_author = "Author"
@@ -172,6 +171,11 @@ Catalog Results = "Catalog Results"
 catalog_login_desc = "Enter your library catalog credentials."
 CD = "CD"
 Change Password = "Change Password"
+channel_add_more = "Add more channels like this"
+channel_expand = "Explore related channels"
+channel_explore = "Explore Channels"
+channel_search = "Show items as search results"
+channel_searchbox_label = "Search for more channels:"
 Check Hold = "Check Hold"
 Check Recall = "Check Recall"
 Checked Out = "Checked Out"
@@ -222,7 +226,6 @@ confirm_ill_request_cancel_selected_text = "Do you wish to cancel your selected
 confirm_new_password = "Confirm New Password"
 confirm_storage_retrieval_request_cancel_all_text = "Do you wish to cancel all your current storage retrieval requests?"
 confirm_storage_retrieval_request_cancel_selected_text = "Do you wish to cancel your selected storage retrieval requests?"
-conjunction_or = "or"
 Contents = "Contents"
 Contributing Source = "Contributing Source"
 Contributors = "Contributors"
@@ -272,6 +275,7 @@ Displaying the top = "Displaying the top"
 Document Inspector = "Document Inspector"
 Document Type = "Document Type"
 DOI = "DOI"
+doi_detected_html = "Your search appears to contain a DOI. Click here to check the availability of the resource: <a href="%%url%%">%%doi%%</a>"
 Draw Search Box = "Draw Search Box"
 Due = "Due"
 Due Date = "Due Date"
@@ -285,6 +289,7 @@ edit_list_fail = "Sorry, you are not permitted to edit this list"
 edit_list_success = "List successfully updated."
 Edition = "Edition"
 eds_expander_fulltext = "Also search within the full text of the articles"
+eds_expander_relatedsubjects = "Apply equivalent subjects"
 eds_expander_thesaurus = "Apply related words"
 eds_limiter_FC = "Catalog Only"
 eds_limiter_FC1 = "Institutional Repository Only"
@@ -323,7 +328,7 @@ error_inconsistent_parameters = "Sorry, an error has occurred. Inconsistent para
 error_page_parameter_list_heading = "Request Parameters"
 Exception = "Exception"
 Excerpt = "Excerpt"
-exclude_facet = "[exclude]"
+exclude_facet = "Exclude matching results"
 exclude_newspapers = "Exclude newspaper articles"
 Expires = "Expires"
 Export = "Export"
@@ -345,6 +350,10 @@ export_selected = "Export Selected"
 export_selected_favorites = "Export Selected Favorites"
 export_success = "Export Complete"
 export_unsupported_format = "Unsupported Export Format"
+external_auth_heading = "Access to licensed material"
+external_auth_login_message = "Login to access licensed material"
+external_auth_unauthorized = "You are not authorized to access licensed material"
+external_auth_unauthorized_desc = "Your login method does not provide access to licensed material. Please log out and then log in using another method."
 FAQs = "FAQs"
 fav_delete = "Delete Selected Favorites"
 fav_delete_deleting = "Your favorite(s) are being deleted."
@@ -382,7 +391,6 @@ for search = "for search"
 Forgot Password = "Forgot Password"
 Form Submitted! = "Form Submitted!"
 Format = "Format"
-found = "found"
 From = "From"
 Full description = "Full description"
 Full text is not displayed to guests = "Full text is not displayed to guests."
@@ -434,7 +442,7 @@ hold_cancel_all = "Cancel All Holds"
 hold_cancel_fail = "Your request was not canceled. Please contact the circulation desk for further assistance"
 hold_cancel_selected = "Cancel Selected Holds"
 hold_cancel_success = "Your request was successfully canceled"
-hold_cancel_success_items = "request(s) were successfully canceled"
+hold_cancel_success_items = "%%count%% request(s) were successfully canceled"
 hold_date_invalid = "Please enter a valid date"
 hold_date_past = "Please enter a date in the future"
 hold_empty_selection = "No holds were selected"
@@ -443,19 +451,20 @@ hold_error_fail = "Your request failed. Please contact the circulation desk for
 hold_invalid_pickup = "An invalid pick up location was entered. Please try again"
 hold_invalid_request_group = "An invalid hold request group was entered. Please try again"
 hold_items_available = "Cannot place a hold because items are available."
-hold_login = "for hold and recall information"
+hold_login = "Login for hold and recall information"
 hold_place = "Place Request"
 hold_place_fail_missing = "Your request failed. Some data was missing. Please contact the circulation desk for further assistance"
 hold_place_success_html = "Your request was successful. <a href="%%url%%">Your Holds and Recalls</a>."
 hold_profile_html = "For hold and recall information, please establish your <a href="%%url%%">Library Catalog Profile</a>."
 hold_queue_position = "Queue Position"
+hold_record_already_on_loan = "You already have the record on loan"
 hold_request_group = "Request from"
 hold_requested_group = "Requested from"
 hold_required_by = "No longer required after"
 hold_success = "Your request was successful"
 Holdings = "Holdings"
 Holdings at Other Libraries = "Holdings at Other Libraries"
-Holdings details from = "Holdings details from"
+holdings_details_from = "Holdings details from %%location%%"
 Holdings_notes = "Notes"
 Holds = "Holds"
 Holds and Recalls = "Holds and Recalls"
@@ -469,7 +478,7 @@ ill_request_cancel_all = "Cancel All Interlibrary Loan Requests"
 ill_request_cancel_fail = "Your request was not canceled. Please contact the circulation desk for further assistance"
 ill_request_cancel_selected = "Cancel Selected Interlibrary Loan Requests"
 ill_request_cancel_success = "Your request was successfully canceled"
-ill_request_cancel_success_items = "request(s) were successfully canceled"
+ill_request_cancel_success_items = "%%count%% request(s) were successfully canceled"
 ill_request_canceled = "Canceled"
 ill_request_check_text = "Check Interlibrary Loan Request"
 ill_request_comments = "Comments"
@@ -498,7 +507,6 @@ ils_offline_login_message = "Your account details will be unavailable during thi
 ils_offline_status = "Our Library Management System is currently under maintenance."
 ils_offline_title = "System Under Maintenance"
 Import Record = "Import Record"
-Import to = "Import to "
 in = "in"
 In This Collection = "In This Collection"
 in_collection_label = "In collection:"
@@ -526,8 +534,8 @@ Item removed from favorites = "Item removed from favorites"
 Item removed from list = "Item removed from list"
 Items = "Items"
 items = "items"
-items_added_to_bookbag = "item(s) added to your Book Bag"
-items_already_in_bookbag = "item(s) are either already in your Book Bag or could not be added"
+items_added_to_bookbag = "%%count%% item(s) added to your Book Bag"
+items_already_in_bookbag = "%%count%% item(s) are either already in your Book Bag or could not be added"
 Journal = "Journal"
 Journal Articles = "Journal Articles"
 Journal Info = "Journal Info"
@@ -645,12 +653,11 @@ nohit_active_filters = "One or more facet filters have been applied to this sear
 nohit_change_tab = "You have been searching in the "%%activeTab%%" tab. You may find something in one of the other tabs:"
 nohit_filters = "Filters currently applied to this search:"
 nohit_heading = "No Results!"
+nohit_lookfor_html = "Your search - <strong>%%lookfor%%</strong> - did not match any resources."
 nohit_no_filters = "No filters were applied to this search."
 nohit_parse_error = "There seems to be a problem with your search query. Please check the syntax. If you are not trying to use advanced features, putting the query inside double quotes may help."
-nohit_prefix = "Your search"
 nohit_query_without_filters = "Remove all filters from this search."
 nohit_spelling = "Perhaps you should try some spelling variations"
-nohit_suffix = "did not match any resources."
 nohit_suggest = "You may want to try to revise your search phrase by removing some words or check your spelling."
 NOT = "NOT"
 Not Illustrated = "Not Illustrated"
@@ -692,7 +699,7 @@ number_decimal_point = "."
 number_thousands_separator = ","
 OAI Server = "OAI Server"
 Occupation = "Occupation"
-of = "of"
+of_num_results = "#%%position%% of %%total%% results"
 old_password = "Old Password"
 On Reserve = "On Reserve"
 On Reserve - Ask at Circulation Desk = "On Reserve - Ask at Circulation Desk"
@@ -700,6 +707,7 @@ on_reserve = "Reserves - Ask at Circulation"
 on_topic = "%%count%% item(s) on this topic"
 Online Access = "Online Access"
 online_resources = "Full Text"
+open_access_limit = "Limit to Open Access content"
 operator_contains = "contains"
 operator_exact = "is (exact)"
 OR = "OR"
@@ -738,8 +746,6 @@ Please check back soon = "Please check back soon"
 Please contact the Library Reference Department for assistance = "Please contact the Library Reference Department for assistance"
 Please enable JavaScript. = "Please enable JavaScript."
 Please upgrade your browser. = "Please upgrade your browser."
-Posted by = "Posted by"
-posted_on = "on"
 Preferences = "Preferences"
 Preferred Library = "Preferred Library"
 Prev = "Prev"
@@ -875,7 +881,12 @@ Sensor Image = "Sensor Image"
 Serial = "Serial"
 Series = "Series"
 Set = "Set"
-Showing = "Showing"
+showing_items_html = "Showing <strong>%%start%% - %%end%%</strong> Items"
+showing_items_of_html = "Showing <strong>%%start%% - %%end%%</strong> of <strong>%%total%%</strong> Items"
+showing_results_for_html = "Showing <strong>%%start%% - %%end%%</strong> results for search '<strong>%%lookfor%%</strong>'"
+showing_results_html = "Showing <strong>%%start%% - %%end%%</strong> results"
+showing_results_of_for_html = "Showing <strong>%%start%% - %%end%%</strong> results of <strong>%%total%%</strong> for search '<strong>%%lookfor%%</strong>'"
+showing_results_of_html = "Showing <strong>%%start%% - %%end%%</strong> results of <strong>%%total%%</strong>"
 sidebar_close = "Collapse Sidebar"
 sidebar_expand = "Expand Sidebar"
 Similar Items = "Similar Items"
@@ -919,7 +930,7 @@ storage_retrieval_request_cancel_all = "Cancel All Storage Retrieval Requests"
 storage_retrieval_request_cancel_fail = "Your request was not canceled. Please contact the circulation desk for further assistance"
 storage_retrieval_request_cancel_selected = "Cancel Selected Storage Retrieval Requests"
 storage_retrieval_request_cancel_success = "Your request was successfully canceled"
-storage_retrieval_request_cancel_success_items = "request(s) were successfully canceled"
+storage_retrieval_request_cancel_success_items = "%%count%% request(s) were successfully canceled"
 storage_retrieval_request_canceled = "Canceled"
 storage_retrieval_request_check_text = "Check Storage Retrieval Request"
 storage_retrieval_request_comments = "Comments"
@@ -957,7 +968,7 @@ Summon Results = "Summon Results"
 summon_database_recommendations = "You may find additional resources here:"
 Supplements = "Supplements"
 Supplied by Amazon = "Supplied by Amazon"
-Switch view to = "Switch view to"
+switch_view = "Switch view to %%view%%"
 switchquery_fuzzy = "Performing a fuzzy search may retrieve terms with similar spellings"
 switchquery_intro = "You may be able to get more results by adjusting your search query."
 switchquery_lowercasebools = "If you are trying to use Boolean operators, they must be ALL CAPS"
@@ -999,8 +1010,7 @@ Too Many Email Recipients = "Too Many Email Recipients"
 too_many_favorites = "This list is too large to display all at once. Try rearranging your favorites into more lists or limiting using tags."
 too_many_new_items = "There are too many new items to display in a single list. Try limiting your search."
 too_many_reserves = "There are too many course reserves to display in a single list. Try limiting your search."
-top_facet_additional_prefix = "Additional "
-top_facet_suffix = "... within your search."
+top_facet_label = "%%label%% within your search."
 Topic = "Topic"
 Topics = "Topics"
 Total Balance Due = "Total Balance Due"
@@ -1029,7 +1039,6 @@ VHS = "VHS"
 Video = "Video"
 Video Clips = "Video Clips"
 Videos = "Videos"
-view already selected = "view already selected"
 View Book Bag = "View Book Bag"
 View Full Collection = "View Full Collection"
 View Full Record = "View Full Record"
@@ -1038,6 +1047,7 @@ View online: Full view Book Preview from the Hathi Trust = "View online: Full vi
 View Record = "View Record"
 View Records = "View Records"
 View this record in EBSCOhost = "View this record in EBSCOhost"
+view_already_selected = "%%current%% view already selected"
 visual_facet_parent = "From"
 Volume = "Volume"
 Volume Holdings = "Volume Holdings"
diff --git a/languages/es.ini b/languages/es.ini
index dc37f0512a5c71afa0be975038794fde25ce7aef..978063f107188d324622b15ac40c772fe371279e 100644
--- a/languages/es.ini
+++ b/languages/es.ini
@@ -7,7 +7,7 @@ Access URL = "URL de Acceso"
 access_denied = "Acceso Denegado"
 Accession Number = "Número de Acceso"
 Account = "Cuenta"
-Add = "Agregar"
+account_block_options_missing = "Algunas opciones se han eliminado debido a un bloqueo en su cuenta. Detalles: %%details%%"
 Add a Library Card = "Agregar una Tarjeta de la Biblioteca"
 Add a Note = "Agregar Nota"
 Add Tag = "Agregar Etiqueta"
@@ -19,8 +19,6 @@ Add your comment = "Agregar comentario"
 add_comment_fail_blank = "No puede estar vacío el comentario."
 add_comment_success = "Se ha agregado el comentario."
 add_favorite_fail = "Error: registro no guardado"
-add_favorite_prefix = "Añadir"
-add_favorite_suffix = "a favoritos"
 add_list_fail = "Error: Lista no creada"
 add_other_libraries = "Incluir artículos en otra Biblioteca"
 add_search = "Agregar Campos de Búsqueda"
@@ -28,6 +26,7 @@ add_search_group = "Agregar Grupos de Búsqueda"
 add_tag_error = "Error: Las etiquetas no se puedieron guardar"
 add_tag_note = "Los espacios separarían las etiquetas. Utilice comillas para etiquetas de varias palabras."
 add_tag_success = "Etiquetas Guardadas"
+add_to_favorites_html = "Añadir <em>%%title%%</em> a favoritos"
 Address = "Dirección"
 adv_search_all = "Todos los Campos"
 adv_search_author = "Autor"
@@ -173,6 +172,10 @@ Catalog Results = "Resultados"
 catalog_login_desc = "Introduzca sus credenciales del catálogo de la biblioteca."
 CD = "CD"
 Change Password = "Cambiar Contraseña"
+channel_add_more = "Añadir más canales como este"
+channel_expand = "Explorar canales relacionados"
+channel_explore = "Explorar canales"
+channel_search = "Mostrar ítemes como resultados de búsqueda"
 Check Hold = "Comprobar Reserva"
 Check Recall = "Comprobar Solicitud"
 Checked Out = "Prestado"
@@ -223,7 +226,6 @@ confirm_ill_request_cancel_selected_text = "¿Desea cancelar sus solicitudes de
 confirm_new_password = "Confirmar Nueva Contraseña"
 confirm_storage_retrieval_request_cancel_all_text = "¿Desea cancelar todas sus solicitudes de recuperación de almacenamiento actuales?"
 confirm_storage_retrieval_request_cancel_selected_text = "¿Desea cancelar sus solicitudes de recuperación de almacenamiento seleccionado?"
-conjunction_or = "o"
 Contents = "Contenido"
 Contributing Source = "Fuente de Contibución"
 Contributors = "Colaboradores"
@@ -273,6 +275,7 @@ Displaying the top = "Mostrando la parte superior"
 Document Inspector = "Inspector de documentos"
 Document Type = "Tipo de Documento"
 DOI = "DOI"
+doi_detected_html = "Su búsqueda parece contener un DOI. Haga clic aquí para ver la disponibilidad del recurso: <a href="%%url%%">%%doi%%</a>"
 Draw Search Box = "Dibujar cajón de búqueda"
 Due = "Vencimiento"
 Due Date = "Fecha de Vencimiento"
@@ -346,6 +349,10 @@ export_selected = "Exportar los Seleccionados"
 export_selected_favorites = "Exportar los Favoritos Seleccionados."
 export_success = "Exportación Completada"
 export_unsupported_format = "Formato de Exportación no soportado."
+external_auth_heading = "Acceso a material licenciado"
+external_auth_login_message = "Iniciar sesión para acceder a material licenciado"
+external_auth_unauthorized = "No está autorizado para acceder a material licenciado"
+external_auth_unauthorized_desc = "Su método de acceso no proporciona acceso a material licenciado. Por favor, cierre la sesión y luego inicie utilizando otro método"
 FAQs = "Preguntas Frecuentes"
 fav_delete = "Borrar Favoritos Seleccionados"
 fav_delete_deleting = "Sus favoritos están siendo eliminados."
@@ -383,7 +390,6 @@ for search = "Para Buscar"
 Forgot Password = "Ha olvidado su contraseña"
 Form Submitted! = "Formulario Enviado!"
 Format = "Formato"
-found = "Encontrado"
 From = "De"
 Full description = "Descripción completa"
 Full text is not displayed to guests = "El texto completo no se muestra a los invitados"
@@ -435,7 +441,7 @@ hold_cancel_all = "Cancelar todas las reservas"
 hold_cancel_fail = "Su solicitud no ha sido cancelada, por favor contactar con el mostrador de circulación para más ayuda"
 hold_cancel_selected = "Cancelar reservas seleccionadas"
 hold_cancel_success = "Su solicitud ha sido cancelada"
-hold_cancel_success_items = "Su solicitud fue cancelada"
+hold_cancel_success_items = "%%count%% Su solicitud fue cancelada"
 hold_date_invalid = "Introduzca una fecha válida"
 hold_date_past = "Introduzca una fecha futura"
 hold_empty_selection = "ninguna reserva fue seleccionada"
@@ -443,19 +449,21 @@ hold_error_blocked = "No cuenta con privilegios para reservar el elemento"
 hold_error_fail = "Su solicitud ha fallado. Contacte con el personal del mostrador para ayuda"
 hold_invalid_pickup = "Ubicación inválida, intente de nuevo."
 hold_invalid_request_group = "Grupo de solicitud de reserva inválido. Por favor, intentar de nuevo"
-hold_login = "Para información de reservas y retiradas"
+hold_items_available = "No se puede colocar una reserva porque los ítemes están disponibles"
+hold_login = "Entrar Para información de reservas y retiradas"
 hold_place = "Hacer solicitud"
 hold_place_fail_missing = "Su solicitud ha fallado, contactar al personal del mostrador de circulación"
 hold_place_success_html = "Se ha realizado su solicitud. <a href="%%url%%">Sus reservas y reclamos</a>."
 hold_profile_html = "Para información de reservas y apartados, por favor establecer su <a href="%%url%%">Perfil del Catálogo de Biblioteca</a>."
 hold_queue_position = "En Cola"
+hold_record_already_on_loan = "Usted ya tiene el registro en préstamo"
 hold_request_group = "Solicitud del"
 hold_requested_group = "Solicitado a"
 hold_required_by = "Ya no es necesario después de"
 hold_success = "Solicitud aprobada"
 Holdings = "Existencias"
 Holdings at Other Libraries = "Existencias en otras Bibliotecas"
-Holdings details from = "Detalle de Existencias desde"
+holdings_details_from = "Detalle de Existencias desde %%location%%"
 Holdings_notes = "Notas"
 Holds = "Reservas"
 Holds and Recalls = "Reservas y Reclamos"
@@ -469,7 +477,7 @@ ill_request_cancel_all = "Cancelar todas las solicitudes de préstamo interbibli
 ill_request_cancel_fail = "Su solicitud no ha sido cancelada, por favor contactar con el mostrador de circulación para más ayuda"
 ill_request_cancel_selected = "Cancelar las solicitudes de préstamo interbibliotecario seleccionadas"
 ill_request_cancel_success = "Su solicitud ha sido cancelada"
-ill_request_cancel_success_items = "Su solicitud fue cancelada"
+ill_request_cancel_success_items = "%%count%% Su solicitud fue cancelada"
 ill_request_canceled = "Cancelado"
 ill_request_check_text = "Compruebe Solicitud de Préstamo Interbibliotecario"
 ill_request_comments = "Comentarios"
@@ -498,7 +506,6 @@ ils_offline_login_message = "El detalle de su cuenta podría no estar disponible
 ils_offline_status = "Nuestro Sistema de Biblioteca se encuentra en mantenimiento."
 ils_offline_title = "Sistema en mantenimiento"
 Import Record = "Registro Importado"
-Import to = "Importar a "
 in = "en"
 In This Collection = "En esta colección"
 in_collection_label = "En colección:"
@@ -526,8 +533,8 @@ Item removed from favorites = "Elemento eliminado de favoritos"
 Item removed from list = "Elemento eliminado de la lista"
 Items = "Elementos"
 items = "elementos"
-items_added_to_bookbag = "Elementos agregados a su Mochila"
-items_already_in_bookbag = "Elementos están en su Mochila o podrían no estar añadidos."
+items_added_to_bookbag = "%%count%% Elementos agregados a su Mochila"
+items_already_in_bookbag = "%%count%% Elementos están en su Mochila o podrían no estar añadidos."
 Journal = "Revista"
 Journal Articles = "Artículos de Revistas"
 Journal Info = "Información de la Revista"
@@ -644,12 +651,11 @@ nohit_active_filters = "Uno o más filtros de faceta se han aplicado a esta bús
 nohit_change_tab = "Ha estado buscando en %%activeTab%% tab. Podría encontrar algo en uno de los otros tabs:"
 nohit_filters = "Filtros aplicados a esta búsqueda"
 nohit_heading = "¡Sin Resultados!"
+nohit_lookfor_html = "Su búsqueda - <strong>%%lookfor%%</strong> - No coincide ningún recurso."
 nohit_no_filters = "Ningún filtro fue aplicado a esta búsqueda."
 nohit_parse_error = "Parece que hay un problema con su consulta. Por favor revise la sintaxis de su consulta. Si no está intentando con búsquedas avanzadas, utilice doble comilla."
-nohit_prefix = "Su búsqueda"
 nohit_query_without_filters = "Remover todos los filtros para esta búsqueda"
 nohit_spelling = "Tal vez debería intentar con algunas variantes ortográficas"
-nohit_suffix = "No coincide ningún recurso."
 nohit_suggest = "Debería intentar revisar su frase de búsqueda eliminando algunas palabras o revise su ortografía."
 NOT = "NO"
 Not Illustrated = "Sin Ilustraciones"
@@ -691,7 +697,7 @@ number_decimal_point = "."
 number_thousands_separator = ","
 OAI Server = "Servidor OAI"
 Occupation = "Ocupación"
-of = "de"
+of_num_results = "#%%position%% de %%total%% Resultados"
 old_password = "Contraseña anterior"
 On Reserve = "En Reserva"
 On Reserve - Ask at Circulation Desk = "En Reserva - consulte en el mostrador de circulación"
@@ -699,6 +705,7 @@ on_reserve = "Reservas - Pregunte en Circulación"
 on_topic = "Elementos %%count%% en este tema"
 Online Access = "Acceso en línea"
 online_resources = "Texto Completo"
+open_access_limit = "Límitar a contenido de acceso abierto"
 operator_contains = "Contiene"
 operator_exact = "es (exacto)"
 OR = "O"
@@ -737,8 +744,6 @@ Please check back soon = "Por favor, vuelva pronto"
 Please contact the Library Reference Department for assistance = "Por favor contacte al Referencista para asistencia"
 Please enable JavaScript. = "Por favor, activar JavaScript!"
 Please upgrade your browser. = "Por favor, actualizar navegador de internet"
-Posted by = "Publicado por"
-posted_on = "en"
 Preferences = "Preferencias"
 Preferred Library = "Biblioteca principal"
 Prev = "Anterior"
@@ -874,7 +879,12 @@ Sensor Image = "Sensor de imagen"
 Serial = "Seriadas"
 Series = "Series"
 Set = "Ingresar"
-Showing = "Mostrando"
+showing_items_html = "Mostrando <strong>%%start%% - %%end%%</strong> Elementos"
+showing_items_of_html = "Mostrando <strong>%%start%% - %%end%%</strong> de <strong>%%total%%</strong> Elementos"
+showing_results_for_html = "Mostrando <strong>%%start%% - %%end%%</strong> Resultados Para Buscar '<strong>%%lookfor%%</strong>'"
+showing_results_html = "Mostrando <strong>%%start%% - %%end%%</strong> Resultados"
+showing_results_of_for_html = "Mostrando <strong>%%start%% - %%end%%</strong> Resultados de <strong>%%total%%</strong> Para Buscar '<strong>%%lookfor%%</strong>'"
+showing_results_of_html = "Mostrando <strong>%%start%% - %%end%%</strong> Resultados de <strong>%%total%%</strong>"
 sidebar_close = "Contraer barra lateral"
 sidebar_expand = "Expander barra lateral"
 Similar Items = "Ejemplares similares"
@@ -918,7 +928,7 @@ storage_retrieval_request_cancel_all = "Cancelar todas las solicitudes de recupe
 storage_retrieval_request_cancel_fail = "Su solicitud no ha sido cancelada, por favor contactar con el mostrador de circulación para más ayuda"
 storage_retrieval_request_cancel_selected = "Cancelar las solicitudes de recuperación de almacenamiento seleccionadas"
 storage_retrieval_request_cancel_success = "Su solicitud ha sido cancelada"
-storage_retrieval_request_cancel_success_items = "Su solicitud fue cancelada"
+storage_retrieval_request_cancel_success_items = "%%count%% Su solicitud fue cancelada"
 storage_retrieval_request_canceled = "Cancelado"
 storage_retrieval_request_check_text = "Comprobar solicitud de Recuperación de Almacenamiento"
 storage_retrieval_request_comments = "Comentarios"
@@ -956,7 +966,7 @@ Summon Results = "Resultados Solicitados"
 summon_database_recommendations = "Podrá encontrar recursos adicionales aquí:"
 Supplements = "Suplementos"
 Supplied by Amazon = "Suministrado por Amazon"
-Switch view to = "Cambiar la vista a"
+switch_view = "Cambiar la vista a %%view%%"
 switchquery_fuzzy = "Realizar una búsqueda difusa puede recuperar términos con ortografía similares"
 switchquery_intro = "Puede conseguir más resultados ajustando la consulta de búsqueda."
 switchquery_lowercasebools = "Si está tratando de utilizar operadores booleanos, deberán estar TODOS EN MAYUSCULAS"
@@ -998,8 +1008,7 @@ Too Many Email Recipients = "Demasiados destinatarios de correo electrónico"
 too_many_favorites = "Lista muy larga para desplegar. Intente con sus favoritos en más de una lista o delimitelos con etiquetas."
 too_many_new_items = "Demasiados nuevos elementos para desplegar en una sola lista. Intente limitando su búsqueda."
 too_many_reserves = "Demasiadas reservas de cursos para desplegar en una sola lista. Intente limitando su búsqueda."
-top_facet_additional_prefix = "Adicional"
-top_facet_suffix = "... dentro de su búsqueda."
+top_facet_label = "%%label%% dentro de su búsqueda."
 Topic = "Tópico"
 Topics = "Tópicos"
 Total Balance Due = "Total de saldo adeudado"
@@ -1028,7 +1037,6 @@ VHS = "VHS"
 Video = "Video"
 Video Clips = "Video Clips"
 Videos = "Videos"
-view already selected = "Ver seleccionados"
 View Book Bag = "Ver Mochila"
 View Full Collection = "Ver colección completa"
 View Full Record = "Ver registro completo"
@@ -1037,6 +1045,7 @@ View online: Full view Book Preview from the Hathi Trust = "Vista en línea: Vis
 View Record = "Ver registro"
 View Records = "Ver registros"
 View this record in EBSCOhost = "Ver este registro en EBSCOhost"
+view_already_selected = "%%current%% Ver seleccionados"
 visual_facet_parent = "De"
 Volume = "Volumen"
 Volume Holdings = "Volumen de existencias"
diff --git a/languages/eu.ini b/languages/eu.ini
index cabf58dd132ff99f788e5bcdd3811ad53124bec9..7e0c75a911b8afb656214b0f83fae079e1b111b6 100644
--- a/languages/eu.ini
+++ b/languages/eu.ini
@@ -627,7 +627,7 @@ Access URL = "URL sarbidea"
 access_denied = "Ez dago sartzerik"
 Accession Number = "Sartzeko zenbakia"
 Account = "Kontua"
-Add = "Erantsi"
+account_block_options_missing = "Hautaketa batzuk ezabatu dira zure kontuak zerbait blokeatuta izateagatik. Xehetasunak: %%details%%"
 Add a Library Card = "Gehitu liburutegirako txartela"
 Add a Note = "Ohar bat erantsi"
 Add Tag = "Etiketa erantsi"
@@ -639,8 +639,6 @@ Add your comment = "Iruzkin bat erantsi"
 add_comment_fail_blank = "Iruzkina ezin da hutsik utzi"
 add_comment_success = "Iruzkina ongi gehitu da"
 add_favorite_fail = "Errorea: erregistroa ez da gorde"
-add_favorite_prefix = "Erantsi"
-add_favorite_suffix = "Gehitu gogokoetan"
 add_list_fail = "Errorea: zerrenda ez da gehitu"
 add_other_libraries = "Beste liburutegi batean dokumentuak sartu"
 add_search = "bilaketa bat gehitu"
@@ -648,6 +646,7 @@ add_search_group = "bilaketa-talde bat gehitu"
 add_tag_error = "Errorea: etiketak ezin izan dira gorde"
 add_tag_note = "Hutsuneek etiketak banantzen dituzte. Komatxoak erabili etiketek hitz bat baino gehiago badute."
 add_tag_success = "Etiketak gordeak"
+add_to_favorites_html = "Erantsi <em>%%title%%</em> Gehitu gogokoetan"
 Address = "Helbidea"
 adv_search_all = "Eremu guztiak"
 adv_search_author = "Egilea"
@@ -793,6 +792,10 @@ Catalog Results = "Katalogoaren emaitzak"
 catalog_login_desc = "Idatzi zure datuak liburutegiko katalogora sartzeko."
 CD = "CDa"
 Change Password = "Aldatu pasahitza"
+channel_add_more = "Gehitu honen bezalako kanal gehiago"
+channel_expand = "Bilatu lotutako kanalak"
+channel_explore = "Esploratu kanalak"
+channel_search = "Erakutsi aleak bilaketaren emaitzetan"
 Check Hold = "Comprobar Reserva"
 Check Recall = "Comprobar Solicitud"
 Checked Out = "Maileguan"
@@ -843,7 +846,6 @@ confirm_ill_request_cancel_selected_text = "Aukeratutako liburutegi arteko maile
 confirm_new_password = "Baieztatu pasahitza berria"
 confirm_storage_retrieval_request_cancel_all_text = "Zure biltegiratzea berreskuratzeko eskaera guztiak ezeztatu nahi dituzu?"
 confirm_storage_retrieval_request_cancel_selected_text = "Aukeratutako biltegiratzea berreskuratzeko eskaerak ezeztatu nahi dituzu?"
-conjunction_or = "edo"
 Contents = "Edukia"
 Contributing Source = "Ekarpen-iturria"
 Contributors = "Egileak"
@@ -893,6 +895,7 @@ Displaying the top = "Goiko aldea aurkezten ari da"
 Document Inspector = "Dokumentu Inspektorea"
 Document Type = "Dokumentu mota"
 DOI = "DOI"
+doi_detected_html = "Badirudi zure bilaketak DOI duela. Egin klik hemen baliabidearen erabilgarritasun-egoera ikusteko: <a href="%%url%%">%%doi%%</a>"
 Draw Search Box = "Marraztu Bilatze Kaxa"
 Due = "Noiz arte"
 Due Date = "Itzulketa data"
@@ -966,6 +969,10 @@ export_selected = "Aukeratutakoak esportatu"
 export_selected_favorites = "Gogokoenak esportatu."
 export_success = "Esportazioa burutua"
 export_unsupported_format = "Esportazio formatu hori ezin da erabili."
+external_auth_heading = "Baimendutako materialerako sarbidea"
+external_auth_login_message = "Sartu zure erabiltzailearen izena eta pasahitza baimendutako materiala ikusteko"
+external_auth_unauthorized = "Ez duzu baimendutako materiala ikusteko baimena"
+external_auth_unauthorized_desc = "Zure sartzeko metodoa ez du baimendutako materiala ikusteko baimenik. Mesedez, irten eta sartu berriro beste metodo bat erabiltzen."
 FAQs = "FAQ"
 fav_delete = "Gogokoenak ezabatu"
 fav_delete_deleting = "Zure gogokoenak ezabatzen ari dira."
@@ -1003,7 +1010,6 @@ for search = "bilaketa honetara"
 Forgot Password = "Pasahitza ahaztuta"
 Form Submitted! = "Inprimakia bidalita!"
 Format = "Formatua"
-found = "Aurkituta"
 From = "Nork"
 Full description = "Deskribapen osoa"
 Full text is not displayed to guests = "Testu osoa ez da erakusten erabiltzaile gonbidatuei"
@@ -1055,7 +1061,7 @@ hold_cancel_all = "Erreserba guztiak ezabatu"
 hold_cancel_fail = "Zure eskaera ezeztatua izan da. Mesedez, mostradoretik pasa."
 hold_cancel_selected = "Aukeratutako erreserbak ezeztatu"
 hold_cancel_success = "Zure eskaera ezeztatua izan da"
-hold_cancel_success_items = "Zure eskaera ezeztatua izan da"
+hold_cancel_success_items = "%%count%% Zure eskaera ezeztatua izan da"
 hold_date_invalid = "baliodun data sartu"
 hold_date_past = "data sartu"
 hold_empty_selection = "ez da erreserbarik aukeratu"
@@ -1063,19 +1069,21 @@ hold_error_blocked = "Ezin duzu dokumentu hori erreserbatu"
 hold_error_fail = "Zure eskaeran errorea egon da. Mesedez mostradoretik pasa lagundu zaitzaten"
 hold_invalid_pickup = "Kokapena ez da baliagarria. Berriz saiatu."
 hold_invalid_request_group = "Erreserbaren eskaera-taldea baliogabea da. Mesedez, saiatu berriro"
-hold_login = "Erreserben informaziorako"
+hold_items_available = "Ezin duzu erreserbarik egin, ale erabilgarririk dagoelako."
+hold_login = "Bazkideak Erreserben informaziorako"
 hold_place = "Eskaera egin"
 hold_place_fail_missing = "Zure eskaeran errorea gertatu da. Mostradoretik pasa lagundu zaitzaten."
 hold_place_success_html = "Zure eskaera burutu da. <a href="%%url%%">Zure erreserbak</a>."
 hold_profile_html = "Erreserba eta gogoratze informaziorako, mesedez ezarri zure <a href="%%url%%">Liburutegiko Katalogorako Profila</a>."
 hold_queue_position = "Ilara"
+hold_record_already_on_loan = "Dokumentua dagoeneko dago zuri mailegatuta"
 hold_request_group = "Eskatu duena"
 hold_requested_group = "Eskatu zuena"
 hold_required_by = "Jadanik ez da beharrezkoa"
 hold_success = "Eskaera baimendua"
 Holdings = "Aleari buruzko argibideak"
 Holdings at Other Libraries = "Beste liburutegietan"
-Holdings details from = "Aleari buruzko argibideak"
+holdings_details_from = "Aleari buruzko argibideak %%location%%"
 Holdings_notes = "Oharrak"
 Holds = "Erreserbak"
 Holds and Recalls = "Erreserbak"
@@ -1089,7 +1097,7 @@ ill_request_cancel_all = "Ezeztatu liburutegi arteko mailegua egiteko eskaera gu
 ill_request_cancel_fail = "Zure eskaera ezeztatua izan da. Mesedez, mostradoretik pasa."
 ill_request_cancel_selected = "Ezeztatu aukeratutako liburutegi arteko mailegua egiteko eskaerak"
 ill_request_cancel_success = "Zure eskaera ezeztatua izan da"
-ill_request_cancel_success_items = "Zure eskaera ezeztatua izan da"
+ill_request_cancel_success_items = "%%count%% Zure eskaera ezeztatua izan da"
 ill_request_canceled = "Ezeztatuta"
 ill_request_check_text = "Aztertu liburutegi arteko mailegua egiteko eskaera"
 ill_request_comments = "Iruzkinak"
@@ -1118,7 +1126,6 @@ ils_offline_login_message = "Zure kontuaren xehetasunei buruzko informazioa ez d
 ils_offline_status = "Mantentze lanak direla eta, gure Liburutegia Kudeatzeko Sistema ez dago erabilgarri."
 ils_offline_title = "Sistema mantentze lanetan ari da"
 Import Record = "Erregistroa hartu"
-Import to = "Hartu"
 in = "non"
 In This Collection = "Bilduma honetan"
 in_collection_label = "Bilduma:"
@@ -1146,8 +1153,8 @@ Item removed from favorites = "Gogokoenetatik ezabatuta"
 Item removed from list = "Zerrendatik ezabatuta"
 Items = "Item-ak"
 items = "itemes"
-items_added_to_bookbag = "Itemes agregados a su Mochila"
-items_already_in_bookbag = "ítemes están en su Mochila o podrían no estar añadidos."
+items_added_to_bookbag = "%%count%% Itemes agregados a su Mochila"
+items_already_in_bookbag = "%%count%% ítemes están en su Mochila o podrían no estar añadidos."
 Journal = "Aldizkaria"
 Journal Articles = "Aldizkariko-artikuluak"
 Journal Info = "Aldizkariari buruzko informazioa"
@@ -1264,12 +1271,11 @@ nohit_active_filters = "Fazeta iragazki bat edo gehiago erabili dira bilaketa ho
 nohit_change_tab = "Bilatu duzu "%%activeTab%%"-en. Nahi baduzu, bila dezakezu beste batzuetan:"
 nohit_filters = "Iragazkirik gabe"
 nohit_heading = "Ez dago emaitzarik"
+nohit_lookfor_html = "Ez dago emaitzarik - <strong>%%lookfor%%</strong> - . Berriz bila dezakezu datuak aldatuz."
 nohit_no_filters = "Ez da inongo iragazkirik jarri."
 nohit_parse_error = "Kontsultarekin arazoak daude. Saiatu berriro."
-nohit_prefix = "Ez dago emaitzarik"
 nohit_query_without_filters = "Ezabatu iragazki guztiak"
 nohit_spelling = "Ez dago iradokizunik"
-nohit_suffix = ". Berriz bila dezakezu datuak aldatuz."
 nohit_suggest = "Esaldia berrikusi."
 NOT = "EZ"
 Not Illustrated = "Irudirik gabe"
@@ -1311,7 +1317,7 @@ number_decimal_point = ","
 number_thousands_separator = "."
 OAI Server = "OAI Zerbitzaria"
 Occupation = "Lanbidea"
-of = "--"
+of_num_results = "#%%position%% -- %%total%% emaitzak"
 old_password = "Aurreko pasahitza"
 On Reserve = "Erreserbatua"
 On Reserve - Ask at Circulation Desk = "Erreserbatua"
@@ -1319,6 +1325,7 @@ on_reserve = "Reservas - Pregunte en Circulación"
 on_topic = "%%count%% item(ak) gai honi buruz"
 Online Access = "Sarrera elektronikoa"
 online_resources = "Testu osoa"
+open_access_limit = "Mugatu emaitzak sarbide irekia duen edukietarako"
 operator_contains = "du"
 operator_exact = "da (zehatza)"
 OR = "EDO"
@@ -1357,8 +1364,6 @@ Please check back soon = "Zuzena den egiaztatu"
 Please contact the Library Reference Department for assistance = "Jar zaitez liburutegiarekin harremanetan"
 Please enable JavaScript. = "Mesedez aktibatu JavaScript."
 Please upgrade your browser. = "Mesedez, eguneratu zure nabigatzailea"
-Posted by = "Bidalia"
-posted_on = "Bidalia"
 Preferences = "Lehentasunak"
 Preferred Library = "Hobetsitako liburutegia"
 Prev = "Aurrekoa"
@@ -1494,7 +1499,12 @@ Sensor Image = "Zentzumen irudia"
 Serial = "Aldizkako argitalpena"
 Series = "Saila"
 Set = "Aukera"
-Showing = "Erakusten"
+showing_items_html = "Erakusten <strong>%%start%% - %%end%%</strong> Item-ak"
+showing_items_of_html = "Erakusten <strong>%%start%% - %%end%%</strong> -- <strong>%%total%%</strong> Item-ak"
+showing_results_for_html = "Erakusten <strong>%%start%% - %%end%%</strong> emaitzak bilaketa honetara '<strong>%%lookfor%%</strong>'"
+showing_results_html = "Erakusten <strong>%%start%% - %%end%%</strong> emaitzak"
+showing_results_of_for_html = "Erakusten <strong>%%start%% - %%end%%</strong> emaitzak -- <strong>%%total%%</strong> bilaketa honetara '<strong>%%lookfor%%</strong>'"
+showing_results_of_html = "Erakusten <strong>%%start%% - %%end%%</strong> emaitzak -- <strong>%%total%%</strong>"
 sidebar_close = "Itxi albokobarra"
 sidebar_expand = "Ireki albokobarra"
 Similar Items = "Antzeko izenburuak"
@@ -1538,7 +1548,7 @@ storage_retrieval_request_cancel_all = "Ezeztatu bilteratze berreskuratze guztia
 storage_retrieval_request_cancel_fail = "Zure eskaera ezeztatua izan da. Mesedez, mostradoretik pasa."
 storage_retrieval_request_cancel_selected = "Ezeztatu aukeratutako bilteratze berreskuratzeak"
 storage_retrieval_request_cancel_success = "Zure eskaera ezeztatua izan da"
-storage_retrieval_request_cancel_success_items = "Zure eskaera ezeztatua izan da"
+storage_retrieval_request_cancel_success_items = "%%count%% Zure eskaera ezeztatua izan da"
 storage_retrieval_request_canceled = "Ezeztatuta"
 storage_retrieval_request_check_text = "Aztertu bilteratze berreskuratzeko eskaera"
 storage_retrieval_request_comments = "Iruzkinak"
@@ -1576,7 +1586,7 @@ Summon Results = "Eskatutako emaitzak"
 summon_database_recommendations = "Errekurtso gehiago hemen aurki ditzakezu:"
 Supplements = "Gehigarriak"
 Supplied by Amazon = "Hornitzailea, Amazon"
-Switch view to = "Ikuspegia aldatu"
+switch_view = "Ikuspegia aldatu %%view%%"
 switchquery_fuzzy = "Fuzzy bilaketa egiten, berdin letreiatzen diren terminoak bila ditzakezu "
 switchquery_intro = "Emaitza gehiago nahi baduzu, doitu zure kontsulta."
 switchquery_lowercasebools = "Operadore booleanoak letra larriz idatzi behar dira"
@@ -1618,8 +1628,7 @@ Too Many Email Recipients = "Jasotzaile gehiegi"
 too_many_favorites = "Lista muy larga para desplegar. Intente con sus favoritos en más de una lista o delimitar con etiquetas."
 too_many_new_items = "Demasiados nuevos ítemes para desplegar en una sola lista. Intente limitando su búsqueda."
 too_many_reserves = "Demasiadas reservas de cursos para desplegar en una sola lista. Intente limitando su búsqueda."
-top_facet_additional_prefix = "Aurrezenbaki gehigarria"
-top_facet_suffix = "bilaketarako iradokizunak"
+top_facet_label = "%%label%% bilaketarako iradokizunak"
 Topic = "Gaia"
 Topics = "Gaiak"
 Total Balance Due = "Balantzearen guztizkoa"
@@ -1648,7 +1657,6 @@ VHS = "VHS"
 Video = "Bideoa"
 Video Clips = "Video Clips"
 Videos = "Bideoak"
-view already selected = "Aukeratutakoak ikusi"
 View Book Bag = "Ver Mochila"
 View Full Collection = "Ikusi Bilduma Osoa"
 View Full Record = "Ikusi Erregistro Osoa"
@@ -1657,6 +1665,7 @@ View online: Full view Book Preview from the Hathi Trust = "Ikuspegia linean: Ha
 View Record = "Ikusi Erregistroa"
 View Records = "Dokumentuak ikusi"
 View this record in EBSCOhost = "Ikusi hau EBSCOhost-en"
+view_already_selected = "%%current%% Aukeratutakoak ikusi"
 visual_facet_parent = "Nork"
 Volume = "Bolumena"
 Volume Holdings = "Liburukiak"
diff --git a/languages/fi.ini b/languages/fi.ini
index 0ce6e619cc538fed22433aedeee075f118020e1a..9dd8ee1de6e6251d2ea200c3bce9f87694070b06 100644
--- a/languages/fi.ini
+++ b/languages/fi.ini
@@ -5,7 +5,7 @@ Access URL = "Linkki aineistoon"
 access_denied = "Pääsy estetty."
 Accession Number = "Hankintanumero"
 Account = "Tili"
-Add = "Lisää"
+account_block_options_missing = "Joitakin toimintoja ei näytetä, koska olet lainaus- tai varauskiellossa. Lisätiedot: %%details%%"
 Add a Library Card = "Lisää kirjastokortti"
 Add a Note = "Lisää merkintä"
 Add Tag = "Lisää tagi"
@@ -17,8 +17,6 @@ Add your comment = "Lisää kommentti"
 add_comment_fail_blank = "Kommentti ei voi olla tyhjä."
 add_comment_success = "Kommentti lisätty."
 add_favorite_fail = "Virhe: tietueen tallennus epäonnistui"
-add_favorite_prefix = "Lisää"
-add_favorite_suffix = "suosikkeihin"
 add_list_fail = "Virhe: listan lisäys epäonnistui"
 add_other_libraries = "Sisällytä muiden kirjastojen artikkelit"
 add_search = "Lisää hakukenttä"
@@ -26,6 +24,7 @@ add_search_group = "Lisää hakuryhmä"
 add_tag_error = "Virhe: tagien tallennus epäonnistui"
 add_tag_note = "Erota tagit välilyönneillä. Käytä lainausmerkkejä monisanaisten tagien kohdalla."
 add_tag_success = "Tagit tallennettu"
+add_to_favorites_html = "Lisää <em>%%title%%</em> suosikkeihin"
 Address = "Osoite"
 adv_search_all = "Kaikki kentät"
 adv_search_author = "Tekijä"
@@ -171,6 +170,10 @@ Catalog Results = "Luettelon tulokset"
 catalog_login_desc = "Syötä kirjastokortin tiedot."
 CD = "CD"
 Change Password = "Vaihda salasana"
+channel_add_more = "Lisää tämänkaltaisia kanavia"
+channel_expand = "Tutki tähän liittyviä kanavia"
+channel_explore = "Tutki kanavia"
+channel_search = "Näytä hakutuloksena"
 Check Hold = "Tarkista varaus"
 Check Recall = "Tarkista varaus"
 Checked Out = "Lainat"
@@ -221,7 +224,6 @@ confirm_ill_request_cancel_selected_text = "Haluatko perua valitsemasi kaukolain
 confirm_new_password = "Vahvista uusi salasana"
 confirm_storage_retrieval_request_cancel_all_text = "Haluatko perua kaikki tilaukset?"
 confirm_storage_retrieval_request_cancel_selected_text = "Haluatko perua valitsemasi tilaukset?"
-conjunction_or = "tai"
 Contents = "Sisältö"
 Contributing Source = "Osallistuva lähde"
 Contributors = "Muut tekijät"
@@ -277,6 +279,7 @@ Displaying the top = "Näytetään ensimmäiset"
 Document Inspector = "Dokumentin tutkija"
 Document Type = "Dokumentin tyyppi"
 DOI = "DOI"
+doi_detected_html = "Hakusi näyttää sisältävän DOI-tunnisteen. Klikkaa tästä tarkistaaksesi saatavuuden: <a href="%%url%%">%%doi%%</a>"
 Draw Search Box = "Valitse alue"
 Due = "Eräpäivä"
 Due Date = "Eräpäivä"
@@ -290,6 +293,7 @@ edit_list_fail = "Listan muokkausoikeudet puuttuvat"
 edit_list_success = "Lista päivitetty."
 Edition = "Painos"
 eds_expander_fulltext = "Hae myös artikkeleiden kokoteksteistä"
+eds_expander_relatedsubjects = "Käytä hakusanoihin liittyviä aiheita"
 eds_expander_thesaurus = "Käytä hakusanoihin liittyviä sanoja"
 eds_limiter_FC = "Vain kirjastoluettelo"
 eds_limiter_FC1 = "Vain elektroniset aineistot"
@@ -350,6 +354,10 @@ export_selected = "Vie valitut"
 export_selected_favorites = "Vie valitut suosikit"
 export_success = "Vienti valmis"
 export_unsupported_format = "Vienti valitussa muodossa ei onnistu"
+external_auth_heading = "Pääsy lisensioituun aineistoon"
+external_auth_login_message = "Kirjaudu sisään päästäksesi lisensioituun aineistoon"
+external_auth_unauthorized = "Sinulla ei ole käyttöoikeutta lisensioituun aineistoon"
+external_auth_unauthorized_desc = "Käyttämälläsi kirjautumistavalla ei ole pääsyä lisensioituun aineistoon. Kirjaudu ensin ulos ja käytä sitten toista kirjautumistapaa."
 FAQs = "UKK:t"
 fav_delete = "Poista valitut suosikit"
 fav_delete_deleting = "Suosikkejasi poistetaan"
@@ -387,7 +395,6 @@ for search = "osumasta haulle"
 Forgot Password = "Salasana unohtunut"
 Form Submitted! = "Lomake lähetetty!"
 Format = "Aineistotyyppi"
-found = "tuloksesta"
 From = "Lähettäjä"
 Full description = "Täydet tiedot"
 Full text is not displayed to guests = "Kokotekstiä ei näytetä vieraille."
@@ -439,7 +446,7 @@ hold_cancel_all = "Peru kaikki varaukset"
 hold_cancel_fail = "Varaustasi ei peruttu. Ota yhteyttä kirjaston asiakaspalveluun."
 hold_cancel_selected = "Peru valitut varaukset"
 hold_cancel_success = "Varaus peruttu"
-hold_cancel_success_items = "varaus(ta) peruttu"
+hold_cancel_success_items = "%%count%% varaus(ta) peruttu"
 hold_date_invalid = "Syötä kelvollinen päivämäärä"
 hold_date_past = "Syötä tätä päivää myöhempi päivämäärä"
 hold_empty_selection = "Yhtään varausta ei valittu"
@@ -448,19 +455,20 @@ hold_error_fail = "Pyyntö epäonnistui. Ota yhteyttä kirjaston asiakaspalveluu
 hold_invalid_pickup = "Valittu noutopaikka on virheellinen. Yritä uudestaan."
 hold_invalid_request_group = "Valittu varausryhmä on virheellinen. Yritä uudestaan."
 hold_items_available = "Varaaminen ei ole mahdollista, koska niteitä on saatavissa."
-hold_login = "tehdäksesi varauspyynnön"
+hold_login = "Kirjaudu sisään tehdäksesi varauspyynnön"
 hold_place = "Tee varaus"
 hold_place_fail_missing = "Pyyntö epäonnistui puuttuvien tietojen vuoksi. Ota yhteyttä kirjaston asiakaspalveluun."
 hold_place_success_html = "Varauspyyntö onnistui. <a href="%%url%%">Varaukset</a>."
 hold_profile_html = "Kirjaudu <a href="%%url%%">kirjastokortilla</a> nähdäksesi varaukset."
 hold_queue_position = "Sijainti jonossa"
+hold_record_already_on_loan = "Teos on jo sinulla lainassa"
 hold_request_group = "Varauksen kohde"
 hold_requested_group = "Varauksen kohde"
 hold_required_by = "Viimeinen voimassaolopäivä"
 hold_success = "Varauspyyntö onnistui"
 Holdings = "Saatavuustiedot"
 Holdings at Other Libraries = "Saatavuus muissa kirjastoissa"
-Holdings details from = "Saatavuus:"
+holdings_details_from = "Saatavuus: %%location%%"
 Holdings_notes = "Huomautukset"
 Holds = "Varaukset"
 Holds and Recalls = "Varaukset"
@@ -474,7 +482,7 @@ ill_request_cancel_all = "Peru kaikki tilaukset"
 ill_request_cancel_fail = "Tilaustasi ei peruttu. Ota yhteyttä asiakaspalveluun."
 ill_request_cancel_selected = "Peru valitut tilaukset"
 ill_request_cancel_success = "Tilaus peruttu"
-ill_request_cancel_success_items = "tilaus(ta) peruttu"
+ill_request_cancel_success_items = "%%count%% tilaus(ta) peruttu"
 ill_request_canceled = "Peruttu"
 ill_request_check_text = "Tarkista kaukolainatilaus"
 ill_request_comments = "Lisätiedot"
@@ -503,7 +511,6 @@ ils_offline_login_message = "Tilitietosi ovat poissa käytöstä tämän ajan. P
 ils_offline_status = "Kirjastojärjestelmä on juuri nyt pois käytöstä."
 ils_offline_title = "Järjestelmä pois käytöstä"
 Import Record = "Tuo tietue"
-Import to = "Tuo kohteeseen "
 in = "kentästä"
 In This Collection = "Tässä kokoelmassa"
 in_collection_label = "Kokoelmassa:"
@@ -531,8 +538,8 @@ Item removed from favorites = "Tietue poistettu suosikeista"
 Item removed from list = "Tietue poistettu listalta"
 Items = "Sisältö"
 items = "tietuetta"
-items_added_to_bookbag = "tietue(et) lisätty kirjakoriin"
-items_already_in_bookbag = "tietue(et) ovat jo kirjakorissa tai lisäys koriin epäonnistui"
+items_added_to_bookbag = "%%count%% tietue(tta) lisätty kirjakoriin"
+items_already_in_bookbag = "%%count%% tietue(tta) on jo kirjakorissa tai lisäys koriin epäonnistui"
 Journal = "Aikakauslehti"
 Journal Articles = "Lehtiartikkelit"
 Journal Info = "Lehden tiedot"
@@ -649,12 +656,11 @@ nohit_active_filters = "Tässä haussa on käytetty suodattimia. Poistamalla suo
 nohit_change_tab = "Haku tehtiin välilehdellä "%%activeTab%%". Voit löytää jotain muilta välilehdiltä:"
 nohit_filters = "Tässä haussa käytetyt suodattimet:"
 nohit_heading = "Ei tuloksia!"
+nohit_lookfor_html = "Haulla - <strong>%%lookfor%%</strong> - ei löytynyt tuloksia."
 nohit_no_filters = "Tässä haussa ei käytetty suodattimia."
 nohit_parse_error = "Hakulausekkeessa on syntaksivirhe. Jos et yritä käyttää erikoishakutapoja, kokeile kyselyn ympäröimistä lainausmerkeillä."
-nohit_prefix = "Haulla"
 nohit_query_without_filters = "Poista kaikki suodattimet tästä hausta."
 nohit_spelling = "Kannattaa kokeilla erilaisia kirjoitusasuja"
-nohit_suffix = "ei löytynyt tuloksia."
 nohit_suggest = "Voit kokeilla muokata hakuehtoja poistamalla joitain hakusanoja tai muuttamalla sanojen kirjoitusasua."
 NOT = "EI"
 Not Illustrated = "Ei kuvitettu"
@@ -696,7 +702,7 @@ number_decimal_point = ","
 number_thousands_separator = " "
 OAI Server = "OAI-palvelin"
 Occupation = "Ammatti"
-of = "yhteensä"
+of_num_results = "%%position%%. yhteensä %%total%% tuloksesta"
 old_password = "Vanha salasana"
 On Reserve = "Rajatussa käytössä"
 On Reserve - Ask at Circulation Desk = "Rajatussa käytössä - pyydä lainaustiskiltä"
@@ -704,6 +710,7 @@ on_reserve = "Rajatussa käytössä - kysy lainaustiskiltä"
 on_topic = "%%count%% tietuetta tästä aiheesta"
 Online Access = "Linkit"
 online_resources = "Kokoteksti"
+open_access_limit = "Rajaa Open Access -aineistoon"
 operator_contains = "sisältää"
 operator_exact = "on (täsmälleen)"
 OR = "TAI"
@@ -742,8 +749,6 @@ Please check back soon = "Tarkista myöhemmin uudelleen"
 Please contact the Library Reference Department for assistance = "Saadaksesi apua ota yhteyttä kirjaston asiakaspalveluun"
 Please enable JavaScript. = "Ota JavaScript käyttöön."
 Please upgrade your browser. = "Ole hyvä ja päivitä selaimesi."
-Posted by = "Lähettänyt"
-posted_on = "pvm"
 Preferences = "Asetukset"
 Preferred Library = "Ensisijainen kirjasto"
 Prev = "Edellinen"
@@ -879,7 +884,12 @@ Sensor Image = "Kaukokartoituskuva"
 Serial = "Kausijulkaisu"
 Series = "Sarja"
 Set = "Aseta"
-Showing = "Näytetään"
+showing_items_html = "Näytetään tulokset <strong>%%start%% - %%end%%</strong>"
+showing_items_of_html = "Näytetään <strong>%%start%% - %%end%%</strong> yhteensä <strong>%%total%%</strong> tuloksesta"
+showing_results_for_html = "Näytetään tulokset <strong>%%start%% - %%end%%</strong> haulle '<strong>%%lookfor%%</strong>'"
+showing_results_html = "Näytetään tulokset <strong>%%start%% - %%end%%</strong>"
+showing_results_of_for_html = "Näytetään <strong>%%start%% - %%end%%</strong> yhteensä <strong>%%total%%</strong> tuloksesta haulle '<strong>%%lookfor%%</strong>'"
+showing_results_of_html = "Näytetään <strong>%%start%% - %%end%%</strong> yhteensä <strong>%%total%%</strong> tuloksesta"
 sidebar_close = "Pienennä sivupalkki"
 sidebar_expand = "Laajenna sivupalkki"
 Similar Items = "Samankaltaisia teoksia"
@@ -923,7 +933,7 @@ storage_retrieval_request_cancel_all = "Peru kaikki tilaukset"
 storage_retrieval_request_cancel_fail = "Tilaustasi ei peruttu. Ota yhteyttä asiakaspalveluun."
 storage_retrieval_request_cancel_selected = "Peru valitut tilaukset"
 storage_retrieval_request_cancel_success = "Tilaus peruttu"
-storage_retrieval_request_cancel_success_items = "tilaus(ta) peruttu"
+storage_retrieval_request_cancel_success_items = "%%count%% tilaus(ta) peruttu"
 storage_retrieval_request_canceled = "Peruttu"
 storage_retrieval_request_check_text = "Tarkista varastotilaus"
 storage_retrieval_request_comments = "Lisätiedot"
@@ -961,7 +971,7 @@ Summon Results = "Summon-tulokset"
 summon_database_recommendations = "Lisäaineistoja mahdollisesti saatavilla:"
 Supplements = "Lisänumerot"
 Supplied by Amazon = "Amazonin tuottama"
-Switch view to = "Vaihda näyttöön:"
+switch_view = "Vaihda näyttöön: %%view%%"
 switchquery_fuzzy = "Sumealla haulla voi löytyä hakutuloksia, joissa on samankaltaisia sanoja"
 switchquery_intro = "Voit saada lisää tuloksia muokkaamalla hakuasi."
 switchquery_lowercasebools = "Jos käytät Boolen operaattoreita, ne täytyy kirjoittaa kokonaan ISOILLA KIRJAIMILLA"
@@ -1003,8 +1013,7 @@ Too Many Email Recipients = "Liian monta sähköpostin vastaanottajaa"
 too_many_favorites = "Listaa ei voida näyttää yhdellä kertaa sen koon vuoksi. Jaa suosikkisi useammalle listalle tai rajaa hakua käyttämällä tageja."
 too_many_new_items = "Kaikkia uutuuksia ei voida näyttää yhdellä listalla. Kokeile haun rajaamista."
 too_many_reserves = "Kaikkia kurssikirjoja ei voida näyttää yhdellä listalla. Kokeile haun rajaamista."
-top_facet_additional_prefix = "Lisää "
-top_facet_suffix = ""
+top_facet_label = "%%label%%"
 Topic = "Aihe"
 Topics = "Aiheet"
 Total Balance Due = "Maksut yhteensä"
@@ -1033,7 +1042,6 @@ VHS = "VHS"
 Video = "Video"
 Video Clips = "Videoleikkeet"
 Videos = "Videot"
-view already selected = "(käytössä)"
 View Book Bag = "Näytä kirjakori"
 View Full Collection = "Näytä koko kokoelma"
 View Full Record = "Näytä koko tietue"
@@ -1042,6 +1050,7 @@ View online: Full view Book Preview from the Hathi Trust = "Saatavilla verkossa:
 View Record = "Näytä tietue"
 View Records = "Näytä tietueet"
 View this record in EBSCOhost = "Näytä tämä tietue EBSCOhost:ssa"
+view_already_selected = "%%current%% (käytössä)"
 visual_facet_parent = "Päätasolta"
 Volume = "Volyymi"
 Volume Holdings = "Numerot saatavissa"
diff --git a/languages/fr.ini b/languages/fr.ini
index 96c1392f4bf8a74439634722aeb901bd20341ee8..1aa149e44bae8aa8ce25a337c4f0eee73203a863 100644
--- a/languages/fr.ini
+++ b/languages/fr.ini
@@ -6,7 +6,7 @@ Access URL = "URL d'accès"
 access_denied = "Accès interdit."
 Accession Number = "Numéro d'inventaire"
 Account = "Compte lecteur"
-Add = "Ajouter"
+account_block_options_missing = "Certains choix ont été retirés en raison d'un blocage sur votre compte. Détails : %%details%%"
 Add a Library Card = "Ajouter une carte de bibliothèque"
 Add a Note = "Ajouter une observation"
 Add Tag = "Ajouter un tag"
@@ -18,8 +18,6 @@ Add your comment = "Ajouter un commentaire"
 add_comment_fail_blank = "Le commentaire ne peut être vide."
 add_comment_success = "Commentaire ajouté."
 add_favorite_fail = "Erreur: les données n'ont pas été enregistrées"
-add_favorite_prefix = "Ajouter"
-add_favorite_suffix = "aux favoris"
 add_list_fail = "Erreur : la liste n'a pas été créée"
 add_other_libraries = "Ajouter des documents provenant d'autres bibliothèques"
 add_search = "Ajouter un champ de recherche"
@@ -27,6 +25,7 @@ add_search_group = "Ajouter un groupe de recherche"
 add_tag_error = "Erreur : les tags n'ont pas été enregistrés"
 add_tag_note = "Séparez les tags par des espaces. Utilisez des guillemets pour les tags contenant plusieurs mots."
 add_tag_success = "Tag enregistré"
+add_to_favorites_html = "Ajouter <em>%%title%%</em> aux favoris"
 Address = "Adresse"
 adv_search_all = "Tous les champs"
 adv_search_author = "Auteur"
@@ -172,6 +171,10 @@ Catalog Results = "Résultats du catalogue"
 catalog_login_desc = "Entrez vos codes d'accès au catalogue"
 CD = "CD"
 Change Password = "Modifier le mot de passe"
+channel_add_more = "Afficher davantage de canaux de ce type"
+channel_expand = "Explorer des canaux similaires"
+channel_explore = "Explorer avec les canaux"
+channel_search = "Afficher les éléments dans la liste de résultats"
 Check Hold = "Voir les réservations"
 Check Recall = "Voir les rappels"
 Checked Out = "Emprunté"
@@ -222,7 +225,6 @@ confirm_ill_request_cancel_selected_text = "Souhaitez-vous annuler les demandes
 confirm_new_password = "Confirmer le nouveau mot de passe"
 confirm_storage_retrieval_request_cancel_all_text = "Souhaitez-vous annuler toutes vos demandes de communication en magasin ?"
 confirm_storage_retrieval_request_cancel_selected_text = "Souhaitez-vous annuler les demandes de communication en magasin sélectionnées ?"
-conjunction_or = "ou"
 Contents = "Contenu"
 Contributing Source = "Sources"
 Contributors = "autres auteurs"
@@ -272,6 +274,7 @@ Displaying the top = "Affichage ascendant"
 Document Inspector = "Inspecteur de document"
 Document Type = "Type de document"
 DOI = "DOI"
+doi_detected_html = "Il semble que votre recherche contienne un DOI. Pour vérifier la disponibilité en ligne de cette ressource, cliquez ici: <a href="%%url%%">%%doi%%</a>"
 Draw Search Box = "Dessiner la boîte de recherche"
 Due = "Délais"
 Due Date = "Délais d'emprunt"
@@ -345,6 +348,10 @@ export_selected = "Exporter la sélection"
 export_selected_favorites = "Exporter les favoris sélectionnés"
 export_success = "Export terminé"
 export_unsupported_format = "Format d'export non supporté"
+external_auth_heading = "Accès aux contenus qui font l'objet d'une licence"
+external_auth_login_message = "Connectez-vous pour accéder aux contenus qui font l'objet d'une licence"
+external_auth_unauthorized = "Vous n'êtes pas autorisé à accéder aux contenus qui font l'objet d'une licence"
+external_auth_unauthorized_desc = "Le mode de connexion que vous avez utilisé ne donne pas accès aux contenus qui font l'objet d'une licence. Merci de vous déconnecter et d'utiliser une autre méthode d'authentification."
 FAQs = "FAQ"
 fav_delete = "Supprimer les favoris sélectionnés"
 fav_delete_deleting = "Vos favoris sont supprimés."
@@ -382,7 +389,6 @@ for search = "pour la recherche"
 Forgot Password = "Mot de passe oublié"
 Form Submitted! = "Formulaire envoyé !"
 Format = "Format"
-found = "trouvé"
 From = "De"
 Full description = "Description complète"
 Full text is not displayed to guests = "Le texte intégral n'est pas affiché aux usagers non authentifiés."
@@ -434,7 +440,7 @@ hold_cancel_all = "Annuler toutes les réservations"
 hold_cancel_fail = "Votre réservation n'a pas été annulée. Veuillez contacter la bibliothèque pour plus d'informations."
 hold_cancel_selected = "Annuler les réservations sélectionnées"
 hold_cancel_success = "Votre réservation a bien été annulée"
-hold_cancel_success_items = "La ou les réservations ont bien été annulées"
+hold_cancel_success_items = "%%count%% la ou les réservations ont bien été annulées"
 hold_date_invalid = "Veuillez saisir une date valide"
 hold_date_past = "Veuillez saisir une date dans le futur"
 hold_empty_selection = "Aucune réservation n'est sélectionnée"
@@ -442,19 +448,21 @@ hold_error_blocked = "Vous n'avez pas les autorisations nécessaires pour réser
 hold_error_fail = "Votre demande a échoué. Veuillez contacter la bibliothèque pour plus d'informations."
 hold_invalid_pickup = "Le lieu de retrait saisi est incorrect. Veuillez réessayer"
 hold_invalid_request_group = "Le groupe utilisé pour la demande de réservation est incorrect. Veuillez réessayer."
+hold_items_available = "La réservation n'est pas possible, car des exemplaires sont disponibles."
 hold_login = "Pour les informations sur les réservations"
 hold_place = "Réserver"
 hold_place_fail_missing = "Votre demande a échoué. Il manquait certaines données. Veuillez contacter la bibliothèque pour plus d'informations"
 hold_place_success_html = "La réservation a bien été enregistrée. <a href="%%url%%">Vos réservations et rappels</a>."
 hold_profile_html = "Pour les réservations et prolongations, veuillez créer un <a href="%%url%%">profil dans le catalogue de la bibliothèque</a>."
 hold_queue_position = "Place dans la file d'attente"
+hold_record_already_on_loan = "L'exemplaire est déjà emprunté sur votre compte"
 hold_request_group = "Demande de"
 hold_requested_group = "Demandé par"
 hold_required_by = "N'est plus nécessaire après"
 hold_success = "Votre demande s'est déroulée correctement"
 Holdings = "Exemplaires"
 Holdings at Other Libraries = "Exemplaires dans les autres bibliothèques"
-Holdings details from = "Informations d'exemplaires de"
+holdings_details_from = "Informations d'exemplaires de %%location%%"
 Holdings_notes = "Notes"
 Holds = "Réservations"
 Holds and Recalls = "Réservations et rappels"
@@ -468,7 +476,7 @@ ill_request_cancel_all = "Annuler toutes les demandes de prêt entre bibliothèq
 ill_request_cancel_fail = "Votre demande n'a pas été annulée. Veuillez contacter la bibliothèque pour plus d'informations."
 ill_request_cancel_selected = "Annuler les demandes de prêt entre bibliothèques sélectionnées."
 ill_request_cancel_success = "Votre demande a bien été annulée"
-ill_request_cancel_success_items = "La ou les demandes ont bien été annulées"
+ill_request_cancel_success_items = "%%count%% la ou les demandes ont bien été annulées"
 ill_request_canceled = "Annulé"
 ill_request_check_text = "Vérifier les demandes de prêt entre bibliothèques."
 ill_request_comments = "Commentaires"
@@ -497,7 +505,6 @@ ils_offline_login_message = "Votre compte personnel sera indisponible pendant ce
 ils_offline_status = "Notre système de gestion de bibliothèque est en cours de maintenance."
 ils_offline_title = "Opération de maintenance en cours"
 Import Record = "Importer les notices"
-Import to = "Importer vers"
 in = "dans"
 In This Collection = "Dans cette collection"
 in_collection_label = "Dans la collection:"
@@ -525,8 +532,8 @@ Item removed from favorites = "Notice retirée des favoris"
 Item removed from list = "Notice retirée de la liste"
 Items = "Éléments"
 items = "notices"
-items_added_to_bookbag = "Notice(s) ajoutée(s) à votre panier"
-items_already_in_bookbag = "La ou les notices sont déjà dans votre panier ou n'ont pu être ajoutées."
+items_added_to_bookbag = "%%count%% notice(s) ajoutée(s) à votre panier"
+items_already_in_bookbag = "%%count%% la ou les notices sont déjà dans votre panier ou n'ont pu être ajoutées."
 Journal = "Revue"
 Journal Articles = "Article de revue"
 Journal Info = "Informations sur la revue"
@@ -643,12 +650,11 @@ nohit_active_filters = "Au moins un filtre a été appliqué à cette recherche.
 nohit_change_tab = "Vous avez recherché dans l'onglet "%%activeTab%%". Vous trouverez peut-être des résultats supplémentaires dans les autres onglets :"
 nohit_filters = "Filtres appliqués à cette recherche"
 nohit_heading = "Aucun résultat."
+nohit_lookfor_html = "Votre recherche - <strong>%%lookfor%%</strong> - ne correspond à aucune ressource."
 nohit_no_filters = "Aucun filtre n'a été appliqué sur cette recherche."
 nohit_parse_error = "Il semblerait qu'il y ait une erreur dans votre recherche. Vérifiez la syntaxe. Si vous ne souhaitez pas utiliser de fonction avancée, vous pouvez essayez de mettre votre recherche entre guillemets."
-nohit_prefix = "Votre recherche"
 nohit_query_without_filters = "Supprimer tous les filtres de cette recherche."
 nohit_spelling = "Essayez une orthographe différente."
-nohit_suffix = "ne correspond à aucune ressource."
 nohit_suggest = "Vérifiez votre recherche en supprimant des mots-clés et en vérifiant l'orthographe."
 NOT = "PAS"
 Not Illustrated = "Sans illustrations"
@@ -690,7 +696,7 @@ number_decimal_point = ","
 number_thousands_separator = " "
 OAI Server = "Serveur OAI"
 Occupation = "Activité"
-of = "de"
+of_num_results = "#%%position%% de %%total%% résultas"
 old_password = "Ancien mot de passe"
 On Reserve = "Mis en réserve"
 On Reserve - Ask at Circulation Desk = "Mis en réserve - Contactez la bibliothèque"
@@ -698,6 +704,7 @@ on_reserve = "Mis en réserve - Faire une demande à la bibliothèque"
 on_topic = "%%count%% élément(s) sur ce sujet"
 Online Access = "Accès en ligne"
 online_resources = "Texte intégral"
+open_access_limit = "Limiter au contenu en accès ouvert"
 operator_contains = "contient"
 operator_exact = "est (exactement)"
 OR = "OU"
@@ -736,8 +743,6 @@ Please check back soon = "Veuillez réessayer plus tard"
 Please contact the Library Reference Department for assistance = "Veuillez contacter votre bibliothèque pour obtenir de l'assistance"
 Please enable JavaScript. = "Veuillez activer JavaScript."
 Please upgrade your browser. = "Veuillez mettre à jour votre navigateur."
-Posted by = "Enregistré par"
-posted_on = "le"
 Preferences = "Préférences"
 Preferred Library = "Bibliothèque favorite"
 Prev = "Précédent"
@@ -873,7 +878,12 @@ Sensor Image = "Image du capteur"
 Serial = "Publication en série"
 Series = "Collection"
 Set = "Changer"
-Showing = "Résultat(s)"
+showing_items_html = "Résultat(s) <strong>%%start%% - %%end%%</strong> Éléments"
+showing_items_of_html = "Résultat(s) <strong>%%start%% - %%end%%</strong> de <strong>%%total%%</strong> Éléments"
+showing_results_for_html = "Résultat(s) <strong>%%start%% - %%end%%</strong> résultas pour la requête '<strong>%%lookfor%%</strong>'"
+showing_results_html = "Résultat(s) <strong>%%start%% - %%end%%</strong> résultas"
+showing_results_of_for_html = "Résultat(s) <strong>%%start%% - %%end%%</strong> résultas de <strong>%%total%%</strong> pour la requête '<strong>%%lookfor%%</strong>'"
+showing_results_of_html = "Résultat(s) <strong>%%start%% - %%end%%</strong> résultas de <strong>%%total%%</strong>"
 sidebar_close = "Cacher la barre latérale"
 sidebar_expand = "Afficher la barre latérale"
 Similar Items = "Documents similaires"
@@ -917,7 +927,7 @@ storage_retrieval_request_cancel_all = "Annuler toutes les demandes de communica
 storage_retrieval_request_cancel_fail = "Votre demande n'a pas été annulée. Veuillez contacter la bibliothèque pour plus d'informations."
 storage_retrieval_request_cancel_selected = "Annuler les demandes de communication en magasin sélectionnées"
 storage_retrieval_request_cancel_success = "Votre demande a bien été annulée"
-storage_retrieval_request_cancel_success_items = "La ou les demandes ont bien été annulées"
+storage_retrieval_request_cancel_success_items = "%%count%% la ou les demandes ont bien été annulées"
 storage_retrieval_request_canceled = "Annulé"
 storage_retrieval_request_check_text = "Consulter les demandes de communication en magasin"
 storage_retrieval_request_comments = "Commentaires"
@@ -955,7 +965,7 @@ Summon Results = "Résultats dans Summon"
 summon_database_recommendations = "Vous pourrez trouver des informations supplémentaires ici :"
 Supplements = "Suppléments"
 Supplied by Amazon = "Mis à disposition par Amazon"
-Switch view to = "Basculer vers la vue"
+switch_view = "Basculer vers la vue %%view%%"
 switchquery_fuzzy = "Effectuer une recherche floue retournera les résultats avec des orthographes proches"
 switchquery_intro = "Vous pourriez obtenir plus de résultats en ajustant votre recherche"
 switchquery_lowercasebools = "Si vous souhaitez utiliser des opérateurs booléens, ils doivent être en MAJUSCULES."
@@ -997,8 +1007,7 @@ Too Many Email Recipients = "Il y a trop d'adresses de courriel."
 too_many_favorites = "La liste est trop longue pour être affichée en une fois. Essayez de réorganiser vos favoris en plusieurs listes ou de limiter à l'aide des tags."
 too_many_new_items = "Il y a trop de nouvelles notices pour les afficher en une seule fois. Essayez de préciser votre recherche."
 too_many_reserves = "Il y a trop de documents mis en réserve pour les afficher en une seule fois. Essayez de préciser votre recherche."
-top_facet_additional_prefix = "En outre "
-top_facet_suffix = "... dans votre recherche."
+top_facet_label = "%%label%% dans votre recherche."
 Topic = "Sujet"
 Topics = "Sujets"
 Total Balance Due = "Solde débiteur total"
@@ -1027,7 +1036,6 @@ VHS = "VHS"
 Video = "Vidéo"
 Video Clips = "vidéo-clips"
 Videos = "Vidéos"
-view already selected = "Voir les éléments déjà sélectionnés"
 View Book Bag = "Consulter le panier"
 View Full Collection = "Voir la collection complète"
 View Full Record = "Voir la notice complète"
@@ -1036,6 +1044,7 @@ View online: Full view Book Preview from the Hathi Trust = "Disponible en ligne
 View Record = "Voir la notice"
 View Records = "Voir les notices"
 View this record in EBSCOhost = "Voir cette notice dans EBSCOhost"
+view_already_selected = "%%current%% voir les éléments déjà sélectionnés"
 visual_facet_parent = "De"
 Volume = "Volume"
 Volume Holdings = "Indications des volumes"
diff --git a/languages/ga.ini b/languages/ga.ini
index ec5cd5647ec2ec09ebbfe694e09bb2605f84e94e..3230374a37abaa75e05b637b59dea9aa3d287894 100644
--- a/languages/ga.ini
+++ b/languages/ga.ini
@@ -3,7 +3,6 @@
 ;note_785_7 = "Nasctha le" ; incomplete translation (en.ini was later revised)
 Access = "Rochtain"
 Account = "Cuntas"
-Add = "Cuir leis"
 Add a Note = "Cuir Nóta Leis"
 Add Tag = "Cuir Clib Leis"
 Add Tags = "Cuir Clibeanna Leis"
@@ -11,8 +10,6 @@ Add to Book Bag = "Cuir leis an Mála Leabhar"
 Add to favorites = "Cuir leis na Ceanáin"
 Add your comment = "Cuir do thuairim leis"
 add_favorite_fail = "Earráid: Níor sábháladh an taifead"
-add_favorite_prefix = "Cuir leis"
-add_favorite_suffix = "na ceanáin"
 add_list_fail = "Earráid: Níor cruthaíodh an liosta"
 add_other_libraries = "Cuir ailt i leabharlanna eile san áireamh"
 add_search = "Cuir Réimse Cuardaigh Leis"
@@ -20,6 +17,7 @@ add_search_group = "Cuir Grúpa Cuardaigh Leis"
 add_tag_error = "Earráid: Níorbh fhéidir na Clibeanna a Shábháil"
 add_tag_note = "Déanfaidh spásanna deighilt idir clibeanna. Bain úsáid as comharthaí athfhriotail le haghaidh clibeanna ilfhocail."
 add_tag_success = "Clibeanna Sábháilte"
+add_to_favorites_html = "Cuir leis <em>%%title%%</em> na ceanáin"
 Address = "Seoladh"
 adv_search_all = "Gach Réimse"
 adv_search_author = "Údar"
@@ -254,7 +252,6 @@ Fines = "Fíneálacha"
 First Name = "Céadainm"
 for search = "le haghaidh cuardaigh"
 Format = "Formáid"
-found = "aimsithe"
 From = "Ó"
 Full description = "Cur síos iomlán"
 fulltext_limit = "Teorannaigh d'ailt a bhfuil an téacs iomlán ar fáil"
@@ -292,14 +289,14 @@ hold_cancel_all = "Cuir gach coimeád ar ceal"
 hold_cancel_fail = "Níor cuireadh d’iarratas ar ceal. Téigh i dteagmháil leis an deasc cúrsaíochta chun tuilleadh cabhrach a fháil"
 hold_cancel_selected = "Cuir gach coimeád roghnaithe ar ceal"
 hold_cancel_success = "D’éirigh leat d’iarratas a chur ar ceal"
-hold_cancel_success_items = "iarratas curtha ar ceal go rathúil"
+hold_cancel_success_items = "%%count%% iarratas curtha ar ceal go rathúil"
 hold_date_invalid = "Cuir dáta bailí isteach"
 hold_date_past = "Cuir dáta sa todhchaí isteach"
 hold_empty_selection = "Níor roghnaíodh coimeád ar bith"
 hold_error_blocked = "Ní do dhóthain pribhléidí agat an mhír seo a chur ar coimeád"
 hold_error_fail = "Theip ar d’iarratas. Téigh i dteagmháil leis an deasc cúrsaíochta chun tuilleadh cabhrach a fháil"
 hold_invalid_pickup = "Cuireadh láthair bailiúcháin neamhbhailí isteach. Bain triail eile as"
-hold_login = "chun eolas maidir le coimeád agus athghlaoch a fháil"
+hold_login = "Logáil Isteach chun eolas maidir le coimeád agus athghlaoch a fháil"
 hold_place = "Déan iarratas"
 hold_place_fail_missing = "Theip ar d’iarratas. Bhí roinnt sonraí in easnamh. Téigh i dteagmháil leis an deasc cúrsaíochta chun tuilleadh cabhrach a fháil"
 hold_place_success_html = "D’éirigh le d’iarratas. <a href="%%url%%">Ábhair ar Coimeád agus Athghlaoite agat</a>."
@@ -308,7 +305,7 @@ hold_required_by = "Níl gá leis seo tar éis"
 hold_success = "D’éirigh le d’iarratas"
 Holdings = "Sealbhúcháin"
 Holdings at Other Libraries = "Sealbhúcháin i Leabharlanna Eile"
-Holdings details from = "Sonraí sealbhúcháin ó"
+holdings_details_from = "Sonraí sealbhúcháin ó %%location%%"
 Holdings_notes = "Nótaí"
 Holds = "Ábhair ar Coimeád"
 Holds and Recalls = "Ábhair ar Coimeád agus Athghlaoite"
@@ -317,7 +314,7 @@ home_browse = "Brabhsáil de réir"
 ill_request_available = "Ar fáil le bailiú"
 ill_request_cancel_fail = "Níor cuireadh d’iarratas ar ceal. Téigh i dteagmháil leis an deasc cúrsaíochta chun tuilleadh cabhrach a fháil"
 ill_request_cancel_success = "D’éirigh leat d’iarratas a chur ar ceal"
-ill_request_cancel_success_items = "iarratas curtha ar ceal go rathúil"
+ill_request_cancel_success_items = "%%count%% iarratas curtha ar ceal go rathúil"
 ill_request_date_invalid = "Cuir dáta bailí isteach"
 ill_request_date_past = "Cuir dáta sa todhchaí isteach"
 ill_request_error_fail = "Theip ar d’iarratas. Téigh i dteagmháil leis an deasc cúrsaíochta chun tuilleadh cabhrach a fháil"
@@ -326,7 +323,6 @@ ill_request_place_fail_missing = "Theip ar d’iarratas. Bhí roinnt sonraí in
 ill_request_place_success = "D’éirigh le d’iarratas"
 Illustrated = "Maisithe"
 Import Record = "Iompórtáil an Taifead seo"
-Import to = "Iompórtáil chuig"
 in = "i"
 Institution = "Institiúid"
 Institutional Login = "Logáil Isteach Institiúide"
@@ -342,8 +338,8 @@ Issue = "Eagrán"
 Item Description = "Cur Síos ar an Mír"
 Item Notes = "Nótaí"
 items = "Míreanna"
-items_added_to_bookbag = "mír(eanna) cuirthe leis an Mála Leabhar"
-items_already_in_bookbag = "tá na míreanna i do Mhála Leabhar cheana féin, nó ní bhféadfaí iad a chur leis"
+items_added_to_bookbag = "%%count%% mír(eanna) cuirthe leis an Mála Leabhar"
+items_already_in_bookbag = "%%count%% tá na míreanna i do Mhála Leabhar cheana féin, nó ní bhféadfaí iad a chur leis"
 Journal = "Iriseán"
 Journal Articles = "Ailt in Iriseáin"
 Journal Title = "Teideal an Iriseáin"
@@ -415,11 +411,10 @@ no_description = "Níl an cur síos sin ar fáil"
 no_items_selected = "Níor roghnaíodh míreanna ar bith"
 nohit_filters = "Scagairí i bhfeidhm ar an gcuardach seo faoi láthair:"
 nohit_heading = "Gan Toradh ar Bith!"
+nohit_lookfor_html = "Do chuardach - <strong>%%lookfor%%</strong> - níor mheaitseáil seo acmhainn ar bith."
 nohit_no_filters = "Níor cuireadh scagaire ar bith i bhfeidhm ar an gcuardach seo."
 nohit_parse_error = "Is cosúil go bhfuil fadhb le do chuardach. Seiceáil an chomhréir. Mura bhfuil ardghnéithe in úsáid agat, d'fhéadfadh go mbeadh sé ina chabhair an t‑iarratas a chur idir comharthaí athfhriotail."
-nohit_prefix = "Do chuardach"
 nohit_spelling = "B'fhéidir gur cheart duit triail a bhaint as roinnt athruithe sa litriú"
-nohit_suffix = "níor mheaitseáil seo acmhainn ar bith."
 nohit_suggest = "B'fhéidir gur mhaith leat téarma do chuardaigh a leasú trí roinnt focal a bhaint amach nó an litriú a sheiceáil."
 NOT = "NÍL"
 Not Illustrated = "Gan a bheith maisithe"
@@ -440,7 +435,6 @@ note_780_5 = "Comhghafa"
 note_785_0 = "Ar lean le"
 Notes = "Nótaí"
 Number = "Uimhir"
-of = "de"
 On Reserve = "Ar Coimeád"
 On Reserve - Ask at Circulation Desk = "Ar Coimeád - Iarr ag an Deasc Cúrsaíochta"
 on_reserve = "Leabhair ar Coimeád - Iarr ag an Deasc Cúrsaíochta"
@@ -465,8 +459,6 @@ Place a Hold = "Cuir Leabhar ar Coimeád"
 Playing Time = "Am Seinnte"
 Please check back soon = "Seiceáil arís go luath"
 Please contact the Library Reference Department for assistance = "Déan teagmháil le Rannóg Thagartha na Leabharlainne chun cabhair a fháil"
-Posted by = "Breactha ag"
-posted_on = "ar"
 Prev = "Ar ais"
 Previous Title = "Teideal Roimhe"
 Print = "Priontáil"
@@ -548,7 +540,6 @@ Sensor Image = "Íomhá an Bhraiteora"
 Serial = "Sraithchlár"
 Series = "Sraith"
 Set = "Socraigh"
-Showing = "Á Thaispeáint"
 Similar Items = "Míreanna Comhchosúla"
 Slide = "Sleamhnán"
 sms_failure = "Earráid! Níorbh fhéidir teachtaireacht a sheoladh."
@@ -578,7 +569,7 @@ Status = "Stádas"
 storage_retrieval_request_available = "Ar fáil le bailiú"
 storage_retrieval_request_cancel_fail = "Níor cuireadh d’iarratas ar ceal. Téigh i dteagmháil leis an deasc cúrsaíochta chun tuilleadh cabhrach a fháil"
 storage_retrieval_request_cancel_success = "D’éirigh leat d’iarratas a chur ar ceal"
-storage_retrieval_request_cancel_success_items = "iarratas curtha ar ceal go rathúil"
+storage_retrieval_request_cancel_success_items = "%%count%% iarratas curtha ar ceal go rathúil"
 storage_retrieval_request_comments = "Tuairimí"
 storage_retrieval_request_date_invalid = "Cuir dáta bailí isteach"
 storage_retrieval_request_date_past = "Cuir dáta sa todhchaí isteach"
@@ -598,7 +589,7 @@ Summary = "Achoimre"
 Summon Results = "Torthaí Summon"
 summon_database_recommendations = "Is féidir leat teacht ar acmhainní breise anseo:"
 Supplied by Amazon = "Curtha ar fáil ag Amazon"
-Switch view to = "Athraigh amharc chuig"
+switch_view = "Athraigh amharc chuig %%view%%"
 System Unavailable = "Níl fáil ar an gCóras"
 Table of Contents = "Clár Ábhair"
 Table of Contents unavailable = "Níl fáil ar an gClár Ábhair"
@@ -619,8 +610,7 @@ To = "Chuig"
 too_many_favorites = "Tá an liosta seo ró-mhór chun taispeáint go léir ag an am céanna. Athchóirigh do ceanáin i níos mó liostaí, nó bain úsáid as clibeanna."
 too_many_new_items = "Tá an iomarca míreanna nua chun iad go léir a thaispeáint i liosta amháin. Déan iarracht do chuardach a theorannú."
 too_many_reserves = "Tá an iomarca leabhair ar coimeád le haghaidh cúrsa chun iad go léir a thaispeáint i liosta amháin. Déan iarracht do chuardach a theorannú."
-top_facet_additional_prefix = "Breise"
-top_facet_suffix = "... laistigh de do chuardach."
+top_facet_label = "%%label%% laistigh de do chuardach."
 Topic = "Topaic"
 Topics = "Topaicí"
 University Library = "Leabharlann Ollscoile"
@@ -634,10 +624,10 @@ VHS = "VHS"
 Video = "Físeán"
 Video Clips = "Gearrthóga Físe"
 Videos = "Físeáin"
-view already selected = "roghnaithe cheana féin"
 View Book Bag = "Féach ar an Mála Leabhar"
 View online: Full view Book Preview from the Hathi Trust = "Amharc ar líne: Amharc Iomlán ar Réamhbhreathnú Leabhair ó Iontaobhas Hathi"
 View Records = "Féach ar thaifid"
+view_already_selected = "%%current%% roghnaithe cheana féin"
 visual_facet_parent = "Ó"
 Volume = "Imleabhar"
 Volume Holdings = "Sealbhúcháin an Imleabhair"
diff --git a/languages/he.ini b/languages/he.ini
index ec0d77142d351d3585ebd383587f23d74cd2f099..76ef98283d923e798b553dc343f4fe55f7fa2f49 100644
--- a/languages/he.ini
+++ b/languages/he.ini
@@ -3,7 +3,6 @@
 ;note_785_7 = "מוזג לתוך" ; incomplete translation (en.ini was later revised)
 Access = "גישה"
 Account = "חשבון"
-Add = "הוספה"
 Add a Note = "הוספת הערה"
 Add Tag = "הוספת תג"
 Add Tags = "הוספת תגיות"
@@ -14,8 +13,6 @@ Add your comment = "הוספת הערה"
 add_comment_fail_blank = "הערה לא יכולה להיות ריקה."
 add_comment_success = "הערה התווספה."
 add_favorite_fail = "שגיאה. רשומה לא נשמרה"
-add_favorite_prefix = "הוספה"
-add_favorite_suffix = "למועדפים"
 add_list_fail = "שגיאה. רשימה לא נוצרה"
 add_other_libraries = "לכלול מאמרים מספריות אחרות"
 add_search = "הוספת חיפוש"
@@ -23,6 +20,7 @@ add_search_group = "הוספת קבוצת חיפוש"
 add_tag_error = "שגיאה. לא יכול לשמור תגים"
 add_tag_note = "רווחים יפרידו תגים. נא להשתמש במרכאות עם תגים בני מספר מלים"
 add_tag_success = "תגים נרשמים"
+add_to_favorites_html = "הוספה <em>%%title%%</em> למועדפים"
 Address = "כתובת"
 adv_search_all = "כל שדות"
 adv_search_author = "מחבר"
@@ -291,7 +289,6 @@ First Name = "שם פרטי"
 fix_metadata = "כן, תקן את המידע, אני אמתין."
 for search = "בשביל חיפוש"
 Format = "פורמט"
-found = "נמצא"
 From = "מ"
 Full description = "תיאור מלא"
 fulltext_limit = "הגבלה למאמרים עם טקסט מלא זמין"
@@ -336,14 +333,14 @@ hold_cancel_all = "ביטול כל ההזמנות"
 hold_cancel_fail = "בקשתך לא בוטלה, יש ליצור קשר עם מחלקת ההשאלה לעזרה נוספת"
 hold_cancel_selected = "ביטול הזמנות מסומנות"
 hold_cancel_success = "בקשתך בוטלה בהצלחה"
-hold_cancel_success_items = "בקשותיך בוטלו בהצלחה"
+hold_cancel_success_items = "%%count%% בקשותיך בוטלו בהצלחה"
 hold_date_invalid = "יש להכניס תאריך תקין"
 hold_date_past = "נא להכניס תאריך עתידי"
 hold_empty_selection = "לא נבחרו הזמנות"
 hold_error_blocked = "אין לך הרשאות מספקות כדי להזמין את הפריט. יש ליצור קשר עם מחלקת ההשאלה לעזרה נוספת."
 hold_error_fail = "בקשתך נכשלה. יש ליצור קשר עם מחלקת ההשאלה לעזרה נוספת."
 hold_invalid_pickup = "מקום האיסוף שצויין אינו תקין. נסו שוב"
-hold_login = "למידע על הזמנה והחזרת פריטים"
+hold_login = "כניסה לחשבון למידע על הזמנה והחזרת פריטים"
 hold_place = "להזמנה"
 hold_place_fail_missing = "בקשתך נכשלה מכיוון שיש חוסר במידע. יש ליצור קשר עם מחלקת ההשאלה לעזרה נוספת."
 hold_place_success_html = "בקשתך בוצעה בהצלחה. <a href="%%url%%">הזמנות ובקשות החזרה שלך</a>."
@@ -353,7 +350,7 @@ hold_required_by = "לא נדרש לאחר"
 hold_success = "בקשתך בוצעה בהצלחה"
 Holdings = "מלאי ספרים"
 Holdings at Other Libraries = "מלאי ספרים בסיפריות אחרות"
-Holdings details from = "פרטי מלאי ספרים מ"
+holdings_details_from = "פרטי מלאי ספרים מ %%location%%"
 Holdings_notes = "הערות"
 Holds = "הזמנות"
 Holds and Recalls = "הזמנות והחזרות"
@@ -363,7 +360,7 @@ Identifier = "מזהה"
 ill_request_available = "זמין לאיסוף"
 ill_request_cancel_fail = "בקשתך לא בוטלה, יש ליצור קשר עם מחלקת ההשאלה לעזרה נוספת"
 ill_request_cancel_success = "בקשתך בוטלה בהצלחה"
-ill_request_cancel_success_items = "בקשותיך בוטלו בהצלחה"
+ill_request_cancel_success_items = "%%count%% בקשותיך בוטלו בהצלחה"
 ill_request_date_invalid = "יש להכניס תאריך תקין"
 ill_request_date_past = "נא להכניס תאריך עתידי"
 ill_request_error_fail = "בקשתך נכשלה. יש ליצור קשר עם מחלקת ההשאלה לעזרה נוספת."
@@ -372,7 +369,6 @@ ill_request_place_fail_missing = "בקשתך נכשלה מכיוון שיש חו
 ill_request_place_success = "בקשתך בוצעה בהצלחה"
 Illustrated = "מאויר"
 Import Record = "יבוא רשומה"
-Import to = "יבוא אל"
 in = "ב"
 In This Collection = "באוסף זה"
 in_collection_label = "באוסף:"
@@ -395,8 +391,8 @@ Item removed from favorites = "פריט הוסר ממועדפים"
 Item removed from list = "פריט הוסר מרשימה"
 Items = "פריטים"
 items = "פריטים"
-items_added_to_bookbag = "הפריט/ים הוספו לילקוט"
-items_already_in_bookbag = "הפריט/ים כבר בילקוט"
+items_added_to_bookbag = "%%count%% הפריט/ים הוספו לילקוט"
+items_already_in_bookbag = "%%count%% הפריט/ים כבר בילקוט"
 Journal = "כתב-עת"
 Journal Articles = "מאמרים"
 Journal Title = "כותרת כתב-העת"
@@ -481,11 +477,10 @@ no_description = "תיאור לא זמין."
 no_items_selected = "לא נבחרו פריטים"
 nohit_filters = "מסננים המיושמים לחיפוש כעת"
 nohit_heading = "אין תוצאות!"
+nohit_lookfor_html = "החיפוש שביצעת - <strong>%%lookfor%%</strong> - חזר ריק."
 nohit_no_filters = "אין לך שום מסננים מיושמים לחיפוש"
 nohit_parse_error = "נראה שישנה בעיה עם שאילתת החיפוש שלך. אנא בדקו את התחביר. אם לא השתמשת בתכונות המתקדמות, לשים את השאילתה בתוך המרכאות עשוי לעזור."
-nohit_prefix = "החיפוש שביצעת"
 nohit_spelling = "אולי כדאי לנסות איות אחר או כתיב מלא"
-nohit_suffix = "חזר ריק."
 nohit_suggest = "אולי כדאי לנסח מחדש את השאילתה, לבחור מילים אחרות או לנסות כתיב מלא."
 NOT = "לא"
 Not Illustrated = "לא מאויר"
@@ -519,7 +514,6 @@ note_785_8 = "השתנה בחזרה ל"
 Notes = "הערות"
 Number = "מספר"
 OAI Server = "שרת OAI"
-of = "מתוך"
 On Reserve = "בשמורים"
 On Reserve - Ask at Circulation Desk = "פריט שמור. נא לברר בדלפק ההשאלה"
 on_reserve = "שמירה"
@@ -545,8 +539,6 @@ Place a Hold = "ביצוע הזמנה"
 Playing Time = "אורך"
 Please check back soon = "אנא בדקו שוב בקרוב"
 Please contact the Library Reference Department for assistance = "אנא צרו קשר עם מחלקת יעץ לסיוע"
-Posted by = "פורסם על ידי"
-posted_on = "ב"
 Preferred Library = "ספריה מועדפת"
 Prev = "הקודם"
 Preview = "תצוגה מקדימה"
@@ -639,7 +631,8 @@ Sensor Image = "תמונת חיישן"
 Serial = "סדרון"
 Series = "סדרה"
 Set = "מערכת"
-Showing = "מראה"
+showing_items_html = "מראה <strong>%%start%% - %%end%%</strong> פריטים"
+showing_items_of_html = "מראה <strong>%%start%% - %%end%%</strong> מתוך <strong>%%total%%</strong> פריטים"
 Similar Items = "פריטים דומים"
 skip_confirm = "האם יש לדלג על שלב זה?"
 skip_fix_metadata = "לא לתקן מטהדאטה בזמן זה."
@@ -673,7 +666,7 @@ status_unknown_message = "סטטוס עדכני לא זמין"
 storage_retrieval_request_available = "זמין לאיסוף"
 storage_retrieval_request_cancel_fail = "בקשתך לא בוטלה, יש ליצור קשר עם מחלקת ההשאלה לעזרה נוספת"
 storage_retrieval_request_cancel_success = "בקשתך בוטלה בהצלחה"
-storage_retrieval_request_cancel_success_items = "בקשותיך בוטלו בהצלחה"
+storage_retrieval_request_cancel_success_items = "%%count%% בקשותיך בוטלו בהצלחה"
 storage_retrieval_request_comments = "הערות"
 storage_retrieval_request_date_invalid = "יש להכניס תאריך תקין"
 storage_retrieval_request_date_past = "נא להכניס תאריך עתידי"
@@ -694,7 +687,7 @@ Summary = "סיכום"
 Summon Results = "תוצאות Summon"
 summon_database_recommendations = "משאבים נוספים"
 Supplied by Amazon = "מסופק על ידי Amazon"
-Switch view to = "שינוי תצוגה ל"
+switch_view = "שינוי תצוגה ל %%view%%"
 System Unavailable = "המערכת לא זמינה"
 Table of Contents = "תוכן הענינים"
 Table of Contents unavailable = "תוכן הענינים לא זמין"
@@ -720,8 +713,7 @@ To = "אל"
 too_many_favorites = "הרשימה ארוכה מכדי להציגה, יש לחלק את המועדפים לכמה רשימות או לסנן את הרשימה על ידי תגיות."
 too_many_new_items = "רשימת הפריטים החדשים ארוכה מכדי להציגה. נסי/ה להגביל את החיפוש."
 too_many_reserves = "רשימת השמורים ארוכה מכדי להציגה. נסי/ה להגביל את החיפוש."
-top_facet_additional_prefix = "נוסף"
-top_facet_suffix = "בתוך החיפוש שלך... "
+top_facet_label = "בתוך החיפוש שלך %%label%%"
 Topic = "נושא"
 Topics = "נושאים"
 tree_search_limit_reached_html = " החיפוש החזיר יותר מדי תוצאות מכדי להציג בעץ. מוצגים <b>%%limit%%</b> הפריטים הראשונים. לחיפוש מלא נא ללחוץ על <a id="fullSearchLink" href="%%url%%" target="_blank">כאן.</a>"
@@ -738,13 +730,13 @@ VHS = "קלטת וידאו"
 Video = "וידאו"
 Video Clips = "סרטונים"
 Videos = "וידאו"
-view already selected = "תצוגה זו כבר נבחרה"
 View Book Bag = "צפיה בפריטים בילקוט"
 View Full Collection = "צפיה באוסף השלם"
 View Full Record = "צפיה ברשומה המלאה"
 View online: Full view Book Preview from the Hathi Trust = "ראה באינטרנט: תצוגה מקדימה מלאה מ Hathi Trust"
 View Record = "צפיה ברשומה"
 View Records = "ראה רשומות"
+view_already_selected = "%%current%% תצוגה זו כבר נבחרה"
 visual_facet_parent = "מ"
 Volume = "כרך"
 Volume Holdings = "מלאי כרכים"
diff --git a/languages/it.ini b/languages/it.ini
index 28478dc12ac0667c9588af6a8d3c676fd114076f..8921598f7c89c35d33cf36d23cc083dc9e752e2a 100644
--- a/languages/it.ini
+++ b/languages/it.ini
@@ -6,7 +6,7 @@ Access URL = "URL di accesso"
 access_denied = "Accesso negato."
 Accession Number = "Accession Number"
 Account = "Account"
-Add = "Aggiungi"
+account_block_options_missing = "Alcune opzioni sono state tolte per via di un blocco del tuo account. Dettagli: %%details%%"
 Add a Library Card = "Aggiungi una tessera di biblioteca"
 Add a Note = "Aggiungi una nota"
 Add Tag = "Aggiungi Tag"
@@ -18,8 +18,6 @@ Add your comment = "Aggiungi un commento"
 add_comment_fail_blank = "Un commento non può essere vuoto."
 add_comment_success = "Commento aggiunto."
 add_favorite_fail = "Errore: record non salvato"
-add_favorite_prefix = "Aggiungi"
-add_favorite_suffix = "ai preferiti"
 add_list_fail = "Errore: lista non creata"
 add_other_libraries = "Includi articoli di altre biblioteche"
 add_search = "Aggiungi campo di ricerca"
@@ -27,6 +25,7 @@ add_search_group = "Aggiungi gruppo di ricerca"
 add_tag_error = "Errore: Tags non salvati"
 add_tag_note = "Gli spazi separeranno i Tag. Usa le virgolette per i Tag multi-parola."
 add_tag_success = "Tag salvati"
+add_to_favorites_html = "Aggiungi <em>%%title%%</em> ai preferiti"
 Address = "Indirizzo"
 adv_search_all = "Tutti i campi"
 adv_search_author = "Autore"
@@ -172,6 +171,10 @@ Catalog Results = "Risultati del Catalogo"
 catalog_login_desc = "Inserisci le credenziali con cui accedi al catalogo della biblioteca."
 CD = "CD"
 Change Password = "Cambia Password"
+channel_add_more = "Aggiungi altre selezioni tipo questa"
+channel_expand = "Esplora selezioni correlate"
+channel_explore = "Esplora selezioni"
+channel_search = "Mostra copie come risultati di ricerca"
 Check Hold = "Controlla le prenotazioni"
 Check Recall = "Controlla le richieste"
 Checked Out = "Non disponibile"
@@ -222,7 +225,6 @@ confirm_ill_request_cancel_selected_text = "Vuoi cancellare le richieste di pres
 confirm_new_password = "Conferma la nuova password"
 confirm_storage_retrieval_request_cancel_all_text = "Vuoi cancellare tutte le tue richieste di volumi da magazzino??"
 confirm_storage_retrieval_request_cancel_selected_text = "Vuoi cancellare le richiestte di volumi da magazzino selezionate?"
-conjunction_or = "o"
 Contents = "Contenuti"
 Contributing Source = "Fonte del contributo"
 Contributors = "Nomi associati"
@@ -272,6 +274,7 @@ Displaying the top = "Displaying the top"
 Document Inspector = "Analizzatore documentale"
 Document Type = "Tipo di documento"
 DOI = "DOI"
+doi_detected_html = "La tua ricerca sembra contenere un DOI. Clicca qui per controllare la disponibilità della risorsa: <a href="%%url%%">%%doi%%</a>"
 Draw Search Box = "Definisci riquadro ricerca"
 Due = "Scadere"
 Due Date = "Data di scadenza"
@@ -285,6 +288,7 @@ edit_list_fail = "Ops, non sei autorizzato a modificare questa lista"
 edit_list_success = "Lista aggiornata con successo."
 Edition = "Edizione"
 eds_expander_fulltext = "Cerca anche nel full text degli articoli"
+eds_expander_relatedsubjects = "Includi record con soggetti equivalenti"
 eds_expander_thesaurus = "Cerca parole correlate"
 eds_limiter_FC = "Solo catalogo"
 eds_limiter_FC1 = "Solo nel repository istitituzionale"
@@ -345,6 +349,10 @@ export_selected = "Esporta i selezionati"
 export_selected_favorites = "Esporta i preferiti selezionati"
 export_success = "Esportazione completata correttamente"
 export_unsupported_format = "Formato di esportazione non supportato"
+external_auth_heading = "Accesso s materiale sottoposto a licenza"
+external_auth_login_message = "Login per accedere a materiale sottoposto a licenza"
+external_auth_unauthorized = "Non sei autorizzato ad accedere a materiale sotto licenza"
+external_auth_unauthorized_desc = "La tua modalità di login non permette di accedere a materiale sottoposto a licenza d'usio. Esci e fai login con un altro metodo."
 FAQs = "FAQ"
 fav_delete = "Elimina i preferiti selezionati"
 fav_delete_deleting = "I tuoi preferiti stanno per essere eliminati."
@@ -382,7 +390,6 @@ for search = "ricerca"
 Forgot Password = "Password dimenticata"
 Form Submitted! = "Messaggio inviato!"
 Format = "Natura"
-found = "trovato"
 From = "Da"
 Full description = "Descrizione completa"
 Full text is not displayed to guests = "Il Full text non è disponibile agli ospiti."
@@ -434,7 +441,7 @@ hold_cancel_all = "Cancella tutte le prenotazioni"
 hold_cancel_fail = "La tua richiesta non è stata cancellata. Contatta il servizio di prestito per assistenza."
 hold_cancel_selected = "Cancella le prenotazioni selezionate"
 hold_cancel_success = "La tua richiesta è stata cancellata con successo"
-hold_cancel_success_items = "richiesta(e) cancellata con successo"
+hold_cancel_success_items = "%%count%% richiesta(e) cancellata(e) con successo"
 hold_date_invalid = "Inserisci una data valida"
 hold_date_past = "Inserisci una data futura"
 hold_empty_selection = "Nessuna prenotazione selezionata"
@@ -442,19 +449,21 @@ hold_error_blocked = "Non hai le autorizzazioni per fare una prenotazione. Conta
 hold_error_fail = "Richiesta fallita. Contatta la biblioteca per chiarimenti."
 hold_invalid_pickup = "Hai inserito un luogo di ritito non valido; per favore correggi."
 hold_invalid_request_group = "Gruppo di richiesta prenotazioni non ammesso. Prova di nuovo."
-hold_login = "per informazioni su prenotazioni e richieste"
+hold_items_available = "La copia non può essere prenotata perchè è disponibile."
+hold_login = "Entra per informazioni su prenotazioni e richieste"
 hold_place = "Richiedi"
 hold_place_fail_missing = "Richiesta fallita. Alcuni dati sono mancanti. Contatta la biblioteca per chiarimenti."
 hold_place_success_html = "Richiesta accettata. <a href="%%url%%">Le tue prenotazioni e richieste</a>."
 hold_profile_html = "Per informazioni su prenotazioni e rinnovi, attiva il tuo <a href="%%url%%">profilo</a>."
 hold_queue_position = "Posizione in coda"
+hold_record_already_on_loan = "Hai gia il record in prestito"
 hold_request_group = "Richiesta di"
 hold_requested_group = "Richiesto da"
 hold_required_by = "Non richiedere più dopo"
 hold_success = "Richiesta accettata"
 Holdings = "Posseduto"
 Holdings at Other Libraries = "Posseduto di altre biblioteche"
-Holdings details from = "Dettagli sul posseduto da"
+holdings_details_from = "Dettagli sul posseduto da %%location%%"
 Holdings_notes = "Note"
 Holds = "Richieste"
 Holds and Recalls = "Prenotazioni e richieste"
@@ -468,7 +477,7 @@ ill_request_cancel_all = "Cancella tutte le richieste di prestito interbibliotec
 ill_request_cancel_fail = "La tua richiesta non è stata cancellata. Contatta il servizio di prestito per assistenza."
 ill_request_cancel_selected = "Cancella le richieste di prestito interbibliotecario selezionate"
 ill_request_cancel_success = "La tua richiesta è stata cancellata con successo"
-ill_request_cancel_success_items = "richiesta(e) cancellata con successo"
+ill_request_cancel_success_items = "%%count%% richiesta(e) cancellata(e) con successo"
 ill_request_canceled = "Canceled"
 ill_request_check_text = "Controlla richiesta di prestito interbibliotecario"
 ill_request_comments = "Commenti"
@@ -497,7 +506,6 @@ ils_offline_login_message = "I dettagli del tuo account non saranno disponibili
 ils_offline_status = "Il sistema di gestione della nostra biblioteca in questo momento è in manutenzione."
 ils_offline_title = "Sistema in manutenzione"
 Import Record = "Importa record"
-Import to = "Importa in"
 in = "in"
 In This Collection = "In questa collezione"
 in_collection_label = "Nella collezione:"
@@ -525,8 +533,8 @@ Item removed from favorites = "Elemento rimosso dai preferiti"
 Item removed from list = "Elemento rimosso dalla lista"
 Items = "Elementi"
 items = "elementi"
-items_added_to_bookbag = "oggetto(i) aggiunto(i) al carrello"
-items_already_in_bookbag = "oggetto(i) già nel carrello o che non può essere aggiunto"
+items_added_to_bookbag = "%%count%% oggetto(i) aggiunto(i) al carrello"
+items_already_in_bookbag = "%%count%% oggetto(i) già nel carrello o che non può essere aggiunto"
 Journal = "Periodico"
 Journal Articles = "Articoli del periodico"
 Journal Info = "Informazioni sulla rivista"
@@ -643,12 +651,11 @@ nohit_active_filters = "Hai applicato uno o più filtri a questa ricerca. Se li
 nohit_change_tab = "Stai cercando in "%%activeTab%%". Potresti trovare ulteriori risultati cercando in:"
 nohit_filters = "Filtri applicati attualmente per questa ricerca:"
 nohit_heading = "Nessun risultato!"
+nohit_lookfor_html = "La tua ricerca - <strong>%%lookfor%%</strong> - non ha trovato dei risultati."
 nohit_no_filters = "Non è stato applicato nessun filtro a questa ricerca."
 nohit_parse_error = "C'è stato un problema nell'interrogazione della ricerca. Controllare la sintassi. Se non stai usando strumenti per la ricerca avanzata, inserire i termini di ricerca tra virgoletta può aiutare."
-nohit_prefix = "La tua ricerca"
 nohit_query_without_filters = "Rimuovi tutti i filtri da questa ricerca."
 nohit_spelling = "Forse hai sbagliato a scrivere i termini di ricerca"
-nohit_suffix = "nessuna risorsa trovata."
 nohit_suggest = "Puoi modificare i termini di riceca rimuovendo alcune parole o controllando lo spelling."
 NOT = "NOT"
 Not Illustrated = "Non illustrato"
@@ -690,7 +697,7 @@ number_decimal_point = ","
 number_thousands_separator = "."
 OAI Server = "OAI Server"
 Occupation = "Occupazione"
-of = "di"
+of_num_results = "#%%position%% di %%total%% risultati"
 old_password = "Vecchia Password"
 On Reserve = "Riservato"
 On Reserve - Ask at Circulation Desk = "Riservato - Chiedere al banco del prestito"
@@ -698,6 +705,7 @@ on_reserve = "Riservato - Chiedi al banco prestiti"
 on_topic = "%%count%% elementi in questo soggetto"
 Online Access = "Accesso online"
 online_resources = "Full Text"
+open_access_limit = "Limita al contenuto Open Access"
 operator_contains = "contiene"
 operator_exact = "= (esatto)"
 OR = "OR"
@@ -736,8 +744,6 @@ Please check back soon = "Per favore ricontrolla tra un pò"
 Please contact the Library Reference Department for assistance = "Per assistenza contattare il banco reference"
 Please enable JavaScript. = "Abilita i avaScript."
 Please upgrade your browser. = "Aggiorna il tuo browser."
-Posted by = "Postato da"
-posted_on = "su"
 Preferences = "Preferenze"
 Preferred Library = "Biblioteca preferita"
 Prev = "Prev"
@@ -873,7 +879,12 @@ Sensor Image = "Sensor Image"
 Serial = "Periodico"
 Series = "Serie"
 Set = "Set"
-Showing = "Mostra"
+showing_items_html = "Mostra <strong>%%start%% - %%end%%</strong> Elementi"
+showing_items_of_html = "Mostra <strong>%%start%% - %%end%%</strong> di <strong>%%total%%</strong> elementi"
+showing_results_for_html = "Mostra <strong>%%start%% - %%end%%</strong> risultati ricerca '<strong>%%lookfor%%</strong>'"
+showing_results_html = "Mostra <strong>%%start%% - %%end%%</strong> risultati"
+showing_results_of_for_html = "Mostra <strong>%%start%% - %%end%%</strong> risultati di <strong>%%total%%</strong> ricerca '<strong>%%lookfor%%</strong>'"
+showing_results_of_html = "Mostra <strong>%%start%% - %%end%%</strong> risultati su <strong>%%total%%</strong>"
 sidebar_close = "Compatta barra"
 sidebar_expand = "Espandi barra"
 Similar Items = "Documenti analoghi"
@@ -917,7 +928,7 @@ storage_retrieval_request_cancel_all = "Cancella tutte le richieste di volumi da
 storage_retrieval_request_cancel_fail = "La tua richiesta non è stata cancellata. Contatta il servizio di prestito per assistenza."
 storage_retrieval_request_cancel_selected = "Cancella le richieste di volumi da magazzino selezionate"
 storage_retrieval_request_cancel_success = "La tua richiesta è stata cancellata con successo"
-storage_retrieval_request_cancel_success_items = "richiesta(e) cancellata con successo"
+storage_retrieval_request_cancel_success_items = "%%count%% richiesta(e) cancellata con successo"
 storage_retrieval_request_canceled = "Cancellato"
 storage_retrieval_request_check_text = "Controlla le richieste di volumi da magazzino "
 storage_retrieval_request_comments = "Commenti"
@@ -955,7 +966,7 @@ Summon Results = "Risultati (da Summon)"
 summon_database_recommendations = "Puoi trovare altre risorse qui:"
 Supplements = "Supplementi"
 Supplied by Amazon = "Fornito da Amazon"
-Switch view to = "Passa alla vista"
+switch_view = "Passa alla vista %%view%%"
 switchquery_fuzzy = "Se esegui una ricerca fuzzy potresti trovare termini con grafia simile"
 switchquery_intro = "Potresti ottenere più risultati modificando la stringa di ricerca."
 switchquery_lowercasebools = "Se stai cercando di usare operatori booleani, devi inserirli IN MAIUSCOLO"
@@ -997,8 +1008,7 @@ Too Many Email Recipients = "Ci sono troppi indirizzi email."
 too_many_favorites = "Questa lista è troppo lunga per essere visualizzata. Prova a disporre i tuoi preferiti in più liste o a limitarli usando i tag."
 too_many_new_items = "Ci sono troppe nuove risorse per visualizzarle tutte. Prova a limitare la ricerca."
 too_many_reserves = "Ci sono troppe risorse riservate per visualizzarle tutte. Prova a limitare la ricerca."
-top_facet_additional_prefix = "Altri "
-top_facet_suffix = "... all'interno della tua ricerca."
+top_facet_label = "%%label%% all'interno della tua ricerca."
 Topic = "Soggetto"
 Topics = "Soggetti"
 Total Balance Due = "Totale importo dovuto"
@@ -1027,7 +1037,6 @@ VHS = "VHS"
 Video = "Video"
 Video Clips = "Video"
 Videos = "Video"
-view already selected = "visualizza i selezionati"
 View Book Bag = "Vedi il carrello"
 View Full Collection = "Vedi la collezione completa"
 View Full Record = "Vedi il record completo"
@@ -1036,6 +1045,7 @@ View online: Full view Book Preview from the Hathi Trust = "Vedi online: Antepri
 View Record = "Vedi il record"
 View Records = "Vedi i record"
 View this record in EBSCOhost = "Vedi questo record in EBSCOhost"
+view_already_selected = "vista %%current%% già selezionata"
 visual_facet_parent = "Da"
 Volume = "Volume"
 Volume Holdings = "Copie del volume"
diff --git a/languages/ja.ini b/languages/ja.ini
index 4e8cc5e2e9055fa58d5706ead13e5ae82f0d5035..969fe8437b81fdc399dbe92218692257ca968350 100644
--- a/languages/ja.ini
+++ b/languages/ja.ini
@@ -7,7 +7,6 @@ Access URL = "アクセスURL"
 access_denied = "アクセスできません。"
 Accession Number = "受入番号"
 Account = "アカウント"
-Add = "追加"
 Add a Library Card = "図書館カードの追加"
 Add a Note = "注記追加"
 Add Tag = "タグ追加"
@@ -19,8 +18,6 @@ Add your comment = "コメントを付ける"
 add_comment_fail_blank = "空白のコメントは許可されていません。何か記入してください。"
 add_comment_success = "コメントが追加されました。"
 add_favorite_fail = "エラー: レコードは保存されませんでした"
-add_favorite_prefix = "お気に入りに"
-add_favorite_suffix = "を追加"
 add_list_fail = "エラー: リストは作成されませんでした"
 add_other_libraries = "他の図書館にある論文を含める"
 add_search = "検索語入力欄を追加"
@@ -28,6 +25,7 @@ add_search_group = "検索グループを追加"
 add_tag_error = "エラー: タグを保存できませんでした"
 add_tag_note = "タグは空白で区別されます。複数語によるタグを作成する場合は引用符で括ってください。"
 add_tag_success = "タグが保存されました"
+add_to_favorites_html = "お気に入りに <em>%%title%%</em> を追加"
 Address = "アドレス"
 adv_search_all = "全フィールド"
 adv_search_author = "著者"
@@ -223,7 +221,6 @@ confirm_ill_request_cancel_selected_text = "選択したILLリクエストをキ
 confirm_new_password = "新パスワードの確認"
 confirm_storage_retrieval_request_cancel_all_text = "すべての所蔵検索リクエストをキャンセルしますか?"
 confirm_storage_retrieval_request_cancel_selected_text = "選択した所蔵検索リクエストをキャンセルしますか?"
-conjunction_or = "OR"
 Contents = "コンテンツ"
 Contributing Source = "貢献者情報源"
 Contributors = "貢献者"
@@ -383,7 +380,6 @@ for search = "検索語"
 Forgot Password = "パスワードを忘れた方"
 Form Submitted! = "送信しました。"
 Format = "フォーマット"
-found = "件見つかりました"
 From = "From"
 Full description = "詳細記述"
 Full text is not displayed to guests = "フルテキストはゲストには表示されません。"
@@ -435,7 +431,7 @@ hold_cancel_all = "すべての予約取消"
 hold_cancel_fail = "予約の取消ができませんでした。閲覧係にご連絡ください。"
 hold_cancel_selected = "選択資料の予約取消"
 hold_cancel_success = "資料の予約を取り消しました"
-hold_cancel_success_items = "資料の予約を取り消しました"
+hold_cancel_success_items = "%%count%% 資料の予約を取り消しました"
 hold_date_invalid = "正しい日付を入力してください"
 hold_date_past = "正しい日付を入力してください"
 hold_empty_selection = "資料が予約されていません"
@@ -443,7 +439,7 @@ hold_error_blocked = "この資料を予約する権限がありません。詳
 hold_error_fail = "予約できませんでした。閲覧係にご連絡ください。"
 hold_invalid_pickup = "受取場所が間違っています。もう一度正しく入力してください。"
 hold_invalid_request_group = "入力した予約リクエストグループは存在しません。再入力してください。"
-hold_login = "(予約・返却請求情報入力)"
+hold_login = "ログイン (予約・返却請求情報入力)"
 hold_place = "予約"
 hold_place_fail_missing = "登録情報が不足のため、予約できませんでした。閲覧係にご連絡ください。"
 hold_place_success_html = "予約を受け付けました. <a href="%%url%%">予約と返却請求</a>."
@@ -455,7 +451,7 @@ hold_required_by = "受取希望期限日"
 hold_success = "予約を受け付けました"
 Holdings = "所蔵"
 Holdings at Other Libraries = "他の図書館での所蔵"
-Holdings details from = "予約・返却請求"
+holdings_details_from = "予約・返却請求 %%location%%"
 Holdings_notes = "注記"
 Holds = "予約"
 Holds and Recalls = "予約と返却請求"
@@ -469,7 +465,7 @@ ill_request_cancel_all = "すべてのILLリクエストのキャンセル"
 ill_request_cancel_fail = "予約の取消ができませんでした。閲覧係にご連絡ください。"
 ill_request_cancel_selected = "選択したILLリクエストのキャンセル"
 ill_request_cancel_success = "資料の予約を取り消しました"
-ill_request_cancel_success_items = "資料の予約を取り消しました"
+ill_request_cancel_success_items = "%%count%% 資料の予約を取り消しました"
 ill_request_canceled = "キャンセル"
 ill_request_check_text = "ILLリクエストの確認"
 ill_request_comments = "コメント"
@@ -498,7 +494,6 @@ ils_offline_login_message = "現在、アカウント情報は利用できませ
 ils_offline_status = "現在、図書館管理システムは保守作業中です。"
 ils_offline_title = "システム保守作業中"
 Import Record = "レコードのインポート"
-Import to = "インポート先: "
 in = ":"
 In This Collection = "このコレクション"
 in_collection_label = "コレクション:"
@@ -526,8 +521,8 @@ Item removed from favorites = "お気に入りから削除されたアイテム"
 Item removed from list = "リストから削除されたアイテ"
 Items = "アイテム"
 items = "件"
-items_added_to_bookbag = "図書バッグに追加した資料"
-items_already_in_bookbag = "指定した資料は既に図書バッグにあるか、追加できませんでした。"
+items_added_to_bookbag = "%%count%% 図書バッグに追加した資料"
+items_already_in_bookbag = "%%count%% 指定した資料は既に図書バッグにあるか、追加できませんでした。"
 Journal = "雑誌"
 Journal Articles = "雑誌論文"
 Journal Info = "雑誌情報"
@@ -644,12 +639,11 @@ nohit_active_filters = "一つ以上のファッセット・フイルターが
 nohit_change_tab = "%%activeTab%%を検索しています。他のタブのひとつで何か見つかるかも知れません。"
 nohit_filters = "現在この検索に適用されているフィルター:"
 nohit_heading = "該当資料なし"
+nohit_lookfor_html = "指定した検索語 - <strong>%%lookfor%%</strong> - に合致する資料はありませんでした。"
 nohit_no_filters = "この検索に適用されているフィルターはありません。"
 nohit_parse_error = "検索クエリに問題があると思われます。検索文法をチェックしてください。特に高度な検索機能を使用していない場合は、検索語を引用符で括ってみると良いかもしれません。"
-nohit_prefix = "指定した検索語"
 nohit_query_without_filters = "この検索からすべてのフイルターを削除します。"
 nohit_spelling = "少々検索語を変更した方が良いでしょう。"
-nohit_suffix = "に合致する資料はありませんでした。"
 nohit_suggest = "検索語の一部を削除したり、スペルをチェックしたりして、検索語句を変えて再度実行してみてください。"
 NOT = "NOT"
 Not Illustrated = "なし"
@@ -691,7 +685,7 @@ number_decimal_point = "."
 number_thousands_separator = ","
 OAI Server = "OAIサーバー"
 Occupation = "職業"
-of = "/"
+of_num_results = "#%%position%% / %%total%% 結果"
 old_password = "旧パスワード"
 On Reserve = "予約の有無"
 On Reserve - Ask at Circulation Desk = "予約あり - 貸出カウンターにお問い合わせください"
@@ -737,8 +731,6 @@ Please check back soon = "しばらくお待ちください"
 Please contact the Library Reference Department for assistance = "詳しくは図書館の管理者にご連絡ください"
 Please enable JavaScript. = "JavaScriptを有効にしてください。"
 Please upgrade your browser. = "ブラウザのバージョンアップを行ってください。"
-Posted by = "投稿:"
-posted_on = "日時:"
 Preferences = "環境設定"
 Preferred Library = "ホーム図書館"
 Prev = "前ページ"
@@ -874,7 +866,12 @@ Sensor Image = "センサー画像"
 Serial = "逐次刊行物"
 Series = "シリーズ"
 Set = "セット"
-Showing = "検索結果"
+showing_items_html = "検索結果 <strong>%%start%% - %%end%%</strong> アイテム"
+showing_items_of_html = "検索結果 <strong>%%start%% - %%end%%</strong> / <strong>%%total%%</strong> アイテム"
+showing_results_for_html = "検索結果 <strong>%%start%% - %%end%%</strong> 結果 検索語 '<strong>%%lookfor%%</strong>'"
+showing_results_html = "検索結果 <strong>%%start%% - %%end%%</strong> 結果"
+showing_results_of_for_html = "検索結果 <strong>%%start%% - %%end%%</strong> 結果 / <strong>%%total%%</strong> 検索語 '<strong>%%lookfor%%</strong>'"
+showing_results_of_html = "検索結果 <strong>%%start%% - %%end%%</strong> 結果 / <strong>%%total%%</strong>"
 sidebar_close = "サイドバーが壊れた"
 sidebar_expand = "拡張サイドバー"
 Similar Items = "類似資料"
@@ -918,7 +915,7 @@ storage_retrieval_request_cancel_all = "すべての所蔵検索リクエスト
 storage_retrieval_request_cancel_fail = "予約の取消ができませんでした。閲覧係にご連絡ください。"
 storage_retrieval_request_cancel_selected = "選択した所蔵検索リクエストのキャンセル"
 storage_retrieval_request_cancel_success = "資料の予約を取り消しました"
-storage_retrieval_request_cancel_success_items = "資料の予約を取り消しました"
+storage_retrieval_request_cancel_success_items = "%%count%% 資料の予約を取り消しました"
 storage_retrieval_request_canceled = "キャンセル"
 storage_retrieval_request_check_text = "所蔵検索リクエスストの確認"
 storage_retrieval_request_comments = "コメント"
@@ -956,7 +953,7 @@ Summon Results = "Summon検索結果"
 summon_database_recommendations = "次のデータベースからも検索できます:"
 Supplements = "補足資料"
 Supplied by Amazon = "Amazon提供"
-Switch view to = "表示画面切替"
+switch_view = "表示画面切替 %%view%%"
 switchquery_fuzzy = "あいまい検索を実行すると似通った綴りの用語を検索されるかも知れません"
 switchquery_intro = "検索結果が意図したものでない場合は、検索語を変更してもう一度検索してください。"
 switchquery_lowercasebools = "論理演算子はすべて大文字で指定してください。"
@@ -998,8 +995,7 @@ Too Many Email Recipients = "メール受信者が多すぎます"
 too_many_favorites = "お気に入り項目が多すぎて一度に表示できません。リストを増やして再配置するか、タグを使って制限してください。"
 too_many_new_items = "新規資料が多すぎて一つのリストに表示できません。検索条件を追加してください。"
 too_many_reserves = "講義資料が多すぎて一つのリストに表示できません。検索条件を追加してください。"
-top_facet_additional_prefix = ""
-top_facet_suffix = " ..."
+top_facet_label = "%%label%% ..."
 Topic = "トピック"
 Topics = "トピックス"
 Total Balance Due = "請求総額"
@@ -1028,7 +1024,6 @@ VHS = "VHS"
 Video = "ビデオ"
 Video Clips = "ビデオクリップ"
 Videos = "ビデオ"
-view already selected = "選択済"
 View Book Bag = "図書バッグを見る"
 View Full Collection = "全コレクションを閲覧"
 View Full Record = "全レコードを閲覧"
@@ -1037,6 +1032,7 @@ View online: Full view Book Preview from the Hathi Trust = "オンライン・
 View Record = "レコードを閲覧"
 View Records = "レコードを見る"
 View this record in EBSCOhost = "EBSCOhostのレコードを表示"
+view_already_selected = "%%current%% 選択済"
 visual_facet_parent = "From"
 Volume = "å·»"
 Volume Holdings = "所蔵巻号"
diff --git a/languages/nl.ini b/languages/nl.ini
index c5eeb428610eda88bf1429a38982cd97a3e11c98..74a8df45c303b89ffbe88c7cea3dd8c25c7b68b5 100644
--- a/languages/nl.ini
+++ b/languages/nl.ini
@@ -7,7 +7,6 @@ Access URL = "URL naar item"
 access_denied = "Toegang geweigerd"
 Accession Number = "Archiefnummer"
 Account = "Account"
-Add = "Toevoegen"
 Add a Library Card = "Voeg een bibliotheekkaart toe"
 Add a Note = "Voeg aantekening toe"
 Add Tag = "Voeg label toe"
@@ -19,8 +18,6 @@ Add your comment = "Geef commentaar"
 add_comment_fail_blank = "Commentaar moet worden ingevuld"
 add_comment_success = "Commentaar toegevoegd."
 add_favorite_fail = "Foutmelding: Record werd niet opgeslagen"
-add_favorite_prefix = "Toevoegen"
-add_favorite_suffix = "aan favorieten"
 add_list_fail = "Foutmelding: lijst werd niet aangemaakt"
 add_other_libraries = "Ook artikelen in andere bibliotheken"
 add_search = "Voeg zoekterm toe"
@@ -28,6 +25,7 @@ add_search_group = "Voeg zoekveldengroep toe"
 add_tag_error = "Foutmelding: De tags konden niet worden opgeslagen"
 add_tag_note = "Tags worden gescheiden door spaties. Gebruik dubbele aanhalingstekens voor tags bestaande uit meer woorden."
 add_tag_success = "Tags opgeslagen"
+add_to_favorites_html = "Toevoegen <em>%%title%%</em> aan favorieten"
 Address = "Adres"
 adv_search_all = "Alle velden"
 adv_search_author = "Auteur"
@@ -223,7 +221,6 @@ confirm_ill_request_cancel_selected_text = "Wil je al de geselecteerde IBL aanvr
 confirm_new_password = "Bevestig Nieuw wachtwoord"
 confirm_storage_retrieval_request_cancel_all_text = "Wil je zeker al jouw aanvragen annuleren?"
 confirm_storage_retrieval_request_cancel_selected_text = "Wil je zeker jouw geselecteerde aanvragen annuleren?"
-conjunction_or = "of"
 Contents = "Inhoud"
 Contributing Source = "Meewerkende bron"
 Contributors = "Medewerkers"
@@ -383,7 +380,6 @@ for search = "Voor zoekopdracht"
 Forgot Password = "Wachtwoord vergeten"
 Form Submitted! = "Formulier ingediend!"
 Format = "Formaat"
-found = "gevonden"
 From = "Van"
 Full description = "Volledige beschrijving"
 Full text is not displayed to guests = "Full text wordt niet getoond aan gasten"
@@ -435,7 +431,7 @@ hold_cancel_all = "Annuleer alle reservaties"
 hold_cancel_fail = "Jouw verzoek werd niet geannuleerd. Contacteer Circulatie voor meer informatie."
 hold_cancel_selected = "Annuleer geselecteerde reservaties"
 hold_cancel_success = "Jouw verzoek werd met succes geannuleerd"
-hold_cancel_success_items = "Jouw verzoek(en) werd(en) met succes geannuleerd"
+hold_cancel_success_items = "%%count%% Jouw verzoek(en) werd(en) met succes geannuleerd"
 hold_date_invalid = "Vul een geldige datum in alsjeblieft"
 hold_date_past = "Vul alsjeblieft een toekomstige datum in"
 hold_empty_selection = "Er werden geen reservaties geselecteerd"
@@ -443,7 +439,7 @@ hold_error_blocked = "Je hebt geen toelating om een reservering te plaatsen voor
 hold_error_fail = "Jouw verzoek is mislukt. Contacteer Circulatie voor meer informatie."
 hold_invalid_pickup = "Er werd een ongeldige afhaal locatie ingegeven. Probeer het opnieuw."
 hold_invalid_request_group = "Een ongeldige reserveringsgroep werd ingevoerd. Probeer het opnieuw"
-hold_login = "Informatie over reserveringen"
+hold_login = "Aanmelden Informatie over reserveringen"
 hold_place = "Formuleer een aanvraag"
 hold_place_fail_missing = "Jouw aanvraag is mislukt. Er ontbreken gegevens. Contacteer alsjeblieft de Informatiebalie voor assistentie"
 hold_place_success_html = "Jouw aanvraag is gelukt. <a href="%%url%%">Jouw Verzoeken tot vasthouden en Reserveringen</a>."
@@ -455,7 +451,7 @@ hold_required_by = "Niet langer gewenst na"
 hold_success = "Jouw aanvraag is gelukt"
 Holdings = "Exemplaren"
 Holdings at Other Libraries = "Exemplaren bij andere bibliotheken"
-Holdings details from = "Exemplaargegevens van"
+holdings_details_from = "Exemplaargegevens van %%location%%"
 Holdings_notes = "Aantekeningen"
 Holds = "Verzoek tot vasthouden"
 Holds and Recalls = "Verzoeken tot vasthouden en Reserveringen"
@@ -469,7 +465,7 @@ ill_request_cancel_all = "Maak alle IBL leen-aanvragen ongedaan"
 ill_request_cancel_fail = "Jouw verzoek werd niet geannuleerd. Contacteer Circulatie voor meer informatie."
 ill_request_cancel_selected = "Maak geselecteerde IBL leen-aanvragen ongedaan"
 ill_request_cancel_success = "Jouw verzoek werd met succes geannuleerd"
-ill_request_cancel_success_items = "Jouw verzoek(en) werd(en) met succes geannuleerd"
+ill_request_cancel_success_items = "%%count%% Jouw verzoek(en) werd(en) met succes geannuleerd"
 ill_request_canceled = "Ongedaan gemaakt"
 ill_request_check_text = "Controleer IBL leen-aanvraag"
 ill_request_comments = "Opmerkingen"
@@ -498,7 +494,6 @@ ils_offline_login_message = "Jouw accountgegevens zullen gedurende die tijd onbe
 ils_offline_status = "Ons bibliotheek beheerssysteem is momenteel in onderhoud."
 ils_offline_title = "Het systeem is offline vanwege onderhoudswerken"
 Import Record = "Importeer record"
-Import to = "Importeer in "
 in = "in"
 In This Collection = "In deze collectie"
 in_collection_label = "In de collectie:"
@@ -526,8 +521,8 @@ Item removed from favorites = "Item verwijderd uit de favorieten"
 Item removed from list = "Item verwijderd uit de lijst"
 Items = "Items"
 items = "items"
-items_added_to_bookbag = "Item(s) in jouw boekentas gestopt"
-items_already_in_bookbag = "Item(s) zat(en) al in jouw boekentas of kon(den) niet toegevoegd worden"
+items_added_to_bookbag = "%%count%% Item(s) in jouw boekentas gestopt"
+items_already_in_bookbag = "%%count%% Item(s) zat(en) al in jouw boekentas of kon(den) niet toegevoegd worden"
 Journal = "Tijdschrift"
 Journal Articles = "Tijdschriftenartikels"
 Journal Info = "Info Tijdschrift"
@@ -644,12 +639,11 @@ nohit_active_filters = "Eén of meerdere filters zijn toegepast op deze zoekopdr
 nohit_change_tab = "U heeft gezocht in het tabblad '%%activeTab%% ". U kunt mogelijk iets vinden in één van de andere tabbladen:"
 nohit_filters = "Filters die actief zijn voor deze zoekopdracht:"
 nohit_heading = "Geen zoekresultaten!"
+nohit_lookfor_html = "Uw zoekopdracht - <strong>%%lookfor%%</strong> - leverde geen resultaten op."
 nohit_no_filters = "Er werden geen filters toegepast op deze zoekopdracht."
 nohit_parse_error = "Er lijkt een probleem te zijn met jouw zoekopdracht. Controleer alsjeblieft de zinsconstructie. Als je niet in uitgebreid zoeken werkt, helpt het misschien om jouw zoekopdracht tussen dubbele aanhalingstekens te zetten."
-nohit_prefix = "Uw zoekopdracht"
 nohit_query_without_filters = "Verwijder alle filters voor deze zoekopdracht."
 nohit_spelling = "Probeer misschien enkele spellingvarianten"
-nohit_suffix = "leverde geen resultaten op."
 nohit_suggest = "Pas eventueel jouw zoekopdracht aan door enkele woorden weg te laten of de spelling te controleren."
 NOT = "NOT"
 Not Illustrated = "Niet geïllustreerd"
@@ -691,7 +685,7 @@ number_decimal_point = ","
 number_thousands_separator = "."
 OAI Server = "OAI Server"
 Occupation = "Beroep"
-of = "van"
+of_num_results = "#%%position%% van %%total%% resultaten"
 old_password = "Oude wachtwoord"
 On Reserve = "Gereserveerd"
 On Reserve - Ask at Circulation Desk = "Gereserveerd - Vraag aan de uitleenbalie"
@@ -737,8 +731,6 @@ Please check back soon = "Controleer het binnenkort nog eens"
 Please contact the Library Reference Department for assistance = "Contacteer de vakspecialist van de bibliotheek"
 Please enable JavaScript. = "Activeer JavaScript."
 Please upgrade your browser. = "Upgrade jouw browser."
-Posted by = "Geplaatst door"
-posted_on = "aan"
 Preferences = "Voorkeuren"
 Preferred Library = "Voorkeurs bibliotheek"
 Prev = "Vorige"
@@ -874,7 +866,12 @@ Sensor Image = "Sensoriële afbeelding"
 Serial = "Serie"
 Series = "Reeks"
 Set = "Aanpassen"
-Showing = "Toon"
+showing_items_html = "Toon <strong>%%start%% - %%end%%</strong> Items"
+showing_items_of_html = "Toon <strong>%%start%% - %%end%%</strong> van <strong>%%total%%</strong> Items"
+showing_results_for_html = "Toon <strong>%%start%% - %%end%%</strong> resultaten Voor zoekopdracht '<strong>%%lookfor%%</strong>'"
+showing_results_html = "Toon <strong>%%start%% - %%end%%</strong> resultaten"
+showing_results_of_for_html = "Toon <strong>%%start%% - %%end%%</strong> resultaten van <strong>%%total%%</strong> Voor zoekopdracht '<strong>%%lookfor%%</strong>'"
+showing_results_of_html = "Toon <strong>%%start%% - %%end%%</strong> resultaten van <strong>%%total%%</strong>"
 sidebar_close = "Zijbalk inklappen"
 sidebar_expand = "Zijbalk uitklappen"
 Similar Items = "Gelijkaardige items"
@@ -918,7 +915,7 @@ storage_retrieval_request_cancel_all = "Annuleer alle aanvragen"
 storage_retrieval_request_cancel_fail = "Jouw verzoek werd niet geannuleerd. Contacteer Circulatie voor meer informatie."
 storage_retrieval_request_cancel_selected = "Annuleer de geselecteerde aanvragen"
 storage_retrieval_request_cancel_success = "Jouw verzoek werd met succes geannuleerd"
-storage_retrieval_request_cancel_success_items = "Jouw verzoek(en) werd(en) met succes geannuleerd"
+storage_retrieval_request_cancel_success_items = "%%count%% Jouw verzoek(en) werd(en) met succes geannuleerd"
 storage_retrieval_request_canceled = "Geannuleerd"
 storage_retrieval_request_check_text = "Controleer de aanvragen"
 storage_retrieval_request_comments = "Commentaar"
@@ -956,7 +953,7 @@ Summon Results = "Resultaten opgeleverd via Summon"
 summon_database_recommendations = "Je kunt hier nog meer bronnen vinden:"
 Supplements = "Aanvulsels"
 Supplied by Amazon = "Beschikbaar bij Amazon"
-Switch view to = "Verander weergave naar"
+switch_view = "Verander weergave naar %%view%%"
 switchquery_fuzzy = "Het uitvoeren van een fuzzy zoekopdracht kan resultaten geven met gelijkende spelling"
 switchquery_intro = "Misschien krijg je meer resultaten door jouw zoekopdracht aan te passen"
 switchquery_lowercasebools = "Als je Booleaanse operatoren wil gebruiken, moeten ze in HOOFDLETTERS staan"
@@ -998,8 +995,7 @@ Too Many Email Recipients = "Te veel email geadresseerden"
 too_many_favorites = "Deze lijst is te lang om in één keer te tonen. Probeer jouw favorieten in verschillende lijsten te ordenen of gebruik tags."
 too_many_new_items = "Zoveel nieuwe items kunnen niet getoond worden in één lijst. Probeer jouw zoekopdracht specifieker te maken."
 too_many_reserves = "Er zijn teveel resultaten om in één lijst te tonen. Beperk jouw zoekopdracht."
-top_facet_additional_prefix = "Extra"
-top_facet_suffix = "... binnen jouw zoekopdracht."
+top_facet_label = "%%label%% binnen jouw zoekopdracht."
 Topic = "Onderwerp"
 Topics = "Onderwerpen"
 Total Balance Due = "Totaal bedrag verschuldigd"
@@ -1028,7 +1024,6 @@ VHS = "VHS"
 Video = "Video"
 Video Clips = "Videoclips"
 Videos = "Video's"
-view already selected = "toon selectie"
 View Book Bag = "Bekijk boekentas"
 View Full Collection = "Bekijk volledige collectie"
 View Full Record = "Bekijk volledig record"
@@ -1037,6 +1032,7 @@ View online: Full view Book Preview from the Hathi Trust = "Bekijk on-line: Voll
 View Record = "Bekijk record"
 View Records = "Bekijk Records"
 View this record in EBSCOhost = "Bekijk dit record in EBSCOhost"
+view_already_selected = "%%current%% toon selectie"
 visual_facet_parent = "Van"
 Volume = "Volume"
 Volume Holdings = "Volume Bezit"
diff --git a/languages/pl.ini b/languages/pl.ini
index fe6402ae98779c5b1cc5ffec578d148a78327c56..25622a15e21e26aad51ccddf9be58f35e64acaa7 100644
--- a/languages/pl.ini
+++ b/languages/pl.ini
@@ -68,7 +68,7 @@ Access URL = "URL dostępu"
 access_denied = "Dostęp niedozwolony."
 Accession Number = "Numer dostępu"
 Account = "Konto czytelnika"
-Add = "Dołączyć"
+account_block_options_missing = "Z powodu zablokowania twojego konta niektóre opcje zostały usunięte. Szczegółowo: %%details%%"
 Add a Library Card = "Dołącz kartę biblioteczną"
 Add a Note = "Dodaj adnotacjÄ™"
 Add Tag = "Dodaj etykietÄ™"
@@ -80,8 +80,6 @@ Add your comment = "Skomentuj"
 add_comment_fail_blank = "Komentarz nie może być pusty."
 add_comment_success = "Komentarz został dołączony"
 add_favorite_fail = "Błąd: Nie udało się zapisać zapisu."
-add_favorite_prefix = ""
-add_favorite_suffix = "Dołącz do ulubionych książek"
 add_list_fail = "Błąd: Nie udało się stworzyć listy."
 add_other_libraries = "Dołącz artykuły innych bibliotek"
 add_search = "Dołącz dalsze pole wyszukiwania"
@@ -89,6 +87,7 @@ add_search_group = "Dołącz dalszą grupę wyszukiwania"
 add_tag_error = "Błąd: Nie udało się zapisać etykiety."
 add_tag_note = "Spacja tworzy nową etykietę. Zastosuj cudzysłów aby stworzyć etykiety z kilkoma słowami, np: "Corporate Identity"."
 add_tag_success = "Etykiety zostały zapisane"
+add_to_favorites_html = " <em>%%title%%</em> Dołącz do ulubionych książek"
 Address = "Adres"
 adv_search_all = "Wszystkie pola"
 adv_search_author = "Autor"
@@ -234,6 +233,10 @@ Catalog Results = "Rezultaty"
 catalog_login_desc = "Podaj dane do logowania."
 CD = "CD"
 Change Password = "Zmień hasło"
+channel_add_more = "Dołącz więcej podobnych kanałów"
+channel_expand = "Przeglądaj podobne kanały"
+channel_explore = "Przeglądaj kanały"
+channel_search = "Pokaż egzemplarze jako rezultaty"
 Check Hold = "Sprawdź możliwość zamówienia / zarezerwowania"
 Check Recall = "Sprawdź możliwość odwołania"
 Checked Out = "Wypożyczone"
@@ -284,7 +287,6 @@ confirm_ill_request_cancel_selected_text = "Czy chcesz usunąć zaznaczone zamó
 confirm_new_password = "Potwierdź nowe hasło"
 confirm_storage_retrieval_request_cancel_all_text = "Czy chcesz usunąć wszystkie zamówienia magazynowe?"
 confirm_storage_retrieval_request_cancel_selected_text = "Czy chcesz usunąć zaznaczone zamówienia magazynowe?"
-conjunction_or = "albo"
 Contents = "Treść"
 Contributing Source = "Źródło przyczyniające"
 Contributors = "Kolejni autorzy"
@@ -334,6 +336,7 @@ Displaying the top = "Widoczne sÄ… pierwsze rezultaty"
 Document Inspector = "Kontroler dokumentów"
 Document Type = "Typ dokumentu"
 DOI = "DOI"
+doi_detected_html = "Twoje wyszukiwanie widocznie zawiera identyfikator DOI. Kliknij tutaj aby sprawdzić dostępność: <a href="%%url%%">%%doi%%</a>"
 Draw Search Box = "Zaznacz zasięg wyszukiwania"
 Due = "do"
 Due Date = "Termin zwrotu"
@@ -407,6 +410,10 @@ export_selected = "Eksportuj zaznaczone książki"
 export_selected_favorites = "Eksportuj zaznaczone ulubione książki"
 export_success = "Eksport zakończony"
 export_unsupported_format = "Niewspomagany format eksportu"
+external_auth_heading = "Logowanie do pełnego dostępu"
+external_auth_login_message = "Zaloguj się, aby mieć dostęp do e-zasobów licencjonowanych."
+external_auth_unauthorized = "Nie masz dostępu do e-zasobów licencjonowanych."
+external_auth_unauthorized_desc = "Twoja metoda logowania nie zapewnia dostępu do e-zasobów licencjonowanych. Wyloguj się, a następnie zaloguj się przy użyciu innej metody."
 FAQs = "Często zadawane pytania"
 fav_delete = "Usuń zaznaczone ulubione książki"
 fav_delete_deleting = "Usunięcie zaznaczonych książek w trakcie."
@@ -444,7 +451,6 @@ for search = "Dla wyszukiwania"
 Forgot Password = "Zapomniałeś hasła?"
 Form Submitted! = "Formularz został wysłany!"
 Format = "Format"
-found = "Znaleziono"
 From = "od"
 Full description = "Szczegółowa specyfikacja"
 Full text is not displayed to guests = "Goście nie mają uprawnień do oglądania artykułów pełnotekstowych."
@@ -496,7 +502,7 @@ hold_cancel_all = "Anuluj wszystkie"
 hold_cancel_fail = "Nie udało się anulować zamówienia lub rezerwacji - skontaktuj się z biblioteką."
 hold_cancel_selected = "Anuluj zaznaczone"
 hold_cancel_success = "Zamówienia i rezerwacje zostały anulowane."
-hold_cancel_success_items = "Zamówienia i rezerwacje zostały anulowane."
+hold_cancel_success_items = "%%count%% Zamówienia i rezerwacje zostały anulowane."
 hold_date_invalid = "Podaj ważną datę"
 hold_date_past = "Podaj datę w przyszłości"
 hold_empty_selection = "Wybierz jakieś zamówienia lub rezerwacje"
@@ -504,19 +510,21 @@ hold_error_blocked = "Nie masz odpowiednich uprawnień do zamówienia lub rezerw
 hold_error_fail = "Zamówienie nie udało się - skontaktuj się z biblioteką."
 hold_invalid_pickup = "Miejsce odebrania nieważne. Spróbuj jeszcze raz."
 hold_invalid_request_group = "Została podana nieważna grupa zamówienia. Spróbuj jeszcze raz."
-hold_login = "Dla informacji o zamówieniu / rezerwacji"
+hold_items_available = "Zamówienie niemożliwe, egzemplarze są dostępne."
+hold_login = "Login Dla informacji o zamówieniu / rezerwacji"
 hold_place = "Zamów / zarezerwuj"
 hold_place_fail_missing = "BÅ‚Ä…d: Brak danych - skontaktuj siÄ™ z bibliotekÄ…."
 hold_place_success_html = "Zamówienie / rezerwacja została wykonana. <a href="%%url%%">Zamówienia</a>."
 hold_profile_html = "Aby zamówić lub rezerwować książkę, utwórz <a href="%%url%%">konto czytelnika</a>."
 hold_queue_position = "Pozycja w kolejce"
+hold_record_already_on_loan = "Masz już tytuł na twoim koncie."
 hold_request_group = "Rezerwacja z"
 hold_requested_group = "Zarezerwowane z"
 hold_required_by = "Nie potrzebne po"
 hold_success = "Zamówienie zostało wykonane / rezerwacja została wykonana"
 Holdings = "Egzemplarz"
 Holdings at Other Libraries = "Egzemplarze w innych bibliotekach"
-Holdings details from = "Szczegóły zapisu"
+holdings_details_from = "Szczegóły zapisu %%location%%"
 Holdings_notes = "Komentarze"
 Holds = "Zamówienia"
 Holds and Recalls = "Zamówienia i odwołania"
@@ -530,7 +538,7 @@ ill_request_cancel_all = "Anuluj wszystkie zamówienia międzybiblioteczne"
 ill_request_cancel_fail = "Nie udało się anulować zamówienia lub rezerwacji - skontaktuj się z biblioteką."
 ill_request_cancel_selected = "Anuluj zaznaczone zamówienia międzybiblioteczne"
 ill_request_cancel_success = "Zamówienia i rezerwacje zostały anulowane."
-ill_request_cancel_success_items = "Zamówienia i rezerwacje zostały anulowane."
+ill_request_cancel_success_items = "%%count%% Zamówienia i rezerwacje zostały anulowane."
 ill_request_canceled = "Anulowane"
 ill_request_check_text = "Sprawdź zamówienia międzybiblioteczne"
 ill_request_comments = "Komentarze"
@@ -559,7 +567,6 @@ ils_offline_login_message = "Niestety! Konto czytelnika obecnie nie jest dostęp
 ils_offline_status = "Niestety! Z powodu przeglądu technicznego system jest niedostępny."
 ils_offline_title = "Z powodu przeglądu technicznego niedostępne"
 Import Record = "Importuj zapis"
-Import to = "Importuj do"
 in = "w"
 In This Collection = "w tej kolekcji"
 in_collection_label = "w kolekcji:"
@@ -587,8 +594,8 @@ Item removed from favorites = "Usunięto książkę z listy ulubionych książek
 Item removed from list = "Usunięto książkę z listy"
 Items = "Książka"
 items = "w liście podręcznej"
-items_added_to_bookbag = "Zaznaczone książki zostały dołączone do listy podręcznej"
-items_already_in_bookbag = "Zaznaczone książki już są w liście podręcznej"
+items_added_to_bookbag = "%%count%% Zaznaczone książki zostały dołączone do listy podręcznej"
+items_already_in_bookbag = "%%count%% Zaznaczone książki już są w liście podręcznej"
 Journal = "Czasopismo"
 Journal Articles = "Artykuł"
 Journal Info = "Opis czasopisma"
@@ -705,12 +712,11 @@ nohit_active_filters = "Jeden lub więcej filtrów został zastosowany do wyszuk
 nohit_change_tab = "Wyszukiwałeś w etykiecie "%%activeTab%%". Może znajdziesz coś w jednej z innych etykiet:"
 nohit_filters = "Zastosowane filtry"
 nohit_heading = "Nie ma rezultatów!"
+nohit_lookfor_html = "Dla wyszukiwania - <strong>%%lookfor%%</strong> - Nie znaleziono tożsamości."
 nohit_no_filters = "W tym wyszukiwaniu nie zastosowałeś filtrów."
 nohit_parse_error = "Wystąpił problem przy wyszukiwaniu - sprawdź składnię. Jeśli nie używasz kompleksowej składni wyszukiwania, napisz parametry w cudzysłowie."
-nohit_prefix = "Dla wyszukiwania"
 nohit_query_without_filters = "Usuń filtry z tego wyszukiwania."
 nohit_spelling = "Spróbuj zastosować inną pisownię."
-nohit_suffix = "Nie znaleziono tożsamości."
 nohit_suggest = "Możesz polepszyć wyszukiwanie usuwając słowa oraz sprawdzając ortografię."
 NOT = "NIE"
 Not Illustrated = "Bez ilustracji"
@@ -752,7 +758,7 @@ number_decimal_point = ","
 number_thousands_separator = "."
 OAI Server = "Server OAI"
 Occupation = "Zawód"
-of = "od"
+of_num_results = "#%%position%% od %%total%% Rezultaty"
 old_password = "Stare hasło"
 On Reserve = "Zarezerwowane"
 On Reserve - Ask at Circulation Desk = "Zarezerwowane - zapytaj bibliotekarza"
@@ -760,6 +766,7 @@ on_reserve = "Zarezerwowane - skontaktuj siÄ™ z bibliotekÄ…"
 on_topic = "%%count%% zapisów na ten temat"
 Online Access = "Dostęp online"
 online_resources = "Artykuły pełnotekstowe"
+open_access_limit = "Zastosuj filtr na e-zasoby Open Access"
 operator_contains = "zawiera"
 operator_exact = "jest (dokładnie)"
 OR = "ALBO"
@@ -798,8 +805,6 @@ Please check back soon = "Spróbuj jeszcze raz"
 Please contact the Library Reference Department for assistance = "Skontaktuj się z biblioteką aby otrzymać dalsze informacje."
 Please enable JavaScript. = "Proszę włączyć javascript."
 Please upgrade your browser. = "Zaktualizuj przeglÄ…darkÄ™."
-Posted by = "Napisane przez"
-posted_on = "w dniu"
 Preferences = "Preferencje"
 Preferred Library = "Preferencyjna biblioteka"
 Prev = "Poprzedni"
@@ -935,7 +940,12 @@ Sensor Image = "Czujnik obrazu"
 Serial = "Wydawnictwo ciągłe"
 Series = "Seria"
 Set = "Zmień"
-Showing = "Rezultaty"
+showing_items_html = "Rezultaty <strong>%%start%% - %%end%%</strong> Książka"
+showing_items_of_html = "Rezultaty <strong>%%start%% - %%end%%</strong> od <strong>%%total%%</strong> Książka"
+showing_results_for_html = "Rezultaty <strong>%%start%% - %%end%%</strong> Rezultaty Dla wyszukiwania '<strong>%%lookfor%%</strong>'"
+showing_results_html = "Rezultaty <strong>%%start%% - %%end%%</strong> Rezultaty"
+showing_results_of_for_html = "Rezultaty <strong>%%start%% - %%end%%</strong> Rezultaty od <strong>%%total%%</strong> Dla wyszukiwania '<strong>%%lookfor%%</strong>'"
+showing_results_of_html = "Rezultaty <strong>%%start%% - %%end%%</strong> Rezultaty od <strong>%%total%%</strong>"
 sidebar_close = "Złóż fiszkę"
 sidebar_expand = "Rozszerz fiszkÄ™"
 Similar Items = "Podobne zapisy"
@@ -979,7 +989,7 @@ storage_retrieval_request_cancel_all = "Anuluj wszystkie zamówienia magazynowe"
 storage_retrieval_request_cancel_fail = "Nie udało się anulować zamówienia lub rezerwacji - skontaktuj się z biblioteką."
 storage_retrieval_request_cancel_selected = "Anuluj zaznaczone zamówienia magazynowe"
 storage_retrieval_request_cancel_success = "Zamówienia i rezerwacje zostały anulowane."
-storage_retrieval_request_cancel_success_items = "Zamówienia i rezerwacje zostały anulowane."
+storage_retrieval_request_cancel_success_items = "%%count%% Zamówienia i rezerwacje zostały anulowane."
 storage_retrieval_request_canceled = "Anuluj"
 storage_retrieval_request_check_text = "Sprawdź zamówienie magazynowe"
 storage_retrieval_request_comments = "Komentarze"
@@ -1017,7 +1027,7 @@ Summon Results = "Cytaty"
 summon_database_recommendations = "Inne możliwe źródła:"
 Supplements = "Suplementy"
 Supplied by Amazon = "Dostarczone przez Amazon"
-Switch view to = "Zmień do wersji"
+switch_view = "Zmień do wersji %%view%%"
 switchquery_fuzzy = "Wyszukiwanie rozmyte (Fuzzy Search) może wykazać rezultaty dla podobnych haseł."
 switchquery_intro = "Możesz otrzymać więcej wyników. Zmodyfikuj wyszukiwanie."
 switchquery_lowercasebools = "Próbujesz użyć operatorów wyszukiwania? Napisz je z dużej litery."
@@ -1059,8 +1069,7 @@ Too Many Email Recipients = "Za dużo adresatów"
 too_many_favorites = "Lista jest za długa aby ją pokazać w całości. Spróbuj rozdzielić ją na dwie listy oraz ograniczyć poprzez filtry."
 too_many_new_items = "Za dużo zapisów aby je wszystkie pokazać. Spróbuj je ograniczyć poprzez filtry."
 too_many_reserves = "Za dużo rezerwacji aby je wszystkie pokazać. Spróbuj je ograniczyć poprzez filtry."
-top_facet_additional_prefix = "Dodatkowo "
-top_facet_suffix = "... w twoim wyszukiwaniu."
+top_facet_label = "%%label%% w twoim wyszukiwaniu."
 Topic = "Temat"
 Topics = "Tematy"
 Total Balance Due = "Suma saldo"
@@ -1089,7 +1098,6 @@ VHS = "VHS"
 Video = "Wideo"
 Video Clips = "Wideoclips"
 Videos = "Wideo"
-view already selected = "Wersja już jest aktywna"
 View Book Bag = "Zobacz listę podręczną"
 View Full Collection = "Zobacz całą kolekcję"
 View Full Record = "Zobacz cały zapis"
@@ -1098,6 +1106,7 @@ View online: Full view Book Preview from the Hathi Trust = "Online: przeglÄ…d od
 View Record = "Zobacz zapis"
 View Records = "Zobacz rekordy"
 View this record in EBSCOhost = "Zobacz zapis w EBSCOhost"
+view_already_selected = "%%current%% Wersja już jest aktywna"
 visual_facet_parent = "od"
 Volume = "Tom"
 Volume Holdings = "Dane tomów"
diff --git a/languages/pt-br.ini b/languages/pt-br.ini
index f28b74135b22cbdf344dbe2c32ef23614c7302b2..22fe2e9ff6b85c47adfb8089f2f4197b119cba16 100644
--- a/languages/pt-br.ini
+++ b/languages/pt-br.ini
@@ -1,12 +1,12 @@
-; For future reference:
-;Brazilian Portugese = "Português (Brasil)"
+; For future reference:
+;Brazilian Portugese = "Português (Brasil)"
 Abstract = "Resumo"
 Access = "Acesso"
 Access URL = "Acessar a URL"
 access_denied = "Access não permitido."
 Accession Number = "Número de chamada"
 Account = "Conta"
-Add = "Adicionar"
+account_block_options_missing = "Algumas opções foram removidas devido a problemas na sua conta. Detalhes: %%details%%"
 Add a Library Card = "Adicionar Cartão de Biblioteca"
 Add a Note = "Adicionar uma nota"
 Add Tag = "Adicionar Tag"
@@ -18,8 +18,6 @@ Add your comment = "Adicionar comentário"
 add_comment_fail_blank = "O comentário não pode estar em branco."
 add_comment_success = "Comentário adicionado."
 add_favorite_fail = "Erro: registro não foi salvo"
-add_favorite_prefix = "Adicionar"
-add_favorite_suffix = "aos favoritos"
 add_list_fail = "Erro: Lista não criada"
 add_other_libraries = "Inclua artigos em outras bibliotecas"
 add_search = "Adicionar campo de busca"
@@ -27,6 +25,7 @@ add_search_group = "Adicionar Grupo de Busca"
 add_tag_error = "Erro: Não foi possível salvar as Tags"
 add_tag_note = "Tags separadas por espaço. Use aspas para tags com várias palavras."
 add_tag_success = "Tags guardadas"
+add_to_favorites_html = "Adicionar <em>%%title%%</em> aos favoritos"
 Address = "Endereço"
 adv_search_all = "Todos os campos"
 adv_search_author = "Autor"
@@ -172,6 +171,10 @@ Catalog Results = "Resultados do Catálogo"
 catalog_login_desc = "Entre com as suas credenciais do catálogo da biblioteca."
 CD = "CD"
 Change Password = "Mudar Senha"
+channel_add_more = "Adicionar mais canais como este"
+channel_expand = "Explorar canais relacionados"
+channel_explore = "Explorar canais"
+channel_search = "Apresentar itens como resultados de busca"
 Check Hold = "Ver Reserva"
 Check Recall = "Ver Pedido de Devolução"
 Checked Out = "Emprestado"
@@ -222,7 +225,6 @@ confirm_ill_request_cancel_selected_text = "Deseja cancelar as requisições de
 confirm_new_password = "Confirmar nova Senha"
 confirm_storage_retrieval_request_cancel_all_text = "Deseja cancelar toda as requisições de recuperação armazenadas?"
 confirm_storage_retrieval_request_cancel_selected_text = "Deseja cancelar as requisições de recuperação armazenadas selecionadas?"
-conjunction_or = "ou"
 Contents = "Conteúdos"
 Contributing Source = "Fonte contribuidora"
 Contributors = "Colaboradores"
@@ -272,6 +274,7 @@ Displaying the top = "Primeiros resultados"
 Document Inspector = "Inspetor de documentos"
 Document Type = "Tipo de documento"
 DOI = "DOI"
+doi_detected_html = "Sua busca aparenta conter um DOI. Clique aqui para checar a disponibilidade do recurso: <a href="%%url%%">%%doi%%</a>"
 Draw Search Box = "Desenhar Caixa de pesquisa"
 Due = "Fim do empréstimo"
 Due Date = "Data fim do empréstimo"
@@ -285,6 +288,7 @@ edit_list_fail = "Desculpe, você não tem permissão para editar esta lista"
 edit_list_success = "Lista atualizada com sucesso."
 Edition = "Edição"
 eds_expander_fulltext = "Busque também nos textos completos do artigos"
+eds_expander_relatedsubjects = "Aplicar assuntos equivalentes"
 eds_expander_thesaurus = "Aplicar palavras relacionadas"
 eds_limiter_FC = "Somente no Catálogo"
 eds_limiter_FC1 = "Somente no Repositório Institucional"
@@ -345,6 +349,10 @@ export_selected = "Exportar selec."
 export_selected_favorites = "Exportar os Favoritos selecionados"
 export_success = "Exportação concluída"
 export_unsupported_format = "Formato de exportação não suportado"
+external_auth_heading = "Acesso a material licenciado"
+external_auth_login_message = "Faça login para acessar material licenciado"
+external_auth_unauthorized = "Você naão está autorizado a acessar material licenciado"
+external_auth_unauthorized_desc = "Sua forma de login não oferta acesso a material licenciado. Por favor, deslogue e se logue novamente de outra forma."
 FAQs = "FAQs"
 fav_delete = "Apagar os Favoritos selecionados"
 fav_delete_deleting = "Os Favoritos selecionados serão apagados."
@@ -382,7 +390,6 @@ for search = "para a busca"
 Forgot Password = "Esqueci minha senha"
 Form Submitted! = "Comentário enviado!"
 Format = "Formato"
-found = "Encontrado"
 From = "De"
 Full description = "ver descrição completa"
 Full text is not displayed to guests = "Texto completo não é apresentado para usuários convidados (não logados)."
@@ -434,7 +441,7 @@ hold_cancel_all = "Cancelar todas as reservas"
 hold_cancel_fail = "A sua reserva não foi cancelada; por favor, contate o Balcão de Atendimento para ajuda adicional"
 hold_cancel_selected = "Cancelar as reservas selecionadas"
 hold_cancel_success = "A sua reserva foi cancelada com sucesso"
-hold_cancel_success_items = "reserva(s) foram canceladas com sucesso"
+hold_cancel_success_items = "%%count%% reserva(s) foram canceladas com sucesso"
 hold_date_invalid = "Por favor, introduza uma data válida"
 hold_date_past = "Por favor, introduza uma data no futuro"
 hold_empty_selection = "Não selecionou nenhuma reserva"
@@ -442,19 +449,21 @@ hold_error_blocked = "Os seus privilégios não lhe permitem colocar uma reserva
 hold_error_fail = "O seu pedido não foi bem-sucedido; por favor, contate o Balcão de Atendimento para ajuda adicional"
 hold_invalid_pickup = "Não introduziu um local de levantamento válido; por favor, tente novamente"
 hold_invalid_request_group = "Um pedido inválido foi entrado. Por favor tente novamente"
-hold_login = "para informação da reserva e levantamento"
+hold_items_available = "Não é permitido colocar uma restrição, pois os itens estão disponíveis."
+hold_login = "Entrar para informação da reserva e levantamento"
 hold_place = "Reservar"
 hold_place_fail_missing = "O seu pedido não foi bem-sucedido: é necessário introduzir mais dados; por favor, contate o Balcão de Atendimento para ajuda adicional"
 hold_place_success_html = "O seu pedido foi salvo com sucesso. <a href="%%url%%">As suas Reservas e Pedidos</a>."
 hold_profile_html = "Para reservas e devoluções, por favor estabeleça seu <a href="%%url%%">Perfil no Catálogo da Biblioteca</a>."
 hold_queue_position = "Posição na fila"
+hold_record_already_on_loan = "Você ja possui um registro de empréstimo"
 hold_request_group = "Pedido de"
 hold_requested_group = "Requisitado por"
 hold_required_by = "Não é necessário depois de"
 hold_success = "O seu pedido foi salvo com sucesso"
 Holdings = "Itens"
 Holdings at Other Libraries = "Itens em outras Bibliotecas"
-Holdings details from = "Detalhes do Exemplar"
+holdings_details_from = "Detalhes do Exemplar %%location%%"
 Holdings_notes = "Observações"
 Holds = "Reservas"
 Holds and Recalls = "Reservas e Pedidos"
@@ -468,7 +477,7 @@ ill_request_cancel_all = "Cancelar todos os pedidos de débito interbiblioteca"
 ill_request_cancel_fail = "A sua reserva não foi cancelada; por favor, contate o Balcão de Atendimento para ajuda adicional"
 ill_request_cancel_selected = "Cancelar as requisições de débito interbibliotecas selecionadas"
 ill_request_cancel_success = "A sua reserva foi cancelada com sucesso"
-ill_request_cancel_success_items = "reserva(s) foram canceladas com sucesso"
+ill_request_cancel_success_items = "%%count%% reserva(s) foram canceladas com sucesso"
 ill_request_canceled = "Cancelado"
 ill_request_check_text = "Checar Pedido de Débito Interbiblioteca"
 ill_request_comments = "Comentários"
@@ -497,7 +506,6 @@ ils_offline_login_message = "Os dados da sua conta estarão indisponíveis duran
 ils_offline_status = "O sistema está em manutenção."
 ils_offline_title = "Sistema em Manutenção"
 Import Record = "Importar Registro"
-Import to = "Importar para"
 in = "em"
 In This Collection = "Nesta coleção"
 in_collection_label = "Na coleção:"
@@ -525,8 +533,8 @@ Item removed from favorites = "Obra retirada dos favoritos"
 Item removed from list = "Obra retirada da lista"
 Items = "Registros"
 items = "registros"
-items_added_to_bookbag = "registro(s) adicionado(s) à cesta"
-items_already_in_bookbag = "registro(s) já estava(m) na cesta"
+items_added_to_bookbag = "%%count%% registro(s) adicionado(s) à cesta"
+items_already_in_bookbag = "%%count%% registro(s) já estava(m) na cesta"
 Journal = "Periódico"
 Journal Articles = "Artigos de Periódicos"
 Journal Info = "Informação de periódico"
@@ -643,12 +651,11 @@ nohit_active_filters = "Uma ou mais filtros de facetas têm sido aplicados a est
 nohit_change_tab = "Você tem buscado na "%%activeTab%%" aba. Você pode encontrar algo em uma das outras abas:"
 nohit_filters = "Filtros aplicados a esta busca:"
 nohit_heading = "Nenhum registro encontrado!"
+nohit_lookfor_html = "A sua busca - <strong>%%lookfor%%</strong> - não corresponde a nenhum registro."
 nohit_no_filters = "Nenhum filtro aplicado à busca."
 nohit_parse_error = "Parece haver um problema com a sua busca. Por favor, verifique a sintaxe. Se você não está à procura de recursos avançados, pode ajudar colocar os termos dentro de aspas."
-nohit_prefix = "A sua busca"
 nohit_query_without_filters = "Remover todos os filtros a partir desta busca."
 nohit_spelling = "Talvez deva tentar algumas variações de ortografia"
-nohit_suffix = "não corresponde a nenhum registro."
 nohit_suggest = "Você pode revisar a sua busca retirando alguns termos ou verificando a ortografia."
 NOT = "NÃO"
 Not Illustrated = "Não Ilustrado"
@@ -690,7 +697,7 @@ number_decimal_point = "."
 number_thousands_separator = ","
 OAI Server = "Servidor OAI"
 Occupation = "Ocupação"
-of = "de"
+of_num_results = "#%%position%% de %%total%% resultados"
 old_password = "Senha Antiga"
 On Reserve = "Reservado"
 On Reserve - Ask at Circulation Desk = "Empréstimo Condicionado; mais informação no Balcão de Atendimento"
@@ -698,6 +705,7 @@ on_reserve = "Reservado"
 on_topic = "%%count%% Item(s) neste tópicoc"
 Online Access = "Acesso em linha"
 online_resources = "Texto Completo"
+open_access_limit = "Limite ao conteúdo de Acesso Aberto"
 operator_contains = "contém"
 operator_exact = "é (exato)"
 OR = "OU"
@@ -736,8 +744,6 @@ Please check back soon = "Por favor, volte em breve"
 Please contact the Library Reference Department for assistance = "Por favor contate o Serviço de Referência da Biblioteca para mais ajuda"
 Please enable JavaScript. = "Por favor ative o JavaScript no seu browser."
 Please upgrade your browser. = "Por favor atualize seu browser."
-Posted by = "Postado por"
-posted_on = "em"
 Preferences = "Preferências"
 Preferred Library = "Biblioteca Preferedida"
 Prev = "Anterior"
@@ -873,7 +879,12 @@ Sensor Image = "Sensor de Imagem"
 Serial = "Periódico"
 Series = "coleção"
 Set = "Definir"
-Showing = "A mostrar"
+showing_items_html = "A mostrar <strong>%%start%% - %%end%%</strong> Registros"
+showing_items_of_html = "A mostrar <strong>%%start%% - %%end%%</strong> de <strong>%%total%%</strong> Registros"
+showing_results_for_html = "A mostrar <strong>%%start%% - %%end%%</strong> resultados para a busca '<strong>%%lookfor%%</strong>'"
+showing_results_html = "A mostrar <strong>%%start%% - %%end%%</strong> resultados"
+showing_results_of_for_html = "A mostrar <strong>%%start%% - %%end%%</strong> resultados de <strong>%%total%%</strong> para a busca '<strong>%%lookfor%%</strong>'"
+showing_results_of_html = "A mostrar <strong>%%start%% - %%end%%</strong> resultados de <strong>%%total%%</strong>"
 sidebar_close = "ocultar barra lateral"
 sidebar_expand = "Expandir barra lateral"
 Similar Items = "Registros relacionados"
@@ -917,7 +928,7 @@ storage_retrieval_request_cancel_all = "Cancelar todos os Pedidos de Recuperaç
 storage_retrieval_request_cancel_fail = "A sua reserva não foi cancelada; por favor, contate o Balcão de Atendimento para ajuda adicional"
 storage_retrieval_request_cancel_selected = "Cancelar Pedido de Recuperação Armazenado"
 storage_retrieval_request_cancel_success = "A sua reserva foi cancelada com sucesso"
-storage_retrieval_request_cancel_success_items = "reserva(s) foram canceladas com sucesso"
+storage_retrieval_request_cancel_success_items = "%%count%% reserva(s) foram canceladas com sucesso"
 storage_retrieval_request_canceled = "Cancelado"
 storage_retrieval_request_check_text = "Checar Pedido de Recuperação Armazenado"
 storage_retrieval_request_comments = "Comentários"
@@ -955,7 +966,7 @@ Summon Results = "Resultados Summon"
 summon_database_recommendations = "Pode encontrar recursos adicionais aqui:"
 Supplements = "Suplementos"
 Supplied by Amazon = "Fornecido pela Amazon"
-Switch view to = "Alterar a visualização para"
+switch_view = "Alterar a visualização para %%view%%"
 switchquery_fuzzy = "Fazer uma busca fuzzy pode resultar em termos de grafias semelhantes"
 switchquery_intro = "Você pode obter mais resultados ajustando o argumento de busca."
 switchquery_lowercasebools = "Caso esteja tentando utilizar os operadores booleanos, deve escrevê-los em Letras MAIÚSCULAS"
@@ -997,8 +1008,7 @@ Too Many Email Recipients = "Excesso de emails destinatário"
 too_many_favorites = "Essa lista é muito grande para mostrar tudo de uma vez. Tente reorganizar seus favoritos em mais listas ou limite o uso de tags."
 too_many_new_items = "Há muitos novos registros para mostrar nma única lista. Tente limitar a sua busca."
 too_many_reserves = "Há demasiadas obras recomendadas para mostrar numa única lista. Tente limitar a sua busca."
-top_facet_additional_prefix = "Adicionais"
-top_facet_suffix = "... dentro de sua busca."
+top_facet_label = "%%label%% dentro de sua busca."
 Topic = "Assunto"
 Topics = "Assuntos"
 Total Balance Due = "Total devido do balanço"
@@ -1027,7 +1037,6 @@ VHS = "VHS"
 Video = "Vídeo"
 Video Clips = "Video Clipes"
 Videos = "Vídeos"
-view already selected = "visualização já selecionada"
 View Book Bag = "Ver cesta"
 View Full Collection = "Ver Coleção Completa"
 View Full Record = "Ver Registro Completo"
@@ -1036,6 +1045,7 @@ View online: Full view Book Preview from the Hathi Trust = "Veja online: Visuali
 View Record = "Ver Registro"
 View Records = "Ver Registros"
 View this record in EBSCOhost = "Visualizar este registro na base de dados BSCOhost"
+view_already_selected = "%%current%% visualização já selecionada"
 visual_facet_parent = "De"
 Volume = "Volume"
 Volume Holdings = "Existências do Volume"
diff --git a/languages/pt.ini b/languages/pt.ini
index 90da6d9c90b6950a45e99b8edad09f27a7b4671a..ef3c97595f83e5bbefe0f5509ba8e6f310459953 100644
--- a/languages/pt.ini
+++ b/languages/pt.ini
@@ -5,7 +5,6 @@ Abstract = "Resumo"
 Access = "Acesso"
 access_denied = "Acesso negado."
 Account = "Conta"
-Add = "Adicionar"
 Add a Note = "Adicionar uma nota"
 Add Tag = "Adicionar Tag"
 Add Tags = "Adicionar Tags"
@@ -16,8 +15,6 @@ Add your comment = "Adicionar comentário"
 add_comment_fail_blank = "O Comentário não pode estar em branco."
 add_comment_success = "Comentário adicionado."
 add_favorite_fail = "Erro: Registo não guardado"
-add_favorite_prefix = "Adicionar"
-add_favorite_suffix = "aos favoritos"
 add_list_fail = "Erro: Lista não criada"
 add_other_libraries = "Inclua artigos em outras bibliotecas"
 add_search = "Adicionar campo de pesquisa"
@@ -25,6 +22,7 @@ add_search_group = "Adicionar Grupo de Pesquisa"
 add_tag_error = "Erro: Não foi possível guardar as Tags"
 add_tag_note = "Tags separadas por espaço. Use aspas para tags com várias palavras"."
 add_tag_success = "Tags guardadas"
+add_to_favorites_html = "Adicionar <em>%%title%%</em> aos favoritos"
 Address = "Endereço"
 adv_search_all = "Todos os campos"
 adv_search_author = "Autor"
@@ -209,7 +207,6 @@ confirm_ill_request_cancel_selected_text = "Você deseja cancelar seus pedidos d
 confirm_new_password = "Confirme a nova senha"
 confirm_storage_retrieval_request_cancel_all_text = "Você deseja cancelar todas as suas solicitações de empréstimos do Depósito atuais?"
 confirm_storage_retrieval_request_cancel_selected_text = "Você deseja cancelar as solicitações de empréstimos do Depósito selecionados?"
-conjunction_or = "ou"
 Contents = "Conteúdos"
 Contributors = "Colaboradores"
 Copies = "Cópias"
@@ -358,7 +355,6 @@ for search = "para a pesquisa"
 Forgot Password = "Esqueceu-se da sua Senha"
 Form Submitted! = "Comentário enviada!"
 Format = "Formato"
-found = "Encontrado"
 From = "De"
 Full description = "ver descrição completa"
 Full text is not displayed to guests = "O texto integral não é exibido em modo guest."
@@ -407,7 +403,7 @@ hold_cancel_all = "Cancelar todas as reservas"
 hold_cancel_fail = "A sua reserva não foi cancelada; por favor, contacte o Balcão de Atendimento para ajuda adicional"
 hold_cancel_selected = "Cancelar as reservas seleccionadas "
 hold_cancel_success = "A sua reserva foi cancelada com sucesso"
-hold_cancel_success_items = "reserva(s) foram canceladas com sucesso"
+hold_cancel_success_items = "%%count%% reserva(s) foram canceladas com sucesso"
 hold_date_invalid = "Por favor, introduza uma data válida"
 hold_date_past = "Por favor, introduza uma data no futuro"
 hold_empty_selection = "Não seleccionou nenhuma reserva"
@@ -415,7 +411,7 @@ hold_error_blocked = "Os seus privilégios não lhe permitem colocar uma reserva
 hold_error_fail = "O seu pedido não foi bem sucedido; por favor, contacte o Balcão de Atendimento para ajuda adicional"
 hold_invalid_pickup = "Não introduziu um local de levantamento válido; por favor, tente novamente"
 hold_invalid_request_group = "Foi inserido um grupo de pedido de reserva inválido. Por favor, tente novamente"
-hold_login = "para informação da reserva e levantamento"
+hold_login = "Entrar para informação da reserva e levantamento"
 hold_place = "Reservar"
 hold_place_fail_missing = "O seu pedido não foi bem sucedido: é necessário introduzir mais dados; por favor, contacte o Balcão de Atendimento para ajuda adicional"
 hold_place_success_html = "O seu pedido foi guardado com sucesso. <a href="%%url%%">As suas Reservas e Pedidos</a>."
@@ -427,7 +423,7 @@ hold_required_by = "Não é necessário depois de"
 hold_success = "O seu pedido foi guardado com sucesso"
 Holdings = "Exemplares"
 Holdings at Other Libraries = "Exemplares noutras Bibliotecas"
-Holdings details from = "Detalhes do Exemplar"
+holdings_details_from = "Detalhes do Exemplar %%location%%"
 Holdings_notes = "Observações"
 Holds = "Reservas"
 Holds and Recalls = "Reservas e Pedidos"
@@ -441,7 +437,7 @@ ill_request_cancel_all = "Cancelar todos os pedidos de empréstimo Interbibliote
 ill_request_cancel_fail = "A sua reserva não foi cancelada; por favor, contacte o Balcão de Atendimento para ajuda adicional"
 ill_request_cancel_selected = "Anular Selecionadas Pedidos Empréstimo Interbibliotecas"
 ill_request_cancel_success = "A sua reserva foi cancelada com sucesso"
-ill_request_cancel_success_items = "reserva(s) foram canceladas com sucesso"
+ill_request_cancel_success_items = "%%count%% reserva(s) foram canceladas com sucesso"
 ill_request_canceled = "Cancelado"
 ill_request_check_text = "Verifique o pedido de Empréstimo Interbibliotecas"
 ill_request_comments = "Comentários"
@@ -470,7 +466,6 @@ ils_offline_login_message = "Os dados da sua conta estarão indisponíveis duran
 ils_offline_status = "O nosso Sistema de Gestão da Biblioteca está em manutenção."
 ils_offline_title = "Sistema em Manutenção"
 Import Record = "Importar Registo"
-Import to = "Importar para"
 in = "Em"
 In This Collection = "Nesta colecção"
 in_collection_label = "Na coleção:"
@@ -497,8 +492,8 @@ Item removed from favorites = "Obra retirada dos favoritos"
 Item removed from list = "Obra retirada da lista"
 Items = "Registos"
 items = "registos"
-items_added_to_bookbag = "registo(s) adicionado(s) ao Carrinho"
-items_already_in_bookbag = "registo(s) já estava(m) no Carrinho"
+items_added_to_bookbag = "%%count%% registo(s) adicionado(s) ao Carrinho"
+items_already_in_bookbag = "%%count%% registo(s) já estava(m) no Carrinho"
 Journal = "Periódico"
 Journal Articles = "Artigos de Periódicos"
 Journal Title = "Título do Periódico"
@@ -596,11 +591,10 @@ no_description = "Descrição não disponível."
 no_items_selected = "Nenhum item selecionado"
 nohit_filters = "Filtros aplicados a esta busca:"
 nohit_heading = "Nenhum registo encontrado!"
+nohit_lookfor_html = "A sua pesquisa - <strong>%%lookfor%%</strong> - não corresponde a nenhum registo."
 nohit_no_filters = "Nenhum filtro aplicado à pesquisa."
 nohit_parse_error = "Parece haver um problema com a sua pesquisa. Por favor, verifique a sintaxe. Se você não está à procura de recursos avançados, pode ajudar colocar os termos dentro de aspas."
-nohit_prefix = "A sua pesquisa"
 nohit_spelling = "Talvez deva tentar algumas variações de ortografia"
-nohit_suffix = "não corresponde a nenhum registo."
 nohit_suggest = "Poderá querer rever sua equação de pesquisa retirando alguns termos ou verificando a ortografia."
 NOT = "NÃO"
 Not Illustrated = "Não Ilustrado"
@@ -640,7 +634,7 @@ Number = "Número"
 number_decimal_point = "."
 number_thousands_separator = ","
 OAI Server = "Servidor OAI"
-of = "de"
+of_num_results = "#%%position%% de %%total%% resultados"
 old_password = "Senha Antiga"
 On Reserve = "Reservado"
 On Reserve - Ask at Circulation Desk = "Empréstimo Condicionado; mais informação no Balcão de Atendimento"
@@ -680,8 +674,6 @@ Please check back soon = "Por favor, volte em breve"
 Please contact the Library Reference Department for assistance = "Por favor contacte o Serviço de Referência da Biblioteca para mais ajuda"
 Please enable JavaScript. = "Por favor active o JavaScript no seu brownser."
 Please upgrade your browser. = "Por favor, atualize o seu navegador."
-Posted by = "Partilhado por"
-posted_on = "em"
 Preferences = "Preferências"
 Preferred Library = "Biblioteca Preferedida"
 Prev = "Anterior"
@@ -811,7 +803,12 @@ Sensor Image = "Sensor de Imagem"
 Serial = "Periódico"
 Series = "Colecção"
 Set = "Definir"
-Showing = "A mostrar"
+showing_items_html = "A mostrar <strong>%%start%% - %%end%%</strong> Registos"
+showing_items_of_html = "A mostrar <strong>%%start%% - %%end%%</strong> de <strong>%%total%%</strong> Registos"
+showing_results_for_html = "A mostrar <strong>%%start%% - %%end%%</strong> resultados para a pesquisa '<strong>%%lookfor%%</strong>'"
+showing_results_html = "A mostrar <strong>%%start%% - %%end%%</strong> resultados"
+showing_results_of_for_html = "A mostrar <strong>%%start%% - %%end%%</strong> resultados de <strong>%%total%%</strong> para a pesquisa '<strong>%%lookfor%%</strong>'"
+showing_results_of_html = "A mostrar <strong>%%start%% - %%end%%</strong> resultados de <strong>%%total%%</strong>"
 Similar Items = "Registos relacionados"
 Skip to content = "Ir para o conteúdo"
 skip_confirm = "Tem certeza de que quer saltar esta etapa?"
@@ -851,7 +848,7 @@ storage_retrieval_request_cancel_all = "Cancelar todos os pedidos ao Depósito"
 storage_retrieval_request_cancel_fail = "A sua reserva não foi cancelada; por favor, contacte o Balcão de Atendimento para ajuda adicional"
 storage_retrieval_request_cancel_selected = "Anular os Pedidos ao Depósito seleccionados"
 storage_retrieval_request_cancel_success = "A sua reserva foi cancelada com sucesso"
-storage_retrieval_request_cancel_success_items = "reserva(s) foram canceladas com sucesso"
+storage_retrieval_request_cancel_success_items = "%%count%% reserva(s) foram canceladas com sucesso"
 storage_retrieval_request_canceled = "Cancelado"
 storage_retrieval_request_check_text = "Verifique o pedido ao Depósito"
 storage_retrieval_request_comments = "Comentários"
@@ -888,7 +885,7 @@ Summon Results = "Resultados Summon"
 summon_database_recommendations = "Pode encontrar recursos adicionais aqui:"
 Supplements = "Suplementos"
 Supplied by Amazon = "Fornecido pela Amazon"
-Switch view to = "Alterar a visualização para"
+switch_view = "Alterar a visualização para %%view%%"
 switchquery_intro = "Pode obter mais resultados ajustando a pesquisa."
 switchquery_lowercasebools = "Se usar operadores Booleanos, por favor insira-os com letras MAIÚSCULAS"
 switchquery_truncatechar = "Use a truncatura para aumentar os seus resultados"
@@ -929,8 +926,7 @@ Too Many Email Recipients = "Muitos destinatários de mail"
 too_many_favorites = "Essa lista é muito grande para mostrar tudo de uma vez. Tente reorganizar seus favoritos em mais listas ou limite o uso de tags."
 too_many_new_items = "Há muitos novos registos para mostrar nma única lista. Tente limitar a sua pesquisa."
 too_many_reserves = "Há demasiadas obras recomendadas para mostrar numa única lista. Tente limitar a sua pesquisa."
-top_facet_additional_prefix = "Adicionais"
-top_facet_suffix = "... dentro de sua pesquisa."
+top_facet_label = "%%label%% dentro de sua pesquisa."
 Topic = "Assunto"
 Topics = "Assuntos"
 Total Balance Due = "Valor total em dívida"
@@ -957,7 +953,6 @@ VHS = "VHS"
 Video = "Vídeo"
 Video Clips = "Clips Video"
 Videos = "Vídeos"
-view already selected = "visualização já seleccionada"
 View Book Bag = "Ver Carrinho"
 View Full Collection = "Ver Colecção Completa"
 View Full Record = "Ver Registro completo"
@@ -966,6 +961,7 @@ View online: Full view Book Preview from the Hathi Trust = "Ver online: Full vis
 View Record = "Ver Registo"
 View Records = "Ver registos"
 View this record in EBSCOhost = "Veja este registoo no EBSCOhost"
+view_already_selected = "%%current%% visualização já seleccionada"
 visual_facet_parent = "De"
 Volume = "Volume"
 Volume Holdings = "Existências do Volume"
diff --git a/languages/ru.ini b/languages/ru.ini
index 134d1f77527cf0eb69cf2598fc65432b32799c86..ec64b25421593f57438647be1f5ab78de32f667d 100644
--- a/languages/ru.ini
+++ b/languages/ru.ini
@@ -23,7 +23,6 @@ Access URL = "Доступ через URL"
 access_denied = "Доступ запрещен."
 Accession Number = "Номер доступа"
 Account = "Акаунт"
-Add = "Добавить"
 Add a Library Card = "Добавить карту библиотеки"
 Add a Note = "Добавить примечание"
 Add Tag = "Добавить метку"
@@ -35,8 +34,6 @@ Add your comment = "Добавить комментарий"
 add_comment_fail_blank = "Невозможен пустой комментарий."
 add_comment_success = "Добавлен комментарий."
 add_favorite_fail = "Ошибка: запись не сохранена"
-add_favorite_prefix = "Добавить"
-add_favorite_suffix = "в избранные"
 add_list_fail = "Ошибка: не создан список"
 add_other_libraries = "Включите статьи в другие библиотеки"
 add_search = "Добавить поле для поиска"
@@ -44,6 +41,7 @@ add_search_group = "Добавить группу для поиска"
 add_tag_error = "Ошибка: невозможно сохранить метки"
 add_tag_note = "Пробелы разделяют метки. Используйте кавычки для многословных меток."
 add_tag_success = "Метки сохранены"
+add_to_favorites_html = "Добавить <em>%%title%%</em> в избранные"
 Address = "Адрес"
 adv_search_all = "Все поля"
 adv_search_author = "Автор"
@@ -235,7 +233,6 @@ confirm_ill_request_cancel_selected_text = "Нужно ли отменить в
 confirm_new_password = "Подтвердить новый пароль"
 confirm_storage_retrieval_request_cancel_all_text = "Нужно ли отменить все Ваши запросы по выборке из хранилища?"
 confirm_storage_retrieval_request_cancel_selected_text = "Нужно ли отменить все Ваши выбранные запросы по выборке из хранилища?"
-conjunction_or = "или"
 Contents = "Контенты"
 Contributing Source = "Источник поступления"
 Contributors = "Спонсоры"
@@ -390,7 +387,6 @@ for search = "для поиска"
 Forgot Password = "Забыт пароль"
 Form Submitted! = "Форма предоставлена!"
 Format = "Формат"
-found = "найдено"
 From = "от"
 Full description = "Полное описание"
 Full text is not displayed to guests = "Гостям не отображается полный текст."
@@ -440,7 +436,7 @@ hold_cancel_all = "Отмена всех задолженностей"
 hold_cancel_fail = "Ваш запрос не отменен. Обратитесь за помощью к библиотекарям."
 hold_cancel_selected = "Отмена выбранных задолженностей."
 hold_cancel_success = "Ваш запрос успешно отменен."
-hold_cancel_success_items = "Запросы успешно отменены."
+hold_cancel_success_items = "%%count%% Запросы успешно отменены."
 hold_date_invalid = "Введите допустимую дату"
 hold_date_past = "Введите какую-нибудь будущую дату."
 hold_empty_selection = "Не выбрано задолженностей."
@@ -448,7 +444,7 @@ hold_error_blocked = "Отсутствуют достаточные права 
 hold_error_fail = "Сбой Вашего запроса Обратитесь за помощью в circulation desk."
 hold_invalid_pickup = "Указаны неверные данные по ячейке подхвата. Повторите попытку."
 hold_invalid_request_group = "Была введена недопустимая "замороженная" группа запросов. Повторите попытку."
-hold_login = "Для информации по задолженностям и напоминаниям"
+hold_login = "Логин Для информации по задолженностям и напоминаниям"
 hold_place = "Поместите запрос"
 hold_place_fail_missing = "Сбой запроса. Пропущены некоторые данные. Обратитесь за помощью к библиотекарям."
 hold_place_success_html = "Ваш запрос успешно выполнен. <a href="%%url%%">Ваши задолженности и напоминания</a>."
@@ -460,7 +456,7 @@ hold_required_by = "Не запрашивайтк после"
 hold_success = "Ваш запрос выполнен"
 Holdings = "Фонды"
 Holdings at Other Libraries = "Фонды других библиотек"
-Holdings details from = "Подробно о фондах из"
+holdings_details_from = "Подробно о фондах из %%location%%"
 Holdings_notes = "Примечания"
 Holds = "Задолженности"
 Holds and Recalls = "Задолженности и напоминания"
@@ -474,7 +470,7 @@ ill_request_cancel_all = "Отмена всех межбиблиотечных 
 ill_request_cancel_fail = "Ваш запрос не отменен. Обратитесь за помощью к библиотекарям."
 ill_request_cancel_selected = "Отмена выбранных межбиблиотечных запросов"
 ill_request_cancel_success = "Ваш запрос успешно отменен."
-ill_request_cancel_success_items = "Запросы успешно отменены."
+ill_request_cancel_success_items = "%%count%% Запросы успешно отменены."
 ill_request_canceled = "Отменен"
 ill_request_check_text = "Проверить межбиблитечный запрос"
 ill_request_comments = "Комментарии"
@@ -503,7 +499,6 @@ ils_offline_login_message = "Ваш логин будут недоступны 
 ils_offline_status = "Система поддержки библиотеки сейчас на техническом обслуживаении."
 ils_offline_title = "Система на техническом обслуживании"
 Import Record = "Запись для импорта"
-Import to = "Импортировать в "
 in = "в"
 In This Collection = "В этой коллекции"
 in_collection_label = "В коллекции:"
@@ -531,8 +526,8 @@ Item removed from favorites = "Документ удален из Избранн
 Item removed from list = "Документ удален из списка"
 Items = "Документы"
 items = "документы"
-items_added_to_bookbag = "документы добавлены в книжную сумку"
-items_already_in_bookbag = "документы либо в книжной сумке, либо их невозможно добавить"
+items_added_to_bookbag = "%%count%% документы добавлены в книжную сумку"
+items_already_in_bookbag = "%%count%% документы либо в книжной сумке, либо их невозможно добавить"
 Journal = "Журнал"
 Journal Articles = "Статьи журнала"
 Journal Info = "Информация журнала"
@@ -648,12 +643,11 @@ nohit_active_filters = "Один или более facet-фильтров был
 nohit_change_tab = "Вы искали в "%%activeTab%%" таблице. Вы можете искать в одной из следующих таблиц:"
 nohit_filters = "Сейчас применимы фильтры для этого поиска:"
 nohit_heading = "Нет результатов!"
+nohit_lookfor_html = "Ваш поиск - <strong>%%lookfor%%</strong> - не найдены соответствующие книги."
 nohit_no_filters = "Не были применены для этого поиска."
 nohit_parse_error = "Кажется, возникла проблема при поиске. Проверьте синтаксис запроса. Если попытаться использовать новые возможности, надо заключить запрос в двойные кавычки."
-nohit_prefix = "Ваш поиск"
 nohit_query_without_filters = "Удалить все фильтры из этого поиска."
 nohit_spelling = "Возможно, требуются некоторые другие вариации"
-nohit_suffix = "не найдены соответствующие книги."
 nohit_suggest = "Возможно, понадобится изменить свой запрос, убрав из него некоторые слова, или или проверить правописание."
 NOT = "НЕ"
 Not Illustrated = "Без иллюстраций"
@@ -694,7 +688,7 @@ Number = "Номер"
 number_decimal_point = "."
 number_thousands_separator = ","
 OAI Server = "OAI-сервер"
-of = "of"
+of_num_results = "#%%position%% of %%total%% результаты"
 old_password = "Старый пароль"
 On Reserve = "Забронировано"
 On Reserve - Ask at Circulation Desk = "Забронировано -Обратитесь к библиотекарям"
@@ -735,8 +729,6 @@ Please check back soon = "Перепроверьте скорее"
 Please contact the Library Reference Department for assistance = "Обратитесь за помощью к библиотекарям"
 Please enable JavaScript. = "Включите JavaScript."
 Please upgrade your browser. = "Надо обновить версию своего браузера."
-Posted by = "Отправлено"
-posted_on = "вкл"
 Preferences = "Ссылки"
 Preferred Library = "Предпочтительная библиотека"
 Prev = "Пред."
@@ -870,7 +862,12 @@ Sensor Image = "Значок сенсора"
 Serial = "Серия"
 Series = "Серии"
 Set = "Множество"
-Showing = "Отображение"
+showing_items_html = "Отображение <strong>%%start%% - %%end%%</strong> Документы"
+showing_items_of_html = "Отображение <strong>%%start%% - %%end%%</strong> of <strong>%%total%%</strong> Документы"
+showing_results_for_html = "Отображение <strong>%%start%% - %%end%%</strong> результаты для поиска '<strong>%%lookfor%%</strong>'"
+showing_results_html = "Отображение <strong>%%start%% - %%end%%</strong> результаты"
+showing_results_of_for_html = "Отображение <strong>%%start%% - %%end%%</strong> результаты of <strong>%%total%%</strong> для поиска '<strong>%%lookfor%%</strong>'"
+showing_results_of_html = "Отображение <strong>%%start%% - %%end%%</strong> результаты of <strong>%%total%%</strong>"
 Similar Items = "Схожие документы"
 Skip to content = "Пропуск в контексте"
 skip_confirm = "Нужно ли пропустить этот шаг?"
@@ -911,7 +908,7 @@ storage_retrieval_request_cancel_all = "Отмена ВСЕХ запросов 
 storage_retrieval_request_cancel_fail = "Ваш запрос не отменен. Обратитесь за помощью к библиотекарям."
 storage_retrieval_request_cancel_selected = "Отмена выбранных запросов выборки из хранилища"
 storage_retrieval_request_cancel_success = "Ваш запрос успешно отменен."
-storage_retrieval_request_cancel_success_items = "Запросы успешно отменены."
+storage_retrieval_request_cancel_success_items = "%%count%% Запросы успешно отменены."
 storage_retrieval_request_canceled = "Отменен"
 storage_retrieval_request_check_text = "Проверьте запрос выборки из хранилища"
 storage_retrieval_request_comments = "Комментарии"
@@ -949,7 +946,7 @@ Summon Results = "Результаты Summon"
 summon_database_recommendations = "Здесь можно найти дополнительные ресурсы:"
 Supplements = "Дополнения"
 Supplied by Amazon = "Поставлено Amazon"
-Switch view to = "Переключить просмотр на"
+switch_view = "Переключить просмотр на %%view%%"
 switchquery_fuzzy = "Fuzzy-поиск может выбирать теримины с похожими произношениями"
 switchquery_intro = "Можно получить больше результатов путем настройки запроса поиска."
 switchquery_lowercasebools = "При использовании булеских операций они должны быть набраны заглавными буквами"
@@ -991,8 +988,7 @@ Too Many Email Recipients = "Слишком много получателей E-
 too_many_favorites = "Список слишком велик для отображения целиком на экране. Превратите свои Избранные в несколько списков или ограничьте использование меток."
 too_many_new_items = "Слишком много документов для отображения в одном списке. Ограничьте свой поиск."
 too_many_reserves = "Слишком много резервов курса для отображения в одном списке. Ограничьте свой поиск."
-top_facet_additional_prefix = "Дополнительно "
-top_facet_suffix = "... внутри своего поиска."
+top_facet_label = "%%label%% внутри своего поиска."
 Topic = "Тема"
 Topics = "Темы"
 Total Balance Due = "Всего оплачиваемых файлов"
@@ -1021,7 +1017,6 @@ VHS = "VHS"
 Video = "Видеозапись"
 Video Clips = "Видеоклипы"
 Videos = "Видеозаписи"
-view already selected = "просмотр уже выбранных"
 View Book Bag = "Просмотр книжной сумки"
 View Full Collection = "Просмотр полной коллекции"
 View Full Record = "Просмотр полной записми"
@@ -1030,6 +1025,7 @@ View online: Full view Book Preview from the Hathi Trust = "online-просмо
 View Record = "Просмотр записи"
 View Records = "Просмотр записей"
 View this record in EBSCOhost = "Просмотр записи в EBSCOhost"
+view_already_selected = "%%current%% просмотр уже выбранных"
 visual_facet_parent = "от"
 Volume = "Том"
 Volume Holdings = "Объемы фондов"
diff --git a/languages/sl.ini b/languages/sl.ini
index 29519ba195a96909466cc91b126c1b65a75e0db6..d766e14ba665a2986bfbaf4baddfab75a5aa2bb2 100644
--- a/languages/sl.ini
+++ b/languages/sl.ini
@@ -2,7 +2,6 @@
 Access = "Dostop"
 access_denied = "Dostop zavrnjen."
 Account = "Račun"
-Add = "Dodaj"
 Add a Note = "Dodaj opombo"
 Add Tag = "Označite"
 Add Tags = "Označite"
@@ -13,8 +12,6 @@ Add your comment = "Dodaj komentar"
 add_comment_fail_blank = "Komentar ne more biti prazen."
 add_comment_success = "Dodan komentar."
 add_favorite_fail = "Napaka: Zadetek ni shranjen"
-add_favorite_prefix = "Dodaj"
-add_favorite_suffix = "v priljubljene"
 add_list_fail = "Napaka: Seznam ni ustvarjen"
 add_other_libraries = "Vključi članke iz drugih knjižnic"
 add_search = "Dodaj iskalno polje"
@@ -22,6 +19,7 @@ add_search_group = "Dodaj iskalno skupino"
 add_tag_error = "Napaka: Ne more shraniti oznak"
 add_tag_note = "Presledki bodo ločili oznake. Uporabite narekovaje za več-besedne oznake."
 add_tag_success = "Oznake shranjene"
+add_to_favorites_html = "Dodaj <em>%%title%%</em> v priljubljene"
 Address = "Naslov"
 adv_search_all = "Vsa polja"
 adv_search_author = "Avtor"
@@ -312,7 +310,6 @@ fix_metadata = "Da, popravite metapodatke; bom počakal"
 for search = "za iskanje"
 Form Submitted! = "Obrazec poslan!"
 Format = "Format"
-found = "najdeno"
 From = "Iz"
 Full description = "Popoln opis"
 fulltext_limit = "Omeji na članke s polnim tekstom"
@@ -357,14 +354,14 @@ hold_cancel_all = "Prekliči vse rezervacije"
 hold_cancel_fail = "Vaša zahteva ni bila preklicana. Za pomoč prosite v izposoji"
 hold_cancel_selected = "Prekliči izbrane rezervacije"
 hold_cancel_success = "Vaša zahteva je bila uspešno preklicana"
-hold_cancel_success_items = "zahteve so bile uspešno preklicane"
+hold_cancel_success_items = "%%count%% zahteve so bile uspešno preklicane"
 hold_date_invalid = "Vstavite veljaven datum"
 hold_date_past = "Vstavite datum, ki prihaja"
 hold_empty_selection = "Niste izbrali rezervacije"
 hold_error_blocked = "Nimate dovolj privilegijev za rezervacijo"
 hold_error_fail = "Vaša zahteva ni bila upsešna. Za pomoč prosite v izposoji"
 hold_invalid_pickup = "Napačna lokacija za prevzem. Poizkusite ponovno"
-hold_login = "za informacije o izposojenih in rezerviranih"
+hold_login = "Prijava za informacije o izposojenih in rezerviranih"
 hold_place = "Postavite zahtevo"
 hold_place_fail_missing = "Vaša zahteva ni bila uspešna. Manjkajo nekateri podatki. Za nadaljno pomoč vprašajte v izposoji"
 hold_place_success_html = "Vaša zahteva je bila uspešna. <a href="%%url%%">Vaše izposojene in rezervirane</a>."
@@ -374,7 +371,7 @@ hold_required_by = "Ni potreben po"
 hold_success = "Vaša zahteva je bila uspešna"
 Holdings = "Zaloga"
 Holdings at Other Libraries = "Zaloga v drugih knjižnicah"
-Holdings details from = "Podrobnosti zaloge"
+holdings_details_from = "Podrobnosti zaloge %%location%%"
 Holdings_notes = "Note"
 Holds = "Izposojeno"
 Holds and Recalls = "Izposojeno in rezervirano"
@@ -384,7 +381,7 @@ Identifier = "Identifikator"
 ill_request_available = "Pripravljeno za prevzem"
 ill_request_cancel_fail = "Vaša zahteva ni bila preklicana. Za pomoč prosite v izposoji"
 ill_request_cancel_success = "Vaša zahteva je bila uspešno preklicana"
-ill_request_cancel_success_items = "zahteve so bile uspešno preklicane"
+ill_request_cancel_success_items = "%%count%% zahteve so bile uspešno preklicane"
 ill_request_date_invalid = "Vstavite veljaven datum"
 ill_request_date_past = "Vstavite datum, ki prihaja"
 ill_request_error_fail = "Vaša zahteva ni bila upsešna. Za pomoč prosite v izposoji"
@@ -399,7 +396,6 @@ ils_offline_login_message = "V tem času bodo podrobnosti vašega računa nedost
 ils_offline_status = "Trenutno vzdržujemo knjižnični informacijski sistem."
 ils_offline_title = "Vzdrževanje sistema"
 Import Record = "Uvozite zadetek"
-Import to = "Izvozite v"
 in = "v"
 In This Collection = "V tej zbirki"
 in_collection_label = "V zbirki:"
@@ -424,8 +420,8 @@ Item removed from favorites = "Odstranjeno iz priljubljenih"
 Item removed from list = "Odstranjeno s seznama"
 Items = "knjige/članki"
 items = "knjige/članki ZADETKI"
-items_added_to_bookbag = "dodane knjige/članki v vaši košarici"
-items_already_in_bookbag = "knjige/članki so ali že dodani v vašo košarico ali pa ne morejo biti dodani"
+items_added_to_bookbag = "%%count%% dodane knjige/članki v vaši košarici"
+items_already_in_bookbag = "%%count%% knjige/članki so ali že dodani v vašo košarico ali pa ne morejo biti dodani"
 Journal = "Revija"
 Journal Articles = "ÄŒlanki"
 Journal Title = "Naslov revije"
@@ -515,11 +511,10 @@ no_description = "Opisa ni na voljo."
 no_items_selected = "Nobena knjiga/članek ni bil izbran"
 nohit_filters = "Veljavni filtri za to iskanje:"
 nohit_heading = "Ni rezultatov!"
+nohit_lookfor_html = "Vaše iskanje - <strong>%%lookfor%%</strong> - ne ujema se z nobenim virom."
 nohit_no_filters = "Ni veljavnih filtrov za to iskanje."
 nohit_parse_error = "Problem se je pojavil z vašim iskanjem. Preverite sintakso. Če ne uporabljate naprednega iskanja pomaga, če date iskalno zahtevo v dvojne narekovaje."
-nohit_prefix = "Vaše iskanje"
 nohit_spelling = "Poizkusite z različnim črkovanjem"
-nohit_suffix = "ne ujema se z nobenim virom."
 nohit_suggest = "Preuredite vaše iskanje ali spremenite črkovanje vaše iskalne zahteve."
 NOT = "NE"
 Not Illustrated = "Ni ilustrirano"
@@ -553,7 +548,6 @@ note_785_8 = "Nazaj spremenjeno"
 Notes = "Note"
 Number = "Å tevilka"
 OAI Server = "OAI Server"
-of = "od"
 On Reserve = "Obvezna literatura"
 On Reserve - Ask at Circulation Desk = "Obvezna litartura - Vprašajte v izposoji"
 on_reserve = "Obvezna literatura - Vprašajte na izposoji"
@@ -580,8 +574,6 @@ Playing Time = "ÄŒas predvajanja"
 Please check back soon = "Kmalu preverite"
 Please contact the Library Reference Department for assistance = "Kontaktirajte oddelek za strokovne referente za pomoč"
 Please enable JavaScript. = "Omogočite JavaScript."
-Posted by = "Objavil"
-posted_on = "na"
 Preferred Library = "Priporočena knjižnica"
 Prev = "Prej."
 Preview = "Predogled"
@@ -678,7 +670,8 @@ Sensor Image = "Sensorska slika"
 Serial = "Serijska publikacija"
 Series = "Serija"
 Set = "Izberi"
-Showing = "Pokaži"
+showing_items_html = "Pokaži <strong>%%start%% - %%end%%</strong> knjige/članki"
+showing_items_of_html = "Pokaži <strong>%%start%% - %%end%%</strong> od <strong>%%total%%</strong> knjige/članki"
 Similar Items = "Podobne knjige/članki"
 skip_confirm = "Ste prepričani, da želite izpustiti naslednji korak?"
 skip_fix_metadata = "Trenutno ne popravi metapodatkov."
@@ -712,7 +705,7 @@ status_unknown_message = "Zaloga ni dosegljiva"
 storage_retrieval_request_available = "Pripravljeno za prevzem"
 storage_retrieval_request_cancel_fail = "Vaša zahteva ni bila preklicana. Za pomoč prosite v izposoji"
 storage_retrieval_request_cancel_success = "Vaša zahteva je bila uspešno preklicana"
-storage_retrieval_request_cancel_success_items = "zahteve so bile uspešno preklicane"
+storage_retrieval_request_cancel_success_items = "%%count%% zahteve so bile uspešno preklicane"
 storage_retrieval_request_comments = "Komentarji"
 storage_retrieval_request_date_invalid = "Vstavite veljaven datum"
 storage_retrieval_request_date_past = "Vstavite datum, ki prihaja"
@@ -733,7 +726,7 @@ Summary = "Izvleček"
 Summon Results = "Summon rezultati"
 summon_database_recommendations = "Dodatne vire lahko najdete v:"
 Supplied by Amazon = "Prispeval Amazon"
-Switch view to = "Spremeni polled na"
+switch_view = "Spremeni polled na %%view%%"
 switchquery_intro = "Dobili boste več rezultatov, če prilagodite vašo iskalno zahtevo."
 switchquery_lowercasebools = "ÄŒe uporabljate Boolove operatorje, uporabite VELIKE ÄŒRKE"
 switchquery_unwantedbools = "Besede AND, OR in NOT lahko zmedejo iskanje; dajte jih v narekovaje"
@@ -770,8 +763,7 @@ To = "Za"
 too_many_favorites = "Seznam je prevelik za enkraten prikaz. Napravite več seznamov v vaših priljubljenih ali omejite uporabo oznak."
 too_many_new_items = "Preveč je zadetkov za prikaz na eni strani. Omejite vaše iskanje."
 too_many_reserves = "Preveč je naslovov obvezne literature za prikaz na eni strani.Omejite vaše iskanje."
-top_facet_additional_prefix = "Dodatno "
-top_facet_suffix = "... znotraj vašega iskanja."
+top_facet_label = "%%label%% znotraj vašega iskanja."
 Topic = "Tema"
 Topics = "Teme"
 Total Balance Due = "Stanje na vašem računu"
@@ -796,13 +788,13 @@ VHS = "VHS"
 Video = "Video"
 Video Clips = "Video posnetki"
 Videos = "Videji"
-view already selected = "že izbran pogled"
 View Book Bag = "Poglej košarico"
 View Full Collection = "Poglej celotno zbirko"
 View Full Record = "Poglej poln zadetek"
 View online: Full view Book Preview from the Hathi Trust = "poglej online: Poln pre ogled knjige na Hathi Trust"
 View Record = "Poglej zadetek"
 View Records = "poglej zadetke"
+view_already_selected = "%%current%% že izbran pogled"
 visual_facet_parent = "Iz"
 Volume = "Zvezek"
 Volume Holdings = "Zaloga"
diff --git a/languages/sv.ini b/languages/sv.ini
index 66953ba17390030dfd95717c119c3dd452d56fd3..6136eba1699ec8e234b0d0a725d0b1709cdf5a5e 100644
--- a/languages/sv.ini
+++ b/languages/sv.ini
@@ -5,7 +5,7 @@ Access URL = "Länk till materialet"
 access_denied = "Ã…tkomst nekad"
 Accession Number = "Accessionsnummer"
 Account = "Konto"
-Add = "Lägg till"
+account_block_options_missing = "Vissa alternativ har tagits bort på grund av låne- efter reserveringsförbud. Detaljer: %%details%%"
 Add a Library Card = "Anslut bibliotekskort till konto"
 Add a Note = "Lägg till en anteckning "
 Add Tag = "Lägg till en tagg"
@@ -17,8 +17,6 @@ Add your comment = "Lägg till en kommentar"
 add_comment_fail_blank = "Comment cannot be blank."
 add_comment_success = "Comment added."
 add_favorite_fail = "Fel: posten kunde inte sparas"
-add_favorite_prefix = "Lägg till"
-add_favorite_suffix = "till favoriter"
 add_list_fail = "Fel: listan kunde inte sparas"
 add_other_libraries = "Inkludera artiklar från andra bibliotek"
 add_search = "Lägg till ett sökfelt"
@@ -26,6 +24,7 @@ add_search_group = "Lägg till en sökgrupp"
 add_tag_error = "Fel: taggarna kunde inte sparas"
 add_tag_note = "Skilj åt taggar med mellanslag. Sätt flerordiga taggar inom citationstecken."
 add_tag_success = "Taggarna sparades"
+add_to_favorites_html = "Lägg till <em>%%title%%</em> till favoriter"
 Address = "Adress"
 adv_search_all = "Alla fält"
 adv_search_author = "Upphovsman"
@@ -171,6 +170,10 @@ Catalog Results = "Resultat i katalogen"
 catalog_login_desc = "Ange din bibliotekskortets nummer och lösenord."
 CD = "CD"
 Change Password = "Ändra lösenord"
+channel_add_more = "Mer liknande kanaler"
+channel_expand = "Utforska relaterade kanaler"
+channel_explore = "Utforska kanaler"
+channel_search = "Visa som sökresultat"
 Check Hold = "Kolla reservering"
 Check Recall = "Kolla återkallelse"
 Checked Out = "LÃ¥n"
@@ -221,7 +224,6 @@ confirm_ill_request_cancel_selected_text = "Är du säker på at du vill annulle
 confirm_new_password = "Bekräfta nytt lösenord"
 confirm_storage_retrieval_request_cancel_all_text = "Vill du annullera alla beställningar?"
 confirm_storage_retrieval_request_cancel_selected_text = "Vill du annullera de valda beställningarna?"
-conjunction_or = "eller"
 Contents = "Innehåll"
 Contributing Source = "Bidragande källa"
 Contributors = "Övriga upphovsmän"
@@ -272,6 +274,7 @@ Displaying the top = "Visar de första"
 Document Inspector = "Document Inspector"
 Document Type = "Dokument typ"
 DOI = "DOI"
+doi_detected_html = "Din sökning verkar innehålla en DOI. Klicka denna länk för att kolla tillgängligheten: <a href="%%url%%">%%doi%%</a>"
 Draw Search Box = "Välj region"
 Due = "Förfaller"
 Due Date = "Förfallodag"
@@ -285,6 +288,7 @@ edit_list_fail = "Rättigheter att ändra listan saknas"
 edit_list_success = "Listan har uppdaterats."
 Edition = "Upplaga"
 eds_expander_fulltext = "Sök också inom fulltext av artiklar"
+eds_expander_relatedsubjects = "Använd relaterade ämnen"
 eds_expander_thesaurus = "Använd relaterade ord"
 eds_limiter_FC = "Endast katalog"
 eds_limiter_FC1 = "Endast elektroniska material"
@@ -345,6 +349,10 @@ export_selected = "Exportera valda"
 export_selected_favorites = "Exportera valda favoriter"
 export_success = "Exporten färdig"
 export_unsupported_format = "Export i det valda formatet är inte möjlig"
+external_auth_heading = "Behörighet att komma åt licensierat material"
+external_auth_login_message = "Logga in för att komma åt licensierat material"
+external_auth_unauthorized = "Du har inte behörighet att komma åt licensierat material"
+external_auth_unauthorized_desc = "Du kan inte komma åt licensierat material med inloggningsmetoden du har använt. Logga ut först och sedan logga in med en annan metod."
 FAQs = "Vanliga frågor"
 fav_delete = "Radera valda favoriter"
 fav_delete_deleting = "Dina favoriter raderas"
@@ -382,7 +390,6 @@ for search = "för sökning"
 Forgot Password = "Glömt lösenord"
 Form Submitted! = "Form Submitted!"
 Format = "Materialtyp"
-found = "hittades"
 From = "Från"
 Full description = "Full beskrivning"
 Full text is not displayed to guests = "Fulltext visas inte till gäster."
@@ -434,7 +441,7 @@ hold_cancel_all = "Annullera alla reserveringar"
 hold_cancel_fail = "Reserveringen kunde inte annulleras. Kontakta kundtjänst."
 hold_cancel_selected = "Annullera valda reserveringar"
 hold_cancel_success = "Reserveringen har annullerats"
-hold_cancel_success_items = "reservering(ar) har annullerats"
+hold_cancel_success_items = "%%count%% reservering(ar) har annullerats"
 hold_date_invalid = "Ange ett giltigt datum"
 hold_date_past = "Ange ett datum som infaller senare än idag"
 hold_empty_selection = "Inga reserveringar valda"
@@ -443,19 +450,20 @@ hold_error_fail = "Begäran misslyckades. Kontakta kundtjänst."
 hold_invalid_pickup = "Det valda avhämtningsstället är felaktigt. Försök igen."
 hold_invalid_request_group = "Det valda gruppet är felaktigt. Försök igen."
 hold_items_available = "Reservering kan inte göras eftersom det finns exemplar tillgängliga för utlåning i biblioteket."
-hold_login = "för att kontrollera reserveringsmöjlighet"
+hold_login = "Logga in för att kontrollera reserveringsmöjlighet"
 hold_place = "Reservera"
 hold_place_fail_missing = "Reservering misslyckades p.g.a. att uppgifter saknas. Kontakta kundtjänst."
 hold_place_success_html = "Material har reserverats. <a href="%%url%%">Reserveringar</a>."
 hold_profile_html = "Logga in <a href %%url%%>med bibliotekskortet</a> för att se reserveringsmöjligheter."
 hold_queue_position = "Placering i kön"
+hold_record_already_on_loan = "Du har detta material redan utlånad"
 hold_request_group = "Reservera från"
 hold_requested_group = "Reserverad från"
 hold_required_by = "Sista giltighetsdagen"
 hold_success = "Material har reserverats."
 Holdings = "Beståndsuppgifter"
 Holdings at Other Libraries = "Beståndsuppgifter i andra bibliotek"
-Holdings details from = "Beståndsuppgifter i"
+holdings_details_from = "Beståndsuppgifter i %%location%%"
 Holdings_notes = "Anmärkningar"
 Holds = "Reserveringar"
 Holds and Recalls = "Reserveringar"
@@ -469,7 +477,7 @@ ill_request_cancel_all = "Annullera alla beställningar"
 ill_request_cancel_fail = "Din beställning annullerades inte. Kontakta kundtjänst."
 ill_request_cancel_selected = "Annullera valda beställningar"
 ill_request_cancel_success = "Beställningen har annullerats"
-ill_request_cancel_success_items = "beställning(ar) har annullerats"
+ill_request_cancel_success_items = "%%count%% beställning(ar) har annullerats"
 ill_request_canceled = "Annullerad"
 ill_request_check_text = "Kolla fjärrlånbeställning"
 ill_request_comments = "Tilläggsuppgifter"
@@ -498,7 +506,6 @@ ils_offline_login_message = "Your account details will be unavailable during thi
 ils_offline_status = "Our Library Management System is currently under maintenance."
 ils_offline_title = "System Under Maintenance"
 Import Record = "Importera posten"
-Import to = "Importera till"
 in = "i fältet"
 In This Collection = "I denna samling"
 in_collection_label = "I samling:"
@@ -526,8 +533,8 @@ Item removed from favorites = "Post raderad från favoriter"
 Item removed from list = "Post raderad från favoriter listan"
 Items = "Objekt"
 items = "poster"
-items_added_to_bookbag = "poster har lagts till i bokkorgen"
-items_already_in_bookbag = "poster finns redan i bokkorgen eller tillägg i korgen misslyckades"
+items_added_to_bookbag = "%%count%% post(er) har lagts till i bokkorgen"
+items_already_in_bookbag = "%%count%% post(er) finns redan i bokkorgen eller tillägg i korgen misslyckades"
 Journal = "Tidskrift"
 Journal Articles = "Tidskriftsartiklar"
 Journal Info = "Tidskrift info"
@@ -644,12 +651,11 @@ nohit_active_filters = "Filtren i bruk i denna sökning. Om du tar bort filtren,
 nohit_change_tab = "Du har sökt i fliken "%%activeTab%%". Du kan hitta något i en av de andra flikar:"
 nohit_filters = "Filtren för denna sökning:"
 nohit_heading = "Inga resultat!"
+nohit_lookfor_html = "Med sökning - <strong>%%lookfor%%</strong> - inga resultat hittades."
 nohit_no_filters = "Inga filter i bruk i denna sökning."
 nohit_parse_error = "Det finns ett syntaxfel i sökfrågan. Om du inte försöker använda speciella sökmetoder kan du pröva att sätta sökfrågan inom citationstecken."
-nohit_prefix = "Med sökning"
 nohit_query_without_filters = "Ta bort alla filtren från denna sökning."
 nohit_spelling = "Det lönar sig att pröva olika skrivformer"
-nohit_suffix = "inga resultat hittades."
 nohit_suggest = "Du kan pröva att ändra sökvillkoren genom att ta bort några sökord eller genom att ändra ordens stavning."
 NOT = "INTE"
 Not Illustrated = "Oillustrerad"
@@ -691,7 +697,7 @@ number_decimal_point = ","
 number_thousands_separator = " "
 OAI Server = "OAI Servern"
 Occupation = "Yrke"
-of = "av"
+of_num_results = "%%position%% av %%total%% resultat"
 old_password = "Gamla lösenordet"
 On Reserve = "I begränsad användning"
 On Reserve - Ask at Circulation Desk = "I begränsad användning - kontakta kundtjänst"
@@ -699,6 +705,7 @@ on_reserve = "I begränsad användning - kontakta kundtjänst"
 on_topic = "%%count%% post(er) om detta ämne"
 Online Access = "Länkar"
 online_resources = "Fulltext"
+open_access_limit = "Begränsa till Open Access -material"
 operator_contains = "innehåller"
 operator_exact = "är (exakt)"
 OR = "ELLER"
@@ -737,8 +744,6 @@ Please check back soon = "Kontrollera på nytt om en stund"
 Please contact the Library Reference Department for assistance = "Kontakta kundtjänst för hjälp"
 Please enable JavaScript. = "Vänligen aktivera JavaScript."
 Please upgrade your browser. = "Vänligen uppgradera din webbläsare."
-Posted by = "Skickat av"
-posted_on = "Datum"
 Preferences = "Inställningar"
 Preferred Library = "Föredraget bibliotek"
 Prev = "Föregående"
@@ -874,7 +879,12 @@ Sensor Image = "Fjärranalysbild"
 Serial = "Periodisk publikation"
 Series = "Serie"
 Set = "Justera"
-Showing = "Visas"
+showing_items_html = "Visas resultat <strong>%%start%% - %%end%%</strong>"
+showing_items_of_html = "Visas <strong>%%start%% - %%end%%</strong> av <strong>%%total%%</strong> resultat"
+showing_results_for_html = "Visas resultat <strong>%%start%% - %%end%%</strong> för sökning '<strong>%%lookfor%%</strong>'"
+showing_results_html = "Visas resultat <strong>%%start%% - %%end%%</strong>"
+showing_results_of_for_html = "Visas <strong>%%start%% - %%end%%</strong> av <strong>%%total%%</strong> resultat för sökning '<strong>%%lookfor%%</strong>'"
+showing_results_of_html = "Visas <strong>%%start%% - %%end%%</strong> av <strong>%%total%%</strong> resultat"
 sidebar_close = "Kollaps sidpanelen"
 sidebar_expand = "Expandera sidpanelen"
 Similar Items = "Liknande verk"
@@ -918,7 +928,7 @@ storage_retrieval_request_cancel_all = "Annullera alla beställningar"
 storage_retrieval_request_cancel_fail = "Din beställning annullerades inte. Kontakta kundtjänst."
 storage_retrieval_request_cancel_selected = "Annullera valda beställningar"
 storage_retrieval_request_cancel_success = "Beställningen har annullerats"
-storage_retrieval_request_cancel_success_items = "beställning(ar) har annullerats"
+storage_retrieval_request_cancel_success_items = "%%count%% beställning(ar) har annullerats"
 storage_retrieval_request_canceled = "Annullerad"
 storage_retrieval_request_check_text = "Kolla magasinsbeställning"
 storage_retrieval_request_comments = "Tilläggsuppgifter"
@@ -956,7 +966,7 @@ Summon Results = "Summon-resultat"
 summon_database_recommendations = "Mer material eventuellt tillgängligt:"
 Supplements = "Supplement"
 Supplied by Amazon = "Levererad av Amazon"
-Switch view to = "Växla vyn till"
+switch_view = "Växla vyn till %%view%%"
 switchquery_fuzzy = "En ungefärlig sökning kan hämta termer med liknande stavning"
 switchquery_intro = "Du kanske kan få fler resultat genom att justera din sökfråga."
 switchquery_lowercasebools = "Om du försöker använda booleska operatorer, måste de skrivas med VERSALER"
@@ -998,8 +1008,7 @@ Too Many Email Recipients = "För många e-postmottagare"
 too_many_favorites = "Hela listan kan inte visas på en gång p.g.a. dess storlek. Dela upp dina favoriter på flera listor eller begränsa sökningen genom att använda taggar."
 too_many_new_items = "Alla nyheter kan inte visas på en lista. Pröva att begränsa sökningen."
 too_many_reserves = "Alla kursböcker kan inte visas på en lista. Pröva att begränsa sökningen."
-top_facet_additional_prefix = "Lägg till"
-top_facet_suffix = ""
+top_facet_label = "%%label%%"
 Topic = "Tema"
 Topics = "Teman"
 Total Balance Due = "Totalt restskuld"
@@ -1028,7 +1037,6 @@ VHS = "VHS"
 Video = "Video"
 Video Clips = "Videoklipp"
 Videos = "Videor"
-view already selected = "visa valda"
 View Book Bag = "Visa bokkorgen"
 View Full Collection = "Visa hel samlingen"
 View Full Record = "Visa hela posten"
@@ -1037,6 +1045,7 @@ View online: Full view Book Preview from the Hathi Trust = "Tillgänglig på nä
 View Record = "Visa posten"
 View Records = "Visa posterna"
 View this record in EBSCOhost = "Visa denna post i EBSCOhost"
+view_already_selected = "%%current%% (vald)"
 visual_facet_parent = "Från"
 Volume = "Volym"
 Volume Holdings = "Tillgängliga nummer"
diff --git a/languages/tr.ini b/languages/tr.ini
index b7014ed6849f2fa05660805209e584721777993b..7f105168e2f13fc6ebf064edec2f1ef2de9ef5a1 100644
--- a/languages/tr.ini
+++ b/languages/tr.ini
@@ -17,7 +17,7 @@ Access URL = "EriÅŸim Adresi URL"
 access_denied = "Giriþ engellendi."
 Accession Number = "Aksesiyon No"
 Account = "Hesap"
-Add = "Ekle"
+account_block_options_missing = "Hesabınızdaki bir engel nedeniyle bazı seçenekler kaldırıldı. Detaylar: %%details%%"
 Add a Library Card = "Kütüphane Kartı Ekle"
 Add a Note = "Not Ekle"
 Add Tag = "Etiketle"
@@ -29,8 +29,6 @@ Add your comment = "Yorum Ekle"
 add_comment_fail_blank = "Yorum boÅŸ olamaz."
 add_comment_success = "Yorum eklendi."
 add_favorite_fail = "Favori Ekleme Hatası"
-add_favorite_prefix = "Ekle"
-add_favorite_suffix = "Favorilere"
 add_list_fail = "Liste Ekleme Hatası"
 add_other_libraries = "Diğer Kütüphane Ekleme Hatası"
 add_search = "Tarama Alanı Ekle"
@@ -38,6 +36,7 @@ add_search_group = "Tarama Grubu Ekle"
 add_tag_error = "Etiket Ekleme Hatası"
 add_tag_note = "Etiket Notu Ekle"
 add_tag_success = "Etiket Ekleme Başarılı"
+add_to_favorites_html = "Ekle <em>%%title%%</em> Favorilere"
 Address = "Adres"
 adv_search_all = "Tüm Alanlar"
 adv_search_author = "Yazar"
@@ -183,6 +182,10 @@ Catalog Results = "Katalog Sonucu"
 catalog_login_desc = "Kütüphane katalog kimlik bilgilerinizi giriniz."
 CD = "CD"
 Change Password = "Åžifre DeÄŸiÅŸtir"
+channel_add_more = "Bunun gibi daha fazla kanal ekleyin"
+channel_expand = "İlgili kanalları keşfedin"
+channel_explore = "Kanalları Keşfedin"
+channel_search = "Öğeleri arama sonuçları olarak göster"
 Check Hold = "Ayrılmışları Kontrol Et"
 Check Recall = "Ä°adeleri Kontrol Et"
 Checked Out = "Ödünçte"
@@ -233,7 +236,6 @@ confirm_ill_request_cancel_selected_text = "Seçtiğiniz kütüphaneler arası 
 confirm_new_password = "Yeni Åžifreyi Onayla"
 confirm_storage_retrieval_request_cancel_all_text = "Tüm güncel depo alma isteklerini iptal etmek istiyor musunuz?"
 confirm_storage_retrieval_request_cancel_selected_text = "Seçmiş olduğunuz depo alam isteklerini iptal etmek istiyor musunuz?"
-conjunction_or = "Veya"
 Contents = "İçindekiler"
 Contributing Source = "Katkıda Bulunan Kaynak"
 Contributors = "DiÄŸer Yazarlar"
@@ -283,6 +285,7 @@ Displaying the top = "Üst gösteriliyor"
 Document Inspector = "Doküman Denetcisi"
 Document Type = "Doküman Türü"
 DOI = "DOI"
+doi_detected_html = "Aramanızın bir DOI içerdiği görülüyor. Kaynağın kullanılabilirliğini kontrol etmek için burayı tıklayın: <a href="%%url%%">%%doi%%</a>"
 Draw Search Box = "Arama Kutusu Düzenle"
 Due = "Ä°ade Tarihi"
 Due Date = "Ä°ade tarihi"
@@ -356,6 +359,10 @@ export_selected = "Aktarım seçildi"
 export_selected_favorites = "Seçilmiş Favorileri Aktar"
 export_success = "Aktarım Tamamlandı"
 export_unsupported_format = "Desteklenmeyen Aktarım Formatı"
+external_auth_heading = "Lisanslı materyale erişim"
+external_auth_login_message = "Lisanslı materyale erişmek için giriş yapın"
+external_auth_unauthorized = "Lisanslı materyale erişme yetkiniz yok"
+external_auth_unauthorized_desc = "Giriş yönteminiz lisanslı materyale erişim sağlamıyor. Lütfen çıkış yapın ve başka bir yöntem kullanarak giriş yapın."
 FAQs = "SSS"
 fav_delete = "Seçilmiş Favorileri Sil"
 fav_delete_deleting = "Favorileriniz silinecek."
@@ -393,7 +400,6 @@ for search = "sonuç. Aranan kelime"
 Forgot Password = "Åžifrenizi mi unuttunuz"
 Form Submitted! = "Formunuz Gönderildi!"
 Format = "Materyal Türü"
-found = "Bulundu"
 From = "den"
 Full description = "Ful tanımlama"
 Full text is not displayed to guests = "Tam metin misafirler için gösterilmez."
@@ -445,7 +451,7 @@ hold_cancel_all = "Tüm ayrılmışları iptal et"
 hold_cancel_fail = "İsteğiniz iptal edilmedi. Lütfen detayli bilgi için ödünç verme masasına başvurunuz."
 hold_cancel_selected = "Seçilmiş yayınları iptal et"
 hold_cancel_success = "İsteğiniz başarıyla iptal edildi"
-hold_cancel_success_items = "istek(ler) başarıyla iptal edildi"
+hold_cancel_success_items = "%%count%% istek(ler) başarıyla iptal edildi"
 hold_date_invalid = "Geçerli bir tarih giriniz"
 hold_date_past = "Gelecekte bir tarih giriniz"
 hold_empty_selection = "Hiç bir kayıt seçilmedi"
@@ -453,19 +459,21 @@ hold_error_blocked = "Bu materyali ödünç alma hakkınız yok. Lütfen detayli
 hold_error_fail = "İsteğiniz başarısız. Lütfen detayli bilgi için ödünç verme masasına başvurunuz."
 hold_invalid_pickup = "Geçersiz yer girildi. Lütfen tekrar deneyin"
 hold_invalid_request_group = "Geçersiz grup isteği girildi. Lütfen tekrar deneyin"
-hold_login = "Ayırın ve bilgileri tekrar çağırın"
+hold_items_available = "Öğeler mevcut olduğu için bekletme yapılamıyor."
+hold_login = "Giriş Ayırın ve bilgileri tekrar çağırın"
 hold_place = "Ä°stek yeri"
 hold_place_fail_missing = "İsteğiniz başarısız. Bazı veriler eksik. Lütfen detayli bilgi için ödünç verme masasına başvurunuz."
 hold_place_success_html = "İsteğiniz başarılı oldu. <a href="%%url%%">Rezerve Ettiğim Materyaller</a>."
 hold_profile_html = "Bilgileri saklamak ve hatırlamak için, lütfen <a href="%%url%%">kütüphane profiliniz ile bağlantı kurun</a>."
 hold_queue_position = "Sıra durumu"
+hold_record_already_on_loan = "Zaten bu kaydı ödünç almışsınız"
 hold_request_group = "Ä°stek Formu"
 hold_requested_group = "Talep"
 hold_required_by = "Artık gerekli değil"
 hold_success = "İsteğiniz başarılı oldu"
 Holdings = "EriÅŸim Bilgileri"
 Holdings at Other Libraries = "Diğer Kütüphanelerdeki Erişim Bilgileri"
-Holdings details from = "Detaylı Erişim Bilgileri"
+holdings_details_from = "Detaylı Erişim Bilgileri %%location%%"
 Holdings_notes = "Notlar"
 Holds = "Rezervelerim"
 Holds and Recalls = "Ayırma ve Hatırlama"
@@ -479,7 +487,7 @@ ill_request_cancel_all = "Tüm kütüphaneler arası ödünç alama isteklerini
 ill_request_cancel_fail = "İsteğiniz iptal edilmedi. Lütfen detayli bilgi için ödünç verme masasına başvurunuz."
 ill_request_cancel_selected = "Seçilmiş kütüphaneler arası ödünç alama isteklerini iptal et"
 ill_request_cancel_success = "İsteğiniz başarıyla iptal edildi"
-ill_request_cancel_success_items = "istek(ler) başarıyla iptal edildi"
+ill_request_cancel_success_items = "%%count%% istek(ler) başarıyla iptal edildi"
 ill_request_canceled = "Ä°ptal edildi"
 ill_request_check_text = "Kütüphaneler arası ödünç alama isteklerini kontrol et"
 ill_request_comments = "Yorumlar"
@@ -508,7 +516,6 @@ ils_offline_login_message = "Hesabınıza ait bilgiler şu anda erişilebilir de
 ils_offline_status = "Kütüphane sistemimiz bakımda."
 ils_offline_title = "Sistem Bakımda"
 Import Record = "Kaydı Al"
-Import to = "Ä°thal Et"
 in = "ile"
 In This Collection = "Bu Koleksiyonda"
 in_collection_label = "Koleksiyonda:"
@@ -536,8 +543,8 @@ Item removed from favorites = "Kayıt favorilerden silindi"
 Item removed from list = "Kayıt listeden silindi"
 Items = "Kayıtlar"
 items = "kayıt"
-items_added_to_bookbag = "Kayıt(lar) kitap sepetinize eklendi"
-items_already_in_bookbag = "Kayıt(lar) zaten kitap sepetinizde veya eklenemedi."
+items_added_to_bookbag = "%%count%% Kayıt(lar) kitap sepetinize eklendi"
+items_already_in_bookbag = "%%count%% Kayıt(lar) zaten kitap sepetinizde veya eklenemedi."
 Journal = "Dergi"
 Journal Articles = "Dergi Makalesi"
 Journal Info = "Süreli Yayın Bilgisi"
@@ -654,12 +661,11 @@ nohit_active_filters = "Bu arama için bir veya daha fazla faset filtresi uygula
 nohit_change_tab = ""%%activeTab%%" sekmesi içinde arama yapmaktasınız. Diğer sekmelerin birisi içinde bir şeyler bulabilirsiniz:"
 nohit_filters = "Bu taramaya uygulanan filtreler"
 nohit_heading = "Sonuç bulunamadı!"
+nohit_lookfor_html = "Taramanız - <strong>%%lookfor%%</strong> - herhangi bir kaynakla eşleşmedi."
 nohit_no_filters = "Hit yok Sıralama yok"
 nohit_parse_error = "nohit ayrıştırma hatası"
-nohit_prefix = "Taramanız"
 nohit_query_without_filters = "Bu aramadan tüm filtreleri kaldır."
 nohit_spelling = "Muhtemelen farklı yazım şekilleri denemelisiniz"
-nohit_suffix = "herhangi bir kaynakla eÅŸleÅŸmedi."
 nohit_suggest = "önerilen nohit"
 NOT = "DEĞİL"
 Not Illustrated = "Resimli DeÄŸil"
@@ -701,7 +707,7 @@ number_decimal_point = "."
 number_thousands_separator = ","
 OAI Server = "OAI Sunucu"
 Occupation = "Meslek"
-of = "arası kayıtlar."
+of_num_results = "#%%position%% arası kayıtlar. %%total%% sonuçlar"
 old_password = "Eski Åžifre"
 On Reserve = "Rezerve"
 On Reserve - Ask at Circulation Desk = "Rezerve için, Ödünç Verme Masasına Başvurunuz"
@@ -709,6 +715,7 @@ on_reserve = "Tezerve EdilmiÅŸ"
 on_topic = "%%count%% konuyla ilgili madde(ler)"
 Online Access = "Online EriÅŸim"
 online_resources = "Tam Metin"
+open_access_limit = "Açık Erişim içeriği sınırı"
 operator_contains = "kapsar"
 operator_exact = "tam"
 OR = "YADA"
@@ -747,8 +754,6 @@ Please check back soon = "Daha sonra tekrar kontrol ediniz"
 Please contact the Library Reference Department for assistance = "Sistem sorumlusuna e-posta yolla"
 Please enable JavaScript. = "Lütfen JavaScripti etkinlestirin."
 Please upgrade your browser. = "Lütfen tarayıcınızı güncelleyin."
-Posted by = "Gönderildi"
-posted_on = "on"
 Preferences = "Tercihler"
 Preferred Library = "Tercih Edilen Kütüphane"
 Prev = "Önceki"
@@ -884,7 +889,12 @@ Sensor Image = "Sensör Resmi"
 Serial = "Süreli"
 Series = "Seri Bilgileri"
 Set = "Set"
-Showing = "Gösterilen"
+showing_items_html = "Gösterilen <strong>%%start%% - %%end%%</strong> Kayıtlar"
+showing_items_of_html = "Gösterilen <strong>%%start%% - %%end%%</strong> arası kayıtlar. <strong>%%total%%</strong> Kayıtlar"
+showing_results_for_html = "Gösterilen <strong>%%start%% - %%end%%</strong> sonuçlar sonuç. Aranan kelime '<strong>%%lookfor%%</strong>'"
+showing_results_html = "Gösterilen <strong>%%start%% - %%end%%</strong> sonuçlar"
+showing_results_of_for_html = "Gösterilen <strong>%%start%% - %%end%%</strong> sonuçlar arası kayıtlar. <strong>%%total%%</strong> sonuç. Aranan kelime '<strong>%%lookfor%%</strong>'"
+showing_results_of_html = "Gösterilen <strong>%%start%% - %%end%%</strong> sonuçlar arası kayıtlar. <strong>%%total%%</strong>"
 sidebar_close = "Kenar Çubuğunu Daralt"
 sidebar_expand = "Kenar Çubuğunu Genişlet"
 Similar Items = "Benzer Materyaller"
@@ -928,7 +938,7 @@ storage_retrieval_request_cancel_all = "Tüm Depolama Alma İsteklerini İptal"
 storage_retrieval_request_cancel_fail = "İsteğiniz iptal edilmedi. Lütfen detayli bilgi için ödünç verme masasına başvurunuz."
 storage_retrieval_request_cancel_selected = "Seçilmiş Depolama Alma İstekleri İptal Et"
 storage_retrieval_request_cancel_success = "İsteğiniz başarıyla iptal edildi"
-storage_retrieval_request_cancel_success_items = "istek(ler) başarıyla iptal edildi"
+storage_retrieval_request_cancel_success_items = "%%count%% istek(ler) başarıyla iptal edildi"
 storage_retrieval_request_canceled = "Ä°ptal edildi"
 storage_retrieval_request_check_text = "Depolama Alma Ä°steklerini Kontrol Edin"
 storage_retrieval_request_comments = "Yorumlar"
@@ -966,7 +976,7 @@ Summon Results = "Alıntı Sonuçları"
 summon_database_recommendations = "Burada ek kaynaklar bulabilirsiniz:"
 Supplements = "Ekler"
 Supplied by Amazon = "Amazon tarafından sağlandı"
-Switch view to = "Görünüm için"
+switch_view = "Görünüm için %%view%%"
 switchquery_fuzzy = "Bulanık arama yapılarak benzer yazımlı terimler elde dilebilir"
 switchquery_intro = "Tarama sorgunuzu ayarlayarak daha fazla sonuca eriþmeniz mümkün olabilir."
 switchquery_lowercasebools = "Eðer Boolean operatörlerini kullanýyorsanýz, onlar büyük harfle yazýlmalýdýr."
@@ -1008,8 +1018,7 @@ Too Many Email Recipients = "Çok fazla eposta alıcısı"
 too_many_favorites = "Liste bir seferde gösterim için çok büyük. Favori listenizi birden fazla liste için yeniden düzenleyin veya etiketleri kullanarak sınırlayın."
 too_many_new_items = "Tek bir listede görüntülemek için çok fazla sayıda kayıt var. Aramanızı sınırlandırın."
 too_many_reserves = "Tek bir liste görüntülemek için çok sayıda kurs rezervleri vardır. Aramanızı sınırlandırın."
-top_facet_additional_prefix = "DiÄŸer "
-top_facet_suffix = "..."
+top_facet_label = "%%label%%"
 Topic = "Konu (Topic)"
 Topics = "Konular"
 Total Balance Due = "Toplam Borç Bakiyesi"
@@ -1038,7 +1047,6 @@ VHS = "VHS"
 Video = "Video"
 Video Clips = "Video Klibi"
 Videos = "Video"
-view already selected = "Seçilmişi göster"
 View Book Bag = "Kitap Sepetini Göster"
 View Full Collection = "Tüm Koleksiyonu Görüntüle"
 View Full Record = "Tam Kayıt Görüntüle"
@@ -1047,6 +1055,7 @@ View online: Full view Book Preview from the Hathi Trust = "Online Görünüm: H
 View Record = "Kayıt Görüntüle"
 View Records = "Kayıtları Göster"
 View this record in EBSCOhost = "Bu Kaydı EBSCOhostda Görüntüle"
+view_already_selected = "%%current%% Seçilmişi göster"
 visual_facet_parent = "den"
 Volume = "Volüm"
 Volume Holdings = "Cilt EriÅŸim Bilgileri"
diff --git a/languages/zh-cn.ini b/languages/zh-cn.ini
index 26c7c0168a7363b56514b7d65e2183cfb202a8c4..cd7407932f442aae54f7fec0db393b119d717f5a 100644
--- a/languages/zh-cn.ini
+++ b/languages/zh-cn.ini
@@ -3,7 +3,6 @@
 ;Simplified Chinese = "中文(简体)"
 Access = "访问"
 Account = "帐户"
-Add = "添加"
 Add a Note = "添加注释"
 Add Tag = "添加标签"
 Add Tags = "添加标签"
@@ -11,8 +10,6 @@ Add to Book Bag = "添加到书包"
 Add to favorites = "加到收藏夹"
 Add your comment = "添加您的评论"
 add_favorite_fail = "错误:记录还没有保存"
-add_favorite_prefix = "加到"
-add_favorite_suffix = "我的最爱"
 add_list_fail = "错误:未创建清单"
 add_other_libraries = "包括其他图书馆的文章"
 add_search = "添加搜索字段"
@@ -20,6 +17,7 @@ add_search_group = "添加搜索组"
 add_tag_error = "错误:无法保存标签"
 add_tag_note = "空格会分离标记。多字标记请使用引号."
 add_tag_success = "标签已保存"
+add_to_favorites_html = "加到 <em>%%title%%</em> 我的最爱"
 Address = "地址"
 adv_search_all = "所有字段"
 adv_search_author = "笔者关键字"
@@ -254,7 +252,6 @@ Fines = "罚款"
 First Name = "名"
 for search = "用于搜索"
 Format = "格式"
-found = "找到"
 From = "来自"
 Full description = "全面介绍"
 fulltext_limit = "限制全文可用的文章"
@@ -292,14 +289,14 @@ hold_cancel_all = "取消所有预定"
 hold_cancel_fail = "您的请求没有被取消,请联系进一步援助的流通服务台"
 hold_cancel_selected = "取消已选择预定"
 hold_cancel_success = "预定取消成功"
-hold_cancel_success_items = "预定取消成功"
+hold_cancel_success_items = "%%count%% 预定取消成功"
 hold_date_invalid = "请输入一个有效的日期"
 hold_date_past = "请输入一个将来的日期"
 hold_empty_selection = "没有选择预定"
 hold_error_blocked = "您没有足够的权限预定这个项目"
 hold_error_fail = "您的请求失败,请联系流通服务台"
 hold_invalid_pickup = "您输入的领取地址无效,请再试一次"
-hold_login = "预定和召回信息"
+hold_login = "登录 预定和召回信息"
 hold_place = "提交请求"
 hold_place_fail_missing = "您的请求失败。一些可能数据缺失,请联系流通服务台"
 hold_place_success_html = "您的预定成功. <a href="%%url%%">您的预约和召回</a>."
@@ -308,7 +305,7 @@ hold_required_by = "预定保留至"
 hold_success = "您的请求成功"
 Holdings = "持有资料"
 Holdings at Other Libraries = "其他图书馆持有资料"
-Holdings details from = "持有资料详情"
+holdings_details_from = "持有资料详情 %%location%%"
 Holdings_notes = "提示"
 Holds = "持有"
 Holds and Recalls = "持有和召回"
@@ -317,7 +314,7 @@ home_browse = "浏览"
 ill_request_available = "可以领取"
 ill_request_cancel_fail = "您的请求没有被取消,请联系进一步援助的流通服务台"
 ill_request_cancel_success = "预定取消成功"
-ill_request_cancel_success_items = "预定取消成功"
+ill_request_cancel_success_items = "%%count%% 预定取消成功"
 ill_request_date_invalid = "请输入一个有效的日期"
 ill_request_date_past = "请输入一个将来的日期"
 ill_request_error_fail = "您的请求失败,请联系流通服务台"
@@ -326,7 +323,6 @@ ill_request_place_fail_missing = "您的请求失败。一些可能数据缺失
 ill_request_place_success = "您的预定成功"
 Illustrated = "插图"
 Import Record = "输入记录"
-Import to = "输入到"
 in = "在"
 Institution = "机构"
 Institutional Login = "机构登录"
@@ -342,8 +338,8 @@ Issue = "发布"
 Item Description = "Item Description"
 Item Notes = "提示"
 items = "items"
-items_added_to_bookbag = "添加到您的书包"
-items_already_in_bookbag = "或是已经在您的书包或无法添加"
+items_added_to_bookbag = "%%count%% 添加到您的书包"
+items_already_in_bookbag = "%%count%% 或是已经在您的书包或无法添加"
 Journal = "杂志"
 Journal Articles = "“杂志文章“"
 Journal Title = "期刊标题"
@@ -415,11 +411,10 @@ no_description = "无描述."
 no_items_selected = "没有被选定的项目"
 nohit_filters = "目前应用于此搜索的过滤器:"
 nohit_heading = "没有结果!"
+nohit_lookfor_html = "你的搜索 - <strong>%%lookfor%%</strong> - 没有匹配的资源。"
 nohit_no_filters = "这个搜索没有用到过滤器."
 nohit_parse_error = "你的搜索查询似乎有问题。请检查语法。如果你不想用先进搜索功能,把查询放在双引号内可能有帮助."
-nohit_prefix = "你的搜索"
 nohit_spelling = "也许你应该尝试一些拼写变化"
-nohit_suffix = "没有匹配的资源。"
 nohit_suggest = "你可能需要修改你的搜索短语,删除一些单词或检查您的拼写是否正确。"
 NOT = "æ— "
 Not Illustrated = "无插图"
@@ -440,7 +435,6 @@ note_780_5 = "留存"
 note_785_0 = "后续"
 Notes = "提示"
 Number = "æ•°"
-of = "of"
 On Reserve = "在储备"
 On Reserve - Ask at Circulation Desk = "在储备-请到流通服务台询问"
 on_reserve = "储备 -请到流通部询问"
@@ -465,8 +459,6 @@ Place a Hold = "预订"
 Playing Time = "播放时间"
 Please check back soon = "请稍候再来"
 Please contact the Library Reference Department for assistance = "请联系图书馆参考部"
-Posted by = "发布者"
-posted_on = "on"
 Prev = "前一个"
 Previous Title = "上一标题"
 Print = "打印"
@@ -548,7 +540,6 @@ Sensor Image = "传感器图像"
 Serial = "序列"
 Series = "丛编"
 Set = "集"
-Showing = "显示"
 Similar Items = "相似书籍"
 Slide = "幻灯片"
 sms_failure = "错误!无法发送邮件."
@@ -578,7 +569,7 @@ Status = "状态"
 storage_retrieval_request_available = "可以领取"
 storage_retrieval_request_cancel_fail = "您的请求没有被取消,请联系进一步援助的流通服务台"
 storage_retrieval_request_cancel_success = "预定取消成功"
-storage_retrieval_request_cancel_success_items = "预定取消成功"
+storage_retrieval_request_cancel_success_items = "%%count%% 预定取消成功"
 storage_retrieval_request_comments = "您的评论"
 storage_retrieval_request_date_invalid = "请输入一个有效的日期"
 storage_retrieval_request_date_past = "请输入一个将来的日期"
@@ -598,7 +589,7 @@ Summary = "总结"
 Summon Results = "召唤结果"
 summon_database_recommendations = "你可以在这里找到更多的资源:"
 Supplied by Amazon = "由 Amazon提供"
-Switch view to = "切换到"
+switch_view = "切换到 %%view%%"
 System Unavailable = "系统无法使用"
 Table of Contents = "书本目录"
 Table of Contents unavailable = "目录不存在"
@@ -619,8 +610,7 @@ To = "到"
 too_many_favorites = "“所列项目太多,不能一次显示。所有尝试重新安排多个收藏夹或限制使用标签"
 too_many_new_items = "搜索结果数目太多,不能一次显示。重新用多个限制搜索"
 too_many_reserves = "搜索课程的数目太多,不能一次显示。重新用多个限制搜索"
-top_facet_additional_prefix = "其他"
-top_facet_suffix = "在您的搜寻… "
+top_facet_label = "在您的搜寻 %%label%%"
 Topic = "主题"
 Topics = "主题"
 University Library = "大学图书馆"
@@ -634,10 +624,10 @@ VHS = "VHS"
 Video = "影片"
 Video Clips = "影片剪辑"
 Videos = "影片"
-view already selected = "查看已有选项"
 View Book Bag = "查看书袋"
 View online: Full view Book Preview from the Hathi Trust = "在线观看:从Hathi信托基金完整图书预览"
 View Records = "查看记录"
+view_already_selected = "%%current%% 查看已有选项"
 visual_facet_parent = "来自"
 Volume = "卷"
 Volume Holdings = "卷数"
diff --git a/languages/zh.ini b/languages/zh.ini
index ca7f776600d15382ccfcc51ff2abafb0690d78f8..bd871b1b9adba2b989bc7e7cff35c532b022b5f6 100644
--- a/languages/zh.ini
+++ b/languages/zh.ini
@@ -3,7 +3,6 @@
 ;note_785_7 = "合併到" ; incomplete translation (en.ini was later revised)
 Access = "訪問"
 Account = "帳戶"
-Add = "添加"
 Add a Note = "添加注釋"
 Add Tag = "添加標簽"
 Add Tags = "添加標簽"
@@ -11,8 +10,6 @@ Add to Book Bag = "添加到書包"
 Add to favorites = "加到收藏夾"
 Add your comment = "添加您的評論"
 add_favorite_fail = "錯誤:記錄還沒有保存"
-add_favorite_prefix = "加到"
-add_favorite_suffix = "我的最愛"
 add_list_fail = "錯誤:未創建清單"
 add_other_libraries = "包括其他圖書館的文章"
 add_search = "添加搜索字段"
@@ -20,6 +17,7 @@ add_search_group = "添加搜索組"
 add_tag_error = "錯誤:無法保存標簽"
 add_tag_note = "空格會分離標記。多字標記請使用引號."
 add_tag_success = "標簽已保存"
+add_to_favorites_html = "加到 <em>%%title%%</em> 我的最愛"
 Address = "地址"
 adv_search_all = "所有字段"
 adv_search_author = "筆者關鍵字"
@@ -254,7 +252,6 @@ Fines = "罰款"
 First Name = "名"
 for search = "用於搜索"
 Format = "格式"
-found = "找到"
 From = "來自"
 Full description = "全面介紹"
 fulltext_limit = "限制全文可用的文章"
@@ -292,14 +289,14 @@ hold_cancel_all = "取消所有預定"
 hold_cancel_fail = "您的請求沒有被取消,請聯繫進一步援助的流通服務台"
 hold_cancel_selected = "取消已選擇預定"
 hold_cancel_success = "預定取消成功"
-hold_cancel_success_items = "預定取消成功"
+hold_cancel_success_items = "%%count%% 預定取消成功"
 hold_date_invalid = "請輸入一個有效的日期"
 hold_date_past = "請輸入一個將來的日期"
 hold_empty_selection = "沒有選擇預定"
 hold_error_blocked = "您沒有足夠的權限預定這個項目"
 hold_error_fail = "您的請求失敗,請聯繫流通服務台"
 hold_invalid_pickup = "您輸入的領取地址無效,請再試一次"
-hold_login = "預定和召回信息"
+hold_login = "登錄 預定和召回信息"
 hold_place = "提交請求"
 hold_place_fail_missing = "您的請求失敗。一些可能數據缺失,請聯繫流通服務台"
 hold_place_success_html = "您的預定成功. <a href="%%url%%">您的預約和召回</a>."
@@ -308,7 +305,7 @@ hold_required_by = "預定保留至"
 hold_success = "您的請求成功"
 Holdings = "持有資料"
 Holdings at Other Libraries = "其他圖書館持有資料"
-Holdings details from = "持有資料詳情"
+holdings_details_from = "持有資料詳情 %%location%%"
 Holdings_notes = "提示"
 Holds = "持有"
 Holds and Recalls = "持有和召回"
@@ -317,7 +314,7 @@ home_browse = "瀏覽"
 ill_request_available = "可以領取"
 ill_request_cancel_fail = "您的請求沒有被取消,請聯繫進一步援助的流通服務台"
 ill_request_cancel_success = "預定取消成功"
-ill_request_cancel_success_items = "預定取消成功"
+ill_request_cancel_success_items = "%%count%% 預定取消成功"
 ill_request_date_invalid = "請輸入一個有效的日期"
 ill_request_date_past = "請輸入一個將來的日期"
 ill_request_error_fail = "您的請求失敗,請聯繫流通服務台"
@@ -326,7 +323,6 @@ ill_request_place_fail_missing = "您的請求失敗。一些可能數據缺失
 ill_request_place_success = "您的預定成功"
 Illustrated = "插圖"
 Import Record = "輸入記錄"
-Import to = "輸入到"
 in = "在"
 Institution = "機構"
 Institutional Login = "機構登錄"
@@ -342,8 +338,8 @@ Issue = "發布"
 Item Description = "Item Description"
 Item Notes = "提示"
 items = "items"
-items_added_to_bookbag = "添加到您的書包"
-items_already_in_bookbag = "或是已經在您的書包或無法添加"
+items_added_to_bookbag = "%%count%% 添加到您的書包"
+items_already_in_bookbag = "%%count%% 或是已經在您的書包或無法添加"
 Journal = "雜誌"
 Journal Articles = "“雜誌文章“"
 Journal Title = "期刊標題"
@@ -415,11 +411,10 @@ no_description = "無描述."
 no_items_selected = "沒有被選定的項目"
 nohit_filters = "目前應用於此搜索的過濾器:"
 nohit_heading = "沒有結果!"
+nohit_lookfor_html = "你的搜索 - <strong>%%lookfor%%</strong> - 沒有匹配的資源。"
 nohit_no_filters = "這個搜索沒有用到過濾器."
 nohit_parse_error = "你的搜索查詢似乎有問題。請檢查語法。如果你不想用先進搜索功能,把查詢放在雙引號內可能有幫助."
-nohit_prefix = "你的搜索"
 nohit_spelling = "也許你應該嘗試一些拼寫變化"
-nohit_suffix = "沒有匹配的資源。"
 nohit_suggest = "你可能需要修改你的搜索短語,刪除一些單詞或檢查您的拼寫是否正確。"
 NOT = "ç„¡"
 Not Illustrated = "無插圖"
@@ -440,7 +435,6 @@ note_780_5 = "留存"
 note_785_0 = "後續"
 Notes = "提示"
 Number = "數"
-of = "of"
 On Reserve = "在儲備"
 On Reserve - Ask at Circulation Desk = "在儲備-請到流通服務台詢問"
 on_reserve = "儲備 -請到流通部詢問"
@@ -465,8 +459,6 @@ Place a Hold = "預訂"
 Playing Time = "播放時間"
 Please check back soon = "請稍候再來"
 Please contact the Library Reference Department for assistance = "請聯系圖書館參考部"
-Posted by = "發布者"
-posted_on = "on"
 Prev = "前一個"
 Previous Title = "上一標題"
 Print = "打印"
@@ -548,7 +540,6 @@ Sensor Image = "傳感器圖像"
 Serial = "序列"
 Series = "叢編"
 Set = "集"
-Showing = "顯示"
 Similar Items = "相似書籍"
 Slide = "幻燈片"
 sms_failure = "錯誤!無法發送郵件."
@@ -578,7 +569,7 @@ Status = "狀態"
 storage_retrieval_request_available = "可以領取"
 storage_retrieval_request_cancel_fail = "您的請求沒有被取消,請聯繫進一步援助的流通服務台"
 storage_retrieval_request_cancel_success = "預定取消成功"
-storage_retrieval_request_cancel_success_items = "預定取消成功"
+storage_retrieval_request_cancel_success_items = "%%count%% 預定取消成功"
 storage_retrieval_request_comments = "您的評論"
 storage_retrieval_request_date_invalid = "請輸入一個有效的日期"
 storage_retrieval_request_date_past = "請輸入一個將來的日期"
@@ -598,7 +589,7 @@ Summary = "總結"
 Summon Results = "召喚結果"
 summon_database_recommendations = "你可以在這裡找到更多的資源:"
 Supplied by Amazon = "由 Amazon提供"
-Switch view to = "切換到"
+switch_view = "切換到 %%view%%"
 System Unavailable = "系統無法使用"
 Table of Contents = "書本目錄"
 Table of Contents unavailable = "目錄不存在"
@@ -619,8 +610,7 @@ To = "到"
 too_many_favorites = "“所列項目太多,不能一次顯示。所有嘗試重新安排多個收藏夾或限制使用標籤"
 too_many_new_items = "搜索結果數目太多,不能一次顯示。重新用多個限制搜索"
 too_many_reserves = "搜索課程的數目太多,不能一次顯示。重新用多個限制搜索"
-top_facet_additional_prefix = "其他"
-top_facet_suffix = "在您的搜尋… "
+top_facet_label = "在您的搜尋 %%label%%"
 Topic = "主題"
 Topics = "主題"
 University Library = "大學圖書館"
@@ -634,10 +624,10 @@ VHS = "VHS"
 Video = "影片"
 Video Clips = "影片剪輯"
 Videos = "影片"
-view already selected = "查看已有選項"
 View Book Bag = "查看書袋"
 View online: Full view Book Preview from the Hathi Trust = "在線觀看:從Hathi信托基金完整圖書預覽"
 View Records = "查看記錄"
+view_already_selected = "%%current%% 查看已有選項"
 visual_facet_parent = "來自"
 Volume = "卷"
 Volume Holdings = "卷數"
diff --git a/module/VuFind/config/module.config.php b/module/VuFind/config/module.config.php
index e727075792b9772e5cbbf2ecceb9503d1532c011..ad31de6c076b628e68555ee9570f130079973e45 100644
--- a/module/VuFind/config/module.config.php
+++ b/module/VuFind/config/module.config.php
@@ -18,6 +18,19 @@ $config = [
                     ],
                 ],
             ],
+            'content-page' => [
+                'type'    => 'Zend\Mvc\Router\Http\Segment',
+                'options' => [
+                    'route'    => '/Content/[:page]',
+                    'constraints' => [
+                        'page'     => '[a-zA-Z][a-zA-Z0-9_-]*',
+                    ],
+                    'defaults' => [
+                        'controller' => 'Content',
+                        'action'     => 'Content',
+                    ]
+                ],
+            ],
             'legacy-alphabrowse-results' => [
                 'type' => 'Zend\Mvc\Router\Http\Literal',
                 'options' => [
@@ -57,57 +70,90 @@ $config = [
                         'action'     => 'Home',
                     ]
                 ]
+            ],
+            'soap-shibboleth-logout-notification-handler' => [
+                'type' => 'Zend\Mvc\Router\Http\Literal',
+                'options' => [
+                    'route' => '/soap/shiblogout',
+                    'defaults' => [
+                        'controller' => 'ShibbolethLogoutNotification',
+                        'action' => 'index'
+                    ]
+                ],
+                'child_routes' => [
+                    'get' => [
+                        'type' => 'method',
+                        'options' => [
+                            'verb' => 'get',
+                            'defaults' => [
+                                'action' => 'get'
+                            ],
+                        ],
+                    ],
+                    'post' => [
+                        'type' => 'method',
+                        'options' => [
+                            'verb' => 'post',
+                            'defaults' => [
+                                'action' => 'post'
+                            ]
+                        ]
+                    ]
+                ]
             ]
         ],
     ],
     'controllers' => [
         'factories' => [
+            'ajax' => 'VuFind\Controller\Factory::getAjaxController',
+            'alphabrowse' => 'VuFind\Controller\Factory::getAlphabrowseController',
+            'author' => 'VuFind\Controller\Factory::getAuthorController',
+            'authority' => 'VuFind\Controller\Factory::getAuthorityController',
             'browse' => 'VuFind\Controller\Factory::getBrowseController',
             'cart' => 'VuFind\Controller\Factory::getCartController',
+            'channels' => 'VuFind\Controller\Factory::getChannelsController',
             'collection' => 'VuFind\Controller\Factory::getCollectionController',
             'collections' => 'VuFind\Controller\Factory::getCollectionsController',
+            'combined' => 'VuFind\Controller\Factory::getCombinedController',
+            'confirm' => 'VuFind\Controller\Factory::getConfirmController',
+            'content' => 'VuFind\Controller\Factory::getContentController',
+            'cover' => 'VuFind\Controller\Factory::getCoverController',
+            'eds' => 'VuFind\Controller\Factory::getEdsController',
+            'edsrecord' => 'VuFind\Controller\Factory::getEdsrecordController',
+            'eit' => 'VuFind\Controller\Factory::getEITController',
+            'eitrecord' => '\VuFind\Controller\Factory::getEITrecordController',
+            'error' => 'VuFind\Controller\Factory::getErrorController',
+            'externalauth' => 'VuFind\Controller\Factory::getExternalAuthController',
+            'feedback' => 'VuFind\Controller\Factory::getFeedbackController',
+            'help' => 'VuFind\Controller\Factory::getHelpController',
+            'hierarchy' => 'VuFind\Controller\Factory::getHierarchyController',
+            'index' => 'VuFind\Controller\Factory::getIndexController',
+            'install' => 'VuFind\Controller\Factory::getInstallController',
+            'libguides' => 'VuFind\Controller\Factory::getLibGuidesController',
+            'librarycards' => 'VuFind\Controller\Factory::getLibraryCardsController',
+            'missingrecord' => 'VuFind\Controller\Factory::getMissingrecordController',
+            'my-research' => 'VuFind\Controller\Factory::getMyResearchController',
+            'oai' => 'VuFind\Controller\Factory::getOaiController',
+            'pazpar2' => 'VuFind\Controller\Factory::getPazpar2Controller',
+            'primo' => 'VuFind\Controller\Factory::getPrimoController',
+            'primorecord' => 'VuFind\Controller\Factory::getPrimorecordController',
+            'qrcode' => 'VuFind\Controller\Factory::getQRCodeController',
             'record' => 'VuFind\Controller\Factory::getRecordController',
+            'records' => 'VuFind\Controller\Factory::getRecordsController',
+            'search' => 'VuFind\Controller\Factory::getSearchController',
+            'shibbolethlogoutnotification' => 'VuFind\Controller\Factory::getShibbolethLogoutNotificationController',
+            'summon' => 'VuFind\Controller\Factory::getSummonController',
+            'summonrecord' => 'VuFind\Controller\Factory::getSummonrecordController',
+            'tag' => 'VuFind\Controller\Factory::getTagController',
             'upgrade' => 'VuFind\Controller\Factory::getUpgradeController',
-        ],
-        'invokables' => [
-            'ajax' => 'VuFind\Controller\AjaxController',
-            'alphabrowse' => 'VuFind\Controller\AlphabrowseController',
-            'author' => 'VuFind\Controller\AuthorController',
-            'authority' => 'VuFind\Controller\AuthorityController',
-            'combined' => 'VuFind\Controller\CombinedController',
-            'confirm' => 'VuFind\Controller\ConfirmController',
-            'cover' => 'VuFind\Controller\CoverController',
-            'eds' => 'VuFind\Controller\EdsController',
-            'edsrecord' => 'VuFind\Controller\EdsrecordController',
-            'eit' => 'VuFind\Controller\EITController',
-            'eitrecord' => '\VuFind\Controller\EITrecordController',
-            'error' => 'VuFind\Controller\ErrorController',
-            'feedback' => 'VuFind\Controller\FeedbackController',
-            'help' => 'VuFind\Controller\HelpController',
-            'hierarchy' => 'VuFind\Controller\HierarchyController',
-            'index' => 'VuFind\Controller\IndexController',
-            'install' => 'VuFind\Controller\InstallController',
-            'libguides' => 'VuFind\Controller\LibGuidesController',
-            'librarycards' => 'VuFind\Controller\LibraryCardsController',
-            'missingrecord' => 'VuFind\Controller\MissingrecordController',
-            'my-research' => 'VuFind\Controller\MyResearchController',
-            'oai' => 'VuFind\Controller\OaiController',
-            'pazpar2' => 'VuFind\Controller\Pazpar2Controller',
-            'primo' => 'VuFind\Controller\PrimoController',
-            'primorecord' => 'VuFind\Controller\PrimorecordController',
-            'qrcode' => 'VuFind\Controller\QRCodeController',
-            'records' => 'VuFind\Controller\RecordsController',
-            'search' => 'VuFind\Controller\SearchController',
-            'summon' => 'VuFind\Controller\SummonController',
-            'summonrecord' => 'VuFind\Controller\SummonrecordController',
-            'tag' => 'VuFind\Controller\TagController',
-            'web' => 'VuFind\Controller\WebController',
-            'worldcat' => 'VuFind\Controller\WorldcatController',
-            'worldcatrecord' => 'VuFind\Controller\WorldcatrecordController',
+            'web' => 'VuFind\Controller\Factory::getWebController',
+            'worldcat' => 'VuFind\Controller\Factory::getWorldcatController',
+            'worldcatrecord' => 'VuFind\Controller\Factory::getWorldcatrecordController',
         ],
     ],
     'controller_plugins' => [
         'factories' => [
+            'favorites' => 'VuFind\Controller\Plugin\Factory::getFavorites',
             'flashmessenger' => 'VuFind\Controller\Plugin\Factory::getFlashMessenger',
             'followup' => 'VuFind\Controller\Plugin\Factory::getFollowup',
             'holds' => 'VuFind\Controller\Plugin\Factory::getHolds',
@@ -120,7 +166,6 @@ $config = [
         ],
         'invokables' => [
             'db-upgrade' => 'VuFind\Controller\Plugin\DbUpgrade',
-            'favorites' => 'VuFind\Controller\Plugin\Favorites',
             'renewals' => 'VuFind\Controller\Plugin\Renewals',
         ]
     ],
@@ -133,6 +178,7 @@ $config = [
             'VuFind\AutocompletePluginManager' => 'VuFind\Service\Factory::getAutocompletePluginManager',
             'VuFind\CacheManager' => 'VuFind\Service\Factory::getCacheManager',
             'VuFind\Cart' => 'VuFind\Service\Factory::getCart',
+            'VuFind\ChannelProviderPluginManager' => 'VuFind\Service\Factory::getChannelProviderPluginManager',
             'VuFind\Config' => 'VuFind\Service\Factory::getConfig',
             'VuFind\ContentPluginManager' => 'VuFind\Service\Factory::getContentPluginManager',
             'VuFind\ContentAuthorNotesPluginManager' => 'VuFind\Service\Factory::getContentAuthorNotesPluginManager',
@@ -144,8 +190,10 @@ $config = [
             'VuFind\DateConverter' => 'VuFind\Service\Factory::getDateConverter',
             'VuFind\DbAdapter' => 'VuFind\Service\Factory::getDbAdapter',
             'VuFind\DbAdapterFactory' => 'VuFind\Service\Factory::getDbAdapterFactory',
+            'VuFind\DbRowPluginManager' => 'VuFind\Service\Factory::getDbRowPluginManager',
             'VuFind\DbTablePluginManager' => 'VuFind\Service\Factory::getDbTablePluginManager',
             'VuFind\Export' => 'VuFind\Service\Factory::getExport',
+            'VuFind\Favorites\FavoritesService' => 'VuFind\Favorites\FavoritesServiceFactory',
             'VuFind\HierarchyDriverPluginManager' => 'VuFind\Service\Factory::getHierarchyDriverPluginManager',
             'VuFind\HierarchyTreeDataFormatterPluginManager' => 'VuFind\Service\Factory::getHierarchyTreeDataFormatterPluginManager',
             'VuFind\HierarchyTreeDataSourcePluginManager' => 'VuFind\Service\Factory::getHierarchyTreeDataSourcePluginManager',
@@ -158,7 +206,7 @@ $config = [
             'VuFind\ILSHoldLogic' => 'VuFind\Service\Factory::getILSHoldLogic',
             'VuFind\ILSHoldSettings' => 'VuFind\Service\Factory::getILSHoldSettings',
             'VuFind\ILSTitleHoldLogic' => 'VuFind\Service\Factory::getILSTitleHoldLogic',
-            'VuFind\Logger' => 'VuFind\Service\Factory::getLogger',
+            'VuFind\Logger' => 'VuFind\Log\LoggerFactory',
             'VuFind\Mailer' => 'VuFind\Mailer\Factory',
             'VuFind\ProxyConfig' => 'VuFind\Service\Factory::getProxyConfig',
             'VuFind\Recaptcha' => 'VuFind\Service\Factory::getRecaptcha',
@@ -167,10 +215,10 @@ $config = [
             'VuFind\RecordDriverPluginManager' => 'VuFind\Service\Factory::getRecordDriverPluginManager',
             'VuFind\RecordLoader' => 'VuFind\Service\Factory::getRecordLoader',
             'VuFind\RecordRouter' => 'VuFind\Service\Factory::getRecordRouter',
-            'VuFind\RecordStats' => 'VuFind\Service\Factory::getRecordStats',
             'VuFind\RecordTabPluginManager' => 'VuFind\Service\Factory::getRecordTabPluginManager',
             'VuFind\RelatedPluginManager' => 'VuFind\Service\Factory::getRelatedPluginManager',
             'VuFind\ResolverDriverPluginManager' => 'VuFind\Service\Factory::getResolverDriverPluginManager',
+            'VuFind\Search' => 'VuFind\Service\Factory::getSearchService',
             'VuFind\Search\BackendManager' => 'VuFind\Service\Factory::getSearchBackendManager',
             'VuFind\Search\Memory' => 'VuFind\Service\Factory::getSearchMemory',
             'VuFind\SearchOptionsPluginManager' => 'VuFind\Service\Factory::getSearchOptionsPluginManager',
@@ -178,21 +226,19 @@ $config = [
             'VuFind\SearchResultsPluginManager' => 'VuFind\Service\Factory::getSearchResultsPluginManager',
             'VuFind\SearchRunner' => 'VuFind\Service\Factory::getSearchRunner',
             'VuFind\SearchSpecsReader' => 'VuFind\Service\Factory::getSearchSpecsReader',
-            'VuFind\SearchStats' => 'VuFind\Service\Factory::getSearchStats',
             'VuFind\SearchTabsHelper' => 'VuFind\Service\Factory::getSearchTabsHelper',
             'VuFind\SessionManager' => 'VuFind\Session\ManagerFactory',
             'VuFind\SessionPluginManager' => 'VuFind\Service\Factory::getSessionPluginManager',
             'VuFind\SMS' => 'VuFind\SMS\Factory',
             'VuFind\Solr\Writer' => 'VuFind\Service\Factory::getSolrWriter',
-            'VuFind\StatisticsDriverPluginManager' => 'VuFind\Service\Factory::getStatisticsDriverPluginManager',
             'VuFind\Tags' => 'VuFind\Service\Factory::getTags',
             'VuFind\Translator' => 'VuFind\Service\Factory::getTranslator',
             'VuFind\WorldCatUtils' => 'VuFind\Service\Factory::getWorldCatUtils',
+            'VuFind\YamlReader' => 'VuFind\Service\Factory::getYamlReader',
         ],
         'invokables' => [
             'VuFind\HierarchicalFacetHelper' => 'VuFind\Search\Solr\HierarchicalFacetHelper',
             'VuFind\IpAddressUtils' => 'VuFind\Net\IpAddressUtils',
-            'VuFind\Search' => 'VuFindSearch\Service',
             'VuFind\Session\Settings' => 'VuFind\Session\Settings',
         ],
         'initializers' => [
@@ -225,18 +271,19 @@ $config = [
         ],
         // PostgreSQL sequence mapping
         'pgsql_seq_mapping'  => [
-            'comments'       => ['id', 'comments_id_seq'],
-            'oai_resumption' => ['id', 'oai_resumption_id_seq'],
-            'record'         => ['id', 'record_id_seq'],
-            'resource'       => ['id', 'resource_id_seq'],
-            'resource_tags'  => ['id', 'resource_tags_id_seq'],
-            'search'         => ['id', 'search_id_seq'],
-            'session'        => ['id', 'session_id_seq'],
-            'tags'           => ['id', 'tags_id_seq'],
-            'user'           => ['id', 'user_id_seq'],
-            'user_card'      => ['id', 'user_card_id_seq'],
-            'user_list'      => ['id', 'user_list_id_seq'],
-            'user_resource'  => ['id', 'user_resource_id_seq'],
+            'comments'         => ['id', 'comments_id_seq'],
+            'external_session' => ['id', 'external_session_id_seq'],
+            'oai_resumption'   => ['id', 'oai_resumption_id_seq'],
+            'record'           => ['id', 'record_id_seq'],
+            'resource'         => ['id', 'resource_id_seq'],
+            'resource_tags'    => ['id', 'resource_tags_id_seq'],
+            'search'           => ['id', 'search_id_seq'],
+            'session'          => ['id', 'session_id_seq'],
+            'tags'             => ['id', 'tags_id_seq'],
+            'user'             => ['id', 'user_id_seq'],
+            'user_card'        => ['id', 'user_card_id_seq'],
+            'user_list'        => ['id', 'user_list_id_seq'],
+            'user_resource'    => ['id', 'user_resource_id_seq'],
         ],
         // This section contains service manager configurations for all VuFind
         // pluggable components:
@@ -248,13 +295,13 @@ $config = [
                     'facebook' => 'VuFind\Auth\Factory::getFacebook',
                     'ils' => 'VuFind\Auth\Factory::getILS',
                     'multiils' => 'VuFind\Auth\Factory::getMultiILS',
+                    'shibboleth' => 'VuFind\Auth\Factory::getShibboleth'
                 ],
                 'invokables' => [
                     'cas' => 'VuFind\Auth\CAS',
                     'database' => 'VuFind\Auth\Database',
                     'ldap' => 'VuFind\Auth\LDAP',
                     'multiauth' => 'VuFind\Auth\MultiAuth',
-                    'shibboleth' => 'VuFind\Auth\Shibboleth',
                     'sip2' => 'VuFind\Auth\SIP2',
                 ],
                 'aliases' => [
@@ -287,6 +334,14 @@ $config = [
                     'tagautocomplete' => 'Tag',
                 ],
             ],
+            'channelprovider' => [
+                'factories' => [
+                    'facets' => 'VuFind\ChannelProvider\Factory::getFacets',
+                    'listitems' => 'VuFind\ChannelProvider\Factory::getListItems',
+                    'random' => 'VuFind\ChannelProvider\Factory::getRandom',
+                    'similaritems' => 'VuFind\ChannelProvider\Factory::getSimilarItems',
+                ]
+            ],
             'content' => [
                 'factories' => [
                     'authornotes' => 'VuFind\Content\Factory::getAuthorNotes',
@@ -317,6 +372,7 @@ $config = [
                 'invokables' => [
                     'google' => 'VuFind\Content\Covers\Google',
                     'librarything' => 'VuFind\Content\Covers\LibraryThing',
+                    'localfile' => 'VuFind\Content\Covers\LocalFile',
                     'openlibrary' => 'VuFind\Content\Covers\OpenLibrary',
                     'summon' => 'VuFind\Content\Covers\Summon',
                 ],
@@ -333,25 +389,41 @@ $config = [
                     'guardian' => 'VuFind\Content\Reviews\Guardian',
                 ],
             ],
+            'db_row' => [
+                'factories' => [
+                    'changetracker' => 'VuFind\Db\Row\Factory::getChangeTracker',
+                    'comments' => 'VuFind\Db\Row\Factory::getComments',
+                    'externalsession' => 'VuFind\Db\Row\Factory::getExternalSession',
+                    'oairesumption' => 'VuFind\Db\Row\Factory::getOaiResumption',
+                    'record' => 'VuFind\Db\Row\Factory::getRecord',
+                    'resource' => 'VuFind\Db\Row\Factory::getResource',
+                    'resourcetags' => 'VuFind\Db\Row\Factory::getResourceTags',
+                    'search' => 'VuFind\Db\Row\Factory::getSearch',
+                    'session' => 'VuFind\Db\Row\Factory::getSession',
+                    'tags' => 'VuFind\Db\Row\Factory::getTags',
+                    'user' => 'VuFind\Db\Row\Factory::getUser',
+                    'usercard' => 'VuFind\Db\Row\Factory::getUserCard',
+                    'userlist' => 'VuFind\Db\Row\Factory::getUserList',
+                    'userresource' => 'VuFind\Db\Row\Factory::getUserResource',
+                ],
+            ],
             'db_table' => [
                 'abstract_factories' => ['VuFind\Db\Table\PluginFactory'],
                 'factories' => [
+                    'changetracker' => 'VuFind\Db\Table\Factory::getChangeTracker',
+                    'comments' => 'VuFind\Db\Table\Factory::getComments',
+                    'externalsession' => 'VuFind\Db\Table\Factory::getExternalSession',
+                    'oairesumption' => 'VuFind\Db\Table\Factory::getOaiResumption',
+                    'record' => 'VuFind\Db\Table\Factory::getRecord',
                     'resource' => 'VuFind\Db\Table\Factory::getResource',
                     'resourcetags' => 'VuFind\Db\Table\Factory::getResourceTags',
+                    'search' => 'VuFind\Db\Table\Factory::getSearch',
+                    'session' => 'VuFind\Db\Table\Factory::getSession',
                     'tags' => 'VuFind\Db\Table\Factory::getTags',
                     'user' => 'VuFind\Db\Table\Factory::getUser',
+                    'usercard' => 'VuFind\Db\Table\Factory::getUserCard',
                     'userlist' => 'VuFind\Db\Table\Factory::getUserList',
-                ],
-                'invokables' => [
-                    'changetracker' => 'VuFind\Db\Table\ChangeTracker',
-                    'comments' => 'VuFind\Db\Table\Comments',
-                    'oairesumption' => 'VuFind\Db\Table\OaiResumption',
-                    'record' => 'VuFind\Db\Table\Record',
-                    'search' => 'VuFind\Db\Table\Search',
-                    'session' => 'VuFind\Db\Table\Session',
-                    'userresource' => 'VuFind\Db\Table\UserResource',
-                    'userstats' => 'VuFind\Db\Table\UserStats',
-                    'userstatsfields' => 'VuFind\Db\Table\UserStatsFields',
+                    'userresource' => 'VuFind\Db\Table\Factory::getUserResource',
                 ],
             ],
             'hierarchy_driver' => [
@@ -392,6 +464,7 @@ $config = [
                     'noils' => 'VuFind\ILS\Driver\Factory::getNoILS',
                     'paia' => 'VuFind\ILS\Driver\Factory::getPAIA',
                     'kohailsdi' => 'VuFind\ILS\Driver\Factory::getKohaILSDI',
+                    'symphony' => 'VuFind\ILS\Driver\Factory::getSymphony',
                     'unicorn' => 'VuFind\ILS\Driver\Factory::getUnicorn',
                     'voyager' => 'VuFind\ILS\Driver\Factory::getVoyager',
                     'voyagerrestful' => 'VuFind\ILS\Driver\Factory::getVoyagerRestful',
@@ -406,7 +479,6 @@ $config = [
                     'polaris' => 'VuFind\ILS\Driver\Polaris',
                     'sample' => 'VuFind\ILS\Driver\Sample',
                     'sierra' => 'VuFind\ILS\Driver\Sierra',
-                    'symphony' => 'VuFind\ILS\Driver\Symphony',
                     'virtua' => 'VuFind\ILS\Driver\Virtua',
                     'xcncip2' => 'VuFind\ILS\Driver\XCNCIP2',
                 ],
@@ -424,7 +496,6 @@ $config = [
                     'expandfacets' => 'VuFind\Recommend\Factory::getExpandFacets',
                     'favoritefacets' => 'VuFind\Recommend\Factory::getFavoriteFacets',
                     'mapselection' => 'VuFind\Recommend\Factory::getMapSelection',
-                    'resultgooglemapajax' => 'VuFind\Recommend\Factory::getResultGoogleMapAjax',
                     'sidefacets' => 'VuFind\Recommend\Factory::getSideFacets',
                     'randomrecommend' => 'VuFind\Recommend\Factory::getRandomRecommend',
                     'summonbestbets' => 'VuFind\Recommend\Factory::getSummonBestBets',
@@ -439,6 +510,8 @@ $config = [
                 ],
                 'invokables' => [
                     'alphabrowselink' => 'VuFind\Recommend\AlphaBrowseLink',
+                    'channels' => 'VuFind\Recommend\Channels',
+                    'doi' => 'VuFind\Recommend\DOI',
                     'europeanaresultsdeferred' => 'VuFind\Recommend\EuropeanaResultsDeferred',
                     'facetcloud' => 'VuFind\Recommend\FacetCloud',
                     'libraryh3lp' => 'VuFind\Recommend\Libraryh3lp',
@@ -446,6 +519,7 @@ $config = [
                     'openlibrarysubjectsdeferred' => 'VuFind\Recommend\OpenLibrarySubjectsDeferred',
                     'pubdatevisajax' => 'VuFind\Recommend\PubDateVisAjax',
                     'removefilters' => 'VuFind\Recommend\RemoveFilters',
+                    'resultgooglemapajax' => 'VuFind\Recommend\Deprecated',
                     'spellingsuggestions' => 'VuFind\Recommend\SpellingSuggestions',
                     'summonbestbetsdeferred' => 'VuFind\Recommend\SummonBestBetsDeferred',
                     'summondatabasesdeferred' => 'VuFind\Recommend\SummonDatabasesDeferred',
@@ -507,6 +581,7 @@ $config = [
                     'worldcatsimilar' => 'VuFind\Related\Factory::getWorldCatSimilar',
                 ],
                 'invokables' => [
+                    'channels' => 'VuFind\Related\Channels',
                     'editions' => 'VuFind\Related\Deprecated',
                     'worldcateditions' => 'VuFind\Related\Deprecated',
                 ],
@@ -536,7 +611,6 @@ $config = [
                     'Solr' => 'VuFind\Search\Factory\SolrDefaultBackendFactory',
                     'SolrAuth' => 'VuFind\Search\Factory\SolrAuthBackendFactory',
                     'SolrReserves' => 'VuFind\Search\Factory\SolrReservesBackendFactory',
-                    'SolrStats' => 'VuFind\Search\Factory\SolrStatsBackendFactory',
                     'SolrWeb' => 'VuFind\Search\Factory\SolrWebBackendFactory',
                     'Summon' => 'VuFind\Search\Factory\SummonBackendFactory',
                     'WorldCat' => 'VuFind\Search\Factory\WorldCatBackendFactory',
@@ -546,7 +620,6 @@ $config = [
                     'authority' => 'SolrAuth',
                     'biblio' => 'Solr',
                     'reserves' => 'SolrReserves',
-                    'stats' => 'SolrStats',
                     // Legacy:
                     'VuFind' => 'Solr',
                 ]
@@ -559,12 +632,16 @@ $config = [
             ],
             'search_params' => [
                 'abstract_factories' => ['VuFind\Search\Params\PluginFactory'],
+                'factories' => [
+                    'solr' => 'VuFind\Search\Params\Factory::getSolr',
+                ],
             ],
             'search_results' => [
                 'abstract_factories' => ['VuFind\Search\Results\PluginFactory'],
                 'factories' => [
                     'favorites' => 'VuFind\Search\Results\Factory::getFavorites',
                     'solr' => 'VuFind\Search\Results\Factory::getSolr',
+                    'tags' => 'VuFind\Search\Results\Factory::getTags',
                 ],
             ],
             'session' => [
@@ -580,20 +657,7 @@ $config = [
                     'memcachesession' => 'Memcache',
                     'mysqlsession' => 'Database',
                 ],
-            ],
-            'statistics_driver' => [
-                'abstract_factories' => ['VuFind\Statistics\Driver\PluginFactory'],
-                'factories' => [
-                    'file' => 'VuFind\Statistics\Driver\Factory::getFile',
-                    'solr' => 'VuFind\Statistics\Driver\Factory::getSolr',
-                ],
-                'invokables' => [
-                    'db' => 'VuFind\Statistics\Driver\Db',
-                ],
-                'aliases' => [
-                    'database' => 'db',
-                ],
-            ],
+            ]
         ],
         // This section behaves just like recorddriver_tabs below, but is used for
         // the collection module instead of the standard record view.
@@ -752,7 +816,9 @@ $staticRoutes = [
     'Browse/Author', 'Browse/Dewey', 'Browse/Era', 'Browse/Genre', 'Browse/Home',
     'Browse/LCC', 'Browse/Region', 'Browse/Tag', 'Browse/Topic', 'Cart/doExport',
     'Cart/Email', 'Cart/Export', 'Cart/Home', 'Cart/MyResearchBulk',
-    'Cart/Processor', 'Cart/Save', 'Cart/SearchResultsBulk', 'Collections/ByTitle',
+    'Cart/Processor', 'Cart/Save', 'Cart/SearchResultsBulk',
+    'Channels/Home', 'Channels/Record', 'Channels/Search',
+    'Collections/ByTitle',
     'Collections/Home', 'Combined/Home', 'Combined/Results', 'Combined/SearchBox',
     'Confirm/Confirm', 'Cover/Show', 'Cover/Unavailable',
     'EDS/Advanced', 'EDS/Home', 'EDS/Search',
diff --git a/module/VuFind/sql/migrations/pgsql/4.0/001-add-external-session-table.sql b/module/VuFind/sql/migrations/pgsql/4.0/001-add-external-session-table.sql
new file mode 100644
index 0000000000000000000000000000000000000000..4ebcb8f70d64cb1d6db674496b566a944114d66f
--- /dev/null
+++ b/module/VuFind/sql/migrations/pgsql/4.0/001-add-external-session-table.sql
@@ -0,0 +1,13 @@
+--
+-- Table structure for table external_session
+--
+
+CREATE TABLE external_session (
+id SERIAL,
+session_id varchar(128) NOT NULL,
+external_session_id varchar(255) NOT NULL,
+created timestamp NOT NULL default '1970-01-01 00:00:00',
+PRIMARY KEY (id),
+UNIQUE (session_id)
+);
+CREATE INDEX external_session_id on external_session(external_session_id);
diff --git a/module/VuFind/sql/migrations/pgsql/4.0/002-modify-user-columns.sql b/module/VuFind/sql/migrations/pgsql/4.0/002-modify-user-columns.sql
new file mode 100644
index 0000000000000000000000000000000000000000..72621b0eeb996ea58035edd3345fbd6a527bd2d9
--- /dev/null
+++ b/module/VuFind/sql/migrations/pgsql/4.0/002-modify-user-columns.sql
@@ -0,0 +1,8 @@
+--
+-- Modifications to table `user`
+--
+
+ALTER TABLE "user"
+  ADD COLUMN cat_id varchar(255);
+
+CREATE UNIQUE INDEX cat_id ON "user" (cat_id);
diff --git a/module/VuFind/sql/mysql.sql b/module/VuFind/sql/mysql.sql
index 9029d54fa5fb9bd72bc8e3b9efcb9b7c59c2e5ba..d00b13cd4fc96b6246a19cfc4e1c921b234dd72d 100644
--- a/module/VuFind/sql/mysql.sql
+++ b/module/VuFind/sql/mysql.sql
@@ -145,6 +145,23 @@ CREATE TABLE `session` (
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 /*!40101 SET character_set_client = @saved_cs_client */;
 
+--
+-- Table structure for table `external_session`
+--
+
+/*!40101 SET @saved_cs_client     = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `external_session` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `session_id` varchar(128) NOT NULL,
+  `external_session_id` varchar(255) NOT NULL,
+  `created` datetime NOT NULL DEFAULT '2000-01-01 00:00:00',
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `session_id` (`session_id`),
+  KEY `external_session_id` (`external_session_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
 --
 -- Table structure for table `tags`
 --
@@ -172,6 +189,7 @@ CREATE TABLE `user` (
   `firstname` varchar(50) NOT NULL DEFAULT '',
   `lastname` varchar(50) NOT NULL DEFAULT '',
   `email` varchar(255) NOT NULL DEFAULT '',
+  `cat_id` varchar(255) DEFAULT NULL,
   `cat_username` varchar(50) DEFAULT NULL,
   `cat_password` varchar(70) DEFAULT NULL,
   `cat_pass_enc` varchar(170) DEFAULT NULL,
@@ -181,7 +199,8 @@ CREATE TABLE `user` (
   `created` datetime NOT NULL DEFAULT '2000-01-01 00:00:00',
   `verify_hash` varchar(42) NOT NULL DEFAULT '',
   PRIMARY KEY (`id`),
-  UNIQUE KEY `username` (`username`)
+  UNIQUE KEY `username` (`username`),
+  UNIQUE KEY `cat_id` (`cat_id`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 /*!40101 SET character_set_client = @saved_cs_client */;
 
@@ -227,39 +246,6 @@ CREATE TABLE `user_resource` (
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 /*!40101 SET character_set_client = @saved_cs_client */;
 
---
--- Table structure for table `user_stats`
---
-
-/*!40101 SET @saved_cs_client     = @@character_set_client */;
-/*!40101 SET character_set_client = utf8 */;
-CREATE TABLE `user_stats` (
-  `id` varchar(24) NOT NULL,
-  `datestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
-  `browser` varchar(32) NOT NULL,
-  `browserVersion` varchar(8) NOT NULL,
-  `ipaddress` varchar(15) NOT NULL,
-  `referrer` varchar(512) NOT NULL,
-  `url` varchar(512) NOT NULL,
-  `session` varchar(64) NOT NULL,
-  PRIMARY KEY (`id`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-/*!40101 SET character_set_client = @saved_cs_client */;
-
---
--- Table structure for table `user_stats_fields`
---
-
-/*!40101 SET @saved_cs_client     = @@character_set_client */;
-/*!40101 SET character_set_client = utf8 */;
-CREATE TABLE `user_stats_fields` (
-  `id` varchar(24) NOT NULL,
-  `field` varchar(32) NOT NULL,
-  `value` varchar(1024) NOT NULL,
-  PRIMARY KEY (`id`,`field`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-/*!40101 SET character_set_client = @saved_cs_client */;
-
 --
 -- Table structure for table `user_card`
 --
diff --git a/module/VuFind/sql/pgsql.sql b/module/VuFind/sql/pgsql.sql
index 94b949066dd4225a0cd9d6419776ec9f0da65e4b..15a7a251e454c4f2343d8179148fb96afa81d75d 100644
--- a/module/VuFind/sql/pgsql.sql
+++ b/module/VuFind/sql/pgsql.sql
@@ -114,6 +114,7 @@ pass_hash varchar(60) DEFAULT NULL,
 firstname varchar(50) NOT NULL DEFAULT '',
 lastname varchar(50) NOT NULL DEFAULT '',
 email varchar(255) NOT NULL DEFAULT '',
+cat_id varchar(255) DEFAULT NULL,
 cat_username varchar(50) DEFAULT NULL,
 cat_password varchar(70) DEFAULT NULL,
 cat_pass_enc varchar(170) DEFAULT NULL,
@@ -123,7 +124,8 @@ home_library varchar(100) NOT NULL DEFAULT '',
 created timestamp NOT NULL DEFAULT '1970-01-01 00:00:00',
 verify_hash varchar(42) NOT NULL DEFAULT '',
 PRIMARY KEY (id),
-UNIQUE (username)
+UNIQUE (username),
+UNIQUE (cat_id)
 );
 
 
@@ -188,6 +190,22 @@ UNIQUE (session_id)
 );
 CREATE INDEX last_used_idx on session(last_used);
 
+--
+-- Table structure for table external_session
+--
+
+DROP TABLE IF EXISTS "external_session";
+
+CREATE TABLE external_session (
+id SERIAL,
+session_id varchar(128) NOT NULL,
+external_session_id varchar(255) NOT NULL,
+created timestamp NOT NULL default '1970-01-01 00:00:00',
+PRIMARY KEY (id),
+UNIQUE (session_id)
+);
+CREATE INDEX external_session_id on external_session(external_session_id);
+
 --
 -- Table structure for table change_tracker
 --
@@ -220,45 +238,6 @@ PRIMARY KEY (id)
 
 -- --------------------------------------------------------
 
---
--- Statistics tables
---
-
---
--- Table structure for table statistics
---
-
-DROP TABLE IF EXISTS "user_stats_fields";
-
-CREATE TABLE user_stats_fields (
-id varchar(24) NOT NULL,
-field varchar(32) NOT NULL,
-value varchar(1024) NOT NULL,
-PRIMARY KEY (id, field)
-);
-
--- --------------------------------------------------------
-
---
--- Table structure for table user_stats
---
-
-DROP TABLE IF EXISTS "user_stats";
-
-CREATE TABLE user_stats (
-id varchar(24) NOT NULL,
-datestamp timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
-browser varchar(32) NOT NULL,
-browserVersion varchar(8) NOT NULL,
-ipaddress varchar(15) NOT NULL,
-referrer varchar(512) NOT NULL,
-url varchar(512) NOT NULL,
-session varchar(64) NOT NULL,
-PRIMARY KEY (id)
-);
-
--- --------------------------------------------------------
-
 --
 -- Table structure for table record
 --
@@ -278,7 +257,7 @@ CREATE TABLE record (
 
 -- --------------------------------------------------------
 
--- 
+--
 -- Table structure for table user_card
 --
 
diff --git a/module/VuFind/src/VuFind/Auth/Factory.php b/module/VuFind/src/VuFind/Auth/Factory.php
index bf6740eed94173e3d3f27dfae0c67a3769e55b0b..28acc1ceb60ea6dabfc9db8044020ba317a7b712 100644
--- a/module/VuFind/src/VuFind/Auth/Factory.php
+++ b/module/VuFind/src/VuFind/Auth/Factory.php
@@ -167,4 +167,18 @@ class Factory
             $sm->getServiceLocator()->get('VuFind\ILSAuthenticator')
         );
     }
+
+    /**
+     * Construct the Shibboleth plugin.
+     *
+     * @param ServiceManager $sm Service manager.
+     *
+     * @return Shibboleth
+     */
+    public static function getShibboleth(ServiceManager $sm)
+    {
+        return new Shibboleth(
+            $sm->getServiceLocator()->get('VuFind\SessionManager')
+        );
+    }
 }
diff --git a/module/VuFind/src/VuFind/Auth/ILS.php b/module/VuFind/src/VuFind/Auth/ILS.php
index 5a0a05ebed69583985da9dc9071384a6e4562f9e..a36db29c27de381c8074ea93d9289686599011cc 100644
--- a/module/VuFind/src/VuFind/Auth/ILS.php
+++ b/module/VuFind/src/VuFind/Auth/ILS.php
@@ -227,7 +227,16 @@ class ILS extends AbstractBase
         }
 
         // Check to see if we already have an account for this user:
-        $user = $this->getUserTable()->getByUsername($info[$usernameField]);
+        $userTable = $this->getUserTable();
+        if (!empty($info['id'])) {
+            $user = $userTable->getByCatalogId($info['id']);
+            if (empty($user)) {
+                $user = $userTable->getByUsername($info[$usernameField]);
+                $user->saveCatalogId($info['id']);
+            }
+        } else {
+            $user = $userTable->getByUsername($info[$usernameField]);
+        }
 
         // No need to store the ILS password in VuFind's main password field:
         $user->password = '';
diff --git a/module/VuFind/src/VuFind/Auth/LDAP.php b/module/VuFind/src/VuFind/Auth/LDAP.php
index d40cbb6557fd0407e925d3b4830e09f1ecba6793..b1fdf5644cd56a0468f680a802b3c5e188293a37 100644
--- a/module/VuFind/src/VuFind/Auth/LDAP.php
+++ b/module/VuFind/src/VuFind/Auth/LDAP.php
@@ -158,9 +158,11 @@ class LDAP extends AbstractBase
         }
 
         // if the host parameter is not specified as ldaps://
-        // then we need to initiate TLS so we
+        // then (unless TLS is disabled) we need to initiate TLS so we
         // can have a secure connection over the standard LDAP port.
-        if (stripos($host, 'ldaps://') === false) {
+        $disableTls = isset($this->config->LDAP->disable_tls)
+            && $this->config->LDAP->disable_tls;
+        if (stripos($host, 'ldaps://') === false && !$disableTls) {
             $this->debug('Starting TLS');
             if (!@ldap_start_tls($connection)) {
                 $this->debug('TLS failed');
diff --git a/module/VuFind/src/VuFind/Auth/Shibboleth.php b/module/VuFind/src/VuFind/Auth/Shibboleth.php
index 874e59e2ea83768dff76f8f55c33b213419be0d7..e9e7a3bb8cff5dd01c30873d5422dbe800ae50d9 100644
--- a/module/VuFind/src/VuFind/Auth/Shibboleth.php
+++ b/module/VuFind/src/VuFind/Auth/Shibboleth.php
@@ -5,6 +5,7 @@
  * PHP version 5
  *
  * Copyright (C) Villanova University 2014.
+ * Copyright (C) The National Library of Finland 2016.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2,
@@ -25,6 +26,7 @@
  * @author   Jochen Lienhard <lienhard@ub.uni-freiburg.de>
  * @author   Bernd Oberknapp <bo@ub.uni-freiburg.de>
  * @author   Demian Katz <demian.katz@villanova.edu>
+ * @author   Ere Maijala <ere.maijala@helsinki.fi>
  * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
  * @link     https://vufind.org Main Page
  */
@@ -40,6 +42,7 @@ use VuFind\Exception\Auth as AuthException;
  * @author   Jochen Lienhard <lienhard@ub.uni-freiburg.de>
  * @author   Bernd Oberknapp <bo@ub.uni-freiburg.de>
  * @author   Demian Katz <demian.katz@villanova.edu>
+ * @author   Ere Maijala <ere.maijala@helsinki.fi>
  * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
  * @link     https://vufind.org Main Page
  */
@@ -47,6 +50,23 @@ class Shibboleth extends AbstractBase
 {
     const DEFAULT_IDPSERVERPARAM = 'Shib-Identity-Provider';
 
+    /**
+     * Session manager
+     *
+     * @var \Zend\Session\ManagerInterface
+     */
+    protected $sessionManager;
+
+    /**
+     * Constructor
+     *
+     * @param \Zend\Session\ManagerInterface $sessionManager Session manager
+     */
+    public function __construct(\Zend\Session\ManagerInterface $sessionManager)
+    {
+        $this->sessionManager = $sessionManager;
+    }
+
     /**
      * Validate configuration parameters.  This is a support method for getConfig(),
      * so the configuration MUST be accessed using $this->config; do not call
@@ -88,12 +108,20 @@ class Shibboleth extends AbstractBase
         $shib = $this->getConfig()->Shibboleth;
         $username = $request->getServer()->get($shib->username);
         if (empty($username)) {
+            $this->debug(
+                "No username attribute ({$shib->username}) present in request: "
+                . print_r($request->getServer()->toArray(), true)
+            );
             throw new AuthException('authentication_error_admin');
         }
 
         // Check if required attributes match up:
         foreach ($this->getRequiredAttributes() as $key => $value) {
             if (!preg_match('/' . $value . '/', $request->getServer()->get($key))) {
+                $this->debug(
+                    "Attribute '$key' does not match required value '$value' in"
+                    . ' request: ' . print_r($request->getServer()->toArray(), true)
+                );
                 throw new AuthException('authentication_error_denied');
             }
         }
@@ -136,6 +164,23 @@ class Shibboleth extends AbstractBase
             );
         }
 
+        // Add session id mapping to external_session table for single logout support
+        if (isset($shib->session_id)) {
+            $shibSessionId = $request->getServer()->get($shib->session_id);
+            if (null !== $shibSessionId) {
+                $localSessionId = $this->sessionManager->getId();
+                $externalSession = $this->getDbTableManager()
+                    ->get('ExternalSession');
+                $externalSession->addSessionMapping(
+                    $localSessionId, $shibSessionId
+                );
+                $this->debug(
+                    "Cached Shibboleth session id '$shibSessionId' for local session"
+                    . " '$localSessionId'"
+                );
+            }
+        }
+
         // Save and return the user object:
         $user->save();
         return $user;
diff --git a/module/VuFind/src/VuFind/Bootstrapper.php b/module/VuFind/src/VuFind/Bootstrapper.php
index 5d521d2399f71a52a21e731faa3cf130f8da187e..23f49552046c6721d328c7b4460901ce2514f807 100644
--- a/module/VuFind/src/VuFind/Bootstrapper.php
+++ b/module/VuFind/src/VuFind/Bootstrapper.php
@@ -201,8 +201,8 @@ class Bootstrapper
     {
         $callback = function ($event) {
             $serviceManager = $event->getApplication()->getServiceManager();
-            $renderer = $serviceManager->get('viewmanager')->getRenderer();
-            $headTitle = $renderer->plugin('headtitle');
+            $helperManager = $serviceManager->get('ViewHelperManager');
+            $headTitle = $helperManager->get('headtitle');
             $headTitle->setDefaultAttachOrder(
                 \Zend\View\Helper\Placeholder\Container\AbstractContainer::SET
             );
diff --git a/module/VuFind/src/VuFind/Cache/Manager.php b/module/VuFind/src/VuFind/Cache/Manager.php
index 7dcd720a2db4eee499c377ac438ea6f7c5b30df6..835c43fa543faeaaecea7354b6fd9901dbcdb4e9 100644
--- a/module/VuFind/src/VuFind/Cache/Manager.php
+++ b/module/VuFind/src/VuFind/Cache/Manager.php
@@ -89,7 +89,7 @@ class Manager
         $cacheBase = $this->getCacheDir();
 
         // Set up standard file-based caches:
-        foreach (['config', 'cover', 'language', 'object'] as $cache) {
+        foreach (['config', 'cover', 'language', 'object', 'yaml'] as $cache) {
             $this->createFileCache($cache, $cacheBase . $cache . 's');
         }
         $this->createFileCache('public', $cacheBase . 'public');
diff --git a/module/VuFind/src/VuFind/Cart.php b/module/VuFind/src/VuFind/Cart.php
index 3195c10216dd81402f1e35cb2ca5f59bff363a91..2f592f1e8c00f53680c7a88e186f1d148395abb4 100644
--- a/module/VuFind/src/VuFind/Cart.php
+++ b/module/VuFind/src/VuFind/Cart.php
@@ -62,6 +62,13 @@ class Cart
      */
     protected $active;
 
+    /**
+     * Is cart configured to toggles in search results?
+     *
+     * @var bool
+     */
+    protected $showTogglesInSearch;
+
     /**
      * Record loader
      *
@@ -83,19 +90,22 @@ class Cart
     /**
      * Constructor
      *
-     * @param \VuFind\Record\Loader $loader        Object for loading records
-     * @param CookieManager         $cookieManager Cookie manager
-     * @param int                   $maxSize       Maximum size of cart contents
-     * @param bool                  $active        Is cart enabled?
+     * @param \VuFind\Record\Loader $loader          Object for loading records
+     * @param CookieManager         $cookieManager   Cookie manager
+     * @param int                   $maxSize         Maximum size of cart contents
+     * @param bool                  $active          Is cart enabled?
+     * @param bool                  $togglesInSearch Is cart configured to toggles
+     * in search results?
      */
     public function __construct(\VuFind\Record\Loader $loader,
         \VuFind\Cookie\CookieManager $cookieManager,
-        $maxSize = 100, $active = true
+        $maxSize = 100, $active = true, $togglesInSearch = true
     ) {
         $this->recordLoader = $loader;
         $this->cookieManager = $cookieManager;
         $this->maxSize = $maxSize;
         $this->active = $active;
+        $this->showTogglesInSearch = $togglesInSearch;
 
         // Initialize contents
         $this->init($this->cookieManager->getCookies());
@@ -228,6 +238,16 @@ class Cart
         return $this->active;
     }
 
+    /**
+     * Process parameters and return the cart content.
+     *
+     * @return bool
+     */
+    public function isActiveInSearch()
+    {
+        return $this->active && $this->showTogglesInSearch;
+    }
+
     /**
      * Initialize the cart model.
      *
diff --git a/module/VuFind/src/VuFind/ChannelProvider/AbstractChannelProvider.php b/module/VuFind/src/VuFind/ChannelProvider/AbstractChannelProvider.php
new file mode 100644
index 0000000000000000000000000000000000000000..2f89e9bf2182e9d8af318fbb5f3facb248b25e50
--- /dev/null
+++ b/module/VuFind/src/VuFind/ChannelProvider/AbstractChannelProvider.php
@@ -0,0 +1,132 @@
+<?php
+/**
+ * Facet-driven channel provider.
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2016.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * @category VuFind
+ * @package  Channels
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development Wiki
+ */
+namespace VuFind\ChannelProvider;
+use VuFind\Cover\Router as CoverRouter;
+use VuFind\Search\Base\Params;
+
+/**
+ * Facet-driven channel provider.
+ *
+ * @category VuFind
+ * @package  Channels
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development Wiki
+ */
+abstract class AbstractChannelProvider implements ChannelProviderInterface
+{
+    /**
+     * Cover router
+     *
+     * @var CoverRouter
+     */
+    protected $coverRouter = null;
+
+    /**
+     * Provider ID
+     *
+     * @var string
+     */
+    protected $providerId = '';
+
+    /**
+     * Hook to configure search parameters before executing search.
+     *
+     * @param Params $params Search parameters to adjust
+     *
+     * @return void
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+     */
+    public function configureSearchParams(Params $params)
+    {
+        // No action necessary by default.
+    }
+
+    /**
+     * Inject cover router
+     *
+     * @param CoverRouter $coverRouter Cover router.
+     *
+     * @return void
+     */
+    public function setCoverRouter(CoverRouter $coverRouter)
+    {
+        $this->coverRouter = $coverRouter;
+    }
+
+    /**
+     * Set an identifier that will be injected as the 'providerId' key of all
+     * channels created by this provider.
+     *
+     * @param string $id Provider ID
+     *
+     * @return void
+     */
+    public function setProviderId($id)
+    {
+        $this->providerId = $id;
+    }
+
+    /**
+     * Set the options for the provider.
+     *
+     * @param array $options Options
+     *
+     * @return void
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+     */
+    public function setOptions(array $options)
+    {
+        // No options required by default
+    }
+
+    /**
+     * Convert a search results object into channel contents.
+     *
+     * @param array|\Traversable $drivers Record drivers to summarize.
+     *
+     * @return array
+     */
+    protected function summarizeRecordDrivers($drivers)
+    {
+        $summary = [];
+        foreach ($drivers as $current) {
+            $summary[] = [
+                'title' => $current->getTitle(),
+                'source' => $current->getSourceIdentifier(),
+                'thumbnail' => $this->coverRouter
+                    ? $this->coverRouter->getUrl($current, 'medium')
+                    : false,
+                'id' => $current->getUniqueId(),
+            ];
+        }
+        return $summary;
+    }
+}
diff --git a/module/VuFind/src/VuFind/ChannelProvider/ChannelProviderInterface.php b/module/VuFind/src/VuFind/ChannelProvider/ChannelProviderInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..bfbdec0b21edbde6e38ce5e21ff0c156eb0c82ef
--- /dev/null
+++ b/module/VuFind/src/VuFind/ChannelProvider/ChannelProviderInterface.php
@@ -0,0 +1,92 @@
+<?php
+/**
+ * Channel provider interface.
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2016.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * @category VuFind
+ * @package  Channels
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development Wiki
+ */
+namespace VuFind\ChannelProvider;
+use VuFind\RecordDriver\AbstractBase as RecordDriver;
+use VuFind\Search\Base\Params, VuFind\Search\Base\Results;
+
+/**
+ * Channel provider interface.
+ *
+ * @category VuFind
+ * @package  Channels
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development Wiki
+ */
+interface ChannelProviderInterface
+{
+    /**
+     * Hook to configure search parameters before executing search.
+     *
+     * @param Params $params Search parameters to adjust
+     *
+     * @return void
+     */
+    public function configureSearchParams(Params $params);
+
+    /**
+     * Return channel information derived from a record driver object.
+     *
+     * @param RecordDriver $driver       Record driver
+     * @param string       $channelToken Token identifying a single specific channel
+     * to load (if omitted, all channels will be loaded)
+     *
+     * @return array
+     */
+    public function getFromRecord(RecordDriver $driver, $channelToken = null);
+
+    /**
+     * Return channel information derived from a search results object.
+     *
+     * @param Results $results      Search results
+     * @param string  $channelToken Token identifying a single specific channel
+     * to load (if omitted, all channels will be loaded)
+     *
+     * @return array
+     */
+    public function getFromSearch(Results $results, $channelToken = null);
+
+    /**
+     * Set the options for the provider.
+     *
+     * @param array $options Options
+     *
+     * @return void
+     */
+    public function setOptions(array $options);
+
+    /**
+     * Set an identifier that will be injected as the 'providerId' key of all
+     * channels created by this provider.
+     *
+     * @param string $id Provider ID
+     *
+     * @return void
+     */
+    public function setProviderId($id);
+}
diff --git a/module/VuFind/src/VuFind/ChannelProvider/Facets.php b/module/VuFind/src/VuFind/ChannelProvider/Facets.php
new file mode 100644
index 0000000000000000000000000000000000000000..ba027d7e947c8eb7571a717b70e70cdfedbdba8e
--- /dev/null
+++ b/module/VuFind/src/VuFind/ChannelProvider/Facets.php
@@ -0,0 +1,321 @@
+<?php
+/**
+ * Facet-driven channel provider.
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2016.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * @category VuFind
+ * @package  Channels
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development Wiki
+ */
+namespace VuFind\ChannelProvider;
+use VuFind\I18n\Translator\TranslatorAwareInterface;
+use VuFind\RecordDriver\AbstractBase as RecordDriver;
+use VuFind\Search\Base\Params, VuFind\Search\Base\Results;
+use VuFind\Search\Results\PluginManager as ResultsManager;
+use Zend\Mvc\Controller\Plugin\Url;
+
+/**
+ * Facet-driven channel provider.
+ *
+ * @category VuFind
+ * @package  Channels
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development Wiki
+ */
+class Facets extends AbstractChannelProvider
+   implements TranslatorAwareInterface
+{
+    use \VuFind\I18n\Translator\TranslatorAwareTrait;
+    /**
+     * Facet fields to use (field name => description).
+     *
+     * @var array
+     */
+    protected $fields;
+
+    /**
+     * Maximum number of different fields to suggest in the channel list.
+     *
+     * @var int
+     */
+    protected $maxFieldsToSuggest;
+
+    /**
+     * Maximum number of values to suggest per field.
+     *
+     * @var int
+     */
+    protected $maxValuesToSuggestPerField;
+
+    /**
+     * Search results manager.
+     *
+     * @var ResultsManager
+     */
+    protected $resultsManager;
+
+    /**
+     * URL helper
+     *
+     * @var Url
+     */
+    protected $url;
+
+    /**
+     * Constructor
+     *
+     * @param ResultsManager $rm      Results manager
+     * @param Url            $url     URL helper
+     * @param array          $options Settings (optional)
+     */
+    public function __construct(ResultsManager $rm, Url $url, array $options = [])
+    {
+        $this->resultsManager = $rm;
+        $this->url = $url;
+        $this->setOptions($options);
+    }
+
+    /**
+     * Set the options for the provider.
+     *
+     * @param array $options Options
+     *
+     * @return void
+     */
+    public function setOptions(array $options)
+    {
+        $this->fields = isset($options['fields'])
+            ? $options['fields']
+            : ['topic_facet' => 'Topic', 'author_facet' => 'Author'];
+        $this->maxFieldsToSuggest = isset($options['maxFieldsToSuggest'])
+            ? $options['maxFieldsToSuggest'] : 2;
+        $this->maxValuesToSuggestPerField
+            = isset($options['maxValuesToSuggestPerField'])
+            ? $options['maxValuesToSuggestPerField'] : 2;
+    }
+
+    /**
+     * Hook to configure search parameters before executing search.
+     *
+     * @param Params $params Search parameters to adjust
+     *
+     * @return void
+     */
+    public function configureSearchParams(Params $params)
+    {
+        foreach ($this->fields as $field => $desc) {
+            $params->addFacet($field, $desc);
+        }
+    }
+
+    /**
+     * Return channel information derived from a record driver object.
+     *
+     * @param RecordDriver $driver       Record driver
+     * @param string       $channelToken Token identifying a single specific channel
+     * to load (if omitted, all channels will be loaded)
+     *
+     * @return array
+     */
+    public function getFromRecord(RecordDriver $driver, $channelToken = null)
+    {
+        $results = $this->resultsManager->get($driver->getSourceIdentifier());
+        if (null !== $channelToken) {
+            return [$this->buildChannelFromToken($results, $channelToken)];
+        }
+        $channels = [];
+        $fieldCount = 0;
+        $data = $driver->getRawData();
+        foreach (array_keys($this->fields) as $field) {
+            if (!isset($data[$field])) {
+                continue;
+            }
+            $currentValueCount = 0;
+            foreach ($data[$field] as $value) {
+                $current = [
+                    'value' => $value,
+                    'displayText' => $value,
+                ];
+                $tokenOnly = $fieldCount >= $this->maxFieldsToSuggest
+                    || $currentValueCount >= $this->maxValuesToSuggestPerField;
+                $channel = $this
+                    ->buildChannelFromFacet($results, $field, $current, $tokenOnly);
+                if ($tokenOnly || count($channel['contents']) > 0) {
+                    $channels[] = $channel;
+                    $currentValueCount++;
+                }
+            }
+            if ($currentValueCount > 0) {
+                $fieldCount++;
+            }
+        }
+        return $channels;
+    }
+
+    /**
+     * Return channel information derived from a search results object.
+     *
+     * @param Results $results      Search results
+     * @param string  $channelToken Token identifying a single specific channel
+     * to load (if omitted, all channels will be loaded)
+     *
+     * @return array
+     */
+    public function getFromSearch(Results $results, $channelToken = null)
+    {
+        if (null !== $channelToken) {
+            return [$this->buildChannelFromToken($results, $channelToken)];
+        }
+        $channels = [];
+        $fieldCount = 0;
+        $facetList = $results->getFacetList();
+        foreach (array_keys($this->fields) as $field) {
+            if (!isset($facetList[$field])) {
+                continue;
+            }
+            $currentValueCount = 0;
+            foreach ($facetList[$field]['list'] as $current) {
+                if (!$current['isApplied']) {
+                    $tokenOnly = $fieldCount >= $this->maxFieldsToSuggest
+                        || $currentValueCount >= $this->maxValuesToSuggestPerField;
+                    $channel = $this->buildChannelFromFacet(
+                        $results, $field, $current, $tokenOnly
+                    );
+                    if ($tokenOnly || count($channel['contents']) > 0) {
+                        $channels[] = $channel;
+                        $currentValueCount++;
+                    }
+                }
+            }
+            if ($currentValueCount > 0) {
+                $fieldCount++;
+            }
+        }
+        return $channels;
+    }
+
+    /**
+     * Turn a filter and title into a token.
+     *
+     * @param string $filter Filter to apply to Solr
+     * @param string $title  Channel title
+     *
+     * @return string
+     */
+    protected function getToken($filter, $title)
+    {
+        return str_replace('|', ' ', $title)    // make sure delimiter not in title
+            . '|' . $filter;
+    }
+
+    /**
+     * Add a new filter to an existing search results object to populate a
+     * channel.
+     *
+     * @param Results $results   Results object
+     * @param string  $filter    Filter to apply to Solr
+     * @param string  $title     Channel title
+     * @param bool    $tokenOnly Create full channel (false) or return a
+     * token for future loading (true)?
+     *
+     * @return array
+     */
+    protected function buildChannel(Results $results, $filter, $title,
+        $tokenOnly = false
+    ) {
+        $retVal = [
+            'title' => $title,
+            'providerId' => $this->providerId,
+            'groupId' => current(explode(':', $filter)),
+            'token' => $this->getToken($filter, $title),
+            'links' => []
+        ];
+        if ($tokenOnly) {
+            return $retVal;
+        }
+
+        $newResults = clone($results);
+        $params = $newResults->getParams();
+
+        // Determine the filter for the current channel, and add it:
+        $params->addFilter($filter);
+
+        $query = $newResults->getUrlQuery();
+        $retVal['links'][] = [
+            'label' => 'channel_search',
+            'icon' => 'fa-list',
+            'url' => $this->url->fromRoute($params->getOptions()->getSearchAction())
+                . $query
+        ];
+        $retVal['links'][] = [
+            'label' => 'channel_expand',
+            'icon' => 'fa-search-plus',
+            'url' => $this->url->fromRoute('channels-search')
+                . $query . '&source=' . urlencode($params->getSearchClassId())
+        ];
+
+        // Run the search and convert the results into a channel:
+        $newResults->performAndProcessSearch();
+        $retVal['contents']
+            = $this->summarizeRecordDrivers($newResults->getResults());
+        return $retVal;
+    }
+
+    /**
+     * Call buildChannel using data from a token.
+     *
+     * @param Results $results Results object
+     * @param string  $token   Token to parse
+     *
+     * @return array
+     */
+    protected function buildChannelFromToken(Results $results, $token)
+    {
+        $parts = explode('|', $token, 2);
+        if (count($parts) < 2) {
+            return [];
+        }
+        return $this->buildChannel($results, $parts[1], $parts[0]);
+    }
+
+    /**
+     * Call buildChannel using data from facet results.
+     *
+     * @param Results $results   Results object
+     * @param string  $field     Field name (for filter)
+     * @param array   $value     Field value information (for filter)
+     * @param bool    $tokenOnly Create full channel (false) or return a
+     * token for future loading (true)?
+     *
+     * @return array
+     */
+    protected function buildChannelFromFacet(Results $results, $field, $value,
+        $tokenOnly = false
+    ) {
+        return $this->buildChannel(
+            $results,
+            "$field:{$value['value']}",
+            $this->translate($this->fields[$field]) . ": {$value['displayText']}",
+            $tokenOnly
+        );
+    }
+}
diff --git a/module/VuFind/src/VuFind/ChannelProvider/Factory.php b/module/VuFind/src/VuFind/ChannelProvider/Factory.php
new file mode 100644
index 0000000000000000000000000000000000000000..413803f34c6184486e5aa1bf344eb710b85652fc
--- /dev/null
+++ b/module/VuFind/src/VuFind/ChannelProvider/Factory.php
@@ -0,0 +1,122 @@
+<?php
+/**
+ * Factory for ChannelProvider plugins.
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2016.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * @category VuFind
+ * @package  Channels
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development Wiki
+ */
+namespace VuFind\ChannelProvider;
+use Zend\ServiceManager\ServiceManager;
+
+/**
+ * Factory for ChannelProvider plugins.
+ *
+ * @category VuFind
+ * @package  Channels
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development Wiki
+ *
+ * @codeCoverageIgnore
+ */
+class Factory
+{
+    /**
+     * Construct the Facets channel provider.
+     *
+     * @param ServiceManager $sm Service manager.
+     *
+     * @return Facets
+     */
+    public static function getFacets(ServiceManager $sm)
+    {
+        $helper = new Facets(
+            $sm->getServiceLocator()->get('VuFind\SearchResultsPluginManager'),
+            $sm->getServiceLocator()->get('ControllerPluginManager')->get('url')
+        );
+        $helper->setCoverRouter(
+            $sm->getServiceLocator()->get('VuFind\Cover\Router')
+        );
+        return $helper;
+    }
+
+    /**
+     * Construct the ListItems channel provider.
+     *
+     * @param ServiceManager $sm Service manager.
+     *
+     * @return ListItems
+     */
+    public static function getListItems(ServiceManager $sm)
+    {
+        $helper = new ListItems(
+            $sm->getServiceLocator()->get('VuFind\DbTablePluginManager')
+                ->get('UserList'),
+            $sm->getServiceLocator()->get('ControllerPluginManager')->get('url'),
+            $sm->getServiceLocator()->get('VuFind\SearchResultsPluginManager')
+        );
+        $helper->setCoverRouter(
+            $sm->getServiceLocator()->get('VuFind\Cover\Router')
+        );
+        return $helper;
+    }
+
+    /**
+     * Construct the Random channel provider.
+     *
+     * @param ServiceManager $sm Service manager.
+     *
+     * @return Random
+     */
+    public static function getRandom(ServiceManager $sm)
+    {
+        $helper = new Random(
+            $sm->getServiceLocator()->get('VuFind\Search'),
+            $sm->getServiceLocator()->get('VuFind\SearchParamsPluginManager')
+        );
+        $helper->setCoverRouter(
+            $sm->getServiceLocator()->get('VuFind\Cover\Router')
+        );
+        return $helper;
+    }
+
+    /**
+     * Construct the SimilarItems channel provider.
+     *
+     * @param ServiceManager $sm Service manager.
+     *
+     * @return SimilarItems
+     */
+    public static function getSimilarItems(ServiceManager $sm)
+    {
+        $helper = new SimilarItems(
+            $sm->getServiceLocator()->get('VuFind\Search'),
+            $sm->getServiceLocator()->get('ControllerPluginManager')->get('url'),
+            $sm->getServiceLocator()->get('VuFind\RecordRouter')
+        );
+        $helper->setCoverRouter(
+            $sm->getServiceLocator()->get('VuFind\Cover\Router')
+        );
+        return $helper;
+    }
+}
diff --git a/module/VuFind/src/VuFind/ChannelProvider/ListItems.php b/module/VuFind/src/VuFind/ChannelProvider/ListItems.php
new file mode 100644
index 0000000000000000000000000000000000000000..d872e2f2786691f1ac031a9bd88477a46e72bd6c
--- /dev/null
+++ b/module/VuFind/src/VuFind/ChannelProvider/ListItems.php
@@ -0,0 +1,257 @@
+<?php
+/**
+ * "List items" channel provider.
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2016.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * @category VuFind
+ * @package  Channels
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development Wiki
+ */
+namespace VuFind\ChannelProvider;
+use VuFind\RecordDriver\AbstractBase as RecordDriver;
+use VuFind\Search\Base\Params, VuFind\Search\Base\Results;
+use Zend\Mvc\Controller\Plugin\Url;
+use Zend\Stdlib\Parameters;
+
+/**
+ * "List items" channel provider.
+ *
+ * @category VuFind
+ * @package  Channels
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development Wiki
+ */
+class ListItems extends AbstractChannelProvider
+{
+    use \VuFind\I18n\Translator\TranslatorAwareTrait;
+
+    /**
+     * IDs of lists to display
+     *
+     * @var array
+     */
+    protected $ids;
+
+    /**
+     * Should we pull in public list results in addition to the whitelist in $ids?
+     *
+     * @var bool
+     */
+    protected $displayPublicLists;
+
+    /**
+     * How many lists should we display before switching over to tokens?
+     *
+     * @var int
+     */
+    protected $initialListsToDisplay;
+
+    /**
+     * UserList table
+     *
+     * @var \VuFind\Db\Table\UserList
+     */
+    protected $userList;
+
+    /**
+     * Results manager
+     *
+     * @var \VuFind\Search\Results\PluginManager
+     */
+    protected $resultsManager;
+
+    /**
+     * URL helper
+     *
+     * @var Url
+     */
+    protected $url;
+
+    /**
+     * Constructor
+     *
+     * @param \VuFind\Db\Table\UserList            $userList       UserList table
+     * @param Url                                  $url            URL helper
+     * @param \VuFind\Search\Results\PluginManager $resultsManager Results manager
+     * @param array                                $options        Settings
+     * (optional)
+     */
+    public function __construct(\VuFind\Db\Table\UserList $userList, Url $url,
+        \VuFind\Search\Results\PluginManager $resultsManager, array $options = []
+    ) {
+        $this->userList = $userList;
+        $this->url = $url;
+        $this->resultsManager = $resultsManager;
+        $this->setOptions($options);
+    }
+
+    /**
+     * Set the options for the provider.
+     *
+     * @param array $options Options
+     *
+     * @return void
+     */
+    public function setOptions(array $options)
+    {
+        $this->ids = isset($options['ids']) ? $options['ids'] : [];
+        $this->displayPublicLists = isset($options['displayPublicLists'])
+            ? (bool)$options['displayPublicLists'] : true;
+        $this->initialListsToDisplay = isset($options['initialListsToDisplay'])
+            ? $options['initialListsToDisplay'] : 2;
+    }
+
+    /**
+     * Return channel information derived from a record driver object.
+     *
+     * @param RecordDriver $driver       Record driver
+     * @param string       $channelToken Token identifying a single specific channel
+     * to load (if omitted, all channels will be loaded)
+     *
+     * @return array
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+     */
+    public function getFromRecord(RecordDriver $driver, $channelToken = null)
+    {
+        return $this->buildListChannels($channelToken);
+    }
+
+    /**
+     * Return channel information derived from a search results object.
+     *
+     * @param Results $results      Search results
+     * @param string  $channelToken Token identifying a single specific channel
+     * to load (if omitted, all channels will be loaded)
+     *
+     * @return array
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+     */
+    public function getFromSearch(Results $results, $channelToken = null)
+    {
+        return $this->buildListChannels($channelToken);
+    }
+
+    /**
+     * Build all of the channel data.
+     *
+     * @param string $channelToken Token identifying a single specific channel
+     * to load (if omitted, all channels will be loaded)
+     *
+     * @return array
+     */
+    protected function buildListChannels($channelToken)
+    {
+        $channels = [];
+        foreach ($this->getLists() as $list) {
+            $tokenOnly = (count($channels) >= $this->initialListsToDisplay);
+            $channel = $this->getChannelFromList($list, $tokenOnly);
+            if ($tokenOnly || count($channel['contents']) > 0) {
+                $channels[] = $channel;
+            }
+        }
+        return $channels;
+    }
+
+    /**
+     * Get a list of public lists to display:
+     *
+     * @return array
+     */
+    protected function getLists()
+    {
+        $lists = [];
+        foreach ($this->ids as $id) {
+            $list = $this->userList->getExisting($id);
+            if ($list->public) {
+                $lists[] = $list;
+            }
+        }
+        if ($this->displayPublicLists) {
+            $ids = $this->ids;
+            $callback = function ($select) use ($ids) {
+                $select->where->equalTo('public', 1);
+                foreach ($ids as $id) {
+                    $select->where->notEqualTo('id', $id);
+                }
+            };
+            foreach ($this->userList->select($callback) as $list) {
+                $lists[] = $list;
+            }
+        }
+        return $lists;
+    }
+
+    /**
+     * Given a list object, return a channel array.
+     *
+     * @param \VuFind\Db\Row\UserList $list      User list
+     * @param bool                    $tokenOnly Return only token information?
+     *
+     * @return array
+     */
+    protected function getChannelFromList($list, $tokenOnly)
+    {
+        $retVal = [
+            'title' => $list->title,
+            'providerId' => $this->providerId,
+            'token' => $list->id,
+            'links' => []
+        ];
+        if ($tokenOnly) {
+            return $retVal;
+        }
+        $results = $this->resultsManager->get('Favorites');
+        $results->getParams()->initFromRequest(new Parameters(['id' => $list->id]));
+        $retVal['contents'] = $this->summarizeRecordDrivers($results->getResults());
+        $retVal['links'][] = [
+            'label' => 'channel_search',
+            'icon' => 'fa-list',
+            'url' => $this->url->fromRoute('userList', ['id' => $list->id])
+        ];
+        return $retVal;
+    }
+
+    /**
+     * Add a new filter to an existing search results object to populate a
+     * channel.
+     *
+     * @param Params $params Search parameter object
+     *
+     * @return array
+     */
+    protected function buildChannelFromParams(Params $params)
+    {
+        $retVal = [
+            'title' => $this->translate('random_recommendation_title'),
+            'providerId' => $this->providerId,
+        ];
+        $query = $params->getQuery();
+        $paramBag = $params->getBackendParameters();
+        $random = $this->searchService->random(
+            $params->getSearchClassId(), $query, $this->channelSize, $paramBag
+        )->getRecords();
+        $retVal['contents'] = $this->summarizeRecordDrivers($random);
+        return $retVal;
+    }
+}
diff --git a/module/VuFind/src/VuFind/Statistics/Driver/PluginFactory.php b/module/VuFind/src/VuFind/ChannelProvider/PluginFactory.php
similarity index 73%
rename from module/VuFind/src/VuFind/Statistics/Driver/PluginFactory.php
rename to module/VuFind/src/VuFind/ChannelProvider/PluginFactory.php
index f68608acb453f753474fb4c5647a7ccc99d2f4df..0c684bcb42ce2a170be1d99bc41df2b2144e79da 100644
--- a/module/VuFind/src/VuFind/Statistics/Driver/PluginFactory.php
+++ b/module/VuFind/src/VuFind/ChannelProvider/PluginFactory.php
@@ -1,10 +1,10 @@
 <?php
 /**
- * Statistics driver plugin factory
+ * Channel provider plugin factory
  *
  * PHP version 5
  *
- * Copyright (C) Villanova University 2010.
+ * Copyright (C) Villanova University 2016.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2,
@@ -20,21 +20,21 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
  * @category VuFind
- * @package  Statistics
+ * @package  Channels
  * @author   Demian Katz <demian.katz@villanova.edu>
  * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
- * @link     https://vufind.org/wiki/development:plugins:statistics_drivers Wiki
+ * @link     https://vufind.org/wiki/development Wiki
  */
-namespace VuFind\Statistics\Driver;
+namespace VuFind\ChannelProvider;
 
 /**
- * Statistics driver plugin factory
+ * Channel provider plugin factory
  *
  * @category VuFind
- * @package  Statistics
+ * @package  Channels
  * @author   Demian Katz <demian.katz@villanova.edu>
  * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
- * @link     https://vufind.org/wiki/development:plugins:statistics_drivers Wiki
+ * @link     https://vufind.org/wiki/development Wiki
  */
 class PluginFactory extends \VuFind\ServiceManager\AbstractPluginFactory
 {
@@ -43,6 +43,6 @@ class PluginFactory extends \VuFind\ServiceManager\AbstractPluginFactory
      */
     public function __construct()
     {
-        $this->defaultNamespace = 'VuFind\Statistics\Driver';
+        $this->defaultNamespace = 'VuFind\ChannelProvider';
     }
 }
diff --git a/module/VuFind/src/VuFind/Statistics/Driver/PluginManager.php b/module/VuFind/src/VuFind/ChannelProvider/PluginManager.php
similarity index 59%
rename from module/VuFind/src/VuFind/Statistics/Driver/PluginManager.php
rename to module/VuFind/src/VuFind/ChannelProvider/PluginManager.php
index ce032a9b3568b833581e2d47a8d56d3e05cf4eb1..4ebf605792a6490998cee3048bc71ed7af65400f 100644
--- a/module/VuFind/src/VuFind/Statistics/Driver/PluginManager.php
+++ b/module/VuFind/src/VuFind/ChannelProvider/PluginManager.php
@@ -1,10 +1,10 @@
 <?php
 /**
- * Statistics driver plugin manager
+ * Channel provider plugin manager
  *
  * PHP version 5
  *
- * Copyright (C) Villanova University 2010.
+ * Copyright (C) Villanova University 2016.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2,
@@ -20,39 +20,24 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
  * @category VuFind
- * @package  Statistics
+ * @package  Channels
  * @author   Demian Katz <demian.katz@villanova.edu>
  * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
- * @link     https://vufind.org/wiki/development:plugins:statistics_drivers Wiki
+ * @link     https://vufind.org/wiki/development Wiki
  */
-namespace VuFind\Statistics\Driver;
-use Zend\ServiceManager\ConfigInterface;
+namespace VuFind\ChannelProvider;
 
 /**
- * Statistics driver plugin manager
+ * Channel provider plugin manager
  *
  * @category VuFind
- * @package  Statistics
+ * @package  Channels
  * @author   Demian Katz <demian.katz@villanova.edu>
  * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
- * @link     https://vufind.org/wiki/development:plugins:statistics_drivers Wiki
+ * @link     https://vufind.org/wiki/development Wiki
  */
 class PluginManager extends \VuFind\ServiceManager\AbstractPluginManager
 {
-    /**
-     * Constructor
-     *
-     * @param ConfigInterface $configuration Configuration settings (optional)
-     */
-    public function __construct(ConfigInterface $configuration = null)
-    {
-        // Stats drivers are not meant to be shared -- every time we retrieve one,
-        // we are building a brand new object.
-        $this->setShareByDefault(false);
-
-        parent::__construct($configuration);
-    }
-
     /**
      * Return the name of the base class or interface that plug-ins must conform
      * to.
@@ -61,6 +46,6 @@ class PluginManager extends \VuFind\ServiceManager\AbstractPluginManager
      */
     protected function getExpectedInterface()
     {
-        return 'VuFind\Statistics\Driver\AbstractBase';
+        return 'VuFind\ChannelProvider\ChannelProviderInterface';
     }
 }
diff --git a/module/VuFind/src/VuFind/ChannelProvider/Random.php b/module/VuFind/src/VuFind/ChannelProvider/Random.php
new file mode 100644
index 0000000000000000000000000000000000000000..51f6b40f55f2b122e6e631cd424ce40748322937
--- /dev/null
+++ b/module/VuFind/src/VuFind/ChannelProvider/Random.php
@@ -0,0 +1,167 @@
+<?php
+/**
+ * "Random items" channel provider.
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2016.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * @category VuFind
+ * @package  Channels
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development Wiki
+ */
+namespace VuFind\ChannelProvider;
+use VuFind\RecordDriver\AbstractBase as RecordDriver;
+use VuFind\Search\Base\Params, VuFind\Search\Base\Results;
+use VuFind\I18n\Translator\TranslatorAwareInterface;
+
+/**
+ * "Random items" channel provider.
+ *
+ * @category VuFind
+ * @package  Channels
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development Wiki
+ */
+class Random extends AbstractChannelProvider
+    implements TranslatorAwareInterface
+{
+    use \VuFind\I18n\Translator\TranslatorAwareTrait;
+
+    /**
+     * Number of results to include in each channel.
+     *
+     * @var int
+     */
+    protected $channelSize;
+
+    /**
+     * Mode
+     *
+     * @var string
+     */
+    protected $mode;
+
+    /**
+     * Search service
+     *
+     * @var \VuFindSearch\Service
+     */
+    protected $searchService;
+
+    /**
+     * Params manager
+     *
+     * @var \VuFind\Search\Params\PluginManager
+     */
+    protected $paramManager;
+
+    /**
+     * Constructor
+     *
+     * @param \VuFindSearch\Service               $search       Search service
+     * @param \VuFind\Search\Params\PluginManager $paramManager Params manager
+     * @param array                               $options      Settings (optional)
+     */
+    public function __construct(\VuFindSearch\Service $search,
+        \VuFind\Search\Params\PluginManager $paramManager, array $options = []
+    ) {
+        $this->searchService = $search;
+        $this->paramManager = $paramManager;
+        $this->setOptions($options);
+    }
+
+    /**
+     * Set the options for the provider.
+     *
+     * @param array $options Options
+     *
+     * @return void
+     */
+    public function setOptions(array $options)
+    {
+        $this->channelSize = isset($options['channelSize'])
+            ? $options['channelSize'] : 20;
+        $this->mode = isset($options['mode']) ? $options['mode'] : 'retain';
+    }
+
+    /**
+     * Return channel information derived from a record driver object.
+     *
+     * @param RecordDriver $driver       Record driver
+     * @param string       $channelToken Token identifying a single specific channel
+     * to load (if omitted, all channels will be loaded) -- not used in this provider
+     *
+     * @return array
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+     */
+    public function getFromRecord(RecordDriver $driver, $channelToken = null)
+    {
+        $randomParams = $this->paramManager->get($driver->getSourceIdentifier());
+        $channel = $this->buildChannelFromParams($randomParams);
+        return (count($channel['contents']) > 0) ? [$channel] : [];
+    }
+
+    /**
+     * Return channel information derived from a search results object.
+     *
+     * @param Results $results      Search results
+     * @param string  $channelToken Token identifying a single specific channel
+     * to load (if omitted, all channels will be loaded) -- not used in this provider
+     *
+     * @return array
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+     */
+    public function getFromSearch(Results $results, $channelToken = null)
+    {
+        $params = $results->getParams();
+        if ("retain" !== $this->mode) {
+            $randomParams = $this->paramManager->get($params->getSearchClassId());
+        } else {
+            $randomParams = clone $params;
+        }
+        $channel = $this->buildChannelFromParams($randomParams);
+        return (count($channel['contents']) > 0) ? [$channel] : [];
+    }
+
+    /**
+     * Add a new filter to an existing search results object to populate a
+     * channel.
+     *
+     * @param Params $params Search parameter object
+     *
+     * @return array
+     */
+    protected function buildChannelFromParams(Params $params)
+    {
+        $retVal = [
+            'title' => $this->translate('random_recommendation_title'),
+            'providerId' => $this->providerId,
+        ];
+        $query = $params->getQuery();
+        $paramBag = $params->getBackendParameters();
+        $random = $this->searchService->random(
+            $params->getSearchClassId(), $query, $this->channelSize, $paramBag
+        )->getRecords();
+        $retVal['contents'] = $this->summarizeRecordDrivers($random);
+        return $retVal;
+    }
+}
diff --git a/module/VuFind/src/VuFind/ChannelProvider/SimilarItems.php b/module/VuFind/src/VuFind/ChannelProvider/SimilarItems.php
new file mode 100644
index 0000000000000000000000000000000000000000..6e369b5083446636af4fe8e90cf73d74cf41314c
--- /dev/null
+++ b/module/VuFind/src/VuFind/ChannelProvider/SimilarItems.php
@@ -0,0 +1,220 @@
+<?php
+/**
+ * "Similar items" channel provider.
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2016.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * @category VuFind
+ * @package  Channels
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development Wiki
+ */
+namespace VuFind\ChannelProvider;
+use VuFind\RecordDriver\AbstractBase as RecordDriver;
+use VuFind\Record\Router as RecordRouter;
+use VuFind\Search\Base\Params, VuFind\Search\Base\Results;
+use VuFind\I18n\Translator\TranslatorAwareInterface;
+use Zend\Mvc\Controller\Plugin\Url;
+
+/**
+ * "Similar items" channel provider.
+ *
+ * @category VuFind
+ * @package  Channels
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development Wiki
+ */
+class SimilarItems extends AbstractChannelProvider
+    implements TranslatorAwareInterface
+{
+    use \VuFind\I18n\Translator\TranslatorAwareTrait;
+
+    /**
+     * Number of results to include in each channel.
+     *
+     * @var int
+     */
+    protected $channelSize;
+
+    /**
+     * Maximum number of records to examine for similar results.
+     *
+     * @var int
+     */
+    protected $maxRecordsToExamine;
+
+    /**
+     * Search service
+     *
+     * @var \VuFindSearch\Service
+     */
+    protected $searchService;
+
+    /**
+     * URL helper
+     *
+     * @var Url
+     */
+    protected $url;
+
+    /**
+     * Record router
+     *
+     * @var RecordRouter
+     */
+    protected $recordRouter;
+
+    /**
+     * Constructor
+     *
+     * @param \VuFindSearch\Service $search  Search service
+     * @param Url                   $url     URL helper
+     * @param RecordRouter          $router  Record router
+     * @param array                 $options Settings (optional)
+     */
+    public function __construct(\VuFindSearch\Service $search, Url $url,
+        RecordRouter $router, array $options = []
+    ) {
+        $this->searchService = $search;
+        $this->url = $url;
+        $this->recordRouter = $router;
+        $this->setOptions($options);
+    }
+
+    /**
+     * Set the options for the provider.
+     *
+     * @param array $options Options
+     *
+     * @return void
+     */
+    public function setOptions(array $options)
+    {
+        $this->channelSize = isset($options['channelSize'])
+            ? $options['channelSize'] : 20;
+        $this->maxRecordsToExamine = isset($options['maxRecordsToExamine'])
+            ? $options['maxRecordsToExamine'] : 2;
+    }
+
+    /**
+     * Return channel information derived from a record driver object.
+     *
+     * @param RecordDriver $driver       Record driver
+     * @param string       $channelToken Token identifying a single specific channel
+     * to load (if omitted, all channels will be loaded)
+     *
+     * @return array
+     */
+    public function getFromRecord(RecordDriver $driver, $channelToken = null)
+    {
+        // If we have a token and it doesn't match the record driver, we can't
+        // fetch any results!
+        if ($channelToken !== null && $channelToken !== $driver->getUniqueID()) {
+            return [];
+        }
+        $channel = $this->buildChannelFromRecord($driver);
+        return (count($channel['contents']) > 0) ? [$channel] : [];
+    }
+
+    /**
+     * Return channel information derived from a search results object.
+     *
+     * @param Results $results      Search results
+     * @param string  $channelToken Token identifying a single specific channel
+     * to load (if omitted, all channels will be loaded)
+     *
+     * @return array
+     */
+    public function getFromSearch(Results $results, $channelToken = null)
+    {
+        $channels = [];
+        foreach ($results->getResults() as $driver) {
+            // If we have a token and it doesn't match the current driver, skip
+            // that driver.
+            if ($channelToken !== null && $channelToken !== $driver->getUniqueID()) {
+                continue;
+            }
+            if (count($channels) < $this->maxRecordsToExamine) {
+                $channel = $this->buildChannelFromRecord($driver);
+                if (count($channel['contents']) > 0) {
+                    $channels[] = $channel;
+                }
+            } else {
+                $channels[] = $this->buildChannelFromRecord($driver, true);
+            }
+        }
+        // If the search results did not include the object we were looking for,
+        // we need to fetch it from the search service:
+        if (empty($channels) && is_object($driver) && $channelToken !== null) {
+            $driver = $this->searchService->retrieve(
+                $driver->getSourceIdentifier(), $channelToken
+            )->first();
+            if ($driver) {
+                $channels[] = $this->buildChannelFromRecord($driver);
+            }
+        }
+        return $channels;
+    }
+
+    /**
+     * Add a new filter to an existing search results object to populate a
+     * channel.
+     *
+     * @param RecordDriver $driver    Record driver
+     * @param bool         $tokenOnly Create full channel (false) or return a
+     * token for future loading (true)?
+     *
+     * @return array
+     */
+    protected function buildChannelFromRecord(RecordDriver $driver,
+        $tokenOnly = false
+    ) {
+        $heading = $this->translate('Similar Items');
+        $retVal = [
+            'title' => "{$heading}: {$driver->getBreadcrumb()}",
+            'providerId' => $this->providerId,
+            'links' => []
+        ];
+        if ($tokenOnly) {
+            $retVal['token'] = $driver->getUniqueID();
+        } else {
+            $params = new \VuFindSearch\ParamBag(['rows' => $this->channelSize]);
+            $similar = $this->searchService->similar(
+                $driver->getSourceIdentifier(), $driver->getUniqueID(), $params
+            );
+            $retVal['contents'] = $this->summarizeRecordDrivers($similar);
+            $route = $this->recordRouter->getRouteDetails($driver);
+            $retVal['links'][] = [
+                'label' => 'View Record',
+                'icon' => 'fa-file-text-o',
+                'url' => $this->url
+                    ->fromRoute($route['route'], $route['params'])
+            ];
+            $retVal['links'][] = [
+                'label' => 'channel_expand',
+                'icon' => 'fa-search-plus',
+                'url' => $this->url->fromRoute('channels-record')
+                    . '?id=' . urlencode($driver->getUniqueID())
+                    . '&source=' . urlencode($driver->getSourceIdentifier())
+            ];
+        }
+        return $retVal;
+    }
+}
diff --git a/module/VuFind/src/VuFind/Config/AccountCapabilities.php b/module/VuFind/src/VuFind/Config/AccountCapabilities.php
index b741f7bc8d81fad9d7b226958d1bfb7ed65a973d..ffa222cc738c4e510397bccb89d28044978768a7 100644
--- a/module/VuFind/src/VuFind/Config/AccountCapabilities.php
+++ b/module/VuFind/src/VuFind/Config/AccountCapabilities.php
@@ -135,6 +135,18 @@ class AccountCapabilities
             ? 'disabled' : 'enabled';
     }
 
+    /**
+     * Get SMS setting ('enabled' or 'disabled').
+     *
+     * @return string
+     */
+    public function getSmsSetting()
+    {
+        return isset($this->config->Mail->sms)
+            && $this->config->Mail->sms === 'disabled'
+            ? 'disabled' : 'enabled';
+    }
+
     /**
      * Is a user account capable of saving data currently available?
      *
diff --git a/module/VuFind/src/VuFind/Config/PluginFactory.php b/module/VuFind/src/VuFind/Config/PluginFactory.php
index 60b36d01f5bcf6b181ddcf79d9bbf63e8168233e..5fbd16913bb3a133cece1813230244e129a4c77c 100644
--- a/module/VuFind/src/VuFind/Config/PluginFactory.php
+++ b/module/VuFind/src/VuFind/Config/PluginFactory.php
@@ -113,6 +113,11 @@ class PluginFactory implements AbstractFactoryInterface
                 )
                 : [];
             foreach ($child as $section => $contents) {
+                // Check if arrays in the current config file should be merged with
+                // preceding arrays from config files defined as Parent_Config.
+                $mergeArraySettings
+                    = !empty($child->Parent_Config->merge_array_settings);
+
                 // Omit Parent_Config from the returned configuration; it is only
                 // needed during loading, and its presence will cause problems in
                 // config files that iterate through all of the sections (e.g.
@@ -126,7 +131,21 @@ class PluginFactory implements AbstractFactoryInterface
                     $config->$section = $child->$section;
                 } else {
                     foreach (array_keys($contents->toArray()) as $key) {
-                        $config->$section->$key = $child->$section->$key;
+                        // If a key is defined as key[] in the config file the key
+                        // remains a Zend\Config\Config object. If the current
+                        // section is not configured as an override section we try to
+                        // merge the key[] values instead of overwriting them.
+                        if (is_object($config->$section->$key)
+                            && is_object($child->$section->$key)
+                            && $mergeArraySettings
+                        ) {
+                            $config->$section->$key = array_merge(
+                                $config->$section->$key->toArray(),
+                                $child->$section->$key->toArray()
+                            );
+                        } else {
+                            $config->$section->$key = $child->$section->$key;
+                        }
                     }
                 }
             }
diff --git a/module/VuFind/src/VuFind/Config/SearchSpecsReader.php b/module/VuFind/src/VuFind/Config/SearchSpecsReader.php
index d772c346e30ba51cc73be9f42cb18387234205c6..e49deb4c3eea0efedbbf1d42892bf03bbec1c373 100644
--- a/module/VuFind/src/VuFind/Config/SearchSpecsReader.php
+++ b/module/VuFind/src/VuFind/Config/SearchSpecsReader.php
@@ -26,7 +26,6 @@
  * @link     https://vufind.org Main Site
  */
 namespace VuFind\Config;
-use Symfony\Component\Yaml\Yaml;
 
 /**
  * VuFind SearchSpecs Configuration Reader
@@ -37,22 +36,8 @@ use Symfony\Component\Yaml\Yaml;
  * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
  * @link     https://vufind.org Main Site
  */
-class SearchSpecsReader
+class SearchSpecsReader extends YamlReader
 {
-    /**
-     * Cache manager
-     *
-     * @var \VuFind\Cache\Manager
-     */
-    protected $cacheManager;
-
-    /**
-     * Cache of loaded search specs.
-     *
-     * @var array
-     */
-    protected $searchSpecs = [];
-
     /**
      * Constructor
      *
@@ -60,96 +45,7 @@ class SearchSpecsReader
      */
     public function __construct(\VuFind\Cache\Manager $cacheManager = null)
     {
-        $this->cacheManager = $cacheManager;
-    }
-
-    /**
-     * Return search specs
-     *
-     * @param string $filename config file name
-     *
-     * @return array
-     */
-    public function get($filename)
-    {
-        // Load data if it is not already in the object's cache:
-        if (!isset($this->searchSpecs[$filename])) {
-            $this->searchSpecs[$filename] = $this->getFromPaths(
-                Locator::getBaseConfigPath($filename),
-                Locator::getLocalConfigPath($filename)
-            );
-        }
-
-        return $this->searchSpecs[$filename];
-    }
-
-    /**
-     * Given core and local filenames, retrieve the searchspecs data.
-     *
-     * @param string $defaultFile Full path to file containing default YAML
-     * @param string $customFile  Full path to file containing local customizations
-     * (may be null if no local file exists).
-     *
-     * @return array
-     */
-    protected function getFromPaths($defaultFile, $customFile = null)
-    {
-        // Connect to searchspecs cache:
-        $cache = (null !== $this->cacheManager)
-            ? $this->cacheManager->getCache('searchspecs') : false;
-
-        // Generate cache key:
-        $cacheKey = basename($defaultFile) . '-'
-            . (file_exists($defaultFile) ? filemtime($defaultFile) : 0);
-        if (!empty($customFile)) {
-            $cacheKey .= '-local-' . filemtime($customFile);
-        }
-        $cacheKey = md5($cacheKey);
-
-        // Generate data if not found in cache:
-        if ($cache === false || !($results = $cache->getItem($cacheKey))) {
-            $results = $this->parseYaml($customFile, $defaultFile);
-            if ($cache !== false) {
-                $cache->setItem($cacheKey, $results);
-            }
-        }
-
-        return $results;
-    }
-
-    /**
-     * Process a YAML file (and its parent, if necessary).
-     *
-     * @param string $file          YAML file to load (will evaluate to empty array
-     * if file does not exist).
-     * @param string $defaultParent Parent YAML file from which $file should
-     * inherit (unless overridden by a specific directive in $file). None by
-     * default.
-     *
-     * @return array
-     */
-    protected function parseYaml($file, $defaultParent = null)
-    {
-        // First load current file:
-        $results = (!empty($file) && file_exists($file))
-            ? Yaml::parse(file_get_contents($file)) : [];
-
-        // Override default parent with explicitly-defined parent, if present:
-        if (isset($results['@parent_yaml'])) {
-            $defaultParent = $results['@parent_yaml'];
-            // Swallow the directive after processing it:
-            unset($results['@parent_yaml']);
-        }
-
-        // Now load in missing sections from parent, if applicable:
-        if (null !== $defaultParent) {
-            foreach ($this->parseYaml($defaultParent) as $section => $contents) {
-                if (!isset($results[$section])) {
-                    $results[$section] = $contents;
-                }
-            }
-        }
-
-        return $results;
+        parent::__construct($cacheManager);
+        $this->cacheName = 'searchspecs';
     }
 }
diff --git a/module/VuFind/src/VuFind/Config/Upgrade.php b/module/VuFind/src/VuFind/Config/Upgrade.php
index e013148a35545bc4015760a7297c79406d3c974f..f1ebe2ed79f3e58389c7926b162270b3b5f51a81 100644
--- a/module/VuFind/src/VuFind/Config/Upgrade.php
+++ b/module/VuFind/src/VuFind/Config/Upgrade.php
@@ -431,7 +431,7 @@ class Upgrade
      *
      * @return void
      */
-    protected function checkTheme($setting, $default)
+    protected function checkTheme($setting, $default = null)
     {
         // If a setting is not set, there is nothing to check:
         $theme = isset($this->newConfigs['config.ini']['Site'][$setting])
@@ -446,13 +446,21 @@ class Upgrade
         if (!file_exists(APPLICATION_PATH . '/themes/' . $theme)
             || !is_dir(APPLICATION_PATH . '/themes/' . $theme)
         ) {
-            $this->addWarning(
-                "WARNING: This version of VuFind does not support "
-                . "the {$theme} theme.  Your config.ini [Site] {$setting} setting "
-                . "has been reset to the default: {$default}.  You may need to "
-                . "reimplement your custom theme."
-            );
-            $this->newConfigs['config.ini']['Site'][$setting] = $default;
+            if ($default === null) {
+                $this->addWarning(
+                    "WARNING: This version of VuFind does not support the {$theme} "
+                    . "theme. As such, we have disabled your {$setting} setting."
+                );
+                unset($this->newConfigs['config.ini']['Site'][$setting]);
+            } else {
+                $this->addWarning(
+                    "WARNING: This version of VuFind does not support "
+                    . "the {$theme} theme. Your config.ini [Site] {$setting} setting"
+                    . " has been reset to the default: {$default}. You may need to "
+                    . "reimplement your custom theme."
+                );
+                $this->newConfigs['config.ini']['Site'][$setting] = $default;
+            }
         }
     }
 
@@ -544,6 +552,15 @@ class Upgrade
             unset($newConfig['BulkExport']['options']);
         }
 
+        // If [Statistics] is present, warn the user about its deprecation.
+        if (isset($newConfig['Statistics'])) {
+            $this->addWarning(
+                'The Statistics module has been removed from Vufind. ' .
+                'For usage tracking, please configure Google Analytics or Piwik.'
+            );
+            unset($newConfig['Statistics']);
+        }
+
         // Warn the user about Amazon configuration issues:
         $this->checkAmazonConfig($newConfig);
 
@@ -555,6 +572,16 @@ class Upgrade
                 . 'longer supported due to changes in Google APIs.'
             );
         }
+        if (isset($newConfig['Content']['recordMap'])
+            && 'google' == strtolower($newConfig['Content']['recordMap'])
+        ) {
+            unset($newConfig['Content']['recordMap']);
+            unset($newConfig['Content']['googleMapApiKey']);
+            $this->addWarning(
+                'Google Maps is no longer a supported Content/recordMap option;'
+                . ' please review your config.ini.'
+            );
+        }
         if (isset($newConfig['GoogleAnalytics']['apiKey'])) {
             if (!isset($newConfig['GoogleAnalytics']['universal'])
                 || !$newConfig['GoogleAnalytics']['universal']
@@ -611,7 +638,7 @@ class Upgrade
 
         // Warn the user if they are using an unsupported theme:
         $this->checkTheme('theme', 'bootprint3');
-        $this->checkTheme('mobile_theme', 'jquerymobile');
+        $this->checkTheme('mobile_theme', null);
 
         // Translate legacy auth settings:
         if (strtolower($newConfig['Authentication']['method']) == 'db') {
@@ -636,17 +663,6 @@ class Upgrade
         // Eliminate obsolete config override settings:
         unset($newConfig['Extra_Config']);
 
-        // Update stats settings:
-        if (isset($newConfig['Statistics']['enabled'])) {
-            // If "enabled" is on, this equates to the new system being in Solr mode:
-            if ($newConfig['Statistics']['enabled']) {
-                $newConfig['Statistics']['mode'] = ['Solr'];
-            }
-
-            // Whether or not "enabled" is on, remove the deprecated setting:
-            unset($newConfig['Statistics']['enabled']);
-        }
-
         // Update generator if it is default value:
         if (isset($newConfig['Site']['generator'])
             && $newConfig['Site']['generator'] == 'VuFind ' . $this->from
diff --git a/module/VuFind/src/VuFind/Config/Writer.php b/module/VuFind/src/VuFind/Config/Writer.php
index 16eac6f366d3e9281da86cb7213460e4453c8eeb..dc56420cf43ba1ff3dda51e543e59a3c167f0e0b 100644
--- a/module/VuFind/src/VuFind/Config/Writer.php
+++ b/module/VuFind/src/VuFind/Config/Writer.php
@@ -120,6 +120,13 @@ class Writer
             } else if (strstr($content, '=')) {
                 $contentParts = explode('=', $content, 2);
                 $key = trim($contentParts[0]);
+                // If the key we are trying to set is already present as an array,
+                // we need to clear out the multiple existing values before writing
+                // in a new one:
+                if ($key == $setting . '[]') {
+                    continue;
+                }
+                // Standard case for match on section + key:
                 if ($currentSection == $section && $key == $setting) {
                     $settingSet = true;
                     if ($value === null) {
@@ -231,6 +238,18 @@ class Writer
             $tabStr .= ' ';
         }
 
+        // Special case: if value is an array, we need to adjust the key
+        // accordingly:
+        if (is_array($value)) {
+            $retVal = '';
+            foreach ($value as $current) {
+                $retVal .= $key . '[]' . $tabStr . " = "
+                    . $this->buildContentValue($current);
+            }
+            return $retVal;
+        }
+
+        // Standard case: value is not an array:
         return $key . $tabStr . " = " . $this->buildContentValue($value);
     }
 
diff --git a/module/VuFind/src/VuFind/Config/YamlReader.php b/module/VuFind/src/VuFind/Config/YamlReader.php
new file mode 100644
index 0000000000000000000000000000000000000000..2e14bb4f7e1e1e63f7d6d45bbaa126419ace27b3
--- /dev/null
+++ b/module/VuFind/src/VuFind/Config/YamlReader.php
@@ -0,0 +1,162 @@
+<?php
+/**
+ * VuFind YAML Configuration Reader
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2010.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * @category VuFind
+ * @package  Config
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org Main Site
+ */
+namespace VuFind\Config;
+use Symfony\Component\Yaml\Yaml;
+
+/**
+ * VuFind YAML Configuration Reader
+ *
+ * @category VuFind
+ * @package  Config
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org Main Site
+ */
+class YamlReader
+{
+    /**
+     * Cache directory name
+     *
+     * @var string
+     */
+    protected $cacheName = 'yaml';
+
+    /**
+     * Cache manager
+     *
+     * @var \VuFind\Cache\Manager
+     */
+    protected $cacheManager;
+
+    /**
+     * Cache of loaded files.
+     *
+     * @var array
+     */
+    protected $files = [];
+
+    /**
+     * Constructor
+     *
+     * @param \VuFind\Cache\Manager $cacheManager Cache manager (optional)
+     */
+    public function __construct(\VuFind\Cache\Manager $cacheManager = null)
+    {
+        $this->cacheManager = $cacheManager;
+    }
+
+    /**
+     * Return a configuration
+     *
+     * @param string $filename config file name
+     *
+     * @return array
+     */
+    public function get($filename)
+    {
+        // Load data if it is not already in the object's cache:
+        if (!isset($this->files[$filename])) {
+            $this->files[$filename] = $this->getFromPaths(
+                Locator::getBaseConfigPath($filename),
+                Locator::getLocalConfigPath($filename)
+            );
+        }
+
+        return $this->files[$filename];
+    }
+
+    /**
+     * Given core and local filenames, retrieve the configuration data.
+     *
+     * @param string $defaultFile Full path to file containing default YAML
+     * @param string $customFile  Full path to file containing local customizations
+     * (may be null if no local file exists).
+     *
+     * @return array
+     */
+    protected function getFromPaths($defaultFile, $customFile = null)
+    {
+        // Connect to the cache:
+        $cache = (null !== $this->cacheManager)
+            ? $this->cacheManager->getCache($this->cacheName) : false;
+
+        // Generate cache key:
+        $cacheKey = basename($defaultFile) . '-'
+            . (file_exists($defaultFile) ? filemtime($defaultFile) : 0);
+        if (!empty($customFile)) {
+            $cacheKey .= '-local-' . filemtime($customFile);
+        }
+        $cacheKey = md5($cacheKey);
+
+        // Generate data if not found in cache:
+        if ($cache === false || !($results = $cache->getItem($cacheKey))) {
+            $results = $this->parseYaml($customFile, $defaultFile);
+            if ($cache !== false) {
+                $cache->setItem($cacheKey, $results);
+            }
+        }
+
+        return $results;
+    }
+
+    /**
+     * Process a YAML file (and its parent, if necessary).
+     *
+     * @param string $file          YAML file to load (will evaluate to empty array
+     * if file does not exist).
+     * @param string $defaultParent Parent YAML file from which $file should
+     * inherit (unless overridden by a specific directive in $file). None by
+     * default.
+     *
+     * @return array
+     */
+    protected function parseYaml($file, $defaultParent = null)
+    {
+        // First load current file:
+        $results = (!empty($file) && file_exists($file))
+            ? Yaml::parse(file_get_contents($file)) : [];
+
+        // Override default parent with explicitly-defined parent, if present:
+        if (isset($results['@parent_yaml'])) {
+            $defaultParent = $results['@parent_yaml'];
+            // Swallow the directive after processing it:
+            unset($results['@parent_yaml']);
+        }
+
+        // Now load in missing sections from parent, if applicable:
+        if (null !== $defaultParent) {
+            foreach ($this->parseYaml($defaultParent) as $section => $contents) {
+                if (!isset($results[$section])) {
+                    $results[$section] = $contents;
+                }
+            }
+        }
+
+        return $results;
+    }
+}
diff --git a/module/VuFind/src/VuFind/Connection/Oracle.php b/module/VuFind/src/VuFind/Connection/Oracle.php
index 24054d5ad6666580220cd53fa6f27a0d666e414d..aa73b4015ad8447c607ec750f29d8cfd12a27654 100644
--- a/module/VuFind/src/VuFind/Connection/Oracle.php
+++ b/module/VuFind/src/VuFind/Connection/Oracle.php
@@ -201,10 +201,11 @@ class Oracle
     public function bindParam(
         $parsed, $place_holder, $data, $data_type = 'string', $length = -1
     ) {
-        if (@oci_bind_by_name(
+        $success = @oci_bind_by_name(
             $parsed, $place_holder, $data, $length,
             $this->getDataTypeConstant($data_type)
-        )) {
+        );
+        if ($success) {
             return true;
         } else {
             $this->handleError('binding', oci_error());
@@ -234,10 +235,11 @@ class Oracle
     public function returnParam(
         $parsed, $place_holder, &$data, $data_type = 'string', $length = -1
     ) {
-        if (@oci_bind_by_name(
+        $success = @oci_bind_by_name(
             $parsed, $place_holder, $data, $length,
             $this->getDataTypeConstant($data_type)
-        )) {
+        );
+        if ($success) {
             return true;
         } else {
             $this->handleError('binding', oci_error());
diff --git a/module/VuFind/src/VuFind/Content/Covers/LocalFile.php b/module/VuFind/src/VuFind/Content/Covers/LocalFile.php
new file mode 100644
index 0000000000000000000000000000000000000000..94d5c30e5b89bc16a4b0b7f890f555fd73cb2de5
--- /dev/null
+++ b/module/VuFind/src/VuFind/Content/Covers/LocalFile.php
@@ -0,0 +1,155 @@
+<?php
+/**
+ * LocalFile cover content loader.
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2010.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * @category VuFind
+ * @package  Content
+ * @author   Leila Gonzales <lmg@agiweb.org>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development Wiki
+ */
+namespace VuFind\Content\Covers;
+
+/**
+ * Local file cover content loader.
+ *
+ * @category VuFind
+ * @package  Content
+ * @author   Leila Gonzales <lmg@agiweb.org>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development Wiki
+ */
+class LocalFile extends \VuFind\Content\AbstractCover
+{
+    /**
+     * Image file extensions to look for when using %anyimage% token.
+     *
+     * @var array
+     */
+    protected $imageExtensions = ["gif", "jpg", "jpeg", "png", "tif", "tiff"];
+
+    /**
+     * MIME types allowed to be loaded from disk.
+     *
+     * @var array
+     */
+    protected $allowedMimeTypes = [
+        "image/gif", "image/jpeg", "image/png", "image/tiff"
+    ];
+
+    /**
+     * Does this plugin support the provided ID array?
+     *
+     * @param array $ids IDs that will later be sent to load() -- see below.
+     *
+     * @return bool
+     */
+    public function supports($ids)
+    {
+        // We won't know what we need until we parse the path string; accept
+        // everything at this stage:
+        return true;
+    }
+
+    /**
+     * Get image location from local file storage.
+     *
+     * @param string $key  local file directory path
+     * @param string $size Size of image to load (small/medium/large)
+     * @param array  $ids  Associative array of identifiers (keys may include 'isbn'
+     * pointing to an ISBN object and 'issn' pointing to a string)
+     *
+     * @return string|bool
+     */
+    public function getUrl($key, $size, $ids)
+    {
+        // convert all of the tokens:
+        $fileName = $this->replaceImageTypeTokens(
+            $this->replaceEnvironmentAndIdTokens($key, $ids)
+        );
+        // Validate MIME type if we have a valid file path.
+        if ($fileName && file_exists($fileName)) {
+            if (in_array(mime_content_type($fileName), $this->allowedMimeTypes)) {
+                return "file://" . $fileName;
+            }
+        }
+        // If we got this far, we couldn't find a match.
+        return false;
+    }
+
+    /**
+     * Convert tokens to ids array values.
+     *
+     * @param string $filePath file path of image file
+     * @param array  $ids      Associative array of identifiers
+     * (keys may include 'isbn' pointing to an ISBN object and
+     * 'issn' pointing to a string)
+     *
+     * @return string
+     */
+    protected function replaceEnvironmentAndIdTokens($filePath, $ids)
+    {
+        // Seed the token array with standard environment variables:
+        $tokens = ['%vufind-home%', '%vufind-local-dir%'];
+        $replacements = [APPLICATION_PATH, LOCAL_OVERRIDE_DIR];
+
+        // Only create tokens for strings, not objects:
+        foreach ($ids as $key => $val) {
+            if (is_string($val)) {
+                $tokens[] = '%' . $key . '%';
+                $replacements[] = $val;
+            }
+        }
+        // Special-case handling for ISBN object:
+        if (isset($ids['isbn'])) {
+            $tokens[] = '%isbn10%';
+            $replacements[] = $ids['isbn']->get10();
+
+            $tokens[] = '%isbn13%';
+            $replacements[] = $ids['isbn']->get13();
+        }
+        return str_replace($tokens, $replacements, $filePath);
+    }
+
+    /**
+     * Convert tokens to image type file extension.
+     *
+     * @param string $fileName file path of image file
+     *
+     * @return bool|string
+     */
+    protected function replaceImageTypeTokens($fileName)
+    {
+        // If anyimage is specified, then we loop through all
+        // image extensions to find the right filename
+        if (strstr($fileName, '%anyimage%')) {
+            foreach ($this->imageExtensions as $val) {
+                foreach ([$val, strtoupper($val), ucwords($val)] as $finalVal) {
+                    $checkFile = str_replace('%anyimage%', $finalVal, $fileName);
+                    if (file_exists($checkFile)) {
+                         return $checkFile;
+                    }
+                }
+            }
+        }
+        // Default behavior: do not modify filename:
+        return $fileName;
+    }
+}
diff --git a/module/VuFind/src/VuFind/Controller/AbstractBase.php b/module/VuFind/src/VuFind/Controller/AbstractBase.php
index d5c19c2a06bd125106437880ccfafb2c5f457b74..86f20e4325cac2e1d3b3040518078534fb6abe82 100644
--- a/module/VuFind/src/VuFind/Controller/AbstractBase.php
+++ b/module/VuFind/src/VuFind/Controller/AbstractBase.php
@@ -32,6 +32,7 @@ use VuFind\Exception\Forbidden as ForbiddenException,
     VuFind\Exception\ILS as ILSException,
     Zend\Mvc\Controller\AbstractActionController,
     Zend\Mvc\MvcEvent,
+    Zend\ServiceManager\ServiceLocatorInterface,
     Zend\View\Model\ViewModel,
     ZfcRbac\Service\AuthorizationServiceAwareInterface,
     ZfcRbac\Service\AuthorizationServiceAwareTrait;
@@ -58,6 +59,23 @@ class AbstractBase extends AbstractActionController
      */
     protected $accessPermission = false;
 
+    /**
+     * Behavior when access is denied. Valid values are 'promptLogin' and 'exception'
+     *
+     * @var string
+     */
+    protected $accessDeniedBehavior = 'promptLogin';
+
+    /**
+     * Constructor
+     *
+     * @param ServiceLocatorInterface $sm Service locator
+     */
+    public function __construct(ServiceLocatorInterface $sm)
+    {
+        $this->setServiceLocator($sm);
+    }
+
     /**
      * Use preDispatch event to block access when appropriate.
      *
@@ -71,9 +89,11 @@ class AbstractBase extends AbstractActionController
         if ($this->accessPermission
             && !$this->getAuthorizationService()->isGranted($this->accessPermission)
         ) {
-            if (!$this->getUser()) {
-                $e->setResponse($this->forceLogin(null, [], false));
-                return;
+            if ($this->accessDeniedBehavior == 'promptLogin') {
+                if (!$this->getUser()) {
+                    $e->setResponse($this->forceLogin(null, [], false));
+                    return;
+                }
             }
             throw new ForbiddenException('Access denied.');
         }
@@ -96,15 +116,6 @@ class AbstractBase extends AbstractActionController
         }
     }
 
-    /**
-     * Constructor
-     */
-    public function __construct()
-    {
-        // Placeholder so child classes can call parent::__construct() in case
-        // of future global behavior.
-    }
-
     /**
      * Create a new ViewModel.
      *
@@ -114,9 +125,9 @@ class AbstractBase extends AbstractActionController
      */
     protected function createViewModel($params = null)
     {
-        if ('lightbox' === $this->params()->fromPost(
-            'layout', $this->params()->fromQuery('layout', false)
-        )) {
+        $layout = $this->params()
+            ->fromPost('layout', $this->params()->fromQuery('layout', false));
+        if ('lightbox' === $layout) {
             $this->layout()->setTemplate('layout/lightbox');
         }
         return new ViewModel($params);
@@ -136,7 +147,7 @@ class AbstractBase extends AbstractActionController
         $view = $this->createViewModel($params);
 
         // Load configuration and current user for convenience:
-        $config = $this->getServiceLocator()->get('VuFind\Config')->get('config');
+        $config = $this->serviceLocator->get('VuFind\Config')->get('config');
         $view->disableFrom
             = (isset($config->Mail->disable_from) && $config->Mail->disable_from);
         $view->editableSubject = isset($config->Mail->user_editable_subjects)
@@ -200,7 +211,7 @@ class AbstractBase extends AbstractActionController
      */
     protected function getAuthManager()
     {
-        return $this->getServiceLocator()->get('VuFind\AuthManager');
+        return $this->serviceLocator->get('VuFind\AuthManager');
     }
 
     /**
@@ -212,7 +223,7 @@ class AbstractBase extends AbstractActionController
      */
     protected function getAuthorizationService()
     {
-        return $this->getServiceLocator()
+        return $this->serviceLocator
             ->get('ZfcRbac\Service\AuthorizationService');
     }
 
@@ -223,7 +234,7 @@ class AbstractBase extends AbstractActionController
      */
     protected function getILSAuthenticator()
     {
-        return $this->getServiceLocator()->get('VuFind\ILSAuthenticator');
+        return $this->serviceLocator->get('VuFind\ILSAuthenticator');
     }
 
     /**
@@ -243,7 +254,7 @@ class AbstractBase extends AbstractActionController
      */
     protected function getViewRenderer()
     {
-        return $this->getServiceLocator()->get('viewmanager')->getRenderer();
+        return $this->serviceLocator->get('ViewRenderer');
     }
 
     /**
@@ -349,7 +360,7 @@ class AbstractBase extends AbstractActionController
      */
     public function getConfig($id = 'config')
     {
-        return $this->getServiceLocator()->get('VuFind\Config')->get($id);
+        return $this->serviceLocator->get('VuFind\Config')->get($id);
     }
 
     /**
@@ -359,7 +370,7 @@ class AbstractBase extends AbstractActionController
      */
     public function getILS()
     {
-        return $this->getServiceLocator()->get('VuFind\ILSConnection');
+        return $this->serviceLocator->get('VuFind\ILSConnection');
     }
 
     /**
@@ -369,7 +380,7 @@ class AbstractBase extends AbstractActionController
      */
     public function getRecordLoader()
     {
-        return $this->getServiceLocator()->get('VuFind\RecordLoader');
+        return $this->serviceLocator->get('VuFind\RecordLoader');
     }
 
     /**
@@ -379,7 +390,7 @@ class AbstractBase extends AbstractActionController
      */
     public function getRecordCache()
     {
-        return $this->getServiceLocator()->get('VuFind\RecordCache');
+        return $this->serviceLocator->get('VuFind\RecordCache');
     }
 
     /**
@@ -389,7 +400,7 @@ class AbstractBase extends AbstractActionController
      */
     public function getRecordRouter()
     {
-        return $this->getServiceLocator()->get('VuFind\RecordRouter');
+        return $this->serviceLocator->get('VuFind\RecordRouter');
     }
 
     /**
@@ -401,7 +412,7 @@ class AbstractBase extends AbstractActionController
      */
     public function getTable($table)
     {
-        return $this->getServiceLocator()->get('VuFind\DbTablePluginManager')
+        return $this->serviceLocator->get('VuFind\DbTablePluginManager')
             ->get($table);
     }
 
@@ -512,7 +523,7 @@ class AbstractBase extends AbstractActionController
      */
     protected function disableSessionWrites()
     {
-        $this->getServiceLocator()->get('VuFind\Session\Settings')->disableWrite();
+        $this->serviceLocator->get('VuFind\Session\Settings')->disableWrite();
     }
 
     /**
@@ -522,7 +533,7 @@ class AbstractBase extends AbstractActionController
      */
     public function getSearchMemory()
     {
-        return $this->getServiceLocator()->get('VuFind\Search\Memory');
+        return $this->serviceLocator->get('VuFind\Search\Memory');
     }
 
     /**
@@ -532,7 +543,7 @@ class AbstractBase extends AbstractActionController
      */
     protected function commentsEnabled()
     {
-        $check = $this->getServiceLocator()->get('VuFind\AccountCapabilities');
+        $check = $this->serviceLocator->get('VuFind\AccountCapabilities');
         return $check->getCommentSetting() !== 'disabled';
     }
 
@@ -543,7 +554,7 @@ class AbstractBase extends AbstractActionController
      */
     protected function listsEnabled()
     {
-        $check = $this->getServiceLocator()->get('VuFind\AccountCapabilities');
+        $check = $this->serviceLocator->get('VuFind\AccountCapabilities');
         return $check->getListSetting() !== 'disabled';
     }
 
@@ -554,7 +565,7 @@ class AbstractBase extends AbstractActionController
      */
     protected function tagsEnabled()
     {
-        $check = $this->getServiceLocator()->get('VuFind\AccountCapabilities');
+        $check = $this->serviceLocator->get('VuFind\AccountCapabilities');
         return $check->getTagSetting() !== 'disabled';
     }
 
@@ -645,7 +656,7 @@ class AbstractBase extends AbstractActionController
      */
     protected function getRecordTabConfig()
     {
-        $cfg = $this->getServiceLocator()->get('Config');
+        $cfg = $this->serviceLocator->get('Config');
         return $cfg['vufind']['recorddriver_tabs'];
     }
 }
diff --git a/module/VuFind/src/VuFind/Controller/AbstractRecord.php b/module/VuFind/src/VuFind/Controller/AbstractRecord.php
index 7ea90a10dba3ca1796b86e05966640ce39671f53..f93093044793e7ddb07421bad656e91709222326 100644
--- a/module/VuFind/src/VuFind/Controller/AbstractRecord.php
+++ b/module/VuFind/src/VuFind/Controller/AbstractRecord.php
@@ -69,13 +69,6 @@ class AbstractRecord extends AbstractBase
      */
     protected $searchClassId = 'Solr';
 
-    /**
-     * Should we log statistics?
-     *
-     * @var bool
-     */
-    protected $logStatistics = true;
-
     /**
      * Record driver
      *
@@ -204,7 +197,7 @@ class AbstractRecord extends AbstractBase
 
         // Save tags, if any:
         if ($tags = $this->params()->fromPost('tag')) {
-            $tagParser = $this->getServiceLocator()->get('VuFind\Tags');
+            $tagParser = $this->serviceLocator->get('VuFind\Tags');
             $driver->addTags($user, $tagParser->parse($tags));
             $this->flashMessenger()
                 ->addMessage(['msg' => 'add_tag_success'], 'success');
@@ -258,12 +251,6 @@ class AbstractRecord extends AbstractBase
      */
     public function homeAction()
     {
-        // Save statistics:
-        if ($this->logStatistics) {
-            $this->getServiceLocator()->get('VuFind\RecordStats')
-                ->log($this->loadRecord(), $this->getRequest());
-        }
-
         return $this->showTab(
             $this->params()->fromRoute('tab', $this->getDefaultTab())
         );
@@ -299,10 +286,12 @@ class AbstractRecord extends AbstractBase
         // Perform the save operation:
         $driver = $this->loadRecord();
         $post = $this->getRequest()->getPost()->toArray();
-        $tagParser = $this->getServiceLocator()->get('VuFind\Tags');
+        $tagParser = $this->serviceLocator->get('VuFind\Tags');
         $post['mytags']
             = $tagParser->parse(isset($post['mytags']) ? $post['mytags'] : '');
-        $results = $driver->saveToFavorites($post, $user);
+        $favorites = $this->serviceLocator
+            ->get('VuFind\Favorites\FavoritesService');
+        $results = $favorites->save($post, $user, $driver);
 
         // Display a success status message:
         $listUrl = $this->url()->fromRoute('userList', ['id' => $results['listId']]);
@@ -419,7 +408,7 @@ class AbstractRecord extends AbstractBase
         $driver = $this->loadRecord();
 
         // Create view
-        $mailer = $this->getServiceLocator()->get('VuFind\Mailer');
+        $mailer = $this->serviceLocator->get('VuFind\Mailer');
         $view = $this->createEmailViewModel(
             null, $mailer->getDefaultRecordSubject($driver)
         );
@@ -449,6 +438,17 @@ class AbstractRecord extends AbstractBase
         return $view;
     }
 
+    /**
+     * Is SMS enabled?
+     *
+     * @return bool
+     */
+    protected function smsEnabled()
+    {
+        $check = $this->serviceLocator->get('VuFind\AccountCapabilities');
+        return $check->getSmsSetting() !== 'disabled';
+    }
+
     /**
      * SMS action - Allows the SMS form to appear.
      *
@@ -456,11 +456,16 @@ class AbstractRecord extends AbstractBase
      */
     public function smsAction()
     {
+        // Make sure comments are enabled:
+        if (!$this->smsEnabled()) {
+            throw new ForbiddenException('SMS disabled');
+        }
+
         // Retrieve the record driver:
         $driver = $this->loadRecord();
 
         // Load the SMS carrier list:
-        $sms = $this->getServiceLocator()->get('VuFind\SMS');
+        $sms = $this->serviceLocator->get('VuFind\SMS');
         $view = $this->createViewModel();
         $view->carriers = $sms->getCarriers();
         $view->validation = $sms->getValidationType();
@@ -515,7 +520,7 @@ class AbstractRecord extends AbstractBase
         $format = $this->params()->fromQuery('style');
 
         // Display export menu if missing/invalid option
-        $export = $this->getServiceLocator()->get('VuFind\Export');
+        $export = $this->serviceLocator->get('VuFind\Export');
         if (empty($format) || !$export->recordSupportsFormat($driver, $format)) {
             if (!empty($format)) {
                 $this->flashMessenger()
@@ -601,15 +606,6 @@ class AbstractRecord extends AbstractBase
             ->getTabRouteDetails($this->loadRecord(), $tab);
         $target = $this->url()->fromRoute($details['route'], $details['params']);
 
-        // Special case: don't use anchors in jquerymobile theme, since they
-        // mess things up!
-        if (strlen($params) && substr($params, 0, 1) == '#') {
-            $themeInfo = $this->getServiceLocator()->get('VuFindTheme\ThemeInfo');
-            if ($themeInfo->getTheme() == 'jquerymobile') {
-                $params = '';
-            }
-        }
-
         return $this->redirect()->toUrl($target . $params);
     }
 
@@ -634,7 +630,7 @@ class AbstractRecord extends AbstractBase
     {
         $driver = $this->loadRecord();
         $request = $this->getRequest();
-        $rtpm = $this->getServiceLocator()->get('VuFind\RecordTabPluginManager');
+        $rtpm = $this->serviceLocator->get('VuFind\RecordTabPluginManager');
         $details = $rtpm->getTabDetailsForRecord(
             $driver, $this->getRecordTabConfig(), $request,
             $this->fallbackDefaultTab
diff --git a/module/VuFind/src/VuFind/Controller/AbstractSearch.php b/module/VuFind/src/VuFind/Controller/AbstractSearch.php
index 6ce2ba82bb7bc6323c664d172f788aaa3c4e632f..0d88e634b10ecaf377758a982506392b0c0e030d 100644
--- a/module/VuFind/src/VuFind/Controller/AbstractSearch.php
+++ b/module/VuFind/src/VuFind/Controller/AbstractSearch.php
@@ -54,13 +54,6 @@ class AbstractSearch extends AbstractBase
      */
     protected $saveToHistory = true;
 
-    /**
-     * Should we log search statistics?
-     *
-     * @var bool
-     */
-    protected $logStatistics = true;
-
     /**
      * Should we remember the search for breadcrumb purposes?
      *
@@ -68,15 +61,6 @@ class AbstractSearch extends AbstractBase
      */
     protected $rememberSearch = true;
 
-    /**
-     * Constructor
-     */
-    public function __construct()
-    {
-        // Placeholder so child classes can call parent::__construct() in case
-        // of future global behavior.
-    }
-
     /**
      * Create a new ViewModel.
      *
@@ -99,7 +83,7 @@ class AbstractSearch extends AbstractBase
     public function advancedAction()
     {
         $view = $this->createViewModel();
-        $view->options = $this->getServiceLocator()
+        $view->options = $this->serviceLocator
             ->get('VuFind\SearchOptionsPluginManager')->get($this->searchClassId);
         if ($view->options->getAdvancedSearchAction() === false) {
             throw new \Exception('Advanced search not supported.');
@@ -115,7 +99,7 @@ class AbstractSearch extends AbstractBase
         // If we have default filters, set them up as a fake "saved" search
         // to properly populate special controls on the advanced screen.
         if (!$view->saved && count($view->options->getDefaultFilters()) > 0) {
-            $view->saved = $this->getServiceLocator()
+            $view->saved = $this->serviceLocator
                 ->get('VuFind\SearchResultsPluginManager')
                 ->get($this->searchClassId);
             $view->saved->getParams()->initFromRequest(
@@ -228,7 +212,7 @@ class AbstractSearch extends AbstractBase
             return null;
         }
 
-        $rManager = $this->getServiceLocator()->get('VuFind\RecommendPluginManager');
+        $rManager = $this->serviceLocator->get('VuFind\RecommendPluginManager');
 
         // Special case: override recommend settings through parameter (used by
         // combined search)
@@ -271,7 +255,7 @@ class AbstractSearch extends AbstractBase
             return $this->redirectToSavedSearch($savedId);
         }
 
-        $runner = $this->getServiceLocator()->get('VuFind\SearchRunner');
+        $runner = $this->serviceLocator->get('VuFind\SearchRunner');
 
         // Send both GET and POST variables to search class:
         $request = $this->getRequest()->getQuery()->toArray()
@@ -311,12 +295,6 @@ class AbstractSearch extends AbstractBase
             }
         }
 
-        // Save statistics:
-        if ($this->logStatistics) {
-            $this->getServiceLocator()->get('VuFind\SearchStats')
-                ->log($results, $this->getRequest());
-        }
-
         // Special case: If we're in RSS view, we need to render differently:
         if (isset($view->params) && $view->params->getView() == 'rss') {
             $response = $this->getResponse();
@@ -327,7 +305,7 @@ class AbstractSearch extends AbstractBase
         }
 
         // Search toolbar
-        $config = $this->getServiceLocator()->get('VuFind\Config')->get('config');
+        $config = $this->serviceLocator->get('VuFind\Config')->get('config');
         $view->showBulkOptions = isset($config->Site->showBulkOptions)
           && $config->Site->showBulkOptions;
 
@@ -346,7 +324,7 @@ class AbstractSearch extends AbstractBase
     {
         // Jump to only result, if configured
         $default = null;
-        $config = $this->getServiceLocator()->get('VuFind\Config')->get('config');
+        $config = $this->serviceLocator->get('VuFind\Config')->get('config');
         if (isset($config->Record->jump_to_single_search_result)
             && $config->Record->jump_to_single_search_result
             && $results->getResultTotal() == 1
@@ -383,7 +361,7 @@ class AbstractSearch extends AbstractBase
     protected function retrieveSearchSecurely($searchId)
     {
         $searchTable = $this->getTable('Search');
-        $sessId = $this->getServiceLocator()->get('VuFind\SessionManager')->getId();
+        $sessId = $this->serviceLocator->get('VuFind\SessionManager')->getId();
         $user = $this->getUser();
         $userId = $user ? $user->id : null;
         return $searchTable->getOwnedRowById($searchId, $sessId, $userId);
@@ -399,7 +377,7 @@ class AbstractSearch extends AbstractBase
     protected function saveSearchToHistory($results)
     {
         $user = $this->getUser();
-        $sessId = $this->getServiceLocator()->get('VuFind\SessionManager')->getId();
+        $sessId = $this->serviceLocator->get('VuFind\SessionManager')->getId();
         $history = $this->getTable('Search');
         $history->saveSearch(
             $this->getResultsManager(), $results, $sessId,
@@ -453,7 +431,7 @@ class AbstractSearch extends AbstractBase
      */
     protected function getResultsManager()
     {
-        return $this->getServiceLocator()->get('VuFind\SearchResultsPluginManager');
+        return $this->serviceLocator->get('VuFind\SearchResultsPluginManager');
     }
 
     /**
@@ -513,7 +491,7 @@ class AbstractSearch extends AbstractBase
      */
     protected function getRangeFieldList($config, $section, $filter)
     {
-        $config = $this->getServiceLocator()->get('VuFind\Config')->get($config);
+        $config = $this->serviceLocator->get('VuFind\Config')->get($config);
         $fields = isset($config->SpecialFacets->$section)
             ? $config->SpecialFacets->$section->toArray() : [];
 
@@ -666,7 +644,7 @@ class AbstractSearch extends AbstractBase
         $section = isset($params[1]) ? $params[1] : 'CheckboxFacets';
 
         // Load config file:
-        $config = $this->getServiceLocator()->get('VuFind\Config')->get($config);
+        $config = $this->serviceLocator->get('VuFind\Config')->get($config);
 
         // Process checkbox settings in config:
         if (substr($section, 0, 1) == '~') {        // reverse flag
@@ -724,7 +702,7 @@ class AbstractSearch extends AbstractBase
                 ? 'count'
                 : current(array_keys($facetSortOptions));
         }
-        $config = $this->getServiceLocator()->get('VuFind\Config')
+        $config = $this->serviceLocator->get('VuFind\Config')
             ->get($options->getFacetsIni());
         $limit = isset($config->Results_Settings->lightboxLimit)
             ? $config->Results_Settings->lightboxLimit
diff --git a/module/VuFind/src/VuFind/Controller/AjaxController.php b/module/VuFind/src/VuFind/Controller/AjaxController.php
index 2295756472bdcac3f58f9ef209241138fe02fc3f..2e7a6bdee092961f87d4b5fcd5ece0a42bbd7d81 100644
--- a/module/VuFind/src/VuFind/Controller/AjaxController.php
+++ b/module/VuFind/src/VuFind/Controller/AjaxController.php
@@ -27,6 +27,7 @@
  */
 namespace VuFind\Controller;
 use VuFind\Exception\Auth as AuthException;
+use Zend\ServiceManager\ServiceLocatorInterface;
 
 /**
  * This controller handles global AJAX functionality
@@ -60,11 +61,14 @@ class AjaxController extends AbstractBase
 
     /**
      * Constructor
+     *
+     * @param ServiceLocatorInterface $sm Service locator
      */
-    public function __construct()
+    public function __construct(ServiceLocatorInterface $sm)
     {
         // Add notices to a key in the output
         set_error_handler(['VuFind\Controller\AjaxController', "storeError"]);
+        parent::__construct($sm);
     }
 
     /**
@@ -110,7 +114,7 @@ class AjaxController extends AbstractBase
         // Process recommendations -- for now, we assume Solr-based search objects,
         // since deferred recommendations work best for modules that don't care about
         // the details of the search objects anyway:
-        $rm = $this->getServiceLocator()->get('VuFind\RecommendPluginManager');
+        $rm = $this->serviceLocator->get('VuFind\RecommendPluginManager');
         $module = $rm->get($this->params()->fromQuery('mod'));
         $module->setConfig($this->params()->fromQuery('params'));
         $results = $this->getResultsManager()->get('Solr');
@@ -143,7 +147,7 @@ class AjaxController extends AbstractBase
     {
         static $hideHoldings = false;
         if ($hideHoldings === false) {
-            $logic = $this->getServiceLocator()->get('VuFind\ILSHoldLogic');
+            $logic = $this->serviceLocator->get('VuFind\ILSHoldLogic');
             $hideHoldings = $logic->getSuppressedLocations();
         }
 
@@ -709,7 +713,7 @@ class AjaxController extends AbstractBase
                 $this->params()->fromPost('source', DEFAULT_SEARCH_BACKEND)
             );
             $tag = $this->params()->fromPost('tag', '');
-            $tagParser = $this->getServiceLocator()->get('VuFind\Tags');
+            $tagParser = $this->serviceLocator->get('VuFind\Tags');
             if (strlen($tag) > 0) { // don't add empty tags
                 if ('false' === $this->params()->fromPost('remove', 'false')) {
                     $driver->addTags($user, $tagParser->parse($tag));
@@ -783,10 +787,9 @@ class AjaxController extends AbstractBase
             trim(strtolower($this->params()->fromQuery('type')))
         );
         $request = $this->getRequest();
-        $config = $this->getServiceLocator()->get('Config');
-        $sconfig = $this->getServiceLocator()->get('VuFind\Config')->get('searches');
+        $config = $this->serviceLocator->get('Config');
 
-        $recordTabPlugin = $this->getServiceLocator()
+        $recordTabPlugin = $this->serviceLocator
             ->get('VuFind\RecordTabPluginManager');
         $details = $recordTabPlugin
             ->getTabDetailsForRecord(
@@ -796,7 +799,7 @@ class AjaxController extends AbstractBase
                 'Information'
             );
 
-        $rtpm = $this->getServiceLocator()->get('VuFind\RecordTabPluginManager');
+        $rtpm = $this->serviceLocator->get('VuFind\RecordTabPluginManager');
         $html = $this->getViewRenderer()
             ->render(
                 "record/ajaxview-" . $viewtype . ".phtml",
@@ -812,71 +815,6 @@ class AjaxController extends AbstractBase
         return $this->output($html, self::STATUS_OK);
     }
 
-    /**
-     * Get map data on search results and output in JSON
-     *
-     * @param array $fields Solr fields to retrieve data from
-     *
-     * @author Chris Hallberg <crhallberg@gmail.com>
-     * @author Lutz Biedinger <lutz.biedinger@gmail.com>
-     *
-     * @return \Zend\Http\Response
-     */
-    protected function getMapDataAjax($fields = ['long_lat'])
-    {
-        $this->disableSessionWrites();  // avoid session write timing bug
-        $results = $this->getResultsManager()->get('Solr');
-        $params = $results->getParams();
-        $params->initFromRequest($this->getRequest()->getQuery());
-
-        $facets = $results->getFullFieldFacets($fields, false);
-
-        $markers = [];
-        $i = 0;
-        $list = isset($facets['long_lat']['data']['list'])
-            ? $facets['long_lat']['data']['list'] : [];
-        foreach ($list as $location) {
-            $longLat = explode(',', $location['value']);
-            $markers[$i] = [
-                'title' => (string)$location['count'], //needs to be a string
-                'location_facet' =>
-                    $location['value'], //needed to load in the location
-                'lon' => $longLat[0],
-                'lat' => $longLat[1]
-            ];
-            $i++;
-        }
-        return $this->output($markers, self::STATUS_OK);
-    }
-
-    /**
-     * Get entry information on entries tied to a specific map location
-     *
-     * @author Chris Hallberg <crhallberg@gmail.com>
-     * @author Lutz Biedinger <lutz.biedinger@gmail.com>
-     *
-     * @return mixed
-     */
-    public function resultgooglemapinfoAction()
-    {
-        $this->disableSessionWrites();  // avoid session write timing bug
-        // Set layout to render content only:
-        $this->layout()->setTemplate('layout/lightbox');
-
-        $results = $this->getResultsManager()->get('Solr');
-        $params = $results->getParams();
-        $params->initFromRequest($this->getRequest()->getQuery());
-
-        return $this->createViewModel(
-            [
-                'results' => $results,
-                'recordSet' => $results->getResults(),
-                'recordCount' => $results->getResultTotal(),
-                'completeListUrl' => $results->getUrlQuery()->getParams()
-            ]
-        );
-    }
-
     /**
      * AJAX for timeline feature (PubDateVisAjax)
      *
@@ -909,9 +847,8 @@ class AjaxController extends AbstractBase
             $facets[$field]['removalURL']
                 = $results->getUrlQuery()->removeFacet(
                     $field,
-                    isset($filters[$field][0]) ? $filters[$field][0] : null,
-                    false
-                );
+                    isset($filters[$field][0]) ? $filters[$field][0] : null
+                )->getParams(false);
         }
         return $this->output($facets, self::STATUS_OK);
     }
@@ -984,7 +921,7 @@ class AjaxController extends AbstractBase
     {
         $this->disableSessionWrites();  // avoid session write timing bug
         $query = $this->getRequest()->getQuery();
-        $autocompleteManager = $this->getServiceLocator()
+        $autocompleteManager = $this->serviceLocator
             ->get('VuFind\AutocompletePluginManager');
         return $this->output(
             $autocompleteManager->getSuggestions($query), self::STATUS_OK
@@ -1026,20 +963,36 @@ class AjaxController extends AbstractBase
                 switch ($requestType) {
                 case 'ILLRequest':
                     $results = $catalog->checkILLRequestIsValid($id, $data, $patron);
-                    $msg = $results
-                        ? 'ill_request_place_text' : 'ill_request_error_blocked';
+                    if (is_array($results)) {
+                        $msg = $results['status'];
+                        $results = $results['valid'];
+                    } else {
+                        $msg = $results
+                            ? 'ill_request_place_text' : 'ill_request_error_blocked';
+                    }
                     break;
                 case 'StorageRetrievalRequest':
                     $results = $catalog->checkStorageRetrievalRequestIsValid(
                         $id, $data, $patron
                     );
-                    $msg = $results ? 'storage_retrieval_request_place_text'
-                        : 'storage_retrieval_request_error_blocked';
+                    if (is_array($results)) {
+                        $msg = $results['status'];
+                        $results = $results['valid'];
+                    } else {
+                        $msg = $results ? 'storage_retrieval_request_place_text'
+                            : 'storage_retrieval_request_error_blocked';
+                    }
                     break;
                 default:
                     $results = $catalog->checkRequestIsValid($id, $data, $patron);
-                    $msg = $results ? 'request_place_text' : 'hold_error_blocked';
-                    break;
+                    if (is_array($results)) {
+                        $msg = $results['status'];
+                        $results = $results['valid'];
+                    } else {
+                        $msg = $results ? 'request_place_text'
+                            : 'hold_error_blocked';
+                        break;
+                    }
                 }
                 return $this->output(
                     ['status' => $results, 'msg' => $this->translate($msg)],
@@ -1178,7 +1131,7 @@ class AjaxController extends AbstractBase
     protected function exportFavoritesAjax()
     {
         $format = $this->params()->fromPost('format');
-        $export = $this->getServiceLocator()->get('VuFind\Export');
+        $export = $this->serviceLocator->get('VuFind\Export');
         $url = $export->getBulkUrl(
             $this->getViewRenderer(), $format,
             $this->params()->fromPost('ids', [])
@@ -1214,7 +1167,7 @@ class AjaxController extends AbstractBase
         $config = $this->getConfig();
         $resolverType = isset($config->OpenURL->resolver)
             ? $config->OpenURL->resolver : 'other';
-        $pluginManager = $this->getServiceLocator()
+        $pluginManager = $this->serviceLocator
             ->get('VuFind\ResolverDriverPluginManager');
         if (!$pluginManager->has($resolverType)) {
             return $this->output(
@@ -1261,11 +1214,15 @@ class AjaxController extends AbstractBase
             $base = false;
         }
 
+        $moreOptionsLink = $resolver->supportsMoreOptionsLink()
+            ? $resolver->getResolverUrl($openUrl) : '';
+
         // Render the links using the view:
         $view = [
             'openUrlBase' => $base, 'openUrl' => $openUrl, 'print' => $print,
             'electronic' => $electronic, 'services' => $services,
-            'searchClassId' => $searchClassId
+            'searchClassId' => $searchClassId,
+            'moreOptionsLink' => $moreOptionsLink
         ];
         $html = $this->getViewRenderer()->render('ajax/resolverLinks.phtml', $view);
 
@@ -1284,7 +1241,7 @@ class AjaxController extends AbstractBase
     protected function keepAliveAjax()
     {
         // Request ID from session to mark it active
-        $this->getServiceLocator()->get('VuFind\SessionManager')->getId();
+        $this->serviceLocator->get('VuFind\SessionManager')->getId();
         return $this->output(true, self::STATUS_OK);
     }
 
@@ -1428,7 +1385,7 @@ class AjaxController extends AbstractBase
 
         $facetList = $facets[$facet]['data']['list'];
 
-        $facetHelper = $this->getServiceLocator()
+        $facetHelper = $this->serviceLocator
             ->get('VuFind\HierarchicalFacetHelper');
         if (!empty($sort)) {
             $facetHelper->sortFacetList($facetList, $sort == 'top');
@@ -1486,7 +1443,7 @@ class AjaxController extends AbstractBase
         }
 
         // This may be called frequently, don't leave sessions dangling
-        $this->getServiceLocator()->get('VuFind\SessionManager')->destroy();
+        $this->serviceLocator->get('VuFind\SessionManager')->destroy();
 
         return $this->output('', self::STATUS_OK);
     }
@@ -1498,6 +1455,34 @@ class AjaxController extends AbstractBase
      */
     protected function getResultsManager()
     {
-        return $this->getServiceLocator()->get('VuFind\SearchResultsPluginManager');
+        return $this->serviceLocator->get('VuFind\SearchResultsPluginManager');
+    }
+
+    /**
+     * Get Ils Status
+     *
+     * This will check the ILS for being online and will return the ils-offline
+     * template upon failure.
+     *
+     * @return \Zend\Http\Response
+     * @author André Lahmann <lahmann@ub.uni-leipzig.de>
+     */
+    protected function getIlsStatusAjax()
+    {
+        $this->disableSessionWrites();  // avoid session write timing bug
+        if ($this->getILS()->getOfflineMode(true) == 'ils-offline') {
+            $offlineModeMsg = $this->params()->fromPost(
+                'offlineModeMsg',
+                $this->params()->fromQuery('offlineModeMsg')
+            );
+            return $this->output(
+                $this->getViewRenderer()->render(
+                    'Helpers/ils-offline.phtml',
+                    compact('offlineModeMsg')
+                ),
+                self::STATUS_OK
+            );
+        }
+        return $this->output('', self::STATUS_OK);
     }
 }
diff --git a/module/VuFind/src/VuFind/Controller/AlphabrowseController.php b/module/VuFind/src/VuFind/Controller/AlphabrowseController.php
index 3a807e24bb420518843f6db216462f4db97b03cc..c4a047aab499a2f4582efc3cf88584b82e3e8e91 100644
--- a/module/VuFind/src/VuFind/Controller/AlphabrowseController.php
+++ b/module/VuFind/src/VuFind/Controller/AlphabrowseController.php
@@ -94,7 +94,7 @@ class AlphabrowseController extends AbstractBase
             ? (int) $config->AlphaBrowse->page_size : 20;
 
         // Connect to Solr:
-        $db = $this->getServiceLocator()->get('VuFind\Search\BackendManager')
+        $db = $this->serviceLocator->get('VuFind\Search\BackendManager')
             ->get('Solr');
 
         // Process incoming parameters:
diff --git a/module/VuFind/src/VuFind/Controller/AuthorController.php b/module/VuFind/src/VuFind/Controller/AuthorController.php
index 96746db8f622221423a58bc806e1c3a36fb81945..9166c1858ff13ccb8ceadd64d77f04a3df1167ef 100644
--- a/module/VuFind/src/VuFind/Controller/AuthorController.php
+++ b/module/VuFind/src/VuFind/Controller/AuthorController.php
@@ -108,7 +108,7 @@ class AuthorController extends AbstractSearch
      */
     protected function resultScrollerActive()
     {
-        $config = $this->getServiceLocator()->get('VuFind\Config')->get('config');
+        $config = $this->serviceLocator->get('VuFind\Config')->get('config');
         return (isset($config->Record->next_prev_navigation)
             && $config->Record->next_prev_navigation);
     }
diff --git a/module/VuFind/src/VuFind/Controller/AuthorityController.php b/module/VuFind/src/VuFind/Controller/AuthorityController.php
index 6959b990acac76093e189e07c0a15318306d5dfd..e7102924d355f51daaf5923ca60c0204e76143a5 100644
--- a/module/VuFind/src/VuFind/Controller/AuthorityController.php
+++ b/module/VuFind/src/VuFind/Controller/AuthorityController.php
@@ -26,6 +26,7 @@
  * @link     https://vufind.org Main Site
  */
 namespace VuFind\Controller;
+use Zend\ServiceManager\ServiceLocatorInterface;
 
 /**
  * Authority Controller
@@ -40,11 +41,13 @@ class AuthorityController extends AbstractSearch
 {
     /**
      * Constructor
+     *
+     * @param ServiceLocatorInterface $sm Service locator
      */
-    public function __construct()
+    public function __construct(ServiceLocatorInterface $sm)
     {
         $this->searchClassId = 'SolrAuth';
-        parent::__construct();
+        parent::__construct($sm);
     }
 
     /**
@@ -72,12 +75,12 @@ class AuthorityController extends AbstractSearch
     public function recordAction()
     {
         $id = $this->params()->fromQuery('id');
-        $cfg = $this->getServiceLocator()->get('Config');
+        $cfg = $this->serviceLocator->get('Config');
         $tabConfig = $cfg['vufind']['recorddriver_tabs'];
-        $driver = $this->getServiceLocator()->get('VuFind\RecordLoader')
+        $driver = $this->serviceLocator->get('VuFind\RecordLoader')
             ->load($id, 'SolrAuth');
         $request = $this->getRequest();
-        $tabs = $this->getServiceLocator()
+        $tabs = $this->serviceLocator
             ->get('VuFind\RecordTabPluginManager')
             ->getTabsForRecord($driver, $tabConfig, $request);
         return $this->createViewModel(['driver' => $driver, 'tabs' => $tabs]);
diff --git a/module/VuFind/src/VuFind/Controller/BrowseController.php b/module/VuFind/src/VuFind/Controller/BrowseController.php
index e27045bb1363eca50f0f374e5df63519b68da7b1..a329fa91dda9487721f5c335078b6da9fcf6595c 100644
--- a/module/VuFind/src/VuFind/Controller/BrowseController.php
+++ b/module/VuFind/src/VuFind/Controller/BrowseController.php
@@ -27,6 +27,8 @@
  */
 namespace VuFind\Controller;
 use VuFind\Exception\Forbidden as ForbiddenException;
+use Zend\Config\Config;
+use Zend\ServiceManager\ServiceLocatorInterface;
 
 /**
  * BrowseController Class
@@ -65,9 +67,10 @@ class BrowseController extends AbstractBase
     /**
      * Constructor
      *
-     * @param \Zend\Config\Config $config VuFind configuration
+     * @param ServiceLocatorInterface $sm     Service manager
+     * @param Config                  $config VuFind configuration
      */
-    public function __construct(\Zend\Config\Config $config)
+    public function __construct(ServiceLocatorInterface $sm, Config $config)
     {
         $this->config = $config;
 
@@ -77,6 +80,7 @@ class BrowseController extends AbstractBase
                 $this->disabledFacets[] = $key;
             }
         }
+        parent::__construct($sm);
     }
 
     /**
@@ -453,7 +457,7 @@ class BrowseController extends AbstractBase
             'era'          => 'By Era'
         ];
 
-        return $this->performBrowse('Author', $categoryList, false);
+        return $this->performBrowse('Author', $categoryList, true);
     }
 
     /**
@@ -590,7 +594,7 @@ class BrowseController extends AbstractBase
     protected function getFacetList($facet, $category = null,
         $sort = 'count', $query = '[* TO *]'
     ) {
-        $results = $this->getServiceLocator()
+        $results = $this->serviceLocator
             ->get('VuFind\SearchResultsPluginManager')->get('Solr');
         $params = $results->getParams();
         $params->addFacet($facet);
diff --git a/module/VuFind/src/VuFind/Controller/CartController.php b/module/VuFind/src/VuFind/Controller/CartController.php
index d3ad3fe8a9bbe487a4f1df5b48f76f6ac199fce8..1ce57449b217f5898172e1c98106c6fba0ab38cc 100644
--- a/module/VuFind/src/VuFind/Controller/CartController.php
+++ b/module/VuFind/src/VuFind/Controller/CartController.php
@@ -27,7 +27,9 @@
  */
 namespace VuFind\Controller;
 use VuFind\Exception\Forbidden as ForbiddenException,
-    VuFind\Exception\Mail as MailException;
+    VuFind\Exception\Mail as MailException,
+    Zend\ServiceManager\ServiceLocatorInterface,
+    Zend\Session\Container;
 
 /**
  * Book Bag / Bulk Action Controller
@@ -50,11 +52,12 @@ class CartController extends AbstractBase
     /**
      * Constructor
      *
-     * @param \Zend\Session\Container $container Session container
+     * @param ServiceLocatorInterface $sm        Service manager
+     * @param Container               $container Session container
      */
-    public function __construct(\Zend\Session\Container $container)
+    public function __construct(ServiceLocatorInterface $sm, Container $container)
     {
-        parent::__construct();
+        parent::__construct($sm);
         $this->session = $container;
     }
 
@@ -65,7 +68,7 @@ class CartController extends AbstractBase
      */
     protected function getCart()
     {
-        return $this->getServiceLocator()->get('VuFind\Cart');
+        return $this->serviceLocator->get('VuFind\Cart');
     }
 
     /**
@@ -263,7 +266,7 @@ class CartController extends AbstractBase
             // Attempt to send the email and show an appropriate flash message:
             try {
                 // If we got this far, we're ready to send the email:
-                $mailer = $this->getServiceLocator()->get('VuFind\Mailer');
+                $mailer = $this->serviceLocator->get('VuFind\Mailer');
                 $mailer->setMaxRecipients($view->maxRecipients);
                 $cc = $this->params()->fromPost('ccself') && $view->from != $view->to
                     ? $view->from : null;
@@ -308,7 +311,7 @@ class CartController extends AbstractBase
      */
     protected function getExport()
     {
-        return $this->getServiceLocator()->get('VuFind\Export');
+        return $this->serviceLocator->get('VuFind\Export');
     }
 
     /**
diff --git a/module/VuFind/src/VuFind/Controller/ChannelsController.php b/module/VuFind/src/VuFind/Controller/ChannelsController.php
new file mode 100644
index 0000000000000000000000000000000000000000..14cf8013883b6b3469a463557b88c4215ba16b2b
--- /dev/null
+++ b/module/VuFind/src/VuFind/Controller/ChannelsController.php
@@ -0,0 +1,203 @@
+<?php
+/**
+ * Channels Controller
+ *
+ * PHP Version 5
+ *
+ * Copyright (C) Villanova University 2016.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.    See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA    02111-1307    USA
+ *
+ * @category VuFind
+ * @package  Controller
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/indexing:alphabetical_heading_browse Wiki
+ */
+namespace VuFind\Controller;
+use Zend\Config\Config;
+
+/**
+ * Channels Class
+ *
+ * Controls the alphabetical browsing feature
+ *
+ * @category VuFind
+ * @package  Controller
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/indexing:alphabetical_heading_browse Wiki
+ */
+class ChannelsController extends AbstractBase
+{
+    /**
+     * Generates static front page of channels.
+     *
+     * @return \Zend\View\Model\ViewModel
+     */
+    public function homeAction()
+    {
+        $view = $this->createViewModel();
+        $runner = $this->serviceLocator->get('VuFind\SearchRunner');
+
+        // Send both GET and POST variables to search class:
+        $request = [];
+
+        $config = $this->getConfig('channels');
+        $defaultSearchClassId = isset($config->General->default_home_source)
+            ? $config->General->default_home_source : DEFAULT_SEARCH_BACKEND;
+        $searchClassId = $this->params()->fromQuery('source', $defaultSearchClassId);
+        $providerIds = isset($config->{"source.$searchClassId"}->home)
+            ? $config->{"source.$searchClassId"}->home->toArray() : [];
+        $providers = $this->getChannelProviderArray($providerIds, $config);
+
+        $callback = function ($runner, $params, $searchClassId) use ($providers) {
+            foreach ($providers as $provider) {
+                $provider->configureSearchParams($params);
+            }
+        };
+        $view->results = $runner->run($request, $searchClassId, $callback);
+
+        $view->channels = [];
+        $view->token = $this->params()->fromQuery('channelToken');
+        foreach ($providers as $provider) {
+            $view->channels = array_merge(
+                $view->channels,
+                $provider->getFromSearch($view->results, $view->token)
+            );
+        }
+        return $view;
+    }
+
+    /**
+     * Generates channels for a record.
+     *
+     * @return \Zend\View\Model\ViewModel
+     */
+    public function recordAction()
+    {
+        $view = $this->createViewModel();
+
+        $loader = $this->getRecordLoader();
+        $source = $this->params()->fromQuery('source', DEFAULT_SEARCH_BACKEND);
+        $view->driver = $loader->load($this->params()->fromQuery('id'), $source);
+
+        $config = $this->getConfig('channels');
+        $providerIds = isset($config->{"source.$source"}->record)
+            ? $config->{"source.$source"}->record->toArray() : [];
+        $view->channels = [];
+        $view->token = $this->params()->fromQuery('channelToken');
+        $providers = $this->getChannelProviderArray($providerIds, $config);
+        foreach ($providers as $provider) {
+            $view->channels = array_merge(
+                $view->channels,
+                $provider->getFromRecord($view->driver, $view->token)
+            );
+        }
+        return $view;
+    }
+
+    /**
+     * Generates channels for a search.
+     *
+     * @return \Zend\View\Model\ViewModel
+     */
+    public function searchAction()
+    {
+        $view = $this->createViewModel();
+
+        $runner = $this->serviceLocator->get('VuFind\SearchRunner');
+
+        // Send both GET and POST variables to search class:
+        $request = $this->getRequest()->getQuery()->toArray()
+            + $this->getRequest()->getPost()->toArray();
+        $searchClassId = $this->params()
+            ->fromQuery('source', DEFAULT_SEARCH_BACKEND);
+
+        $config = $this->getConfig('channels');
+        $providerIds = isset($config->{"source.$searchClassId"}->search)
+            ? $config->{"source.$searchClassId"}->search->toArray() : [];
+        $providers = $this->getChannelProviderArray($providerIds, $config);
+
+        $callback = function ($runner, $params, $searchClassId) use ($providers) {
+            foreach ($providers as $provider) {
+                $provider->configureSearchParams($params);
+            }
+        };
+        $view->results = $runner->run($request, $searchClassId, $callback);
+
+        $view->channels = [];
+        $view->lookfor = $this->params()->fromQuery('lookfor');
+        $view->token = $this->params()->fromQuery('channelToken');
+        foreach ($providers as $provider) {
+            $view->channels = array_merge(
+                $view->channels,
+                $provider->getFromSearch($view->results, $view->token)
+            );
+        }
+        return $view;
+    }
+
+    /**
+     * Get an array of channel providers matching the provided IDs (or just one,
+     * if the channelProvider GET parameter is set).
+     *
+     * @param array  $providerIds Array of IDs to load
+     * @param Config $config      Channel configuration
+     *
+     * @return array
+     */
+    protected function getChannelProviderArray($providerIds, $config)
+    {
+        $id = $this->params()->fromQuery('channelProvider');
+        if (!empty($id) && in_array($id, $providerIds)) {
+            return [$this->getChannelProvider($id, $config)];
+        }
+        $results = [];
+        foreach ($providerIds as $id) {
+            $results[] = $this->getChannelProvider($id, $config);
+        }
+        return $results;
+    }
+
+    /**
+     * Convenience method to retrieve a channel provider.
+     *
+     * @param string $providerId Channel provider name and optional config
+     * (colon-delimited)
+     * @param Config $config     Channel configuration
+     *
+     * @return \VuFind\ChannelProvider\ChannelProviderInterface
+     */
+    protected function getChannelProvider($providerId, Config $config)
+    {
+        // The provider ID consists of a service name and an optional config
+        // section -- break out the relevant parts:
+        list($serviceName, $configSection) = explode(':', $providerId . ':');
+
+        // Load configuration, using default value if necessary:
+        if (empty($configSection)) {
+            $configSection = "provider.$serviceName";
+        }
+        $options = isset($config->{$configSection})
+            ? $config->{$configSection}->toArray() : [];
+
+        // Load the service, and configure appropriately:
+        $provider = $this->serviceLocator
+            ->get('VuFind\ChannelProviderPluginManager')->get($serviceName);
+        $provider->setProviderId($providerId);
+        $provider->setOptions($options);
+        return $provider;
+    }
+}
diff --git a/module/VuFind/src/VuFind/Controller/CollectionController.php b/module/VuFind/src/VuFind/Controller/CollectionController.php
index a0233529ab007f335f498858b0d8b18f34dc4af9..758f67b5ee0ac989b7c547e9bac66330be3e7f22 100644
--- a/module/VuFind/src/VuFind/Controller/CollectionController.php
+++ b/module/VuFind/src/VuFind/Controller/CollectionController.php
@@ -26,6 +26,8 @@
  * @link     https://vufind.org Main Site
  */
 namespace VuFind\Controller;
+use Zend\Config\Config;
+use Zend\ServiceManager\ServiceLocatorInterface;
 
 /**
  * Collection Controller
@@ -41,12 +43,13 @@ class CollectionController extends AbstractRecord
     /**
      * Constructor
      *
-     * @param \Zend\Config\Config $config VuFind configuration
+     * @param ServiceLocatorInterface $sm     Service manager
+     * @param Config                  $config VuFind configuration
      */
-    public function __construct(\Zend\Config\Config $config)
+    public function __construct(ServiceLocatorInterface $sm, Config $config)
     {
         // Call standard record controller initialization:
-        parent::__construct();
+        parent::__construct($sm);
 
         // Set default tab, if specified:
         if (isset($config->Collections->defaultTab)) {
@@ -61,7 +64,7 @@ class CollectionController extends AbstractRecord
      */
     protected function getRecordTabConfig()
     {
-        $cfg = $this->getServiceLocator()->get('Config');
+        $cfg = $this->serviceLocator->get('Config');
         return $cfg['vufind']['recorddriver_collection_tabs'];
     }
 
@@ -89,7 +92,7 @@ class CollectionController extends AbstractRecord
      */
     protected function resultScrollerActive()
     {
-        $config = $this->getServiceLocator()->get('VuFind\Config')->get('config');
+        $config = $this->serviceLocator->get('VuFind\Config')->get('config');
         return (isset($config->Record->next_prev_navigation)
             && $config->Record->next_prev_navigation);
     }
diff --git a/module/VuFind/src/VuFind/Controller/CollectionsController.php b/module/VuFind/src/VuFind/Controller/CollectionsController.php
index d62386910fcced39457d344d180097bc0953f941..503ebffe5fef224e488e97bee8a8595d7b921daf 100644
--- a/module/VuFind/src/VuFind/Controller/CollectionsController.php
+++ b/module/VuFind/src/VuFind/Controller/CollectionsController.php
@@ -27,6 +27,8 @@
  */
 namespace VuFind\Controller;
 use VuFindSearch\Query\Query;
+use Zend\Config\Config;
+use Zend\ServiceManager\ServiceLocatorInterface;
 
 /**
  * Collections Controller
@@ -49,11 +51,13 @@ class CollectionsController extends AbstractBase
     /**
      * Constructor
      *
-     * @param \Zend\Config\Config $config VuFind configuration
+     * @param ServiceLocatorInterface $sm     Service manager
+     * @param Config                  $config VuFind configuration
      */
-    public function __construct(\Zend\Config\Config $config)
+    public function __construct(ServiceLocatorInterface $sm, Config $config)
     {
         $this->config = $config;
+        parent::__construct($sm);
     }
 
     /**
@@ -111,7 +115,7 @@ class CollectionsController extends AbstractBase
         $limit = $this->getBrowseLimit();
 
         // Load Solr data or die trying:
-        $db = $this->getServiceLocator()->get('VuFind\Search\BackendManager')
+        $db = $this->serviceLocator->get('VuFind\Search\BackendManager')
             ->get('Solr');
         $result = $db->alphabeticBrowse($source, $from, $page, $limit);
 
@@ -168,7 +172,7 @@ class CollectionsController extends AbstractBase
 
         $browseField = "hierarchy_browse";
 
-        $searchObject = $this->getServiceLocator()
+        $searchObject = $this->serviceLocator
             ->get('VuFind\SearchResultsPluginManager')->get('Solr');
         foreach ($appliedFilters as $filter) {
             $searchObject->getParams()->addFilter($filter);
@@ -333,7 +337,7 @@ class CollectionsController extends AbstractBase
     {
         $title = addcslashes($title, '"');
         $query = new Query("is_hierarchy_title:\"$title\"", 'AllFields');
-        $searchService = $this->getServiceLocator()->get('VuFind\Search');
+        $searchService = $this->serviceLocator->get('VuFind\Search');
         $result = $searchService->search('Solr', $query, 0, $this->getBrowseLimit());
         return $result->getRecords();
     }
diff --git a/module/VuFind/src/VuFind/Controller/CombinedController.php b/module/VuFind/src/VuFind/Controller/CombinedController.php
index 50832b8e8bfadb7758eb021833d43e78eb5b96c0..7f59203591a433ad23708d00d62d50a541e40ea9 100644
--- a/module/VuFind/src/VuFind/Controller/CombinedController.php
+++ b/module/VuFind/src/VuFind/Controller/CombinedController.php
@@ -26,6 +26,7 @@
  * @link     https://vufind.org Main Site
  */
 namespace VuFind\Controller;
+use Zend\ServiceManager\ServiceLocatorInterface;
 
 /**
  * Redirects the user to the appropriate default VuFind action.
@@ -40,11 +41,13 @@ class CombinedController extends AbstractSearch
 {
     /**
      * Constructor
+     *
+     * @param ServiceLocatorInterface $sm Service locator
      */
-    public function __construct()
+    public function __construct(ServiceLocatorInterface $sm)
     {
         $this->searchClassId = 'Combined';
-        parent::__construct();
+        parent::__construct($sm);
     }
 
     /**
@@ -71,7 +74,7 @@ class CombinedController extends AbstractSearch
 
         // Validate configuration:
         $sectionId = $this->params()->fromQuery('id');
-        $config = $this->getServiceLocator()->get('VuFind\Config')->get('combined')
+        $config = $this->serviceLocator->get('VuFind\Config')->get('combined')
             ->toArray();
         $tabConfig = $this->getTabConfig($config);
         if (!isset($tabConfig[$sectionId])) {
@@ -80,7 +83,7 @@ class CombinedController extends AbstractSearch
         list($searchClassId) = explode(':', $sectionId);
 
         // Retrieve results:
-        $options = $this->getServiceLocator()
+        $options = $this->serviceLocator
             ->get('VuFind\SearchOptionsPluginManager');
         $currentOptions = $options->get($searchClassId);
         list($controller, $action)
@@ -103,8 +106,8 @@ class CombinedController extends AbstractSearch
         ) {
             $html = '';
         } else {
-            $cart = $this->getServiceLocator()->get('VuFind\Cart');
-            $general = $this->getServiceLocator()->get('VuFind\Config')
+            $cart = $this->serviceLocator->get('VuFind\Cart');
+            $general = $this->serviceLocator->get('VuFind\Config')
                 ->get('config');
             $viewParams = [
                 'searchClassId' => $searchClassId,
@@ -115,7 +118,10 @@ class CombinedController extends AbstractSearch
                     && isset($general->Site->showBulkOptions)
                     && $general->Site->showBulkOptions
             ];
-            $html = $this->getViewRenderer()->render(
+            // Load custom CSS, if necessary:
+            $html = $this->getViewRenderer()->plugin('headLink')->__invoke();
+            // Render content:
+            $html .= $this->getViewRenderer()->render(
                 'combined/results-list.phtml',
                 $viewParams
             );
@@ -134,7 +140,7 @@ class CombinedController extends AbstractSearch
         // Set up current request context:
         $request = $this->getRequest()->getQuery()->toArray()
             + $this->getRequest()->getPost()->toArray();
-        $results = $this->getServiceLocator()->get('VuFind\SearchRunner')->run(
+        $results = $this->serviceLocator->get('VuFind\SearchRunner')->run(
             $request, 'Combined', $this->getSearchSetupCallback()
         );
 
@@ -145,9 +151,9 @@ class CombinedController extends AbstractSearch
 
         // Gather combined results:
         $combinedResults = [];
-        $options = $this->getServiceLocator()
+        $options = $this->serviceLocator
             ->get('VuFind\SearchOptionsPluginManager');
-        $config = $this->getServiceLocator()->get('VuFind\Config')->get('combined')
+        $config = $this->serviceLocator->get('VuFind\Config')->get('combined')
             ->toArray();
         $supportsCart = false;
         $supportsCartOptions = [];
@@ -195,7 +201,7 @@ class CombinedController extends AbstractSearch
         }
 
         // Get default config for showBulkOptions
-        $settings = $this->getServiceLocator()->get('VuFind\Config')->get('config');
+        $settings = $this->serviceLocator->get('VuFind\Config')->get('config');
 
         // Build view model:
         return $this->createViewModel(
@@ -235,16 +241,28 @@ class CombinedController extends AbstractSearch
             }
             unset($params['activeSearchClassId']); // don't need to pass this forward
 
-            $route = $this->getServiceLocator()
+            $route = $this->serviceLocator
                 ->get('VuFind\SearchOptionsPluginManager')
                 ->get($searchClassId)->getSearchAction();
             $base = $this->url()->fromRoute($route);
             return $this->redirect()->toUrl($base . '?' . http_build_query($params));
         case 'External':
             $lookfor = $this->params()->fromQuery('lookfor');
-            return $this->redirect()->toUrl($target . urlencode($lookfor));
+            $finalTarget = (false === strpos($target, '%%lookfor%%'))
+                ? $target . urlencode($lookfor)
+                : str_replace('%%lookfor%%', urlencode($lookfor), $target);
+            return $this->redirect()->toUrl($finalTarget);
         default:
-            throw new \Exception('Unexpected search type.');
+            // If parameters are completely missing, just redirect to home instead
+            // of throwing an error; this is possibly a misbehaving crawler that
+            // followed the SearchBox URL without passing any parameters.
+            if (empty($type) && empty($target)) {
+                return $this->redirect()->toRoute('home');
+            }
+            // If we have a weird value here, report it as an Exception:
+            throw new \VuFind\Exception\BadRequest(
+                'Unexpected search type: "' . $type . '".'
+            );
         }
     }
 
diff --git a/module/VuFind/src/VuFind/Controller/ContentController.php b/module/VuFind/src/VuFind/Controller/ContentController.php
new file mode 100644
index 0000000000000000000000000000000000000000..52eae317006e457c1e97932a3d4367483ae5d808
--- /dev/null
+++ b/module/VuFind/src/VuFind/Controller/ContentController.php
@@ -0,0 +1,96 @@
+<?php
+/**
+ * Content Controller
+ *
+ * PHP Version 5
+ *
+ * Copyright (C) Villanova University 2011.
+ * Copyright (C) The National Library of Finland 2014-2016.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.    See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA    02111-1307    USA
+ *
+ * @category VuFind
+ * @package  Controller
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @author   Ere Maijala <ere.maijala@helsinki.fi>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org Main Page
+ */
+namespace VuFind\Controller;
+
+/**
+ * Controller for mostly static pages that doesn't fall under any particular
+ * function.
+ *
+ * @category VuFind
+ * @package  Controller
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @author   Ere Maijala <ere.maijala@helsinki.fi>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org Main Page
+ */
+class ContentController extends AbstractBase
+{
+    /**
+     * Default action if none provided
+     *
+     * @return Zend\View\Model\ViewModel
+     */
+    public function contentAction()
+    {
+        $page = $this->params()->fromRoute('page');
+        $themeInfo = $this->serviceLocator->get('VuFindTheme\ThemeInfo');
+        $language = $this->serviceLocator->get('VuFind\Translator')
+            ->getLocale();
+        $defaultLanguage = $this->getConfig()->Site->language;
+
+        // Try to find a template using
+        // 1.) Current language suffix
+        // 2.) Default language suffix
+        // 3.) No language suffix
+        $currentTpl = "templates/content/{$page}_$language.phtml";
+        $defaultTpl = "templates/content/{$page}_$defaultLanguage.phtml";
+        if (null !== $themeInfo->findContainingTheme($currentTpl)) {
+            $page = "{$page}_$language";
+        } elseif (null !== $themeInfo->findContainingTheme($defaultTpl)) {
+            $page = "{$page}_$defaultLanguage";
+        }
+
+        if (empty($page) || 'content' === $page
+            || null === $themeInfo->findContainingTheme(
+                "templates/content/$page.phtml"
+            )
+        ) {
+            return $this->notFoundAction($this->getResponse());
+        }
+
+        $view = $this->createViewModel(['page' => $page]);
+        return $view;
+    }
+
+    /**
+     * Action called if matched action does not exist
+     *
+     * @return array
+     */
+    public function notFoundAction()
+    {
+        $response   = $this->response;
+
+        if ($response instanceof \Zend\Http\Response) {
+            return $this->createHttpNotFoundModel($response);
+        }
+        return $this->createConsoleNotFoundModel($response);
+    }
+}
diff --git a/module/VuFind/src/VuFind/Controller/CoverController.php b/module/VuFind/src/VuFind/Controller/CoverController.php
index 310980d4ffa2a22322e5d1f5d4a827dab48cf4e2..9284ca2b3e32bf4f5702560b8f22041f8b0d8ae1 100644
--- a/module/VuFind/src/VuFind/Controller/CoverController.php
+++ b/module/VuFind/src/VuFind/Controller/CoverController.php
@@ -60,7 +60,7 @@ class CoverController extends AbstractBase
      */
     protected function getCacheDir()
     {
-        return $this->getServiceLocator()->get('VuFind\CacheManager')
+        return $this->serviceLocator->get('VuFind\CacheManager')
             ->getCache('cover')->getOptions()->getCacheDir();
     }
 
@@ -76,13 +76,13 @@ class CoverController extends AbstractBase
             $cacheDir = $this->getCacheDir();
             $this->loader = new Loader(
                 $this->getConfig(),
-                $this->getServiceLocator()->get('VuFind\ContentCoversPluginManager'),
-                $this->getServiceLocator()->get('VuFindTheme\ThemeInfo'),
-                $this->getServiceLocator()->get('VuFind\Http')->createClient(),
+                $this->serviceLocator->get('VuFind\ContentCoversPluginManager'),
+                $this->serviceLocator->get('VuFindTheme\ThemeInfo'),
+                $this->serviceLocator->get('VuFind\Http')->createClient(),
                 $cacheDir
             );
             \VuFind\ServiceManager\Initializer::initInstance(
-                $this->loader, $this->getServiceLocator()
+                $this->loader, $this->serviceLocator
             );
         }
         return $this->loader;
@@ -96,7 +96,7 @@ class CoverController extends AbstractBase
     protected function getProxy()
     {
         if (!$this->proxy) {
-            $client = $this->getServiceLocator()->get('VuFind\Http')->createClient();
+            $client = $this->serviceLocator->get('VuFind\Http')->createClient();
             $cacheDir = $this->getCacheDir() . '/proxy';
             $config = $this->getConfig()->toArray();
             $whitelist = isset($config['Content']['coverproxyCache'])
@@ -125,6 +125,8 @@ class CoverController extends AbstractBase
             'issn' => $params()->fromQuery('issn'),
             'oclc' => $params()->fromQuery('oclc'),
             'upc' => $params()->fromQuery('upc'),
+            'recordid' => $params()->fromQuery('recordid'),
+            'source' => $params()->fromQuery('source'),
         ];
     }
 
diff --git a/module/VuFind/src/VuFind/Controller/EITController.php b/module/VuFind/src/VuFind/Controller/EITController.php
index d77b3113113c6aa9fab0038d57916d098e67b7bc..79bd63712c3cc47a65a64ff3c0e128448ae9b76c 100644
--- a/module/VuFind/src/VuFind/Controller/EITController.php
+++ b/module/VuFind/src/VuFind/Controller/EITController.php
@@ -26,6 +26,7 @@
  * @link     https://vufind.org Main Site
  */
 namespace VuFind\Controller;
+use Zend\ServiceManager\ServiceLocatorInterface;
 
 /**
  * EIT Controller
@@ -40,12 +41,14 @@ class EITController extends AbstractSearch
 {
     /**
      * Constructor
+     *
+     * @param ServiceLocatorInterface $sm Service locator
      */
-    public function __construct()
+    public function __construct(ServiceLocatorInterface $sm)
     {
         $this->accessPermission = 'access.EITModule';
         $this->searchClassId = 'EIT';
-        parent::__construct();
+        parent::__construct($sm);
     }
 
     /**
@@ -55,7 +58,7 @@ class EITController extends AbstractSearch
      */
     protected function resultScrollerActive()
     {
-        $config = $this->getServiceLocator()->get('VuFind\Config')->get('EIT');
+        $config = $this->serviceLocator->get('VuFind\Config')->get('EIT');
         return (isset($config->Record->next_prev_navigation)
             && $config->Record->next_prev_navigation);
     }
diff --git a/module/VuFind/src/VuFind/Controller/EITrecordController.php b/module/VuFind/src/VuFind/Controller/EITrecordController.php
index f5c523484687e3afb7d4944053dc84f85a6d8834..d16202bcddeae61bf0b878ad5b579d971931f650 100644
--- a/module/VuFind/src/VuFind/Controller/EITrecordController.php
+++ b/module/VuFind/src/VuFind/Controller/EITrecordController.php
@@ -27,6 +27,7 @@
  * @link     https://vufind.org Main Site
  */
 namespace VuFind\Controller;
+use Zend\ServiceManager\ServiceLocatorInterface;
 
 /**
  * EIT Record Controller
@@ -43,8 +44,10 @@ class EITrecordController extends AbstractRecord
 {
     /**
      * Constructor
+     *
+     * @param ServiceLocatorInterface $sm Service locator
      */
-    public function __construct()
+    public function __construct(ServiceLocatorInterface $sm)
     {
         // Override some defaults:
         $this->accessPermission = 'access.EITModule';
@@ -52,7 +55,7 @@ class EITrecordController extends AbstractRecord
         $this->defaultTab = 'Description';
 
         // Call standard record controller initialization:
-        parent::__construct();
+        parent::__construct($sm);
     }
 
     /**
@@ -62,7 +65,7 @@ class EITrecordController extends AbstractRecord
      */
     protected function resultScrollerActive()
     {
-        $config = $this->getServiceLocator()->get('VuFind\Config')->get('EIT');
+        $config = $this->serviceLocator->get('VuFind\Config')->get('EIT');
         return (isset($config->Record->next_prev_navigation)
             && $config->Record->next_prev_navigation);
     }
diff --git a/module/VuFind/src/VuFind/Controller/EdsController.php b/module/VuFind/src/VuFind/Controller/EdsController.php
index 8c4053ab033b1deea65f1488856e1f0d1d1d8fc3..24b8f5434d0b4767a74a21f612bf3462546fcd6d 100644
--- a/module/VuFind/src/VuFind/Controller/EdsController.php
+++ b/module/VuFind/src/VuFind/Controller/EdsController.php
@@ -26,8 +26,9 @@
  * @link     https://vufind.org Main Site
  */
 namespace VuFind\Controller;
-
 use VuFind\Solr\Utils as SolrUtils;
+use Zend\ServiceManager\ServiceLocatorInterface;
+
 /**
  * EDS Controller
  *
@@ -41,11 +42,13 @@ class EdsController extends AbstractSearch
 {
     /**
      * Constructor
+     *
+     * @param ServiceLocatorInterface $sm Service locator
      */
-    public function __construct()
+    public function __construct(ServiceLocatorInterface $sm)
     {
         $this->searchClassId = 'EDS';
-        parent::__construct();
+        parent::__construct($sm);
     }
 
     /**
@@ -55,7 +58,7 @@ class EdsController extends AbstractSearch
      */
     protected function resultScrollerActive()
     {
-        $config = $this->getServiceLocator()->get('VuFind\Config')->get('EDS');
+        $config = $this->serviceLocator->get('VuFind\Config')->get('EDS');
         return (isset($config->Record->next_prev_navigation)
             && $config->Record->next_prev_navigation);
     }
@@ -87,9 +90,7 @@ class EdsController extends AbstractSearch
     public function homeAction()
     {
         $this->setUp();
-        return $this->createViewModel(
-            ['results' => $this->getHomePageFacets()]
-        );
+        return $this->createViewModel();
     }
 
     /**
@@ -106,7 +107,7 @@ class EdsController extends AbstractSearch
      * Return a Search Results object containing advanced facet information.  This
      * data may come from the cache.
      *
-     * @return \VuFind\Search\EDS\Results
+     * @return array
      */
     protected function getAdvancedFacets()
     {
@@ -129,18 +130,6 @@ class EdsController extends AbstractSearch
         return $availableLimiters;
     }
 
-    /**
-     * Return a Search Results object containing homepage facet information.  This
-     * data may come from the cache.
-     *
-     * @return \VuFind\Search\EDS\Results
-     */
-    protected function getHomePageFacets()
-    {
-        // For now, we'll use the same fields as the advanced search screen.
-        return $this->getAdvancedFacets();
-    }
-
     /**
      * Process the facets to be used as limits on the Advanced Search screen.
      *
diff --git a/module/VuFind/src/VuFind/Controller/EdsrecordController.php b/module/VuFind/src/VuFind/Controller/EdsrecordController.php
index 559dfb06f2b992bddd7756e6fca711f332480af2..e409e99ada79653e70ab650f145a7d700b0dcbe0 100644
--- a/module/VuFind/src/VuFind/Controller/EdsrecordController.php
+++ b/module/VuFind/src/VuFind/Controller/EdsrecordController.php
@@ -27,6 +27,7 @@
  */
 namespace VuFind\Controller;
 use VuFind\Exception\Forbidden as ForbiddenException;
+use Zend\ServiceManager\ServiceLocatorInterface;
 
 /**
  * EDS Record Controller
@@ -41,15 +42,17 @@ class EdsrecordController extends AbstractRecord
 {
     /**
      * Constructor
+     *
+     * @param ServiceLocatorInterface $sm Service locator
      */
-    public function __construct()
+    public function __construct(ServiceLocatorInterface $sm)
     {
         // Override some defaults:
         $this->searchClassId = 'EDS';
         $this->fallbackDefaultTab = 'Description';
 
         // Call standard record controller initialization:
-        parent::__construct();
+        parent::__construct($sm);
     }
 
     /**
@@ -78,7 +81,7 @@ class EdsrecordController extends AbstractRecord
      */
     protected function resultScrollerActive()
     {
-        $config = $this->getServiceLocator()->get('VuFind\Config')->get('EDS');
+        $config = $this->serviceLocator->get('VuFind\Config')->get('EDS');
         return (isset($config->Record->next_prev_navigation)
             && $config->Record->next_prev_navigation);
     }
diff --git a/module/VuFind/src/VuFind/Controller/ExternalAuthController.php b/module/VuFind/src/VuFind/Controller/ExternalAuthController.php
new file mode 100644
index 0000000000000000000000000000000000000000..b5201e923dab9d6216f1cecafa9b278ce361bf0a
--- /dev/null
+++ b/module/VuFind/src/VuFind/Controller/ExternalAuthController.php
@@ -0,0 +1,118 @@
+<?php
+/**
+ * External Authentication/Authorization Controller
+ *
+ * PHP Version 5
+ *
+ * Copyright (C) The National Library of Finland 2016.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.    See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA    02111-1307    USA
+ *
+ * @category VuFind
+ * @package  Controller
+ * @author   Ere Maijala <ere.maijala@helsinki.fi>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development:plugins:controllers Wiki
+ */
+namespace VuFind\Controller;
+
+/**
+ * External Authentication/Authorization Controller
+ *
+ * Provides authorization support for external systems, e.g. EZproxy
+ *
+ * @category VuFind
+ * @package  Controller
+ * @author   Ere Maijala <ere.maijala@helsinki.fi>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development:plugins:controllers Wiki
+ */
+class ExternalAuthController extends AbstractBase
+{
+    /**
+     * Permission from permissions.ini required for EZProxy authorization.
+     *
+     * @var string
+     */
+    protected $ezproxyRequiredPermission = 'ezproxy.authorized';
+
+    /**
+     * Provides an EZproxy session to an authorized user
+     *
+     * @return mixed
+     *
+     * @throws \Exception
+     */
+    public function ezproxyLoginAction()
+    {
+        $config = $this->getConfig();
+        if (empty($config->EZproxy->host)) {
+            throw new \Exception('EZproxy host not defined in configuration');
+        }
+
+        $user = $this->getUser();
+        if ($user) {
+            // Logged in, check for authorization
+            $authService = $this->serviceLocator
+                ->get('ZfcRbac\Service\AuthorizationService');
+            if (!$authService->isGranted($this->ezproxyRequiredPermission)) {
+                $view = $this->createViewModel();
+                $view->unauthorized = true;
+                $this->flashMessenger()->addErrorMessage(
+                    'external_auth_unauthorized'
+                );
+                return $view;
+            }
+            $url = $this->params()->fromPost(
+                'url', $this->params()->fromQuery('url')
+            );
+            return $this->redirect()->toUrl(
+                $this->createEzproxyTicketUrl($user->username, $url)
+            );
+        }
+        return $this->forceLogin('external_auth_login_message');
+    }
+
+    /**
+     * Create a ticket login URL for EZproxy
+     *
+     * @param string $user User name to pass on to EZproxy
+     * @param string $url  The original URL
+     *
+     * @return string EZproxy URL
+     *
+     * @throws \Exception
+     * @see    https://www.oclc.org/support/services/ezproxy/documentation/usr
+     * /ticket/php.en.html
+     */
+    protected function createEzproxyTicketUrl($user, $url)
+    {
+        $config = $this->getConfig();
+        if (empty($config->EZproxy->secret)) {
+            throw new \Exception('EZproxy secret not defined in configuration');
+        }
+
+        $packet = '$u' . time() . '$e';
+        $hash = new \Zend\Crypt\Hash();
+        $algorithm = !empty($config->EZproxy->secret_hash_method)
+            ? $config->EZproxy->secret_hash_method : 'SHA512';
+        $ticket = $config->EZproxy->secret . $user . $packet;
+        $ticket = $hash->compute($algorithm, $ticket);
+        $ticket .= $packet;
+        $params = http_build_query(
+            ['user' => $user, 'ticket' => $ticket, 'url' => $url]
+        );
+        return $config->EZproxy->host . "/login?$params";
+    }
+}
diff --git a/module/VuFind/src/VuFind/Controller/Factory.php b/module/VuFind/src/VuFind/Controller/Factory.php
index 44c6f963ced36dc3136139853f3f24297e7e31f5..79fcd32f993c79db2f570997fc2f76d557553447 100644
--- a/module/VuFind/src/VuFind/Controller/Factory.php
+++ b/module/VuFind/src/VuFind/Controller/Factory.php
@@ -20,7 +20,7 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
  * @category VuFind
- * @package  View_Helpers
+ * @package  Controller
  * @author   Demian Katz <demian.katz@villanova.edu>
  * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
  * @link     https://vufind.org/wiki/development Wiki
@@ -32,7 +32,7 @@ use Zend\ServiceManager\ServiceManager;
  * Factory for controllers.
  *
  * @category VuFind
- * @package  View_Helpers
+ * @package  Controller
  * @author   Demian Katz <demian.katz@villanova.edu>
  * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
  * @link     https://vufind.org/wiki/development Wiki
@@ -41,6 +41,43 @@ use Zend\ServiceManager\ServiceManager;
  */
 class Factory
 {
+    /**
+     * Construct a generic controller.
+     *
+     * @param string         $name Name of table to construct (fully qualified
+     * class name, or else a class name within the current namespace)
+     * @param ServiceManager $sm   Service manager
+     *
+     * @return object
+     */
+    public static function getGenericController($name, ServiceManager $sm)
+    {
+        // Prepend the current namespace unless we receive a FQCN:
+        $class = (strpos($name, '\\') === false)
+            ? __NAMESPACE__ . '\\' . $name : $name;
+        if (!class_exists($class)) {
+            throw new \Exception('Cannot construct ' . $class);
+        }
+        return new $class($sm->getServiceLocator());
+    }
+
+    /**
+     * Construct a generic controller.
+     *
+     * @param string $name Method name being called
+     * @param array  $args Method arguments
+     *
+     * @return object
+     */
+    public static function __callStatic($name, $args)
+    {
+        // Strip "get" from method name to get name of class; pass first argument
+        // on assumption that it should be the ServiceManager object.
+        return static::getGenericController(
+            substr($name, 3), isset($args[0]) ? $args[0] : null
+        );
+    }
+
     /**
      * Construct the BrowseController.
      *
@@ -51,6 +88,7 @@ class Factory
     public static function getBrowseController(ServiceManager $sm)
     {
         return new BrowseController(
+            $sm->getServiceLocator(),
             $sm->getServiceLocator()->get('VuFind\Config')->get('config')
         );
     }
@@ -65,6 +103,7 @@ class Factory
     public static function getCartController(ServiceManager $sm)
     {
         return new CartController(
+            $sm->getServiceLocator(),
             new \Zend\Session\Container(
                 'cart_followup',
                 $sm->getServiceLocator()->get('VuFind\SessionManager')
@@ -82,6 +121,7 @@ class Factory
     public static function getCollectionController(ServiceManager $sm)
     {
         return new CollectionController(
+            $sm->getServiceLocator(),
             $sm->getServiceLocator()->get('VuFind\Config')->get('config')
         );
     }
@@ -96,10 +136,26 @@ class Factory
     public static function getCollectionsController(ServiceManager $sm)
     {
         return new CollectionsController(
+            $sm->getServiceLocator(),
             $sm->getServiceLocator()->get('VuFind\Config')->get('config')
         );
     }
 
+    /**
+     * Construct the IndexController.
+     *
+     * @param ServiceManager $sm Service manager.
+     *
+     * @return RecordController
+     */
+    public static function getIndexController(ServiceManager $sm)
+    {
+        return new IndexController(
+            $sm->getServiceLocator()->get('VuFind\Config')->get('config'),
+            $sm->getServiceLocator()->get('VuFind\AuthManager')
+        );
+    }
+
     /**
      * Construct the RecordController.
      *
@@ -110,6 +166,7 @@ class Factory
     public static function getRecordController(ServiceManager $sm)
     {
         return new RecordController(
+            $sm->getServiceLocator(),
             $sm->getServiceLocator()->get('VuFind\Config')->get('config')
         );
     }
@@ -124,6 +181,7 @@ class Factory
     public static function getUpgradeController(ServiceManager $sm)
     {
         return new UpgradeController(
+            $sm->getServiceLocator(),
             $sm->getServiceLocator()->get('VuFind\CookieManager'),
             new \Zend\Session\Container(
                 'upgrade', $sm->getServiceLocator()->get('VuFind\SessionManager')
diff --git a/module/VuFind/src/VuFind/Controller/FeedbackController.php b/module/VuFind/src/VuFind/Controller/FeedbackController.php
index a067b886bb8be78841f7f6b2e9a01221e6775cf0..13f750ae6269e09f44d112ccebe71e1e804e5147 100644
--- a/module/VuFind/src/VuFind/Controller/FeedbackController.php
+++ b/module/VuFind/src/VuFind/Controller/FeedbackController.php
@@ -59,7 +59,7 @@ class FeedbackController extends AbstractBase
             }
 
             // These settings are set in the feedback settion of your config.ini
-            $config = $this->getServiceLocator()->get('VuFind\Config')
+            $config = $this->serviceLocator->get('VuFind\Config')
                 ->get('config');
             $feedback = isset($config->Feedback) ? $config->Feedback : null;
             $recipient_email = isset($feedback->recipient_email)
@@ -85,7 +85,7 @@ class FeedbackController extends AbstractBase
             // This sets up the email to be sent
             // Attempt to send the email and show an appropriate flash message:
             try {
-                $mailer = $this->getServiceLocator()->get('VuFind\Mailer');
+                $mailer = $this->serviceLocator->get('VuFind\Mailer');
                 $mailer->send(
                     new Address($recipient_email, $recipient_name),
                     new Address($sender_email, $sender_name),
diff --git a/module/VuFind/src/VuFind/Controller/HierarchyController.php b/module/VuFind/src/VuFind/Controller/HierarchyController.php
index 23b59619058f6dd31ab361d2404e95544a8eb45a..3ed8b0dd7fbebaeae08d60bc02bea73f93ba46d9 100644
--- a/module/VuFind/src/VuFind/Controller/HierarchyController.php
+++ b/module/VuFind/src/VuFind/Controller/HierarchyController.php
@@ -89,7 +89,7 @@ class HierarchyController extends AbstractBase
         $lookfor = $this->params()->fromQuery('lookfor', '');
         $searchType = $this->params()->fromQuery('type', 'AllFields');
 
-        $results = $this->getServiceLocator()
+        $results = $this->serviceLocator
             ->get('VuFind\SearchResultsPluginManager')->get('Solr');
         $results->getParams()->setBasicSearch($lookfor, $searchType);
         $results->getParams()->addFilter('hierarchy_top_id:' . $hierarchyID);
@@ -120,7 +120,7 @@ class HierarchyController extends AbstractBase
         $this->disableSessionWrites();  // avoid session write timing bug
         // Retrieve the record from the index
         $id = $this->params()->fromQuery('id');
-        $loader = $this->getServiceLocator()->get('VuFind\RecordLoader');
+        $loader = $this->serviceLocator->get('VuFind\RecordLoader');
         try {
             if ($recordDriver = $loader->load($id)) {
                 $results = $recordDriver->getHierarchyDriver()->render(
@@ -153,7 +153,7 @@ class HierarchyController extends AbstractBase
         $this->disableSessionWrites();  // avoid session write timing bug
         // Retrieve the record from the index
         $id = $this->params()->fromQuery('id');
-        $loader = $this->getServiceLocator()->get('VuFind\RecordLoader');
+        $loader = $this->serviceLocator->get('VuFind\RecordLoader');
         try {
             if ($recordDriver = $loader->load($id)) {
                 $results = $recordDriver->getHierarchyDriver()
@@ -183,7 +183,7 @@ class HierarchyController extends AbstractBase
     public function getrecordAction()
     {
         $id = $this->params()->fromQuery('id');
-        $loader = $this->getServiceLocator()->get('VuFind\RecordLoader');
+        $loader = $this->serviceLocator->get('VuFind\RecordLoader');
         try {
             $record = $loader->load($id);
             $result = $this->getViewRenderer()->record($record)
diff --git a/module/VuFind/src/VuFind/Controller/HoldsTrait.php b/module/VuFind/src/VuFind/Controller/HoldsTrait.php
index b3cfa79a82ee46a04369b6d17c90f0e3e3567f0b..0028faea2a0b4e5748de306af433c5bfdf50c69d 100644
--- a/module/VuFind/src/VuFind/Controller/HoldsTrait.php
+++ b/module/VuFind/src/VuFind/Controller/HoldsTrait.php
@@ -38,17 +38,6 @@ namespace VuFind\Controller;
  */
 trait HoldsTrait
 {
-    /**
-     * Action for dealing with blocked holds.
-     *
-     * @return mixed
-     */
-    public function blockedholdAction()
-    {
-        $this->flashMessenger()->addMessage('hold_error_blocked', 'error');
-        return $this->redirectToRecord('#top');
-    }
-
     /**
      * Action for dealing with holds.
      *
@@ -84,16 +73,23 @@ trait HoldsTrait
         }
 
         // Block invalid requests:
-        if (!$catalog->checkRequestIsValid(
+        $validRequest = $catalog->checkRequestIsValid(
             $driver->getUniqueID(), $gatheredDetails, $patron
-        )) {
-            return $this->blockedholdAction();
+        );
+        if ((is_array($validRequest) && !$validRequest['valid']) || !$validRequest) {
+            $this->flashMessenger()->addErrorMessage(
+                is_array($validRequest)
+                    ? $validRequest['status'] : 'hold_error_blocked'
+            );
+            return $this->redirectToRecord('#top');
         }
 
         // Send various values to the view so we can build the form:
         $requestGroups = $catalog->checkCapability(
-            'getRequestGroups', [$driver->getUniqueID(), $patron]
-        ) ? $catalog->getRequestGroups($driver->getUniqueID(), $patron) : [];
+            'getRequestGroups', [$driver->getUniqueID(), $patron, $gatheredDetails]
+        ) ? $catalog->getRequestGroups(
+            $driver->getUniqueID(), $patron, $gatheredDetails
+        ) : [];
         $extraHoldFields = isset($checkHolds['extraHoldFields'])
             ? explode(":", $checkHolds['extraHoldFields']) : [];
 
@@ -114,18 +110,19 @@ trait HoldsTrait
         $pickup = $catalog->getPickUpLocations($patron, $pickupDetails);
 
         // Process form submissions if necessary:
-        if (!is_null($this->params()->fromPost('placeHold'))) {
+        if (null !== $this->params()->fromPost('placeHold')) {
             // If the form contained a pickup location or request group, make sure
             // they are valid:
-            $valid = $this->holds()->validateRequestGroupInput(
+            $validGroup = $this->holds()->validateRequestGroupInput(
                 $gatheredDetails, $extraHoldFields, $requestGroups
             );
-            if (!$valid) {
+            $validPickup = $validGroup && $this->holds()->validatePickUpInput(
+                $gatheredDetails['pickUpLocation'], $extraHoldFields, $pickup
+            );
+            if (!$validGroup) {
                 $this->flashMessenger()
                     ->addMessage('hold_invalid_request_group', 'error');
-            } elseif (!$this->holds()->validatePickUpInput(
-                $gatheredDetails['pickUpLocation'], $extraHoldFields, $pickup
-            )) {
+            } elseif (!$validPickup) {
                 $this->flashMessenger()->addMessage('hold_invalid_pickup', 'error');
             } else {
                 // If we made it this far, we're ready to place the hold;
@@ -168,7 +165,7 @@ trait HoldsTrait
         $defaultRequired = $this->holds()->getDefaultRequiredDate(
             $checkHolds, $catalog, $patron, $gatheredDetails
         );
-        $defaultRequired = $this->getServiceLocator()->get('VuFind\DateConverter')
+        $defaultRequired = $this->serviceLocator->get('VuFind\DateConverter')
             ->convertToDisplayDate("U", $defaultRequired);
         try {
             $defaultPickup
diff --git a/module/VuFind/src/VuFind/Controller/ILLRequestsTrait.php b/module/VuFind/src/VuFind/Controller/ILLRequestsTrait.php
index eaa943d0416008bac083a0b7101617c59bbb7345..24d3ba082caa3ac405ecea8d21a2e9ebf90cd4b1 100644
--- a/module/VuFind/src/VuFind/Controller/ILLRequestsTrait.php
+++ b/module/VuFind/src/VuFind/Controller/ILLRequestsTrait.php
@@ -38,17 +38,6 @@ namespace VuFind\Controller;
  */
 trait ILLRequestsTrait
 {
-    /**
-     * Action for dealing with blocked ILL requests.
-     *
-     * @return mixed
-     */
-    public function blockedILLRequestAction()
-    {
-        $this->flashMessenger()->addMessage('ill_request_error_blocked', 'error');
-        return $this->redirectToRecord('#top');
-    }
-
     /**
      * Action for dealing with ILL requests.
      *
@@ -86,10 +75,15 @@ trait ILLRequestsTrait
         }
 
         // Block invalid requests:
-        if (!$catalog->checkILLRequestIsValid(
+        $validRequest = $catalog->checkILLRequestIsValid(
             $driver->getUniqueID(), $gatheredDetails, $patron
-        )) {
-            return $this->blockedILLRequestAction();
+        );
+        if ((is_array($validRequest) && !$validRequest['valid']) || !$validRequest) {
+            $this->flashMessenger()->addErrorMessage(
+                is_array($validRequest)
+                    ? $validRequest['status'] : 'ill_request_error_blocked'
+            );
+            return $this->redirectToRecord('#top');
         }
 
         // Send various values to the view so we can build the form:
@@ -138,7 +132,7 @@ trait ILLRequestsTrait
         // Find and format the default required date:
         $defaultRequired = $this->ILLRequests()
             ->getDefaultRequiredDate($checkRequests);
-        $defaultRequired = $this->getServiceLocator()->get('VuFind\DateConverter')
+        $defaultRequired = $this->serviceLocator->get('VuFind\DateConverter')
             ->convertToDisplayDate("U", $defaultRequired);
 
         // Get pickup libraries
diff --git a/module/VuFind/src/VuFind/Controller/IndexController.php b/module/VuFind/src/VuFind/Controller/IndexController.php
index f5a10651c3a83090a7445897e030754cd37fe963..3abd92f9ee6c9e972605ed803bae24c1333c07d9 100644
--- a/module/VuFind/src/VuFind/Controller/IndexController.php
+++ b/module/VuFind/src/VuFind/Controller/IndexController.php
@@ -26,6 +26,8 @@
  * @link     https://vufind.org Main Site
  */
 namespace VuFind\Controller;
+use Zend\Config\Config;
+use VuFind\Auth\Manager as AuthManager;
 
 /**
  * Redirects the user to the appropriate default VuFind action.
@@ -36,8 +38,34 @@ namespace VuFind\Controller;
  * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
  * @link     https://vufind.org Main Site
  */
-class IndexController extends AbstractBase
+class IndexController extends \Zend\Mvc\Controller\AbstractActionController
 {
+    /**
+     * VuFind configuration
+     *
+     * @var Config
+     */
+    protected $config;
+
+    /**
+     * Auth manager
+     *
+     * @var AuthManager
+     */
+    protected $authManager;
+
+    /**
+     * Constructor
+     *
+     * @param Config      $config      VuFind configuration
+     * @param AuthManager $authManager Auth manager
+     */
+    public function __construct(Config $config, AuthManager $authManager)
+    {
+        $this->config = $config;
+        $this->authManager = $authManager;
+    }
+
     /**
      * Determines what elements are displayed on the home page based on whether
      * the user is logged in.
@@ -46,12 +74,12 @@ class IndexController extends AbstractBase
      */
     public function homeAction()
     {
-        $config = $this->getConfig();
-        $loggedInModule = isset($config->Site->defaultLoggedInModule)
-            ? $config->Site->defaultLoggedInModule : 'MyResearch';
-        $loggedOutModule = isset($config->Site->defaultModule)
-            ? $config->Site->defaultModule : 'Search';
-        $module = $this->getUser() ? $loggedInModule : $loggedOutModule;
-        return $this->forwardTo($module, 'Home');
+        $loggedInModule = isset($this->config->Site->defaultLoggedInModule)
+            ? $this->config->Site->defaultLoggedInModule : 'MyResearch';
+        $loggedOutModule = isset($this->config->Site->defaultModule)
+            ? $this->config->Site->defaultModule : 'Search';
+        $module = $this->authManager->isLoggedIn()
+            ? $loggedInModule : $loggedOutModule;
+        return $this->forward()->dispatch($module, ['action' => 'Home']);
     }
 }
diff --git a/module/VuFind/src/VuFind/Controller/InstallController.php b/module/VuFind/src/VuFind/Controller/InstallController.php
index 04397d971f7146cf9f43b6b38eda2841e50f0348..41da1a674e0192de95106a46abae3a636f246513 100644
--- a/module/VuFind/src/VuFind/Controller/InstallController.php
+++ b/module/VuFind/src/VuFind/Controller/InstallController.php
@@ -165,7 +165,7 @@ class InstallController extends AbstractBase
      */
     protected function checkCache()
     {
-        $cache = $this->getServiceLocator()->get('VuFind\CacheManager');
+        $cache = $this->serviceLocator->get('VuFind\CacheManager');
         return [
             'title' => 'Cache',
             'status' => !$cache->hasDirectoryCreationError(),
@@ -180,7 +180,7 @@ class InstallController extends AbstractBase
      */
     public function fixcacheAction()
     {
-        $cache = $this->getServiceLocator()->get('VuFind\CacheManager');
+        $cache = $this->serviceLocator->get('VuFind\CacheManager');
         $view = $this->createViewModel();
         $view->cacheDir = $cache->getCacheDir();
         if (function_exists('posix_getpwuid') && function_exists('posix_geteuid')) {
@@ -237,7 +237,7 @@ class InstallController extends AbstractBase
     {
         $requiredFunctionsExist
             = function_exists('mb_substr') && is_callable('imagecreatefromstring')
-              && function_exists('mcrypt_module_open')
+              && function_exists('openssl_encrypt')
               && class_exists('XSLTProcessor');
 
         return [
@@ -288,10 +288,10 @@ class InstallController extends AbstractBase
             $problems++;
         }
 
-        // Is the mcrypt library missing?
-        if (!function_exists('mcrypt_module_open')) {
+        // Is the openssl library missing?
+        if (!function_exists('openssl_encrypt')) {
             $msg
-                = "Your PHP installation appears to be missing the mcrypt plug-in."
+                = "Your PHP installation appears to be missing the openssl plug-in."
                 . " For better security support, it is recommended that you add"
                 . " this. For details on how to do this, see "
                 . "https://vufind.org/wiki/installation "
@@ -354,7 +354,7 @@ class InstallController extends AbstractBase
                 try {
                     $dbName = ($view->driver == 'pgsql')
                         ? 'template1' : $view->driver;
-                    $db = $this->getServiceLocator()->get('VuFind\DbAdapterFactory')
+                    $db = $this->serviceLocator->get('VuFind\DbAdapterFactory')
                         ->getAdapterFromConnectionString("{$connection}/{$dbName}");
                 } catch (\Exception $e) {
                     $this->flashMessenger()
@@ -390,7 +390,7 @@ class InstallController extends AbstractBase
                         foreach ($preCommands as $query) {
                             $db->query($query, $db::QUERY_MODE_EXECUTE);
                         }
-                        $dbFactory = $this->getServiceLocator()
+                        $dbFactory = $this->serviceLocator
                             ->get('VuFind\DbAdapterFactory');
                         $db = $dbFactory->getAdapterFromConnectionString(
                             $connection . '/' . $view->dbname
@@ -509,13 +509,7 @@ class InstallController extends AbstractBase
         if (in_array($config->Catalog->driver, ['Sample', 'Demo'])) {
             $status = false;
         } else {
-            try {
-                $catalog = $this->getILS();
-                $catalog->getStatus('1');
-                $status = true;
-            } catch (\Exception $e) {
-                $status = false;
-            }
+            $status = 'ils-offline' !== $this->getILS()->getOfflineMode(true);
         }
         return ['title' => 'ILS', 'status' => $status, 'fix' => 'fixils'];
     }
@@ -588,7 +582,7 @@ class InstallController extends AbstractBase
     protected function testSearchService()
     {
         // Try to retrieve an arbitrary ID -- this will fail if Solr is down:
-        $searchService = $this->getServiceLocator()->get('VuFind\Search');
+        $searchService = $this->serviceLocator->get('VuFind\Search');
         $searchService->retrieve('Solr', '1');
     }
 
@@ -803,7 +797,7 @@ class InstallController extends AbstractBase
     {
         // Try to retrieve an SSL URL; if we're misconfigured, it will fail.
         try {
-            $this->getServiceLocator()->get('VuFind\Http')
+            $this->serviceLocator->get('VuFind\Http')
                 ->get('https://google.com');
             $status = true;
         } catch (\VuFindHttp\Exception\RuntimeException $e) {
diff --git a/module/VuFind/src/VuFind/Controller/LibGuidesController.php b/module/VuFind/src/VuFind/Controller/LibGuidesController.php
index 18384f9f3a2a36c6dd8ecfbf758b92af28c4c690..b73f97a2cf3e8dc17e6e22c94a530aaa1fa8d07b 100644
--- a/module/VuFind/src/VuFind/Controller/LibGuidesController.php
+++ b/module/VuFind/src/VuFind/Controller/LibGuidesController.php
@@ -26,6 +26,7 @@
  * @link     https://vufind.org Main Site
  */
 namespace VuFind\Controller;
+use Zend\ServiceManager\ServiceLocatorInterface;
 
 /**
  * LibGuides Controller
@@ -40,11 +41,13 @@ class LibGuidesController extends AbstractSearch
 {
     /**
      * Constructor
+     *
+     * @param ServiceLocatorInterface $sm Service locator
      */
-    public function __construct()
+    public function __construct(ServiceLocatorInterface $sm)
     {
         $this->searchClassId = 'LibGuides';
-        parent::__construct();
+        parent::__construct($sm);
     }
 
     /**
@@ -64,7 +67,7 @@ class LibGuidesController extends AbstractSearch
      */
     protected function resultScrollerActive()
     {
-        $config = $this->getServiceLocator()->get('VuFind\Config')->get('LibGuides');
+        $config = $this->serviceLocator->get('VuFind\Config')->get('LibGuides');
         return (isset($config->Record->next_prev_navigation)
             && $config->Record->next_prev_navigation);
     }
diff --git a/module/VuFind/src/VuFind/Controller/MyResearchController.php b/module/VuFind/src/VuFind/Controller/MyResearchController.php
index 60cffadf461a169c57cdf51745e44be87875e5d9..e55310344d530b7b50cc282f0fcf360a9995ccbf 100644
--- a/module/VuFind/src/VuFind/Controller/MyResearchController.php
+++ b/module/VuFind/src/VuFind/Controller/MyResearchController.php
@@ -29,6 +29,7 @@ namespace VuFind\Controller;
 
 use VuFind\Exception\Auth as AuthException,
     VuFind\Exception\Forbidden as ForbiddenException,
+    VuFind\Exception\ILS as ILSException,
     VuFind\Exception\Mail as MailException,
     VuFind\Exception\ListPermission as ListPermissionException,
     VuFind\Exception\RecordMissing as RecordMissingException,
@@ -79,6 +80,37 @@ class MyResearchController extends AbstractBase
         $this->setFollowupUrlToReferer();
     }
 
+    /**
+     * Execute the request
+     *
+     * @param \Zend\Mvc\MvcEvent $event Event
+     *
+     * @return mixed
+     * @throws Exception\DomainException
+     */
+    public function onDispatch(\Zend\Mvc\MvcEvent $event)
+    {
+        // Catch any ILSExceptions thrown during processing and display a generic
+        // failure message to the user (instead of going to the fatal exception
+        // screen). This offers a slightly more forgiving experience when there is
+        // an unexpected ILS issue. Note that most ILS exceptions are handled at a
+        // lower level in the code (see \VuFind\ILS\Connection and the config.ini
+        // loadNoILSOnFailure setting), but there are some rare edge cases (for
+        // example, when the MultiBackend driver fails over to NoILS while used in
+        // combination with MultiILS authentication) that could lead here.
+        try {
+            return parent::onDispatch($event);
+        } catch (ILSException $exception) {
+            // Always display generic message:
+            $this->flashMessenger()->addErrorMessage('ils_connection_failed');
+            // In development mode, also show technical failure message:
+            if ('development' == APPLICATION_ENV) {
+                $this->flashMessenger()->addErrorMessage($exception->getMessage());
+            }
+            return $this->createViewModel();
+        }
+    }
+
     /**
      * Prepare and direct the home page where it needs to go
      *
@@ -294,7 +326,7 @@ class MyResearchController extends AbstractBase
     protected function setSavedFlagSecurely($searchId, $saved, $userId)
     {
         $searchTable = $this->getTable('Search');
-        $sessId = $this->getServiceLocator()->get('VuFind\SessionManager')->getId();
+        $sessId = $this->serviceLocator->get('VuFind\SessionManager')->getId();
         $row = $searchTable->getOwnedRowById($searchId, $sessId, $userId);
         if (empty($row)) {
             throw new ForbiddenException('Access denied.');
@@ -312,7 +344,7 @@ class MyResearchController extends AbstractBase
     public function savesearchAction()
     {
         // Fail if saved searches are disabled.
-        $check = $this->getServiceLocator()->get('VuFind\AccountCapabilities');
+        $check = $this->serviceLocator->get('VuFind\AccountCapabilities');
         if ($check->getSavedSearchSetting() === 'disabled') {
             throw new ForbiddenException('Saved searches disabled.');
         }
@@ -372,6 +404,7 @@ class MyResearchController extends AbstractBase
 
         // Obtain user information from ILS:
         $catalog = $this->getILS();
+        $this->addAccountBlocksToFlashMessenger($catalog, $patron);
         $profile = $catalog->getMyProfile($patron);
         $profile['home_library'] = $user->home_library;
         $view->profile = $profile;
@@ -387,6 +420,29 @@ class MyResearchController extends AbstractBase
         return $view;
     }
 
+    /**
+     * Add account blocks to the flash messenger as errors.
+     * These messages are lightbox ignored.
+     *
+     * @param \VuFind\ILS\Connection $catalog Catalog connection
+     * @param array                  $patron  Patron details
+     *
+     * @return void
+     */
+    public function addAccountBlocksToFlashMessenger($catalog, $patron)
+    {
+        if ($catalog->checkCapability('getAccountBlocks', compact($patron))
+            && $blocks = $catalog->getAccountBlocks($patron)
+        ) {
+            foreach ($blocks as $block) {
+                $this->flashMessenger()->addMessage(
+                    [ 'msg' => $block, 'dataset' => [ 'lightbox-ignore' => '1' ] ],
+                    'error'
+                );
+            }
+        }
+    }
+
     /**
      * Catalog Login Action
      *
@@ -520,22 +576,24 @@ class MyResearchController extends AbstractBase
     protected function processEditSubmit($user, $driver, $listID)
     {
         $lists = $this->params()->fromPost('lists');
-        $tagParser = $this->getServiceLocator()->get('VuFind\Tags');
+        $tagParser = $this->serviceLocator->get('VuFind\Tags');
+        $favorites = $this->serviceLocator
+            ->get('VuFind\Favorites\FavoritesService');
         foreach ($lists as $list) {
             $tags = $this->params()->fromPost('tags' . $list);
-            $driver->saveToFavorites(
+            $favorites->save(
                 [
                     'list'  => $list,
                     'mytags'  => $tagParser->parse($tags),
                     'notes' => $this->params()->fromPost('notes' . $list)
                 ],
-                $user
+                $user, $driver
             );
         }
         // add to a new list?
         $addToList = $this->params()->fromPost('addToList');
         if ($addToList > -1) {
-            $driver->saveToFavorites(['list' => $addToList], $user);
+            $favorites->save(['list' => $addToList], $user, $driver);
         }
         $this->flashMessenger()->addMessage('edit_list_success', 'success');
 
@@ -675,7 +733,7 @@ class MyResearchController extends AbstractBase
 
         // If we got this far, we just need to display the favorites:
         try {
-            $runner = $this->getServiceLocator()->get('VuFind\SearchRunner');
+            $runner = $this->serviceLocator->get('VuFind\SearchRunner');
 
             // We want to merge together GET, POST and route parameters to
             // initialize our search object:
@@ -684,7 +742,7 @@ class MyResearchController extends AbstractBase
                 + ['id' => $this->params()->fromRoute('id')];
 
             // Set up listener for recommendations:
-            $rManager = $this->getServiceLocator()
+            $rManager = $this->serviceLocator
                 ->get('VuFind\RecommendPluginManager');
             $setupCallback = function ($runner, $params, $searchId) use ($rManager) {
                 $listener = new RecommendListener($rManager, $searchId);
@@ -876,7 +934,7 @@ class MyResearchController extends AbstractBase
         $id = isset($current['id']) ? $current['id'] : null;
         $source = isset($current['source'])
             ? $current['source'] : DEFAULT_SEARCH_BACKEND;
-        $record = $this->getServiceLocator()->get('VuFind\RecordLoader')
+        $record = $this->serviceLocator->get('VuFind\RecordLoader')
             ->load($id, $source, true);
         $record->setExtraDetail('ils_details', $current);
         return $record;
@@ -1079,6 +1137,9 @@ class MyResearchController extends AbstractBase
         // Connect to the ILS:
         $catalog = $this->getILS();
 
+        // Display account blocks, if any:
+        $this->addAccountBlocksToFlashMessenger($catalog, $patron);
+
         // Get the current renewal status and process renewal form, if necessary:
         $renewStatus = $catalog->checkFunction('Renewals', compact('patron'));
         $renewResult = $renewStatus
@@ -1167,9 +1228,11 @@ class MyResearchController extends AbstractBase
                 }
                 $source = isset($row['source'])
                     ? $row['source'] : DEFAULT_SEARCH_BACKEND;
-                $row['driver'] = $this->getServiceLocator()
+                $row['driver'] = $this->serviceLocator
                     ->get('VuFind\RecordLoader')->load($row['id'], $source);
-                $row['title'] = $row['driver']->getShortTitle();
+                if (empty($row['title'])) {
+                    $row['title'] = $row['driver']->getShortTitle();
+                }
             } catch (\Exception $e) {
                 if (!isset($row['title'])) {
                     $row['title'] = null;
@@ -1272,7 +1335,7 @@ class MyResearchController extends AbstractBase
                                 . $user->verify_hash . '&auth_method=' . $method
                         ]
                     );
-                    $this->getServiceLocator()->get('VuFind\Mailer')->send(
+                    $this->serviceLocator->get('VuFind\Mailer')->send(
                         $user->email,
                         $config->Site->email,
                         $this->translate('recovery_email_subject'),
diff --git a/module/VuFind/src/VuFind/Controller/OaiController.php b/module/VuFind/src/VuFind/Controller/OaiController.php
index dde6a3ffd5f2542451b6eb6156cb3cf8e7307fca..eee989ac5aae9cbe77a7aa6a6d7d151114e8b565 100644
--- a/module/VuFind/src/VuFind/Controller/OaiController.php
+++ b/module/VuFind/src/VuFind/Controller/OaiController.php
@@ -100,9 +100,9 @@ class OaiController extends AbstractBase
                 $this->getRequest()->getPost()->toArray()
             );
             $server = new $serverClass(
-                $this->getServiceLocator()->get('VuFind\SearchResultsPluginManager'),
-                $this->getServiceLocator()->get('VuFind\RecordLoader'),
-                $this->getServiceLocator()->get('VuFind\DbTablePluginManager'),
+                $this->serviceLocator->get('VuFind\SearchResultsPluginManager'),
+                $this->serviceLocator->get('VuFind\RecordLoader'),
+                $this->serviceLocator->get('VuFind\DbTablePluginManager'),
                 $config, $baseURL, $params
             );
             $server->setRecordLinkHelper(
diff --git a/module/VuFind/src/VuFind/Controller/Pazpar2Controller.php b/module/VuFind/src/VuFind/Controller/Pazpar2Controller.php
index f6d6fbe938e6340f96e8edaae52ddeda836f1bab..a8d0e81fa5c0595625851a2c392077e7f86d0d27 100644
--- a/module/VuFind/src/VuFind/Controller/Pazpar2Controller.php
+++ b/module/VuFind/src/VuFind/Controller/Pazpar2Controller.php
@@ -26,6 +26,7 @@
  * @link     https://vufind.org Main Site
  */
 namespace VuFind\Controller;
+use Zend\ServiceManager\ServiceLocatorInterface;
 
 /**
  * Pazpar2 Controller
@@ -40,11 +41,13 @@ class Pazpar2Controller extends AbstractSearch
 {
     /**
      * Constructor
+     *
+     * @param ServiceLocatorInterface $sm Service locator
      */
-    public function __construct()
+    public function __construct(ServiceLocatorInterface $sm)
     {
         $this->searchClassId = 'Pazpar2';
-        parent::__construct();
+        parent::__construct($sm);
     }
 
     /**
diff --git a/module/VuFind/src/VuFind/Controller/Pazpar2recordController.php b/module/VuFind/src/VuFind/Controller/Pazpar2recordController.php
index 7ef8067c38671e81cd6a321caa6a7a9efcbd1741..4ebefc7de515f5c4e9d2cd39fe105d248c2cd191 100644
--- a/module/VuFind/src/VuFind/Controller/Pazpar2recordController.php
+++ b/module/VuFind/src/VuFind/Controller/Pazpar2recordController.php
@@ -26,6 +26,7 @@
  * @link     https://vufind.org Main Site
  */
 namespace VuFind\Controller;
+use Zend\ServiceManager\ServiceLocatorInterface;
 
 /**
  * Pazpar2 Record Controller
@@ -40,8 +41,10 @@ class Pazpar2recordController extends AbstractRecord
 {
     /**
      * Constructor
+     *
+     * @param ServiceLocatorInterface $sm Service locator
      */
-    public function __construct()
+    public function __construct(ServiceLocatorInterface $sm)
     {
         throw new \Exception('Pazpar2 record view not supported.');
 
@@ -49,6 +52,6 @@ class Pazpar2recordController extends AbstractRecord
         $this->searchClassId = 'Pazpar2';
 
         // Call standard record controller initialization:
-        parent::__construct();
+        parent::__construct($sm);
     }
 }
diff --git a/module/VuFind/src/VuFind/Controller/Plugin/DbUpgrade.php b/module/VuFind/src/VuFind/Controller/Plugin/DbUpgrade.php
index 43e594e9c7203b25bbbd6e591ceb7cb43496160e..6e56bcc252d00b8d7f483c14a7bb3d9b76846697 100644
--- a/module/VuFind/src/VuFind/Controller/Plugin/DbUpgrade.php
+++ b/module/VuFind/src/VuFind/Controller/Plugin/DbUpgrade.php
@@ -217,6 +217,9 @@ class DbUpgrade extends AbstractPlugin
      */
     protected function getCollationProblemsForTable($table)
     {
+        if (!isset($this->dbCommands[$table['Name']][0])) {
+            return false;
+        }
         // For now, we'll only detect problems in utf8-encoded tables; if the
         // user has a Latin1 database, they probably have more complex issues to
         // work through anyway.
@@ -369,7 +372,7 @@ class DbUpgrade extends AbstractPlugin
      */
     protected function getTableColumns($table)
     {
-        $info = $this->getTableInfo(true);
+        $info = $this->getTableInfo();
         $columns = isset($info[$table]) ? $info[$table]->getColumns() : [];
         $retVal = [];
         foreach ($columns as $current) {
@@ -378,6 +381,44 @@ class DbUpgrade extends AbstractPlugin
         return $retVal;
     }
 
+    /**
+     * Get information on all constraints in a table, keyed by type and constraint
+     * name. Primary key is double-keyed as ['primary']['primary'] to keep the
+     * structure consistent (since primary keys are not explicitly named in the
+     * source SQL).
+     *
+     * @param string $table Table to describe.
+     *
+     * @throws \Exception
+     * @return array
+     */
+    protected function getTableConstraints($table)
+    {
+        $info = $this->getTableInfo();
+        $constraints = isset($info[$table]) ? $info[$table]->getConstraints() : [];
+        $retVal = [];
+        foreach ($constraints as $current) {
+            $fields = ['fields' => $current->getColumns()];
+            switch ($current->getType()) {
+            case 'FOREIGN KEY':
+                $retVal['foreign'][$current->getName()] = $fields;
+                break;
+            case 'PRIMARY KEY':
+                $retVal['primary']['primary'] = $fields;
+                break;
+            case 'UNIQUE':
+                $retVal['unique'][$current->getName()] = $fields;
+                break;
+            default:
+                throw new \Exception(
+                    'Unexpected constraint type: ' . $current->getType()
+                );
+                break;
+            }
+        }
+        return $retVal;
+    }
+
     /**
      * Get a list of missing tables in the database.
      *
@@ -429,6 +470,7 @@ class DbUpgrade extends AbstractPlugin
     public function getMissingColumns($missingTables = [])
     {
         $missing = [];
+        $this->getTableInfo(true); // force reload of table info
         foreach ($this->dbCommands as $table => $sql) {
             // Skip missing tables if we're logging
             if (in_array($table, $missingTables)) {
@@ -465,6 +507,118 @@ class DbUpgrade extends AbstractPlugin
         return $missing;
     }
 
+    /**
+     * Given a field list extracted from a MySQL table definition (e.g. `a`,`b`)
+     * return an array of fields (e.g. ['a', 'b']).
+     *
+     * @param string $fields Field list
+     *
+     * @return array
+     */
+    protected function explodeFields($fields)
+    {
+        return array_map('trim', explode(',', str_replace('`', '', $fields)));
+    }
+
+    /**
+     * Compare expected vs. actual constraints and return an array of SQL
+     * clauses required to create the missing constraints.
+     *
+     * @param array $expected Expected constraints (based on mysql.sql)
+     * @param array $actual   Actual constraints (pulled from database metadata)
+     *
+     * @return array
+     */
+    protected function compareConstraints($expected, $actual)
+    {
+        $missing = [];
+        foreach ($expected as $type => $constraints) {
+            foreach ($constraints as $constraint) {
+                $matchFound = false;
+                foreach ($actual[$type] as $existing) {
+                    $diffCount = count(
+                        array_diff($constraint['fields'], $existing['fields'])
+                    ) + count(
+                        array_diff($existing['fields'], $constraint['fields'])
+                    );
+                    if ($diffCount == 0) {
+                        $matchFound = true;
+                        break;
+                    }
+                }
+                if (!$matchFound) {
+                    $missing[] = trim(rtrim($constraint['sql'], ','));
+                }
+            }
+        }
+        return $missing;
+    }
+
+    /**
+     * Get a list of missing constraints in the database tables (associative array,
+     * key = table name, value = array of missing constraint definitions).
+     *
+     * @param array $missingTables List of missing tables
+     *
+     * @throws \Exception
+     * @return array
+     */
+    public function getMissingConstraints($missingTables = [])
+    {
+        $missing = [];
+        foreach ($this->dbCommands as $table => $sql) {
+            // Skip missing tables if we're logging
+            if (in_array($table, $missingTables)) {
+                continue;
+            }
+
+            // Parse column names out of the CREATE TABLE SQL, which will always be
+            // the first entry in the array; we assume the standard mysqldump
+            // formatting is used here.
+            preg_match_all(
+                '/^  PRIMARY KEY \(`([^)]*)`\).*$/m', $sql[0], $primaryMatches
+            );
+            preg_match_all(
+                '/^  CONSTRAINT `([^`]+)` FOREIGN KEY \(`([^)]*)`\).*$/m',
+                $sql[0], $foreignKeyMatches
+            );
+            preg_match_all(
+                '/^  UNIQUE KEY `([^`]+)`.*\(`([^)]*)`\).*$/m', $sql[0],
+                $uniqueMatches
+            );
+            $expectedConstraints = [
+                'primary' => [
+                    'primary' => [
+                        'sql' => $primaryMatches[0][0],
+                        'fields' => $this->explodeFields($primaryMatches[1][0]),
+                    ],
+                ],
+            ];
+            foreach ($uniqueMatches[0] as $i => $sql) {
+                $expectedConstraints['unique'][$uniqueMatches[1][$i]] = [
+                    'sql' => $sql,
+                    'fields' => $this->explodeFields($uniqueMatches[2][$i]),
+                ];
+            }
+            foreach ($foreignKeyMatches[0] as $i => $sql) {
+                $expectedConstraints['foreign'][$foreignKeyMatches[1][$i]] = [
+                    'sql' => $sql,
+                    'fields' => $this->explodeFields($foreignKeyMatches[2][$i]),
+                ];
+            }
+
+            // Now check for missing columns and build our return array:
+            $actualConstraints = $this->getTableConstraints($table);
+
+            $mismatches = $this
+                ->compareConstraints($expectedConstraints, $actualConstraints);
+            if (!empty($mismatches)) {
+                $missing[$table] = $mismatches;
+            }
+        }
+        return $missing;
+    }
+
     /**
      * Given a current row default, return true if the current default matches the
      * one found in the SQL provided as the $sql parameter. Return false if there
@@ -559,6 +713,7 @@ class DbUpgrade extends AbstractPlugin
         $missingColumns = []
     ) {
         $modified = [];
+        $this->getTableInfo(true); // force reload of table info
         foreach ($this->dbCommands as $table => $sql) {
             // Skip missing tables if we're logging
             if (in_array($table, $missingTables)) {
@@ -634,6 +789,29 @@ class DbUpgrade extends AbstractPlugin
         return $sqlcommands;
     }
 
+    /**
+     * Create missing constraints based on the output of getMissingConstraints().
+     *
+     * @param array $constraints Output of getMissingConstraints()
+     * @param bool  $logsql      Should we return the SQL as a string rather than
+     * execute it?
+     *
+     * @throws \Exception
+     * @return string        SQL if $logsql is true, empty string otherwise
+     */
+    public function createMissingConstraints($constraints, $logsql = false)
+    {
+        $sqlcommands = '';
+        foreach ($constraints as $table => $sql) {
+            foreach ($sql as $constraint) {
+                $sqlcommands .= $this->query(
+                    "ALTER TABLE $table ADD {$constraint};", $logsql
+                );
+            }
+        }
+        return $sqlcommands;
+    }
+
     /**
      * Modify columns based on the output of getModifiedColumns().
      *
diff --git a/module/VuFind/src/VuFind/Controller/Plugin/Factory.php b/module/VuFind/src/VuFind/Controller/Plugin/Factory.php
index ba55d930e825b2728bc31b71c8d061987a4f18fd..63c7261e64f5286f4b49900d14f7591e25b4159b 100644
--- a/module/VuFind/src/VuFind/Controller/Plugin/Factory.php
+++ b/module/VuFind/src/VuFind/Controller/Plugin/Factory.php
@@ -41,6 +41,22 @@ use Zend\ServiceManager\ServiceManager;
  */
 class Factory
 {
+    /**
+     * Construct the Favorites plugin.
+     *
+     * @param ServiceManager $sm Service manager.
+     *
+     * @return \Zend\Mvc\Controller\Plugin\Favorites
+     */
+    public static function getFavorites(ServiceManager $sm)
+    {
+        return new Favorites(
+            $sm->getServiceLocator()->get('VuFind\RecordLoader'),
+            $sm->getServiceLocator()->get('VuFind\RecordCache'),
+            $sm->getServiceLocator()->get('VuFind\Tags')
+        );
+    }
+
     /**
      * Construct the FlashMessenger plugin.
      *
@@ -145,7 +161,8 @@ class Factory
         $config = $sm->getServiceLocator()->get('VuFind\Config')->get('config');
         $useIndex = isset($config->Reserves->search_enabled)
             && $config->Reserves->search_enabled;
-        return new Reserves($useIndex);
+        $ss = $useIndex ? $sm->getServiceLocator()->get('VuFind\Search') : null;
+        return new Reserves($useIndex, $ss);
     }
 
     /**
@@ -161,7 +178,8 @@ class Factory
             new \Zend\Session\Container(
                 'ResultScroller',
                 $sm->getServiceLocator()->get('VuFind\SessionManager')
-            )
+            ),
+            $sm->getServiceLocator()->get('VuFind\SearchResultsPluginManager')
         );
     }
 
diff --git a/module/VuFind/src/VuFind/Controller/Plugin/Favorites.php b/module/VuFind/src/VuFind/Controller/Plugin/Favorites.php
index 5e3e4e5befc609232f4fbc2d267d13e66001d301..8682f28f4f6ca3f60578d3d20d43a7619b5dd2f2 100644
--- a/module/VuFind/src/VuFind/Controller/Plugin/Favorites.php
+++ b/module/VuFind/src/VuFind/Controller/Plugin/Favorites.php
@@ -26,9 +26,11 @@
  * @link     https://vufind.org Main Page
  */
 namespace VuFind\Controller\Plugin;
-use VuFind\Exception\LoginRequired as LoginRequiredException,
-    Zend\Mvc\Controller\Plugin\AbstractPlugin,
-    VuFind\Db\Row\User, VuFind\Record\Cache;
+use VuFind\Exception\LoginRequired as LoginRequiredException;
+use VuFind\Db\Row\User;
+use VuFind\Record\Cache;
+use VuFind\Record\Loader;
+use VuFind\Tags;
 
 /**
  * Zend action helper to perform favorites-related actions
@@ -39,8 +41,43 @@ use VuFind\Exception\LoginRequired as LoginRequiredException,
  * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
  * @link     https://vufind.org Main Page
  */
-class Favorites extends AbstractPlugin
+class Favorites extends \Zend\Mvc\Controller\Plugin\AbstractPlugin
 {
+    /**
+     * Record cache
+     *
+     * @var Cache
+     */
+    protected $cache;
+
+    /**
+     * Record loader
+     *
+     * @var Loader
+     */
+    protected $loader;
+
+    /**
+     * Tag parser
+     *
+     * @var Tags
+     */
+    protected $tags;
+
+    /**
+     * Constructor
+     *
+     * @param Loader $loader Record loader
+     * @param Cache  $cache  Record cache
+     * @param Tags   $tags   Tag parser
+     */
+    public function __construct(Loader $loader, Cache $cache, Tags $tags)
+    {
+        $this->loader = $loader;
+        $this->cache = $cache;
+        $this->tags = $tags;
+    }
+
     /**
      * Support method for saveBulk() -- get list to save records into. Either
      * retrieves existing list or creates a new one.
@@ -67,23 +104,20 @@ class Favorites extends AbstractPlugin
     /**
      * Support method for saveBulk() -- save a batch of records to the cache.
      *
-     * @param Cache $recordCache    Cache service
      * @param array $cacheRecordIds Array of IDs in source|id format
      *
      * @return void
      */
-    protected function cacheBatch(Cache $recordCache, array $cacheRecordIds)
+    protected function cacheBatch(array $cacheRecordIds)
     {
         if ($cacheRecordIds) {
-            $recordLoader = $this->getController()->getServiceLocator()
-                ->get('VuFind\RecordLoader');
             // Disable the cache so that we fetch latest versions, not cached ones:
-            $recordLoader->setCacheContext(Cache::CONTEXT_DISABLED);
-            $records = $recordLoader->loadBatch($cacheRecordIds);
+            $this->loader->setCacheContext(Cache::CONTEXT_DISABLED);
+            $records = $this->loader->loadBatch($cacheRecordIds);
             // Re-enable the cache so that we actually save the records:
-            $recordLoader->setCacheContext(Cache::CONTEXT_FAVORITE);
+            $this->loader->setCacheContext(Cache::CONTEXT_FAVORITE);
             foreach ($records as $record) {
-                $recordCache->createOrUpdate(
+                $this->cache->createOrUpdate(
                     $record->getUniqueID(), $record->getSourceIdentifier(),
                     $record->getRawData()
                 );
@@ -113,10 +147,7 @@ class Favorites extends AbstractPlugin
 
         // Load helper objects needed for the saving process:
         $list = $this->getList(isset($params['list']) ? $params['list'] : '', $user);
-        $tagParser = $this->getController()->getServiceLocator()->get('VuFind\Tags');
-        $recordCache = $this->getController()->getServiceLocator()
-            ->get('VuFind\RecordCache');
-        $recordCache->setContext(Cache::CONTEXT_FAVORITE);
+        $this->cache->setContext(Cache::CONTEXT_FAVORITE);
 
         $cacheRecordIds = [];   // list of record IDs to save to cache
         foreach ($params['ids'] as $current) {
@@ -129,16 +160,16 @@ class Favorites extends AbstractPlugin
 
             // Add the information to the user's account:
             $tags = isset($params['mytags'])
-                ? $tagParser->parse($params['mytags']) : [];
+                ? $this->tags->parse($params['mytags']) : [];
             $user->saveResource($resource, $list, $tags, '', false);
 
             // Collect record IDs for caching
-            if ($recordCache->isCachable($resource->source)) {
+            if ($this->cache->isCachable($resource->source)) {
                 $cacheRecordIds[] = $current;
             }
         }
 
-        $this->cacheBatch($recordCache, $cacheRecordIds);
+        $this->cacheBatch($cacheRecordIds);
         return ['listId' => $list->id];
     }
 
diff --git a/module/VuFind/src/VuFind/Controller/Plugin/Holds.php b/module/VuFind/src/VuFind/Controller/Plugin/Holds.php
index b8ce7380ec049f8beb95634b7f49c4d0bfe8844a..e39e55017a83ebc832c5621385579d864f1ffbb6 100644
--- a/module/VuFind/src/VuFind/Controller/Plugin/Holds.php
+++ b/module/VuFind/src/VuFind/Controller/Plugin/Holds.php
@@ -159,13 +159,12 @@ class Holds extends AbstractRequestBase
                 $flashMsg->addMessage('hold_cancel_fail', 'error');
             } else {
                 if ($cancelResults['count'] > 0) {
-                    // TODO : add a mechanism for inserting tokens into translated
-                    // messages so we can avoid a double translation here.
                     $msg = $this->getController()
-                        ->translate('hold_cancel_success_items');
-                    $flashMsg->addMessage(
-                        $cancelResults['count'] . ' ' . $msg, 'success'
-                    );
+                        ->translate(
+                            'hold_cancel_success_items',
+                            ['%%count%%' => $cancelResults['count']]
+                        );
+                    $flashMsg->addMessage($msg, 'success');
                 }
                 return $cancelResults;
             }
diff --git a/module/VuFind/src/VuFind/Controller/Plugin/ILLRequests.php b/module/VuFind/src/VuFind/Controller/Plugin/ILLRequests.php
index 6a6d3172bda810e1ac7e0b87a5fdc7b12861712a..dbbcea26ddfc4b5d8c0735e628c8cb975ab43c55 100644
--- a/module/VuFind/src/VuFind/Controller/Plugin/ILLRequests.php
+++ b/module/VuFind/src/VuFind/Controller/Plugin/ILLRequests.php
@@ -156,14 +156,12 @@ class ILLRequests extends AbstractRequestBase
                 $flashMsg->addMessage('ill_request_cancel_fail', 'error');
             } else {
                 if ($cancelResults['count'] > 0) {
-                    // TODO : add a mechanism for inserting tokens into translated
-                    // messages so we can avoid a double translation here.
-                    $msg = $this->getController()->translate(
-                        'ill_request_cancel_success_items'
-                    );
-                    $flashMsg->addMessage(
-                        $cancelResults['count'] . ' ' . $msg, 'success'
-                    );
+                    $msg = $this->getController()
+                        ->translate(
+                            'ill_request_cancel_success_items',
+                            ['%%count%%' => $cancelResults['count']]
+                        );
+                    $flashMsg->addMessage($msg, 'success');
                 }
                 return $cancelResults;
             }
diff --git a/module/VuFind/src/VuFind/Controller/Plugin/Reserves.php b/module/VuFind/src/VuFind/Controller/Plugin/Reserves.php
index cbd33a53db63d535d4b07f2051bbbc47687b4879..51f8e25c4c1ab434443334785be5ed49eacb8f36 100644
--- a/module/VuFind/src/VuFind/Controller/Plugin/Reserves.php
+++ b/module/VuFind/src/VuFind/Controller/Plugin/Reserves.php
@@ -26,6 +26,7 @@
  * @link     https://vufind.org Main Page
  */
 namespace VuFind\Controller\Plugin;
+use VuFindSearch\Service;
 use Zend\Mvc\Controller\Plugin\AbstractPlugin;
 
 /**
@@ -47,15 +48,28 @@ class Reserves extends AbstractPlugin
      */
     protected $useIndex;
 
+    /**
+     * Search service
+     *
+     * @var Service
+     */
+    protected $searchService;
+
     /**
      * Constructor
      *
-     * @param bool $useIndex Do we need to use the Solr index for reserves (true)
-     * or the ILS driver (false)?
+     * @param bool    $useIndex      Do we need to use the Solr index for reserves
+     * (true) or the ILS driver (false)?
+     * @param Service $searchService Search service (only required when $useIndex
+     * is true).
      */
-    public function __construct($useIndex = false)
+    public function __construct($useIndex = false, Service $searchService = null)
     {
         $this->useIndex = $useIndex;
+        if ($useIndex && null === $searchService) {
+            throw new \Exception('Missing required search service');
+        }
+        $this->searchService = $searchService;
     }
 
     /**
@@ -84,8 +98,7 @@ class Reserves extends AbstractPlugin
         if ($this->useIndex()) {
             // get the selected reserve record from reserves index
             // and extract the bib IDs from it
-            $result = $this->getController()->getServiceLocator()
-                ->get('VuFind\Search')
+            $result = $this->searchService
                 ->retrieve('SolrReserves', $course . '|' . $inst . '|' . $dept);
             $bibs = [];
             if ($result->getTotal() < 1) {
diff --git a/module/VuFind/src/VuFind/Controller/Plugin/ResultScroller.php b/module/VuFind/src/VuFind/Controller/Plugin/ResultScroller.php
index 04396779c4da5fd5f9984177fbb06cbfbda16f22..6383f83cc9c735a03e523b873a5ede9ba11439ed 100644
--- a/module/VuFind/src/VuFind/Controller/Plugin/ResultScroller.php
+++ b/module/VuFind/src/VuFind/Controller/Plugin/ResultScroller.php
@@ -26,8 +26,9 @@
  * @link     https://vufind.org/wiki/development Wiki
  */
 namespace VuFind\Controller\Plugin;
-use Zend\Mvc\Controller\Plugin\AbstractPlugin,
-    Zend\Session\Container as SessionContainer;
+use VuFind\Search\Results\PluginManager as ResultsManager;
+use Zend\Mvc\Controller\Plugin\AbstractPlugin;
+use Zend\Session\Container as SessionContainer;
 
 /**
  * Class for managing "next" and "previous" navigation within result sets.
@@ -54,18 +55,29 @@ class ResultScroller extends AbstractPlugin
      */
     protected $data;
 
+    /**
+     * Results manager
+     *
+     * @var ResultsManager
+     */
+    protected $resultsManager;
+
     /**
      * Constructor. Create a new search result scroller.
      *
      * @param SessionContainer $session Session container
+     * @param ResultsManager   $rm      Results manager
      * @param bool             $enabled Is the scroller enabled?
      */
-    public function __construct(SessionContainer $session, $enabled = true)
-    {
+    public function __construct(SessionContainer $session, ResultsManager $rm,
+        $enabled = true
+    ) {
         $this->enabled = $enabled;
 
         // Set up session namespace for the class.
         $this->data = $session;
+
+        $this->resultsManager = $rm;
     }
 
     /**
@@ -553,11 +565,9 @@ class ResultScroller extends AbstractPlugin
             $row = $searchTable->getRowById($this->data->searchId, false);
             if (!empty($row)) {
                 $minSO = $row->getSearchObject();
-                $manager = $this->getController()->getServiceLocator()
-                    ->get('VuFind\SearchResultsPluginManager');
-                $search = $minSO->deminify($manager);
-                // The saved search does not remember its original limit;
-                // we should reapply it from the session data:
+                $search = $minSO->deminify($this->resultsManager);
+                // The saved search does not remember its original limit or sort;
+                // we should reapply them from the session data:
                 $search->getParams()->setLimit($this->data->limit);
                 $search->getParams()->setSort($this->data->sort);
                 return $search;
diff --git a/module/VuFind/src/VuFind/Controller/Plugin/StorageRetrievalRequests.php b/module/VuFind/src/VuFind/Controller/Plugin/StorageRetrievalRequests.php
index c1f1bf1a2bf7fd7dac7e92850a4d01d0590a623d..e524f79107bc7f149585a81f80f6a03b112ab350 100644
--- a/module/VuFind/src/VuFind/Controller/Plugin/StorageRetrievalRequests.php
+++ b/module/VuFind/src/VuFind/Controller/Plugin/StorageRetrievalRequests.php
@@ -157,14 +157,12 @@ class StorageRetrievalRequests extends AbstractRequestBase
                     ->addMessage('storage_retrieval_request_cancel_fail', 'error');
             } else {
                 if ($cancelResults['count'] > 0) {
-                    // TODO : add a mechanism for inserting tokens into translated
-                    // messages so we can avoid a double translation here.
-                    $msg = $this->getController()->translate(
-                        'storage_retrieval_request_cancel_success_items'
-                    );
-                    $flashMsg->addMessage(
-                        $cancelResults['count'] . ' ' . $msg, 'success'
-                    );
+                    $msg = $this->getController()
+                        ->translate(
+                            'storage_retrieval_request_cancel_success_items',
+                            ['%%count%%' => $cancelResults['count']]
+                        );
+                    $flashMsg->addMessage($msg, 'success');
                 }
                 return $cancelResults;
             }
diff --git a/module/VuFind/src/VuFind/Controller/PrimoController.php b/module/VuFind/src/VuFind/Controller/PrimoController.php
index adfb41dfd3db6f5ebe7b389ea13b16dee8f23f2a..2d83b0944d467e012af02ab838404acf2a8b46f5 100644
--- a/module/VuFind/src/VuFind/Controller/PrimoController.php
+++ b/module/VuFind/src/VuFind/Controller/PrimoController.php
@@ -26,6 +26,7 @@
  * @link     https://vufind.org Main Site
  */
 namespace VuFind\Controller;
+use Zend\ServiceManager\ServiceLocatorInterface;
 
 /**
  * Primo Central Controller
@@ -40,11 +41,13 @@ class PrimoController extends AbstractSearch
 {
     /**
      * Constructor
+     *
+     * @param ServiceLocatorInterface $sm Service locator
      */
-    public function __construct()
+    public function __construct(ServiceLocatorInterface $sm)
     {
         $this->searchClassId = 'Primo';
-        parent::__construct();
+        parent::__construct($sm);
     }
 
     /**
@@ -64,7 +67,7 @@ class PrimoController extends AbstractSearch
      */
     protected function resultScrollerActive()
     {
-        $config = $this->getServiceLocator()->get('VuFind\Config')->get('Primo');
+        $config = $this->serviceLocator->get('VuFind\Config')->get('Primo');
         return (isset($config->Record->next_prev_navigation)
             && $config->Record->next_prev_navigation);
     }
diff --git a/module/VuFind/src/VuFind/Controller/PrimorecordController.php b/module/VuFind/src/VuFind/Controller/PrimorecordController.php
index a1e53fd789d7e39c6cbd13c9bc88439bc2ca97df..fbd480fa77655ee146677f64629d66efdd84c7f5 100644
--- a/module/VuFind/src/VuFind/Controller/PrimorecordController.php
+++ b/module/VuFind/src/VuFind/Controller/PrimorecordController.php
@@ -26,6 +26,7 @@
  * @link     https://vufind.org Main Site
  */
 namespace VuFind\Controller;
+use Zend\ServiceManager\ServiceLocatorInterface;
 
 /**
  * Primo Central Record Controller
@@ -40,15 +41,17 @@ class PrimorecordController extends AbstractRecord
 {
     /**
      * Constructor
+     *
+     * @param ServiceLocatorInterface $sm Service locator
      */
-    public function __construct()
+    public function __construct(ServiceLocatorInterface $sm)
     {
         // Override some defaults:
         $this->searchClassId = 'Primo';
         $this->fallbackDefaultTab = 'Description';
 
         // Call standard record controller initialization:
-        parent::__construct();
+        parent::__construct($sm);
     }
 
     /**
@@ -58,7 +61,7 @@ class PrimorecordController extends AbstractRecord
      */
     protected function resultScrollerActive()
     {
-        $config = $this->getServiceLocator()->get('VuFind\Config')->get('Primo');
+        $config = $this->serviceLocator->get('VuFind\Config')->get('Primo');
         return (isset($config->Record->next_prev_navigation)
             && $config->Record->next_prev_navigation);
     }
diff --git a/module/VuFind/src/VuFind/Controller/QRCodeController.php b/module/VuFind/src/VuFind/Controller/QRCodeController.php
index 7f2b3dd27eca13d05c82edfc6a6b39e4fb260235..e55acfa37aa1acacc8128782e06b3fadfccbe4aa 100644
--- a/module/VuFind/src/VuFind/Controller/QRCodeController.php
+++ b/module/VuFind/src/VuFind/Controller/QRCodeController.php
@@ -59,10 +59,10 @@ class QRCodeController extends AbstractBase
         if (!$this->loader) {
             $this->loader = new Loader(
                 $this->getConfig(),
-                $this->getServiceLocator()->get('VuFindTheme\ThemeInfo')
+                $this->serviceLocator->get('VuFindTheme\ThemeInfo')
             );
             \VuFind\ServiceManager\Initializer::initInstance(
-                $this->loader, $this->getServiceLocator()
+                $this->loader, $this->serviceLocator
             );
         }
         return $this->loader;
diff --git a/module/VuFind/src/VuFind/Controller/RecordController.php b/module/VuFind/src/VuFind/Controller/RecordController.php
index 05b2c6cebcab1561300c9c45c6261bc4c85752b8..af8aa12c9388bc351a7303a0c44304b1c25ccec2 100644
--- a/module/VuFind/src/VuFind/Controller/RecordController.php
+++ b/module/VuFind/src/VuFind/Controller/RecordController.php
@@ -26,6 +26,8 @@
  * @link     https://vufind.org Main Site
  */
 namespace VuFind\Controller;
+use Zend\Config\Config;
+use Zend\ServiceManager\ServiceLocatorInterface;
 
 /**
  * Record Controller
@@ -45,12 +47,13 @@ class RecordController extends AbstractRecord
     /**
      * Constructor
      *
-     * @param \Zend\Config\Config $config VuFind configuration
+     * @param ServiceLocatorInterface $sm     Service manager
+     * @param Config                  $config VuFind configuration
      */
-    public function __construct(\Zend\Config\Config $config)
+    public function __construct(ServiceLocatorInterface $sm, Config $config)
     {
         // Call standard record controller initialization:
-        parent::__construct();
+        parent::__construct($sm);
 
         // Load default tab setting:
         $this->fallbackDefaultTab = isset($config->Site->defaultRecordTab)
@@ -64,7 +67,7 @@ class RecordController extends AbstractRecord
      */
     protected function resultScrollerActive()
     {
-        $config = $this->getServiceLocator()->get('VuFind\Config')->get('config');
+        $config = $this->serviceLocator->get('VuFind\Config')->get('config');
         return (isset($config->Record->next_prev_navigation)
             && $config->Record->next_prev_navigation);
     }
diff --git a/module/VuFind/src/VuFind/Controller/RecordsController.php b/module/VuFind/src/VuFind/Controller/RecordsController.php
index 1cdd6d6c222f8f48131aa2d48d58d7a8e2e7881c..5d28ea2eeceffd7715604e8b34b68a24d52280fc 100644
--- a/module/VuFind/src/VuFind/Controller/RecordsController.php
+++ b/module/VuFind/src/VuFind/Controller/RecordsController.php
@@ -26,6 +26,7 @@
  * @link     https://vufind.org Main Site
  */
 namespace VuFind\Controller;
+use Zend\ServiceManager\ServiceLocatorInterface;
 
 /**
  * Records Controller
@@ -40,11 +41,13 @@ class RecordsController extends AbstractSearch
 {
     /**
      * Constructor
+     *
+     * @param ServiceLocatorInterface $sm Service locator
      */
-    public function __construct()
+    public function __construct(ServiceLocatorInterface $sm)
     {
         $this->searchClassId = 'MixedList';
-        parent::__construct();
+        parent::__construct($sm);
     }
 
     /**
diff --git a/module/VuFind/src/VuFind/Controller/SearchController.php b/module/VuFind/src/VuFind/Controller/SearchController.php
index e32847da14fc7e44c9eae78a375f495f8e6c0891..45d69f2f3d8dfe93953328aca5103dc6fe686f82 100644
--- a/module/VuFind/src/VuFind/Controller/SearchController.php
+++ b/module/VuFind/src/VuFind/Controller/SearchController.php
@@ -52,7 +52,7 @@ class SearchController extends AbstractSearch
 
         // Set up facet information:
         $view->facetList = $this->processAdvancedFacets(
-            $this->getAdvancedFacets()->getFacetList(), $view->saved
+            $this->getAdvancedFacets(), $view->saved
         );
         $specialFacets = $this->parseSpecialFacetsSetting(
             $view->options->getSpecialAdvancedFacets()
@@ -81,7 +81,7 @@ class SearchController extends AbstractSearch
     {
         // If a URL was explicitly passed in, use that; otherwise, try to
         // find the HTTP referrer.
-        $mailer = $this->getServiceLocator()->get('VuFind\Mailer');
+        $mailer = $this->serviceLocator->get('VuFind\Mailer');
         $view = $this->createEmailViewModel(null, $mailer->getDefaultLinkSubject());
         $mailer->setMaxRecipients($view->maxRecipients);
         // Set up reCaptcha
@@ -185,7 +185,7 @@ class SearchController extends AbstractSearch
         $hierarchicalFacets = $this->getHierarchicalFacets();
         $facetHelper = null;
         if (!empty($hierarchicalFacets)) {
-            $facetHelper = $this->getServiceLocator()
+            $facetHelper = $this->serviceLocator
                 ->get('VuFind\HierarchicalFacetHelper');
         }
         foreach ($facetList as $facet => &$list) {
@@ -240,7 +240,7 @@ class SearchController extends AbstractSearch
         // Retrieve search history
         $search = $this->getTable('Search');
         $searchHistory = $search->getSearches(
-            $this->getServiceLocator()->get('VuFind\SessionManager')->getId(),
+            $this->serviceLocator->get('VuFind\SessionManager')->getId(),
             is_object($user) ? $user->id : null
         );
 
@@ -284,7 +284,8 @@ class SearchController extends AbstractSearch
     {
         return $this->createViewModel(
             [
-                'results' => $this->getHomePageFacets(),
+                'results' => $this->getResultsObjectWithHiddenFilters('Solr'),
+                'facetList' => $this->getHomePageFacets(),
                 'hierarchicalFacets' => $this->getHierarchicalFacets(),
                 'hierarchicalFacetSortOptions'
                     => $this->getHierarchicalFacetSortSettings()
@@ -365,10 +366,10 @@ class SearchController extends AbstractSearch
         // (check it's set first -- RSS feed will return a response model rather
         // than a view model):
         if (isset($view->results)) {
-            $url = $view->results->getUrlQuery();
-            $url->setDefaultParameter('range', $range);
-            $url->setDefaultParameter('department', $dept);
-            $url->setSuppressQuery(true);
+            $view->results->getUrlQuery()
+                ->setDefaultParameter('range', $range)
+                ->setDefaultParameter('department', $dept)
+                ->setSuppressQuery(true);
         }
 
         // We don't want new items hidden filters to propagate to other searches:
@@ -434,7 +435,7 @@ class SearchController extends AbstractSearch
             + $this->getRequest()->getPost()->toArray()
         );
         $view = $this->createViewModel();
-        $runner = $this->getServiceLocator()->get('VuFind\SearchRunner');
+        $runner = $this->serviceLocator->get('VuFind\SearchRunner');
         $view->results = $runner->run(
             $request, 'SolrReserves', $this->getSearchSetupCallback()
         );
@@ -494,11 +495,11 @@ class SearchController extends AbstractSearch
         // (but only do this if we have access to a results object, which we
         // won't in RSS mode):
         if (isset($view->results)) {
-            $url = $view->results->getUrlQuery();
-            $url->setDefaultParameter('course', $course);
-            $url->setDefaultParameter('inst', $inst);
-            $url->setDefaultParameter('dept', $dept);
-            $url->setSuppressQuery(true);
+            $view->results->getUrlQuery()
+                ->setDefaultParameter('course', $course)
+                ->setDefaultParameter('inst', $inst)
+                ->setDefaultParameter('dept', $dept)
+                ->setSuppressQuery(true);
         }
         return $view;
     }
@@ -529,6 +530,40 @@ class SearchController extends AbstractSearch
         return parent::resultsAction();
     }
 
+    /**
+     * Get active hidden filter settings.
+     *
+     * @return array
+     */
+    protected function getActiveHiddenFilters()
+    {
+        return $this->serviceLocator->get('VuFind\SearchTabsHelper')
+            ->getHiddenFilters($this->searchClassId);
+    }
+
+    /**
+     * Create a results object with hidden filters pre-populated.
+     *
+     * @param string $backend ID of results object to create
+     * @param array  $filters Hidden filter settings (null for defaults)
+     *
+     * @return \VuFind\Search\Base\Results
+     */
+    protected function getResultsObjectWithHiddenFilters($backend, $filters = null)
+    {
+        if (null === $filters) {
+            $filters = $this->getActiveHiddenFilters();
+        }
+        $results = $this->getResultsManager()->get($backend);
+        $params = $results->getParams();
+        foreach ($filters as $key => $subFilters) {
+            foreach ($subFilters as $filter) {
+                $params->addHiddenFilter("$key:$filter");
+            }
+        }
+        return $results;
+    }
+
     /**
      * Return a Search Results object containing requested facet information.  This
      * data may come from the cache.
@@ -536,52 +571,49 @@ class SearchController extends AbstractSearch
      * @param string $initMethod Name of params method to use to request facets
      * @param string $cacheName  Cache key for facet data
      *
-     * @return \VuFind\Search\Solr\Results
+     * @return array
      */
     protected function getFacetResults($initMethod, $cacheName)
     {
         // Check if we have facet results cached, and build them if we don't.
-        $cache = $this->getServiceLocator()->get('VuFind\CacheManager')
+        $cache = $this->serviceLocator->get('VuFind\CacheManager')
             ->getCache('object');
-        $searchTabsHelper = $this->getServiceLocator()
-            ->get('VuFind\SearchTabsHelper');
-        $hiddenFilters = $searchTabsHelper->getHiddenFilters($this->searchClassId);
+        $hiddenFilters = $this->getActiveHiddenFilters();
         $hiddenFiltersHash = md5(json_encode($hiddenFilters));
-        $cacheName .= "-$hiddenFiltersHash";
-        if (!($results = $cache->getItem($cacheName))) {
+        $cacheName .= "List-$hiddenFiltersHash";
+        if (!($list = $cache->getItem($cacheName))) {
             // Use advanced facet settings to get summary facets on the front page;
             // we may want to make this more flexible later.  Also keep in mind that
             // the template is currently looking for certain hard-coded fields; this
             // should also be made smarter.
-            $results = $this->getResultsManager()->get('Solr');
+            $results = $this->getResultsObjectWithHiddenFilters(
+                'Solr', $hiddenFilters
+            );
             $params = $results->getParams();
             $params->$initMethod();
-            foreach ($hiddenFilters as $key => $filters) {
-                foreach ($filters as $filter) {
-                    $params->addHiddenFilter("$key:$filter");
-                }
-            }
-
-            // We only care about facet lists, so don't get any results (this helps
-            // prevent problems with serialized File_MARC objects in the cache):
-            $params->setLimit(0);
-
-            $results->getResults();                     // force processing for cache
 
-            $cache->setItem($cacheName, $results);
+            // Avoid a backend request if there are no facets configured by the given
+            // init method.
+            if (!empty($params->getFacetConfig())) {
+                // We only care about facet lists, so don't get any results (this
+                // helps prevent problems with serialized File_MARC objects in the
+                // cache):
+                $params->setLimit(0);
+                $list = $results->getFacetList();
+            } else {
+                $list = [];
+            }
+            $cache->setItem($cacheName, $list);
         }
 
-        // Restore the real service locator to the object (it was lost during
-        // serialization):
-        $results->restoreServiceLocator($this->getServiceLocator());
-        return $results;
+        return $list;
     }
 
     /**
      * Return a Search Results object containing advanced facet information.  This
      * data may come from the cache.
      *
-     * @return \VuFind\Search\Solr\Results
+     * @return array
      */
     protected function getAdvancedFacets()
     {
@@ -594,7 +626,7 @@ class SearchController extends AbstractSearch
      * Return a Search Results object containing homepage facet information.  This
      * data may come from the cache.
      *
-     * @return \VuFind\Search\Solr\Results
+     * @return array
      */
     protected function getHomePageFacets()
     {
@@ -641,7 +673,7 @@ class SearchController extends AbstractSearch
 
         // Get suggestions and make sure they are an array (we don't want to JSON
         // encode them into an object):
-        $autocompleteManager = $this->getServiceLocator()
+        $autocompleteManager = $this->serviceLocator
             ->get('VuFind\AutocompletePluginManager');
         $suggestions = $autocompleteManager->getSuggestions(
             $query, 'type', 'lookfor'
@@ -664,7 +696,7 @@ class SearchController extends AbstractSearch
      */
     protected function resultScrollerActive()
     {
-        $config = $this->getServiceLocator()->get('VuFind\Config')->get('config');
+        $config = $this->serviceLocator->get('VuFind\Config')->get('config');
         return (isset($config->Record->next_prev_navigation)
             && $config->Record->next_prev_navigation);
     }
diff --git a/module/VuFind/src/VuFind/Controller/ShibbolethLogoutNotificationController.php b/module/VuFind/src/VuFind/Controller/ShibbolethLogoutNotificationController.php
new file mode 100644
index 0000000000000000000000000000000000000000..1cb7b77f7df3b62b8c4a04584fea091d97055edd
--- /dev/null
+++ b/module/VuFind/src/VuFind/Controller/ShibbolethLogoutNotificationController.php
@@ -0,0 +1,183 @@
+<?php
+/**
+ * Shibboleth Logout Notification API Controller
+ *
+ * PHP version 5
+ *
+ * Copyright (C) The National Library of Finland 2016.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * @category VuFind
+ * @package  Controller
+ * @author   Ere Maijala <ere.maijala@helsinki.fi>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org Main Site
+ */
+namespace VuFind\Controller;
+
+use Zend\ServiceManager\ServiceLocatorInterface;
+use Zend\Stdlib\ResponseInterface as Response;
+
+/**
+ * Handles Shibboleth back-channel logout notifications.
+ *
+ * @category VuFind
+ * @package  Controller
+ * @author   Ere Maijala <ere.maijala@helsinki.fi>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org Main Site
+ */
+class ShibbolethLogoutNotificationController extends AbstractBase
+{
+    /**
+     * Constructor
+     *
+     * @param ServiceLocatorInterface $sm Service locator
+     */
+    public function __construct(ServiceLocatorInterface $sm)
+    {
+        $this->accessPermission = 'access.api.ShibbolethLogoutNotification';
+        $this->accessDeniedBehavior = 'exception';
+        parent::__construct($sm);
+    }
+
+    /**
+     * GET method handler for the logout handler
+     *
+     * @return Response
+     */
+    public function getAction()
+    {
+        $this->disableSessionWrites();
+        $response = $this->getResponse();
+        $response->getHeaders()->addHeaderLine(
+            'Content-Type', 'application/wsdl+xml'
+        );
+        $response->setContent($this->getWsdl());
+        return $response;
+    }
+
+    /**
+     * POST method handler for the logout handler
+     *
+     * @return Response
+     */
+    public function postAction()
+    {
+        $this->disableSessionWrites();
+        $soapServer = new \Zend\Soap\Server(
+            'data://text/plain;base64,' . base64_encode($this->getWsdl())
+        );
+        $soapServer->setReturnResponse(true);
+        $soapServer->setObject($this);
+        $soapResponse = $soapServer->handle();
+        if ($soapResponse instanceof \SoapFault) {
+            $soapResponse = (string)$soapResponse;
+        }
+        $response = $this->getResponse();
+        $response->getHeaders()->addHeaderLine('Content-Type', 'text/xml');
+        $response->setContent($soapResponse);
+        return $response;
+    }
+
+    /**
+     * Logout notification handler
+     *
+     * @param string $sessionId External session id
+     *
+     * @return void
+     */
+    public function logoutNotification($sessionId)
+    {
+        $table = $this->getTable('ExternalSession');
+        $row = $table->getByExternalSessionId(trim($sessionId));
+        if (empty($row)) {
+            return;
+        }
+        $sessionManager = $this->serviceLocator->get('VuFind\SessionManager');
+        $handler = $sessionManager->getSaveHandler();
+        $handler->destroy($row['session_id']);
+        return;
+    }
+
+    /**
+     * Get WSDL for the service
+     *
+     * @return string
+     */
+    protected function getWsdl()
+    {
+        list($uri) = explode('?', $this->getRequest()->getUriString());
+        return <<<EOT
+<?xml version ="1.0" encoding ="UTF-8" ?>
+<definitions name="LogoutNotification"
+  targetNamespace="urn:mace:shibboleth:2.0:sp:notify"
+  xmlns:notify="urn:mace:shibboleth:2.0:sp:notify"
+  xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
+  xmlns="http://schemas.xmlsoap.org/wsdl/">
+
+    <types>
+       <schema targetNamespace="urn:mace:shibboleth:2.0:sp:notify"
+           xmlns="http://www.w3.org/2000/10/XMLSchema"
+           xmlns:notify="urn:mace:shibboleth:2.0:sp:notify">
+
+            <simpleType name="string">
+                <restriction base="string">
+                    <minLength value="1"/>
+                </restriction>
+            </simpleType>
+
+            <element name="OK" type="notify:OKType"/>
+            <complexType name="OKType">
+                <sequence/>
+            </complexType>
+
+        </schema>
+    </types>
+
+    <message name="getLogoutNotificationRequest">
+        <part name="SessionID" type="notify:string"/>
+    </message>
+
+    <message name="getLogoutNotificationResponse" >
+        <part name="OK"/>
+    </message>
+
+    <portType name="LogoutNotificationPortType">
+        <operation name="LogoutNotification">
+            <input message="getLogoutNotificationRequest"/>
+            <output message="getLogoutNotificationResponse"/>
+        </operation>
+    </portType>
+
+    <binding name="LogoutNotificationBinding"
+        type="notify:LogoutNotificationPortType">
+        <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
+        <operation name="LogoutNotification">
+            <soap:operation
+                soapAction="urn:xmethods-logout-notification#LogoutNotification"/>
+        </operation>
+    </binding>
+
+    <service name="LogoutNotificationService">
+          <port name="LogoutNotificationPort"
+            binding="notify:LogoutNotificationBinding">
+            <soap:address location="$uri"/>
+          </port>
+    </service>
+</definitions>
+EOT;
+    }
+}
diff --git a/module/VuFind/src/VuFind/Controller/StorageRetrievalRequestsTrait.php b/module/VuFind/src/VuFind/Controller/StorageRetrievalRequestsTrait.php
index e76997c3c392f95b7f9d99804079bd36471bcf0d..272ff2af2ee92f2c959af2a33349a9df2de72ac4 100644
--- a/module/VuFind/src/VuFind/Controller/StorageRetrievalRequestsTrait.php
+++ b/module/VuFind/src/VuFind/Controller/StorageRetrievalRequestsTrait.php
@@ -38,18 +38,6 @@ namespace VuFind\Controller;
  */
 trait StorageRetrievalRequestsTrait
 {
-    /**
-     * Action for dealing with blocked storage retrieval requests.
-     *
-     * @return mixed
-     */
-    public function blockedStorageRetrievalRequestAction()
-    {
-        $this->flashMessenger()
-            ->addMessage('storage_retrieval_request_error_blocked', 'error');
-        return $this->redirectToRecord('#top');
-    }
-
     /**
      * Action for dealing with storage retrieval requests.
      *
@@ -87,10 +75,16 @@ trait StorageRetrievalRequestsTrait
         }
 
         // Block invalid requests:
-        if (!$catalog->checkStorageRetrievalRequestIsValid(
+        $validRequest = $catalog->checkStorageRetrievalRequestIsValid(
             $driver->getUniqueID(), $gatheredDetails, $patron
-        )) {
-            return $this->blockedStorageRetrievalRequestAction();
+        );
+        if ((is_array($validRequest) && !$validRequest['valid']) || !$validRequest) {
+            $this->flashMessenger()->addErrorMessage(
+                is_array($validRequest)
+                    ? $validRequest['status']
+                    : 'storage_retrieval_request_error_blocked'
+            );
+            return $this->redirectToRecord('#top');
         }
 
         // Send various values to the view so we can build the form:
@@ -138,7 +132,7 @@ trait StorageRetrievalRequestsTrait
         // Find and format the default required date:
         $defaultRequired = $this->storageRetrievalRequests()
             ->getDefaultRequiredDate($checkRequests);
-        $defaultRequired = $this->getServiceLocator()->get('VuFind\DateConverter')
+        $defaultRequired = $this->serviceLocator->get('VuFind\DateConverter')
             ->convertToDisplayDate("U", $defaultRequired);
         try {
             $defaultPickup
diff --git a/module/VuFind/src/VuFind/Controller/SummonController.php b/module/VuFind/src/VuFind/Controller/SummonController.php
index 95fbb8c9875f5a725bd6df7abf7e0c4b559e3739..9598e0a0cd442ffbd10099e7265edae75fbf3bfe 100644
--- a/module/VuFind/src/VuFind/Controller/SummonController.php
+++ b/module/VuFind/src/VuFind/Controller/SummonController.php
@@ -27,6 +27,7 @@
  */
 namespace VuFind\Controller;
 use Zend\Mvc\MvcEvent;
+use Zend\ServiceManager\ServiceLocatorInterface;
 
 /**
  * Summon Controller
@@ -41,11 +42,13 @@ class SummonController extends AbstractSearch
 {
     /**
      * Constructor
+     *
+     * @param ServiceLocatorInterface $sm Service locator
      */
-    public function __construct()
+    public function __construct(ServiceLocatorInterface $sm)
     {
         $this->searchClassId = 'Summon';
-        parent::__construct();
+        parent::__construct($sm);
     }
 
     /**
@@ -55,7 +58,7 @@ class SummonController extends AbstractSearch
      */
     protected function resultScrollerActive()
     {
-        $config = $this->getServiceLocator()->get('VuFind\Config')->get('Summon');
+        $config = $this->serviceLocator->get('VuFind\Config')->get('Summon');
         return (isset($config->Record->next_prev_navigation)
             && $config->Record->next_prev_navigation);
     }
@@ -101,7 +104,7 @@ class SummonController extends AbstractSearch
 
         // Set up facet information:
         $view->facetList = $this->processAdvancedFacets(
-            $this->getAdvancedFacets()->getFacetList(), $view->saved
+            $this->getAdvancedFacets(), $view->saved
         );
         $specialFacets = $this->parseSpecialFacetsSetting(
             $view->options->getSpecialAdvancedFacets()
@@ -125,7 +128,10 @@ class SummonController extends AbstractSearch
     public function homeAction()
     {
         return $this->createViewModel(
-            ['results' => $this->getHomePageFacets()]
+            [
+                'results' => $this->getResultsManager()->get('Summon'),
+                'facetList' => $this->getHomePageFacets(),
+            ]
         );
     }
 
@@ -143,15 +149,15 @@ class SummonController extends AbstractSearch
      * Return a Search Results object containing advanced facet information.  This
      * data may come from the cache.
      *
-     * @return \VuFind\Search\Summon\Results
+     * @return array
      */
     protected function getAdvancedFacets()
     {
         // Check if we have facet results cached, and build them if we don't.
-        $cache = $this->getServiceLocator()->get('VuFind\CacheManager')
+        $cache = $this->serviceLocator->get('VuFind\CacheManager')
             ->getCache('object');
-        if (!($results = $cache->getItem('summonSearchAdvancedFacets'))) {
-            $config = $this->getServiceLocator()->get('VuFind\Config')
+        if (!($list = $cache->getItem('summonSearchAdvancedFacetsList'))) {
+            $config = $this->serviceLocator->get('VuFind\Config')
                 ->get('Summon');
             $limit = isset($config->Advanced_Facet_Settings->facet_limit)
                 ? $config->Advanced_Facet_Settings->facet_limit : 100;
@@ -179,22 +185,19 @@ class SummonController extends AbstractSearch
             $params->setLimit(0);
 
             // force processing for cache
-            $results->getResults();
+            $list = $results->getFacetList();
 
-            $cache->setItem('summonSearchAdvancedFacets', $results);
+            $cache->setItem('summonSearchAdvancedFacetsList', $list);
         }
 
-        // Restore the real service locator to the object (it was lost during
-        // serialization):
-        $results->restoreServiceLocator($this->getServiceLocator());
-        return $results;
+        return $list;
     }
 
     /**
      * Return a Search Results object containing homepage facet information.  This
      * data may come from the cache.
      *
-     * @return \VuFind\Search\Summon\Results
+     * @return array
      */
     protected function getHomePageFacets()
     {
diff --git a/module/VuFind/src/VuFind/Controller/SummonrecordController.php b/module/VuFind/src/VuFind/Controller/SummonrecordController.php
index f173a437134c2410acc1d7978a21bf399bf6d609..f5cc870535cf726d55de76ce325887e80a5a8585 100644
--- a/module/VuFind/src/VuFind/Controller/SummonrecordController.php
+++ b/module/VuFind/src/VuFind/Controller/SummonrecordController.php
@@ -27,6 +27,7 @@
  */
 namespace VuFind\Controller;
 use Zend\Mvc\MvcEvent;
+use Zend\ServiceManager\ServiceLocatorInterface;
 
 /**
  * Summon Record Controller
@@ -41,15 +42,17 @@ class SummonrecordController extends AbstractRecord
 {
     /**
      * Constructor
+     *
+     * @param ServiceLocatorInterface $sm Service locator
      */
-    public function __construct()
+    public function __construct(ServiceLocatorInterface $sm)
     {
         // Override some defaults:
         $this->searchClassId = 'Summon';
         $this->fallbackDefaultTab = 'Description';
 
         // Call standard record controller initialization:
-        parent::__construct();
+        parent::__construct($sm);
     }
 
     /**
@@ -59,7 +62,7 @@ class SummonrecordController extends AbstractRecord
      */
     protected function resultScrollerActive()
     {
-        $config = $this->getServiceLocator()->get('VuFind\Config')->get('Summon');
+        $config = $this->serviceLocator->get('VuFind\Config')->get('Summon');
         return (isset($config->Record->next_prev_navigation)
             && $config->Record->next_prev_navigation);
     }
diff --git a/module/VuFind/src/VuFind/Controller/TagController.php b/module/VuFind/src/VuFind/Controller/TagController.php
index a4a8d2b6e83e686b2f4462ee8824a2a166a9ba7f..e7f66af4bca40cf351a15a4e79d5254276c8d20c 100644
--- a/module/VuFind/src/VuFind/Controller/TagController.php
+++ b/module/VuFind/src/VuFind/Controller/TagController.php
@@ -27,6 +27,7 @@
  */
 namespace VuFind\Controller;
 use VuFind\Exception\Forbidden as ForbiddenException;
+use Zend\ServiceManager\ServiceLocatorInterface;
 
 /**
  * Tag Controller
@@ -41,11 +42,13 @@ class TagController extends AbstractSearch
 {
     /**
      * Constructor
+     *
+     * @param ServiceLocatorInterface $sm Service locator
      */
-    public function __construct()
+    public function __construct(ServiceLocatorInterface $sm)
     {
         $this->searchClassId = 'Tags';
-        parent::__construct();
+        parent::__construct($sm);
     }
 
     /**
diff --git a/module/VuFind/src/VuFind/Controller/UpgradeController.php b/module/VuFind/src/VuFind/Controller/UpgradeController.php
index eb2a7a5db3e3d062dd5b387af136386c0d1719bc..fed899adb550914e72abba2c57506041451c6d09 100644
--- a/module/VuFind/src/VuFind/Controller/UpgradeController.php
+++ b/module/VuFind/src/VuFind/Controller/UpgradeController.php
@@ -30,8 +30,11 @@
 namespace VuFind\Controller;
 use ArrayObject, VuFind\Config\Locator as ConfigLocator,
     VuFind\Cookie\Container as CookieContainer,
+    VuFind\Cookie\CookieManager,
     VuFind\Exception\RecordMissing as RecordMissingException,
-    Zend\Mvc\MvcEvent;
+    Zend\Mvc\MvcEvent,
+    Zend\ServiceManager\ServiceLocatorInterface,
+    Zend\Session\Container;
 
 /**
  * Class controls VuFind upgrading.
@@ -55,7 +58,7 @@ class UpgradeController extends AbstractBase
     /**
      * Session container
      *
-     * @var \Zend\Session\Container
+     * @var Container
      */
     protected $session;
 
@@ -69,12 +72,15 @@ class UpgradeController extends AbstractBase
     /**
      * Constructor
      *
-     * @param \VuFind\Cookie\CookieManager $cookieManager    Cookie manager
-     * @param \Zend\Session\Container      $sessionContainer Session container
+     * @param ServiceLocatorInterface $sm               Service manager
+     * @param CookieManager           $cookieManager    Cookie manager
+     * @param Container               $sessionContainer Session container
      */
-    public function __construct(\VuFind\Cookie\CookieManager $cookieManager,
-        \Zend\Session\Container $sessionContainer
+    public function __construct(ServiceLocatorInterface $sm,
+        CookieManager $cookieManager, Container $sessionContainer
     ) {
+        parent::__construct($sm);
+
         // We want to use cookies for tracking the state of the upgrade, since the
         // session is unreliable -- if the user upgrades a configuration that uses
         // a different session handler than the default one, we'll lose track of our
@@ -229,7 +235,7 @@ class UpgradeController extends AbstractBase
         // subsequent calls.
         static $adapter = false;
         if (!$adapter) {
-            $factory = $this->getServiceLocator()->get('VuFind\DbAdapterFactory');
+            $factory = $this->serviceLocator->get('VuFind\DbAdapterFactory');
             $adapter = $factory->getAdapter(
                 $this->session->dbRootUser, $this->session->dbRootPass
             );
@@ -284,17 +290,6 @@ class UpgradeController extends AbstractBase
                 . ' legacy "VuFind" source value(s) in resource table'
             );
         }
-
-        $userStatsFields = $this->getTable('userstatsfields');
-        $usfWhere = ['field' => 'recordSource', 'value' => 'VuFind'];
-        $usfRows = $userStatsFields->select($usfWhere);
-        if (count($usfRows) > 0) {
-            $userStatsFields->update(['value' => 'Solr'], $usfWhere);
-            $this->session->warnings->append(
-                'Converted ' . count($usfRows)
-                . ' legacy "VuFind" source value(s) in user_stats_fields table'
-            );
-        }
     }
 
     /**
@@ -304,7 +299,7 @@ class UpgradeController extends AbstractBase
      */
     protected function fixSearchChecksumsInDatabase()
     {
-        $manager = $this->getServiceLocator()
+        $manager = $this->serviceLocator
             ->get('VuFind\SearchResultsPluginManager');
         $search = $this->getTable('search');
         $searchWhere = ['checksum' => null, 'saved' => 1];
@@ -399,6 +394,24 @@ class UpgradeController extends AbstractBase
                 ->updateModifiedColumns($modifiedCols, $this->logsql);
         }
 
+        // Check for missing constraints.
+        $missingConstraints = $this->dbUpgrade()->getMissingConstraints($mT);
+        if (!empty($missingConstraints)) {
+            // Only manipulate DB if we're not in logging mode:
+            if (!$this->logsql) {
+                if (!$this->hasDatabaseRootCredentials()) {
+                    return $this->forwardTo('Upgrade', 'GetDbCredentials');
+                }
+                $this->dbUpgrade()->setAdapter($this->getRootDbAdapter());
+                $this->session->warnings->append(
+                    "Added constraint(s) to table(s): "
+                    . implode(', ', array_keys($missingConstraints))
+                );
+            }
+            $sql .= $this->dbUpgrade()
+                ->createMissingConstraints($missingConstraints, $this->logsql);
+        }
+
         // Check for encoding problems.
         $encProblems = $this->dbUpgrade()->getEncodingProblems();
         if (!empty($encProblems)) {
@@ -464,7 +477,7 @@ class UpgradeController extends AbstractBase
                 // If this is a MySQL connection, we can do an automatic upgrade;
                 // if VuFind is using a different database, we have to prompt the
                 // user to check the migrations directory and upgrade manually.
-                $adapter = $this->getServiceLocator()->get('VuFind\DbAdapter');
+                $adapter = $this->serviceLocator->get('VuFind\DbAdapter');
                 $platform = $adapter->getDriver()->getDatabasePlatformName();
                 if (strtolower($platform) == 'mysql') {
                     $upgradeResult = $this->upgradeMySQL($adapter);
@@ -562,7 +575,7 @@ class UpgradeController extends AbstractBase
                 // Test the connection:
                 try {
                     // Query a table known to exist
-                    $factory = $this->getServiceLocator()
+                    $factory = $this->serviceLocator
                         ->get('VuFind\DbAdapterFactory');
                     $db = $factory->getAdapter($dbrootuser, $pass);
                     $db->query("SELECT * FROM user;");
@@ -691,7 +704,7 @@ class UpgradeController extends AbstractBase
 
         // Process submit button:
         if ($this->formWasSubmitted('submit')) {
-            $converter = $this->getServiceLocator()->get('VuFind\DateConverter');
+            $converter = $this->serviceLocator->get('VuFind\DateConverter');
             foreach ($problems as $problem) {
                 try {
                     $driver = $this->getRecordLoader()
@@ -794,7 +807,7 @@ class UpgradeController extends AbstractBase
     {
         // If the cache is messed up, nothing is going to work right -- check that
         // first:
-        $cache = $this->getServiceLocator()->get('VuFind\CacheManager');
+        $cache = $this->serviceLocator->get('VuFind\CacheManager');
         if ($cache->hasDirectoryCreationError()) {
             return $this->redirect()->toRoute('install-fixcache');
         }
diff --git a/module/VuFind/src/VuFind/Controller/WebController.php b/module/VuFind/src/VuFind/Controller/WebController.php
index 11089c3ce22fa26c172bb2d67cafe86906db9379..34b12c2e7510cd6374d0d4d43d23140794690e43 100644
--- a/module/VuFind/src/VuFind/Controller/WebController.php
+++ b/module/VuFind/src/VuFind/Controller/WebController.php
@@ -26,6 +26,7 @@
  * @link     https://vufind.org Main Site
  */
 namespace VuFind\Controller;
+use Zend\ServiceManager\ServiceLocatorInterface;
 
 /**
  * Web Controller
@@ -40,11 +41,13 @@ class WebController extends AbstractSearch
 {
     /**
      * Constructor
+     *
+     * @param ServiceLocatorInterface $sm Service locator
      */
-    public function __construct()
+    public function __construct(ServiceLocatorInterface $sm)
     {
         $this->searchClassId = 'SolrWeb';
-        parent::__construct();
+        parent::__construct($sm);
     }
 
     /**
diff --git a/module/VuFind/src/VuFind/Controller/WorldcatController.php b/module/VuFind/src/VuFind/Controller/WorldcatController.php
index 86dc102675bfe6b4a743df165af5e092fb6cded0..afea1a75129fb4c1a46a62636c1b61185aff3a41 100644
--- a/module/VuFind/src/VuFind/Controller/WorldcatController.php
+++ b/module/VuFind/src/VuFind/Controller/WorldcatController.php
@@ -26,6 +26,7 @@
  * @link     https://vufind.org Main Site
  */
 namespace VuFind\Controller;
+use Zend\ServiceManager\ServiceLocatorInterface;
 
 /**
  * WorldCat Controller
@@ -40,11 +41,13 @@ class WorldcatController extends AbstractSearch
 {
     /**
      * Constructor
+     *
+     * @param ServiceLocatorInterface $sm Service locator
      */
-    public function __construct()
+    public function __construct(ServiceLocatorInterface $sm)
     {
         $this->searchClassId = 'WorldCat';
-        parent::__construct();
+        parent::__construct($sm);
     }
 
     /**
@@ -54,7 +57,7 @@ class WorldcatController extends AbstractSearch
      */
     protected function resultScrollerActive()
     {
-        $config = $this->getServiceLocator()->get('VuFind\Config')->get('WorldCat');
+        $config = $this->serviceLocator->get('VuFind\Config')->get('WorldCat');
         return (isset($config->Record->next_prev_navigation)
             && $config->Record->next_prev_navigation);
     }
diff --git a/module/VuFind/src/VuFind/Controller/WorldcatrecordController.php b/module/VuFind/src/VuFind/Controller/WorldcatrecordController.php
index a3249ac11e4e5e754c7c5a622e74903b04106acf..974f23c7a99f06248ea96c0a357e524a7e79f836 100644
--- a/module/VuFind/src/VuFind/Controller/WorldcatrecordController.php
+++ b/module/VuFind/src/VuFind/Controller/WorldcatrecordController.php
@@ -26,6 +26,7 @@
  * @link     https://vufind.org Main Site
  */
 namespace VuFind\Controller;
+use Zend\ServiceManager\ServiceLocatorInterface;
 
 /**
  * WorldCat Record Controller
@@ -40,14 +41,16 @@ class WorldcatrecordController extends AbstractRecord
 {
     /**
      * Constructor
+     *
+     * @param ServiceLocatorInterface $sm Service locator
      */
-    public function __construct()
+    public function __construct(ServiceLocatorInterface $sm)
     {
         // Override some defaults:
         $this->searchClassId = 'WorldCat';
 
         // Call standard record controller initialization:
-        parent::__construct();
+        parent::__construct($sm);
     }
 
     /**
@@ -57,7 +60,7 @@ class WorldcatrecordController extends AbstractRecord
      */
     protected function resultScrollerActive()
     {
-        $config = $this->getServiceLocator()->get('VuFind\Config')->get('WorldCat');
+        $config = $this->serviceLocator->get('VuFind\Config')->get('WorldCat');
         return (isset($config->Record->next_prev_navigation)
             && $config->Record->next_prev_navigation);
     }
diff --git a/module/VuFind/src/VuFind/Cookie/CookieManager.php b/module/VuFind/src/VuFind/Cookie/CookieManager.php
index 05a9d0008f0e29e2b4e854eef0a32dd7dd697ccc..66d95e0c99ea2ba659514a16f02cfb048d3fae04 100644
--- a/module/VuFind/src/VuFind/Cookie/CookieManager.php
+++ b/module/VuFind/src/VuFind/Cookie/CookieManager.php
@@ -59,21 +59,31 @@ class CookieManager
      */
     protected $secure;
 
+    /**
+     * The name of the session cookie
+     *
+     * @var string
+     */
+    protected $sessionName;
+
     /**
      * Constructor
      *
-     * @param array  $cookies Cookie array to manipulate (e.g. $_COOKIE)
-     * @param string $path    Cookie base path (default = /)
-     * @param string $domain  Cookie domain
-     * @param bool   $secure  Are cookies secure only? (default = false)
+     * @param array  $cookies     Cookie array to manipulate (e.g. $_COOKIE)
+     * @param string $path        Cookie base path (default = /)
+     * @param string $domain      Cookie domain
+     * @param bool   $secure      Are cookies secure only? (default = false)
+     * @param string $sessionName Session cookie name (if null defaults to PHP
+     * settings)
      */
     public function __construct($cookies, $path = '/', $domain = null,
-        $secure = false
+        $secure = false, $sessionName = null
     ) {
         $this->cookies = $cookies;
         $this->path = $path;
         $this->domain = $domain;
         $this->secure = $secure;
+        $this->sessionName = $sessionName;
     }
 
     /**
@@ -116,6 +126,16 @@ class CookieManager
         return $this->secure;
     }
 
+    /**
+     * Get the name of the cookie
+     *
+     * @return mixed
+     */
+    public function getSessionName()
+    {
+        return $this->sessionName;
+    }
+
     /**
      * Support method for setGlobalCookie -- proxy PHP's setcookie() function
      * for compatibility with unit testing.
diff --git a/module/VuFind/src/VuFind/Cover/Loader.php b/module/VuFind/src/VuFind/Cover/Loader.php
index 14f549b5d11e9e3b8717aab261eacb4ae053af8d..b48675e37acc770538c9e7941a5d794017f6d723 100644
--- a/module/VuFind/src/VuFind/Cover/Loader.php
+++ b/module/VuFind/src/VuFind/Cover/Loader.php
@@ -111,6 +111,20 @@ class Loader extends \VuFind\ImageLoader
      */
     protected $upc = null;
 
+    /**
+     * User record id number parameter
+     *
+     * @var string
+     */
+    protected $recordid = null;
+
+    /**
+     * User record source parameter
+     *
+     * @var string
+     */
+    protected $source = null;
+
     /**
      * User size parameter
      *
@@ -150,11 +164,11 @@ class Loader extends \VuFind\ImageLoader
     }
 
     /**
-     * Get Cover Generator Object
+     * Get settings for the cover generator.
      *
-     * @return VuFind\Cover\Generator
+     * @return array
      */
-    public function getCoverGenerator()
+    protected function getCoverGeneratorSettings()
     {
         $settings = isset($this->config->DynamicCovers)
             ? $this->config->DynamicCovers->toArray() : [];
@@ -163,7 +177,33 @@ class Loader extends \VuFind\ImageLoader
         ) {
             $settings['backgroundMode'] = $this->config->Content->makeDynamicCovers;
         }
-        return new \VuFind\Cover\Generator($this->themeTools, $settings);
+        $size = $this->size;
+        $pickSize = function ($setting) use ($size) {
+            if (isset($setting[$size])) {
+                return $setting[$size];
+            }
+            if (isset($setting['*'])) {
+                return $setting['*'];
+            }
+            return $setting;
+        };
+        return array_map($pickSize, $settings);
+    }
+
+    /**
+     * Get Cover Generator Object (or return false if disabled)
+     *
+     * @return VuFind\Cover\Generator|bool
+     */
+    public function getCoverGenerator()
+    {
+        if (isset($this->config->Content->makeDynamicCovers)
+            && $this->config->Content->makeDynamicCovers
+        ) {
+            $settings = $this->getCoverGeneratorSettings();
+            return new \VuFind\Cover\Generator($this->themeTools, $settings);
+        }
+        return false;
     }
 
     /**
@@ -183,6 +223,8 @@ class Loader extends \VuFind\ImageLoader
             'issn' => null,
             'oclc' => null,
             'upc' => null,
+            'recordid' => null,
+            'source' => null,
         ];
     }
 
@@ -227,6 +269,8 @@ class Loader extends \VuFind\ImageLoader
         }
         $this->oclc = $settings['oclc'];
         $this->upc = $settings['upc'];
+        $this->recordid = $settings['recordid'];
+        $this->source = $settings['source'];
         $this->type = preg_replace('/[^a-zA-Z]/', '', $settings['type']);
         $this->size = $settings['size'];
     }
@@ -260,10 +304,8 @@ class Loader extends \VuFind\ImageLoader
         } else if (!$this->fetchFromAPI()
             && !$this->fetchFromContentType()
         ) {
-            if (isset($this->config->Content->makeDynamicCovers)
-                && $this->config->Content->makeDynamicCovers
-            ) {
-                $this->image = $this->getCoverGenerator()->generate(
+            if ($generator = $this->getCoverGenerator()) {
+                $this->image = $generator->generate(
                     $settings['title'], $settings['author'], $settings['callnumber']
                 );
                 $this->contentType = 'image/png';
@@ -297,8 +339,13 @@ class Loader extends \VuFind\ImageLoader
             return $this->getCachePath($this->size, 'OCLC' . $ids['oclc']);
         } else if (isset($ids['upc'])) {
             return $this->getCachePath($this->size, 'UPC' . $ids['upc']);
+        } else if (isset($ids['recordid']) && isset($ids['source'])) {
+            return $this->getCachePath(
+                $this->size,
+                'ID' . md5($ids['source'] . '|' . $ids['recordid'])
+            );
         }
-        throw new \Exception('Unexpected code path reached!');
+        throw new \Exception('Cannot determine local file path.');
     }
 
     /**
@@ -321,6 +368,12 @@ class Loader extends \VuFind\ImageLoader
         if ($this->upc && strlen($this->upc) > 0) {
             $ids['upc'] = $this->upc;
         }
+        if ($this->recordid && strlen($this->recordid) > 0) {
+            $ids['recordid'] = $this->recordid;
+        }
+        if ($this->source && strlen($this->source) > 0) {
+            $ids['source'] = $this->source;
+        }
         return $ids;
     }
 
@@ -533,44 +586,52 @@ class Loader extends \VuFind\ImageLoader
      */
     protected function processImageURL($url, $cache = true)
     {
-        // Attempt to pull down the image:
-        $result = $this->client->setUri($url)->send();
-        if (!$result->isSuccess()) {
-            $this->debug("Failed to retrieve image from " + $url);
-            return false;
-        }
+        // Check to see if url is a file path
+        if (substr($url, 0, 7) == "file://") {
+            $imagePath = substr($url, 7);
 
-        $image = $result->getBody();
+            // Display the image:
+            $this->contentType =  mime_content_type($imagePath);
+            $this->image = file_get_contents($imagePath);
+            return true;
+        } else {
+            // Attempt to pull down the image:
+            $result = $this->client->setUri($url)->send();
+            if (!$result->isSuccess()) {
+                $this->debug("Failed to retrieve image from " + $url);
+                return false;
+            }
+            $image = $result->getBody();
 
-        if ('' == $image) {
-            return false;
-        }
+            if ('' == $image) {
+                return false;
+            }
 
-        // Figure out file paths -- $tempFile will be used to store the
-        // image for analysis.  $finalFile will be used for long-term storage if
-        // $cache is true or for temporary display purposes if $cache is false.
-        $tempFile = str_replace('.jpg', uniqid(), $this->localFile);
-        $finalFile = $cache ? $this->localFile : $tempFile . '.jpg';
+            // Figure out file paths -- $tempFile will be used to store the
+            // image for analysis.  $finalFile will be used for long-term storage if
+            // $cache is true or for temporary display purposes if $cache is false.
+            $tempFile = str_replace('.jpg', uniqid(), $this->localFile);
+            $finalFile = $cache ? $this->localFile : $tempFile . '.jpg';
 
-        // Write image data to disk:
-        if (!@file_put_contents($tempFile, $image)) {
-            throw new \Exception("Unable to write to image directory.");
-        }
+            // Write image data to disk:
+            if (!@file_put_contents($tempFile, $image)) {
+                throw new \Exception("Unable to write to image directory.");
+            }
 
-        // Move temporary file to final location:
-        if (!$this->validateAndMoveTempFile($image, $tempFile, $finalFile)) {
-            return false;
-        }
+            // Move temporary file to final location:
+            if (!$this->validateAndMoveTempFile($image, $tempFile, $finalFile)) {
+                return false;
+            }
 
-        // Display the image:
-        $this->contentType = 'image/jpeg';
-        $this->image = file_get_contents($finalFile);
+            // Display the image:
+            $this->contentType = 'image/jpeg';
+            $this->image = file_get_contents($finalFile);
 
-        // If we don't want to cache the image, delete it now that we're done.
-        if (!$cache) {
-            @unlink($finalFile);
+            // If we don't want to cache the image, delete it now that we're done.
+            if (!$cache) {
+                @unlink($finalFile);
+            }
+            return true;
         }
-
-        return true;
     }
 }
diff --git a/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Mvc/Router/ConsoleRouterTest.php b/module/VuFind/src/VuFind/Db/Row/ExternalSession.php
similarity index 54%
rename from module/VuFindConsole/tests/unit-tests/src/VuFindTest/Mvc/Router/ConsoleRouterTest.php
rename to module/VuFind/src/VuFind/Db/Row/ExternalSession.php
index 34dac835f5d7a461dab995b924e15ae416e6ba18..07452cfbe24f525d9c3ea98749c11a4be7421760 100644
--- a/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Mvc/Router/ConsoleRouterTest.php
+++ b/module/VuFind/src/VuFind/Db/Row/ExternalSession.php
@@ -1,10 +1,11 @@
 <?php
 /**
- * ConsoleRouter Test Class
+ * Row Definition for external_session
  *
  * PHP version 5
  *
  * Copyright (C) Villanova University 2010.
+ * Copyrught (C) The National Library of Finland 2016.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2,
@@ -20,39 +21,33 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
  * @category VuFind
- * @package  Tests
+ * @package  Db_Row
  * @author   Demian Katz <demian.katz@villanova.edu>
+ * @author   Ere Maijala <ere.maijala@helsinki.fi>
  * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
- * @link     https://vufind.org/wiki/development:testing:unit_tests Wiki
+ * @link     https://vufind.org Main Site
  */
-namespace VuFindTest\Mvc\Router;
-use VuFindConsole\Mvc\Router\ConsoleRouter;
+namespace VuFind\Db\Row;
 
 /**
- * InjectTemplateListener Test Class
+ * Row Definition for external_session
  *
  * @category VuFind
- * @package  Tests
+ * @package  Db_Row
  * @author   Demian Katz <demian.katz@villanova.edu>
+ * @author   Ere Maijala <ere.maijala@helsinki.fi>
  * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
- * @link     https://vufind.org/wiki/development:testing:unit_tests Wiki
+ * @link     https://vufind.org Main Site
  */
-class ConsoleRouterTest extends \PHPUnit_Framework_TestCase
+class ExternalSession extends RowGateway
 {
     /**
-     * Test routing.
+     * Constructor
      *
-     * @return void
+     * @param \Zend\Db\Adapter\Adapter $adapter Database adapter
      */
-    public function testRoute()
+    public function __construct($adapter)
     {
-        $router = ConsoleRouter::factory();
-        $router->setCliDir(__DIR__);
-        $request = $this->getMock('Zend\Console\Request', ['getScriptName']);
-        $request->expects($this->any())->method('getScriptName')
-            ->will($this->returnValue('ConsoleRouterTest.php'));
-        $result = $router->match($request);
-        $this->assertEquals($result->getParam('controller'), 'Router');
-        $this->assertEquals($result->getParam('action'), 'ConsoleRouterTest');
+        parent::__construct('id', 'external_session', $adapter);
     }
 }
diff --git a/module/VuFind/src/VuFind/Db/Row/Factory.php b/module/VuFind/src/VuFind/Db/Row/Factory.php
new file mode 100644
index 0000000000000000000000000000000000000000..7ec15d670d32b0cb5abe5516cb107f441096aaf8
--- /dev/null
+++ b/module/VuFind/src/VuFind/Db/Row/Factory.php
@@ -0,0 +1,117 @@
+<?php
+/**
+ * Factory for DB rows.
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2014.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * @category VuFind
+ * @package  Db_Table
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development Wiki
+ */
+namespace VuFind\Db\Row;
+use Zend\ServiceManager\ServiceManager;
+
+/**
+ * Factory for DB tables.
+ *
+ * @category VuFind
+ * @package  Db_Table
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development Wiki
+ *
+ * @codeCoverageIgnore
+ */
+class Factory
+{
+    /**
+     * Construct a generic row object.
+     *
+     * @param string         $name Name of row to construct (fully qualified
+     * class name, or else a class name within the current namespace)
+     * @param ServiceManager $sm   Service manager
+     * @param array          $args Extra constructor arguments for row object
+     *
+     * @return object
+     */
+    public static function getGenericRow($name, ServiceManager $sm, $args = [])
+    {
+        // Prepend the current namespace unless we receive a FQCN:
+        $class = (strpos($name, '\\') === false)
+            ? __NAMESPACE__ . '\\' . $name : $name;
+        if (!class_exists($class)) {
+            throw new \Exception('Cannot construct ' . $class);
+        }
+        $adapter = $sm->getServiceLocator()->get('VuFind\DbAdapter');
+        return new $class($adapter, ...$args);
+    }
+
+    /**
+     * Default factory behavior.
+     *
+     * @param string $name Method name being called
+     * @param array  $args Method arguments
+     *
+     * @return object
+     */
+    public static function __callStatic($name, $args)
+    {
+        // Strip "get" off method name, and use the remainder as the table name;
+        // grab the first argument to pass through as the service manager.
+        return static::getGenericRow(substr($name, 3), array_shift($args));
+    }
+
+    /**
+     * Construct the User row prototype.
+     *
+     * @param ServiceManager $sm Service manager.
+     *
+     * @return User
+     */
+    public static function getUser(ServiceManager $sm)
+    {
+        $config = $sm->getServiceLocator()->get('VuFind\Config')->get('config');
+        $privacy = isset($config->Authentication->privacy)
+            && $config->Authentication->privacy;
+        $rowClass = $privacy ? 'PrivateUser' : 'User';
+        $prototype = static::getGenericRow($rowClass, $sm);
+        $prototype->setConfig($config);
+        if ($privacy) {
+            $sessionManager = $sm->getServiceLocator()->get('VuFind\SessionManager');
+            $session = new \Zend\Session\Container('Account', $sessionManager);
+            $prototype->setSession($session);
+        }
+        return $prototype;
+    }
+
+    /**
+     * Construct the UserList row prototype.
+     *
+     * @param ServiceManager $sm Service manager.
+     *
+     * @return UserList
+     */
+    public static function getUserList(ServiceManager $sm)
+    {
+        $sessionManager = $sm->getServiceLocator()->get('VuFind\SessionManager');
+        $session = new \Zend\Session\Container('List', $sessionManager);
+        return static::getGenericRow('UserList', $sm, [$session]);
+    }
+}
diff --git a/module/VuFind/src/VuFind/Db/Row/PluginManager.php b/module/VuFind/src/VuFind/Db/Row/PluginManager.php
new file mode 100644
index 0000000000000000000000000000000000000000..b3e8b0da52b5bb6a96ad4cbe3b6f82518c65c425
--- /dev/null
+++ b/module/VuFind/src/VuFind/Db/Row/PluginManager.php
@@ -0,0 +1,51 @@
+<?php
+/**
+ * Database row plugin manager
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2017.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * @category VuFind
+ * @package  Db_Row
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development:plugins:database_gateways Wiki
+ */
+namespace VuFind\Db\Row;
+
+/**
+ * Database row plugin manager
+ *
+ * @category VuFind
+ * @package  Db_Row
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development:plugins:database_gateways Wiki
+ */
+class PluginManager extends \VuFind\ServiceManager\AbstractPluginManager
+{
+    /**
+     * Return the name of the base class or interface that plug-ins must conform
+     * to.
+     *
+     * @return string
+     */
+    protected function getExpectedInterface()
+    {
+        return 'VuFind\Db\Row\RowGateway';
+    }
+}
diff --git a/module/VuFind/src/VuFind/Db/Row/User.php b/module/VuFind/src/VuFind/Db/Row/User.php
index d72c030e31a4d77119c739614d651912839c68b8..446722e3ec9fbb6dd160b7df955bcc747a6b5ac9 100644
--- a/module/VuFind/src/VuFind/Db/Row/User.php
+++ b/module/VuFind/src/VuFind/Db/Row/User.php
@@ -29,7 +29,7 @@ namespace VuFind\Db\Row;
 use Zend\Db\Sql\Expression,
     Zend\Db\Sql\Predicate\Predicate,
     Zend\Db\Sql\Sql,
-    Zend\Crypt\Symmetric\Mcrypt,
+    Zend\Crypt\Symmetric\Openssl,
     Zend\Crypt\Password\Bcrypt,
     Zend\Crypt\BlockCipher as BlockCipher;
 
@@ -102,6 +102,20 @@ class User extends RowGateway implements \VuFind\Db\Table\DbTableAwareInterface,
         $this->cat_pass_enc = null;
     }
 
+    /**
+     * Save ILS ID.
+     *
+     * @param string $catId Catalog ID to save.
+     *
+     * @return mixed        The output of the save method.
+     * @throws \VuFind\Exception\PasswordSecurity
+     */
+    public function saveCatalogId($catId)
+    {
+        $this->cat_id = $catId;
+        return $this->save();
+    }
+
     /**
      * Save ILS login credentials.
      *
@@ -196,7 +210,7 @@ class User extends RowGateway implements \VuFind\Db\Table\DbTableAwareInterface,
         $algo = isset($this->config->Authentication->ils_encryption_algo)
             ? $this->config->Authentication->ils_encryption_algo
             : 'blowfish';
-        $cipher = new BlockCipher(new Mcrypt(['algorithm' => $algo]));
+        $cipher = new BlockCipher(new Openssl(['algorithm' => $algo]));
         $cipher->setKey($this->encryptionKey);
         return $encrypt ? $cipher->encrypt($text) : $cipher->decrypt($text);
     }
diff --git a/module/VuFind/src/VuFind/Db/Row/UserList.php b/module/VuFind/src/VuFind/Db/Row/UserList.php
index ea1ba710352d0f3a0647267f761ad4aa1122cdad..89384d0a2020cfc7b71aeaab8d6f451e423af141 100644
--- a/module/VuFind/src/VuFind/Db/Row/UserList.php
+++ b/module/VuFind/src/VuFind/Db/Row/UserList.php
@@ -26,8 +26,9 @@
  * @link     https://vufind.org Main Site
  */
 namespace VuFind\Db\Row;
-use VuFind\Exception\ListPermission as ListPermissionException,
-    VuFind\Exception\MissingField as MissingFieldException;
+use VuFind\Exception\ListPermission as ListPermissionException;
+use VuFind\Exception\MissingField as MissingFieldException;
+use Zend\Session\Container;
 
 /**
  * Row Definition for user_list
@@ -45,7 +46,7 @@ class UserList extends RowGateway implements \VuFind\Db\Table\DbTableAwareInterf
     /**
      * Session container for last list information.
      *
-     * @var \Zend\Session\Container
+     * @var Container
      */
     protected $session = null;
 
@@ -53,9 +54,11 @@ class UserList extends RowGateway implements \VuFind\Db\Table\DbTableAwareInterf
      * Constructor
      *
      * @param \Zend\Db\Adapter\Adapter $adapter Database adapter
+     * @param Container                $session Session container
      */
-    public function __construct($adapter)
+    public function __construct($adapter, Container $session = null)
     {
+        $this->session = $session;
         parent::__construct('id', 'user_list', $adapter);
     }
 
@@ -139,11 +142,11 @@ class UserList extends RowGateway implements \VuFind\Db\Table\DbTableAwareInterf
     /**
      * Set session container
      *
-     * @param \Zend\Session\Container $session Session container
+     * @param Container $session Session container
      *
      * @return void
      */
-    public function setSession(\Zend\Session\Container $session)
+    public function setSession(Container $session)
     {
         $this->session = $session;
     }
diff --git a/module/VuFind/src/VuFind/Db/Table/ChangeTracker.php b/module/VuFind/src/VuFind/Db/Table/ChangeTracker.php
index f0eae0978e78b7e179291f19ad8eb0d17688a66e..174cc7d6747e1a62d6c51f03df65d34197be30d6 100644
--- a/module/VuFind/src/VuFind/Db/Table/ChangeTracker.php
+++ b/module/VuFind/src/VuFind/Db/Table/ChangeTracker.php
@@ -26,6 +26,8 @@
  * @link     https://vufind.org Main Site
  */
 namespace VuFind\Db\Table;
+use VuFind\Db\Row\RowGateway;
+use Zend\Db\Adapter\Adapter;
 
 /**
  * Table Definition for change_tracker
@@ -47,10 +49,17 @@ class ChangeTracker extends Gateway
 
     /**
      * Constructor
+     *
+     * @param Adapter       $adapter Database adapter
+     * @param PluginManager $tm      Table manager
+     * @param array         $cfg     Zend Framework configuration
+     * @param RowGateway    $rowObj  Row prototype object (null for default)
+     * @param string        $table   Name of database table to interface with
      */
-    public function __construct()
-    {
-        parent::__construct('change_tracker', 'VuFind\Db\Row\ChangeTracker');
+    public function __construct(Adapter $adapter, PluginManager $tm, $cfg,
+        RowGateway $rowObj = null, $table = 'change_tracker'
+    ) {
+        parent::__construct($adapter, $tm, $cfg, $rowObj, $table);
     }
 
     /**
diff --git a/module/VuFind/src/VuFind/Db/Table/Comments.php b/module/VuFind/src/VuFind/Db/Table/Comments.php
index a75089e2eb1ffbc944af7acea3553fc3497f8a49..b3afb81a5fd5fd004f1f1e46b65c520ad730028b 100644
--- a/module/VuFind/src/VuFind/Db/Table/Comments.php
+++ b/module/VuFind/src/VuFind/Db/Table/Comments.php
@@ -26,6 +26,8 @@
  * @link     https://vufind.org Main Site
  */
 namespace VuFind\Db\Table;
+use VuFind\Db\Row\RowGateway;
+use Zend\Db\Adapter\Adapter;
 use Zend\Db\Sql\Expression;
 
 /**
@@ -41,10 +43,17 @@ class Comments extends Gateway
 {
     /**
      * Constructor
+     *
+     * @param Adapter       $adapter Database adapter
+     * @param PluginManager $tm      Table manager
+     * @param array         $cfg     Zend Framework configuration
+     * @param RowGateway    $rowObj  Row prototype object (null for default)
+     * @param string        $table   Name of database table to interface with
      */
-    public function __construct()
-    {
-        parent::__construct('comments', 'VuFind\Db\Row\Comments');
+    public function __construct(Adapter $adapter, PluginManager $tm, $cfg,
+        RowGateway $rowObj = null, $table = 'comments'
+    ) {
+        parent::__construct($adapter, $tm, $cfg, $rowObj, $table);
     }
 
     /**
diff --git a/module/VuFind/src/VuFind/Db/Table/ExpirationTrait.php b/module/VuFind/src/VuFind/Db/Table/ExpirationTrait.php
new file mode 100644
index 0000000000000000000000000000000000000000..87dc27ad61fe8ec76a5c845d46eeb0c837bc598e
--- /dev/null
+++ b/module/VuFind/src/VuFind/Db/Table/ExpirationTrait.php
@@ -0,0 +1,108 @@
+<?php
+/**
+ * Trait for tables that support expiration
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2010.
+ * Copyright (C) The National Library of Finland 2016.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * @category VuFind
+ * @package  Db_Table
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @author   Ere Maijala <ere.maijala@helsinki.fi>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org Main Page
+ */
+namespace VuFind\Db\Table;
+use Zend\Db\Sql\Expression;
+use Zend\Db\Sql\Select;
+
+/**
+ * Trait for tables that support expiration
+ *
+ * @category VuFind
+ * @package  Db_Table
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @author   Ere Maijala <ere.maijala@helsinki.fi>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org Main Site
+ */
+trait ExpirationTrait
+{
+    /**
+     * Update the select statement to find records to delete.
+     *
+     * @param Select $select  Select clause
+     * @param int    $daysOld Age in days of an "expired" record.
+     * @param int    $idFrom  Lowest id of rows to delete.
+     * @param int    $idTo    Highest id of rows to delete.
+     *
+     * @return void
+     */
+    abstract protected function expirationCallback($select, $daysOld, $idFrom = null,
+        $idTo = null
+    );
+
+    /**
+     * Delete expired records. Allows setting of 'from' and 'to' ID's so that rows
+     * can be deleted in small batches.
+     *
+     * @param int $daysOld Age in days of an "expired" record.
+     * @param int $idFrom  Lowest id of rows to delete.
+     * @param int $idTo    Highest id of rows to delete.
+     *
+     * @return int Number of rows deleted
+     */
+    public function deleteExpired($daysOld = 2, $idFrom = null, $idTo = null)
+    {
+        // Determine the expiration date:
+        $callback = function ($select) use ($daysOld, $idFrom, $idTo) {
+            $this->expirationCallback($select, $daysOld, $idFrom, $idTo);
+        };
+        return $this->delete($callback);
+    }
+
+    /**
+     * Get the lowest id and highest id for expired records.
+     *
+     * @param int $daysOld Age in days of an "expired" record.
+     *
+     * @return array|bool Array of lowest id and highest id or false if no expired
+     * records found
+     */
+    public function getExpiredIdRange($daysOld = 2)
+    {
+        // Determine the expiration date:
+        $callback = function ($select) use ($daysOld) {
+            $this->expirationCallback($select, $daysOld);
+        };
+        $select = $this->getSql()->select();
+        $select->columns(
+            [
+                'id' => new Expression('1'), // required for TableGateway
+                'minId' => new Expression('MIN(id)'),
+                'maxId' => new Expression('MAX(id)'),
+            ]
+        );
+        $select->where($callback);
+        $result = $this->selectWith($select)->current();
+        if (null === $result->minId) {
+            return false;
+        }
+        return [$result->minId, $result->maxId];
+    }
+}
diff --git a/module/VuFind/src/VuFind/Db/Table/ExternalSession.php b/module/VuFind/src/VuFind/Db/Table/ExternalSession.php
new file mode 100644
index 0000000000000000000000000000000000000000..6f7a738dc546fedaadba8a0e0155fb7d1fe9fa21
--- /dev/null
+++ b/module/VuFind/src/VuFind/Db/Table/ExternalSession.php
@@ -0,0 +1,127 @@
+<?php
+/**
+ * Table Definition for external_session
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2010.
+ * Copyright (C) The National Library of Finland 2016.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * @category VuFind
+ * @package  Db_Table
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @author   Ere Maijala <ere.maijala@helsinki.fi>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org Main Page
+ */
+namespace VuFind\Db\Table;
+use VuFind\Db\Row\RowGateway;
+use Zend\Db\Adapter\Adapter;
+
+/**
+ * Table Definition for external_session
+ *
+ * @category VuFind
+ * @package  Db_Table
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @author   Ere Maijala <ere.maijala@helsinki.fi>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org Main Site
+ */
+class ExternalSession extends Gateway
+{
+    use ExpirationTrait;
+
+    /**
+     * Constructor
+     *
+     * @param Adapter       $adapter Database adapter
+     * @param PluginManager $tm      Table manager
+     * @param array         $cfg     Zend Framework configuration
+     * @param RowGateway    $rowObj  Row prototype object (null for default)
+     * @param string        $table   Name of database table to interface with
+     */
+    public function __construct(Adapter $adapter, PluginManager $tm, $cfg,
+        RowGateway $rowObj = null, $table = 'external_session'
+    ) {
+        parent::__construct($adapter, $tm, $cfg, $rowObj, $table);
+    }
+
+    /**
+     * Add a mapping between local and external session id's
+     *
+     * @param string $localSessionId    Local (VuFind) session id
+     * @param string $externalSessionId External session id
+     *
+     * @return void
+     */
+    public function addSessionMapping($localSessionId, $externalSessionId)
+    {
+        $this->destroySession($localSessionId);
+        $row = $this->createRow();
+        $row->session_id = $localSessionId;
+        $row->external_session_id = $externalSessionId;
+        $row->created = date('Y-m-d H:i:s');
+        $row->save();
+    }
+
+    /**
+     * Retrieve an object from the database based on an external session ID
+     *
+     * @param string $sid External session ID to retrieve
+     *
+     * @return \VuFind\Db\Row\ExternalSession
+     */
+    public function getByExternalSessionId($sid)
+    {
+        return $this->select(['external_session_id' => $sid])->current();
+    }
+
+    /**
+     * Destroy data for the given session ID.
+     *
+     * @param string $sid Session ID to erase
+     *
+     * @return void
+     */
+    public function destroySession($sid)
+    {
+        $this->delete(['session_id' => $sid]);
+    }
+
+    /**
+     * Update the select statement to find records to delete.
+     *
+     * @param Select $select  Select clause
+     * @param int    $daysOld Age in days of an "expired" record.
+     * @param int    $idFrom  Lowest id of rows to delete.
+     * @param int    $idTo    Highest id of rows to delete.
+     *
+     * @return void
+     */
+    protected function expirationCallback($select, $daysOld, $idFrom = null,
+        $idTo = null
+    ) {
+        $expireDate = date('Y-m-d', time() - $daysOld * 24 * 60 * 60);
+        $where = $select->where->lessThan('created', $expireDate);
+        if (null !== $idFrom) {
+            $where->and->greaterThanOrEqualTo('id', $idFrom);
+        }
+        if (null !== $idTo) {
+            $where->and->lessThanOrEqualTo('id', $idTo);
+        }
+    }
+}
diff --git a/module/VuFind/src/VuFind/Db/Table/Factory.php b/module/VuFind/src/VuFind/Db/Table/Factory.php
index 389455d6e65e2ad83a9c01f81f6cec2497a7666b..e5868f949692d37ce8ac251e80a7381ff81f273f 100644
--- a/module/VuFind/src/VuFind/Db/Table/Factory.php
+++ b/module/VuFind/src/VuFind/Db/Table/Factory.php
@@ -41,6 +41,69 @@ use Zend\ServiceManager\ServiceManager;
  */
 class Factory
 {
+    /**
+     * Return row prototype object (null if unavailable)
+     *
+     * @param ServiceManager $sm   Service manager
+     * @param string         $name Name of row prototype to retrieve
+     *
+     * @return object
+     */
+    public static function getRowPrototype(ServiceManager $sm, $name)
+    {
+        if ($name) {
+            $rowManager = $sm->getServiceLocator()->get('VuFind\DbRowPluginManager');
+            return $rowManager->has($name) ? $rowManager->get($name) : null;
+        }
+        return null;
+    }
+
+    /**
+     * Construct a generic table object.
+     *
+     * @param string         $name    Name of table to construct (fully qualified
+     * class name, or else a class name within the current namespace)
+     * @param ServiceManager $sm      Service manager
+     * @param string         $rowName Name of custom row prototype object to
+     * retrieve (null for none).
+     * @param array          $args    Extra constructor arguments for table object
+     *
+     * @return object
+     */
+    public static function getGenericTable($name, ServiceManager $sm,
+        $rowName = null, $args = []
+    ) {
+        // Prepend the current namespace unless we receive a FQCN:
+        $class = (strpos($name, '\\') === false)
+            ? __NAMESPACE__ . '\\' . $name : $name;
+        if (!class_exists($class)) {
+            throw new \Exception('Cannot construct ' . $class);
+        }
+        $adapter = $sm->getServiceLocator()->get('VuFind\DbAdapter');
+        $config = $sm->getServiceLocator()->get('config');
+        return new $class(
+            $adapter, $sm, $config, static::getRowPrototype($sm, $rowName), ...$args
+        );
+    }
+
+    /**
+     * Default factory behavior.
+     *
+     * @param string $name Method name being called
+     * @param array  $args Method arguments
+     *
+     * @return object
+     */
+    public static function __callStatic($name, $args)
+    {
+        // Strip "get" off method name, and use the remainder as the table name;
+        // grab the first argument to pass through as the service manager.
+        $dbName = substr($name, 3);
+        return static::getGenericTable(
+            $dbName, array_shift($args), strtolower($dbName)
+        );
+    }
+
     /**
      * Construct the Resource table.
      *
@@ -50,37 +113,43 @@ class Factory
      */
     public static function getResource(ServiceManager $sm)
     {
-        return new Resource($sm->getServiceLocator()->get('VuFind\DateConverter'));
+        $converter = $sm->getServiceLocator()->get('VuFind\DateConverter');
+        $loader = $sm->getServiceLocator()->get('VuFind\RecordLoader');
+        return static::getGenericTable(
+            'Resource', $sm, 'resource', [$converter, $loader]
+        );
     }
 
     /**
-     * Construct the Tags table.
+     * Construct the ResourceTags table.
      *
      * @param ServiceManager $sm Service manager.
      *
      * @return User
      */
-    public static function getTags(ServiceManager $sm)
+    public static function getResourceTags(ServiceManager $sm)
     {
         $config = $sm->getServiceLocator()->get('VuFind\Config')->get('config');
         $caseSensitive = isset($config->Social->case_sensitive_tags)
             && $config->Social->case_sensitive_tags;
-        return new Tags($caseSensitive);
+        return static::getGenericTable(
+            'ResourceTags', $sm, 'resourcetags', [$caseSensitive]
+        );
     }
 
     /**
-     * Construct the ResourceTags table.
+     * Construct the Tags table.
      *
      * @param ServiceManager $sm Service manager.
      *
      * @return User
      */
-    public static function getResourceTags(ServiceManager $sm)
+    public static function getTags(ServiceManager $sm)
     {
         $config = $sm->getServiceLocator()->get('VuFind\Config')->get('config');
         $caseSensitive = isset($config->Social->case_sensitive_tags)
             && $config->Social->case_sensitive_tags;
-        return new ResourceTags($caseSensitive);
+        return static::getGenericTable('Tags', $sm, 'tags', [$caseSensitive]);
     }
 
     /**
@@ -93,16 +162,14 @@ class Factory
     public static function getUser(ServiceManager $sm)
     {
         $config = $sm->getServiceLocator()->get('VuFind\Config')->get('config');
-        // Use a special row class when we're in privacy mode:
         $privacy = isset($config->Authentication->privacy)
             && $config->Authentication->privacy;
-        $rowClass = 'VuFind\Db\Row\\' . ($privacy ? 'PrivateUser' : 'User');
         $session = null;
         if ($privacy) {
             $sessionManager = $sm->getServiceLocator()->get('VuFind\SessionManager');
             $session = new \Zend\Session\Container('Account', $sessionManager);
         }
-        return new User($config, $rowClass, $session);
+        return static::getGenericTable('User', $sm, 'user', [$config, $session]);
     }
 
     /**
@@ -116,6 +183,6 @@ class Factory
     {
         $sessionManager = $sm->getServiceLocator()->get('VuFind\SessionManager');
         $session = new \Zend\Session\Container('List', $sessionManager);
-        return new UserList($session);
+        return static::getGenericTable('UserList', $sm, 'userlist', [$session]);
     }
 }
diff --git a/module/VuFind/src/VuFind/Db/Table/Gateway.php b/module/VuFind/src/VuFind/Db/Table/Gateway.php
index 7caccd9b582a38a85ae15fc588c6723e453457da..773339fbcbc627de9d63a7e881067f1d7cfd4e85 100644
--- a/module/VuFind/src/VuFind/Db/Table/Gateway.php
+++ b/module/VuFind/src/VuFind/Db/Table/Gateway.php
@@ -26,10 +26,10 @@
  * @link     https://vufind.org Main Site
  */
 namespace VuFind\Db\Table;
-use Zend\Db\TableGateway\AbstractTableGateway,
-    Zend\Db\TableGateway\Feature,
-    Zend\ServiceManager\ServiceLocatorAwareInterface,
-    Zend\ServiceManager\ServiceLocatorInterface;
+use VuFind\Db\Row\RowGateway;
+use Zend\Db\Adapter\Adapter;
+use Zend\Db\TableGateway\AbstractTableGateway;
+use Zend\Db\TableGateway\Feature;
 
 /**
  * Generic VuFind table gateway.
@@ -40,56 +40,51 @@ use Zend\Db\TableGateway\AbstractTableGateway,
  * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
  * @link     https://vufind.org Main Site
  */
-class Gateway extends AbstractTableGateway implements ServiceLocatorAwareInterface
+class Gateway extends AbstractTableGateway
 {
-    use \Zend\ServiceManager\ServiceLocatorAwareTrait;
-
     /**
-     * Name of class used to represent rows (null for default)
+     * Table manager
      *
-     * @var string
+     * @var PluginManager
      */
-    protected $rowClass = null;
-    
+    protected $tableManager;
+
     /**
      * Constructor
      *
-     * @param string $table    Name of database table to interface with
-     * @param string $rowClass Name of class used to represent rows (null for
-     * default)
+     * @param Adapter       $adapter Database adapter
+     * @param PluginManager $tm      Table manager
+     * @param array         $cfg     Zend Framework configuration
+     * @param RowGateway    $rowObj  Row prototype object (null for default)
+     * @param string        $table   Name of database table to interface with
      */
-    public function __construct($table, $rowClass = null)
-    {
+    public function __construct(Adapter $adapter, PluginManager $tm, $cfg,
+        RowGateway $rowObj, $table
+    ) {
+        $this->adapter = $adapter;
+        $this->tableManager = $tm;
         $this->table = $table;
-        $this->rowClass = $rowClass;
-    }
 
-    /**
-     * Set database adapter
-     *
-     * @param \Zend\Db\Adapter\Adapter $adapter Database adapter
-     *
-     * @return void
-     */
-    public function setAdapter(\Zend\Db\Adapter\Adapter $adapter)
-    {
-        $this->adapter = $adapter;
+        $this->initializeFeatures($cfg);
+        $this->initialize();
+
+        if (null !== $rowObj) {
+            $resultSetPrototype = $this->getResultSetPrototype();
+            $resultSetPrototype->setArrayObjectPrototype($rowObj);
+        }
     }
 
     /**
-     * Initialize
+     * Initialize features
+     *
+     * @param array $cfg Zend Framework configuration
      *
      * @return void
      */
-    public function initialize()
+    public function initializeFeatures($cfg)
     {
-        if ($this->isInitialized) {
-            return;
-        }
-
         // Special case for PostgreSQL sequences:
         if ($this->adapter->getDriver()->getDatabasePlatformName() == "Postgresql") {
-            $cfg = $this->getServiceLocator()->getServiceLocator()->get('config');
             $maps = isset($cfg['vufind']['pgsql_seq_mapping'])
                 ? $cfg['vufind']['pgsql_seq_mapping'] : null;
             if (isset($maps[$this->table])) {
@@ -103,31 +98,6 @@ class Gateway extends AbstractTableGateway implements ServiceLocatorAwareInterfa
                 );
             }
         }
-
-        parent::initialize();
-        if (null !== $this->rowClass) {
-            $resultSetPrototype = $this->getResultSetPrototype();
-            $resultSetPrototype->setArrayObjectPrototype(
-                $this->initializeRowPrototype()
-            );
-        }
-    }
-
-    /**
-     * Construct the prototype for rows.
-     *
-     * @return object
-     */
-    protected function initializeRowPrototype()
-    {
-        $prototype = new $this->rowClass($this->getAdapter());
-        if ($prototype instanceof ServiceLocatorAwareInterface) {
-            $prototype->setServiceLocator($this->getServiceLocator());
-        }
-        \VuFind\ServiceManager\Initializer::initInstance(
-            $prototype, $this->getServiceLocator()->getServiceLocator()
-        );
-        return $prototype;
     }
 
     /**
@@ -171,6 +141,6 @@ class Gateway extends AbstractTableGateway implements ServiceLocatorAwareInterfa
      */
     public function getDbTable($table)
     {
-        return $this->getServiceLocator()->get($table);
+        return $this->tableManager->get($table);
     }
 }
diff --git a/module/VuFind/src/VuFind/Db/Table/OaiResumption.php b/module/VuFind/src/VuFind/Db/Table/OaiResumption.php
index d90831ef9e74b05a00ee629fd354c50b2644e99a..57da6b8b892b589f33b7a6729b2a1051d2db2266 100644
--- a/module/VuFind/src/VuFind/Db/Table/OaiResumption.php
+++ b/module/VuFind/src/VuFind/Db/Table/OaiResumption.php
@@ -26,6 +26,8 @@
  * @link     https://vufind.org Main Site
  */
 namespace VuFind\Db\Table;
+use VuFind\Db\Row\RowGateway;
+use Zend\Db\Adapter\Adapter;
 
 /**
  * Table Definition for oai_resumption
@@ -40,10 +42,17 @@ class OaiResumption extends Gateway
 {
     /**
      * Constructor
+     *
+     * @param Adapter       $adapter Database adapter
+     * @param PluginManager $tm      Table manager
+     * @param array         $cfg     Zend Framework configuration
+     * @param RowGateway    $rowObj  Row prototype object (null for default)
+     * @param string        $table   Name of database table to interface with
      */
-    public function __construct()
-    {
-        parent::__construct('oai_resumption', 'VuFind\Db\Row\OaiResumption');
+    public function __construct(Adapter $adapter, PluginManager $tm, $cfg,
+        RowGateway $rowObj = null, $table = 'oai_resumption'
+    ) {
+        parent::__construct($adapter, $tm, $cfg, $rowObj, $table);
     }
 
     /**
diff --git a/module/VuFind/src/VuFind/Db/Table/PluginManager.php b/module/VuFind/src/VuFind/Db/Table/PluginManager.php
index 2ac45b87643d1a0b4b1fd52b5dd1136da6be0cf6..cd36600bef1d8665c955902f340c622973c2c6b9 100644
--- a/module/VuFind/src/VuFind/Db/Table/PluginManager.php
+++ b/module/VuFind/src/VuFind/Db/Table/PluginManager.php
@@ -26,7 +26,6 @@
  * @link     https://vufind.org/wiki/development:plugins:database_gateways Wiki
  */
 namespace VuFind\Db\Table;
-use Zend\ServiceManager\ConfigInterface;
 
 /**
  * Database table plugin manager
@@ -39,24 +38,6 @@ use Zend\ServiceManager\ConfigInterface;
  */
 class PluginManager extends \VuFind\ServiceManager\AbstractPluginManager
 {
-    /**
-     * Constructor
-     *
-     * Make sure table gateways are properly initialized.
-     *
-     * @param ConfigInterface $configuration Configuration settings (optional)
-     */
-    public function __construct(ConfigInterface $configuration = null)
-    {
-        parent::__construct($configuration);
-        $initializer = function ($instance, $manager) {
-            $instance
-                ->setAdapter($manager->getServiceLocator()->get('VuFind\DbAdapter'));
-            $instance->initialize();
-        };
-        $this->addInitializer($initializer, false);
-    }
-
     /**
      * Return the name of the base class or interface that plug-ins must conform
      * to.
diff --git a/module/VuFind/src/VuFind/Db/Table/Record.php b/module/VuFind/src/VuFind/Db/Table/Record.php
index ac614c4b5eb2cf3dda6a47c404429d7ccd7f3588..ee06382137b99b297ccbbe92bde12a6192f92cbd 100644
--- a/module/VuFind/src/VuFind/Db/Table/Record.php
+++ b/module/VuFind/src/VuFind/Db/Table/Record.php
@@ -30,6 +30,8 @@
  */
 namespace VuFind\Db\Table;
 
+use VuFind\Db\Row\RowGateway;
+use Zend\Db\Adapter\Adapter;
 use Zend\Db\Sql\Predicate\Expression;
 use Zend\Db\Sql\Where;
 
@@ -47,10 +49,17 @@ class Record extends Gateway
 {
     /**
      * Constructor
+     *
+     * @param Adapter       $adapter Database adapter
+     * @param PluginManager $tm      Table manager
+     * @param array         $cfg     Zend Framework configuration
+     * @param RowGateway    $rowObj  Row prototype object (null for default)
+     * @param string        $table   Name of database table to interface with
      */
-    public function __construct()
-    {
-        parent::__construct('record', 'VuFind\Db\Row\Record');
+    public function __construct(Adapter $adapter, PluginManager $tm, $cfg,
+        RowGateway $rowObj = null, $table = 'record'
+    ) {
+        parent::__construct($adapter, $tm, $cfg, $rowObj, $table);
     }
 
     /**
diff --git a/module/VuFind/src/VuFind/Db/Table/Resource.php b/module/VuFind/src/VuFind/Db/Table/Resource.php
index 796c643693d92f36939e16280e237cb973fce25d..fe48f39213d9206099fc0f3d7ddc16194c672d6e 100644
--- a/module/VuFind/src/VuFind/Db/Table/Resource.php
+++ b/module/VuFind/src/VuFind/Db/Table/Resource.php
@@ -26,6 +26,10 @@
  * @link     https://vufind.org Main Site
  */
 namespace VuFind\Db\Table;
+use VuFind\Date\Converter as DateConverter;
+use VuFind\Db\Row\RowGateway;
+use VuFind\Record\Loader;
+use Zend\Db\Adapter\Adapter;
 use Zend\Db\Sql\Expression;
 
 /**
@@ -42,19 +46,35 @@ class Resource extends Gateway
     /**
      * Date converter
      *
-     * @var \VuFind\Date\Converter
+     * @var DateConverter
      */
     protected $dateConverter;
 
+    /**
+     * Record loader
+     *
+     * @var Loader
+     */
+    protected $recordLoader;
+
     /**
      * Constructor
      *
-     * @param \VuFind\Date\Converter $converter Date converter
+     * @param Adapter       $adapter   Database adapter
+     * @param PluginManager $tm        Table manager
+     * @param array         $cfg       Zend Framework configuration
+     * @param RowGateway    $rowObj    Row prototype object (null for default)
+     * @param DateConverter $converter Date converter
+     * @param Loader        $loader    Record loader
+     * @param string        $table     Name of database table to interface with
      */
-    public function __construct(\VuFind\Date\Converter $converter)
-    {
+    public function __construct(Adapter $adapter, PluginManager $tm, $cfg,
+        RowGateway $rowObj, DateConverter $converter, Loader $loader,
+        $table = 'resource'
+    ) {
         $this->dateConverter = $converter;
-        parent::__construct('resource', 'VuFind\Db\Row\Resource');
+        $this->recordLoader = $loader;
+        parent::__construct($adapter, $tm, $cfg, $rowObj, $table);
     }
 
     /**
@@ -88,9 +108,8 @@ class Resource extends Gateway
             $result->source = $source;
 
             // Load record if it was not provided:
-            if (is_null($driver)) {
-                $driver = $this->getServiceLocator()->getServiceLocator()
-                    ->get('VuFind\RecordLoader')->load($id, $source);
+            if (null === $driver) {
+                $driver = $this->recordLoader->load($id, $source);
             }
 
             // Load metadata into the database for sorting/failback purposes:
diff --git a/module/VuFind/src/VuFind/Db/Table/ResourceTags.php b/module/VuFind/src/VuFind/Db/Table/ResourceTags.php
index d2a4b60efb74894db8df88f70d42328253f66451..8bbbe2ff42136a8cf2af29ab4765fac43034c66a 100644
--- a/module/VuFind/src/VuFind/Db/Table/ResourceTags.php
+++ b/module/VuFind/src/VuFind/Db/Table/ResourceTags.php
@@ -26,6 +26,8 @@
  * @link     https://vufind.org Main Site
  */
 namespace VuFind\Db\Table;
+use VuFind\Db\Row\RowGateway;
+use Zend\Db\Adapter\Adapter;
 use Zend\Db\Sql\Expression;
 
 /**
@@ -49,12 +51,18 @@ class ResourceTags extends Gateway
     /**
      * Constructor
      *
-     * @param bool $caseSensitive Are tags case sensitive?
+     * @param Adapter       $adapter       Database adapter
+     * @param PluginManager $tm            Table manager
+     * @param array         $cfg           Zend Framework configuration
+     * @param RowGateway    $rowObj        Row prototype object (null for default)
+     * @param bool          $caseSensitive Are tags case sensitive?
+     * @param string        $table         Name of database table to interface with
      */
-    public function __construct($caseSensitive = false)
-    {
-        parent::__construct('resource_tags', 'VuFind\Db\Row\ResourceTags');
+    public function __construct(Adapter $adapter, PluginManager $tm, $cfg,
+        RowGateway $rowObj = null, $caseSensitive = false, $table = 'resource_tags'
+    ) {
         $this->caseSensitive = $caseSensitive;
+        parent::__construct($adapter, $tm, $cfg, $rowObj, $table);
     }
 
     /**
diff --git a/module/VuFind/src/VuFind/Db/Table/Search.php b/module/VuFind/src/VuFind/Db/Table/Search.php
index aa7d516245fc9087c9520a52e7d98c62dea13846..be014d837f6ff72642c95a4e5f58e57558561d1d 100644
--- a/module/VuFind/src/VuFind/Db/Table/Search.php
+++ b/module/VuFind/src/VuFind/Db/Table/Search.php
@@ -5,7 +5,7 @@
  * PHP version 5
  *
  * Copyright (C) Villanova University 2010.
- * Copyright (C) The National Library of Finland 2016.
+ * Copyright (C) The National Library of Finland 2016-2017.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2,
@@ -29,9 +29,10 @@
  */
 namespace VuFind\Db\Table;
 use minSO;
+use VuFind\Db\Row\RowGateway;
+use Zend\Db\Adapter\Adapter;
 use Zend\Db\Adapter\ParameterContainer;
 use Zend\Db\TableGateway\Feature;
-use Zend\Db\Sql\Expression;
 
 /**
  * Table Definition for search
@@ -45,25 +46,32 @@ use Zend\Db\Sql\Expression;
  */
 class Search extends Gateway
 {
+    use ExpirationTrait;
+
     /**
      * Constructor
+     *
+     * @param Adapter       $adapter Database adapter
+     * @param PluginManager $tm      Table manager
+     * @param array         $cfg     Zend Framework configuration
+     * @param RowGateway    $rowObj  Row prototype object (null for default)
+     * @param string        $table   Name of database table to interface with
      */
-    public function __construct()
-    {
-        parent::__construct('search', 'VuFind\Db\Row\Search');
+    public function __construct(Adapter $adapter, PluginManager $tm, $cfg,
+        RowGateway $rowObj = null, $table = 'search'
+    ) {
+        parent::__construct($adapter, $tm, $cfg, $rowObj, $table);
     }
 
     /**
-     * Initialize
+     * Initialize features
+     *
+     * @param array $cfg Zend Framework configuration
      *
      * @return void
      */
-    public function initialize()
+    public function initializeFeatures($cfg)
     {
-        if ($this->isInitialized) {
-            return;
-        }
-
         // Special case for PostgreSQL inserts -- we need to provide an extra
         // clue so that the database knows how to write bytea data correctly:
         if ($this->adapter->getDriver()->getDatabasePlatformName() == "Postgresql") {
@@ -72,12 +80,12 @@ class Search extends Gateway
             }
             $eventFeature = new Feature\EventFeature();
             $eventFeature->getEventManager()->attach(
-                Feature\EventFeature::EVENT_PRE_INITIALIZE, [$this, 'onPreInsert']
+                Feature\EventFeature::EVENT_PRE_INITIALIZE, [$this, 'onPreInit']
             );
             $this->featureSet->addFeature($eventFeature);
         }
 
-        parent::initialize();
+        parent::initializeFeatures($cfg);
     }
 
     /**
@@ -90,7 +98,7 @@ class Search extends Gateway
      *
      * @return void
      */
-    public function onPreInsert($event)
+    public function onPreInit($event)
     {
         $driver = $event->getTarget()->getAdapter()->getDriver();
         $statement = $driver->createStatement();
@@ -132,64 +140,6 @@ class Search extends Gateway
         return $this->select($callback);
     }
 
-    /**
-     * Delete expired searches. Allows setting of 'from' and 'to' ID's so that rows
-     * can be deleted in small batches.
-     *
-     * @param int $daysOld Age in days of an "expired" search.
-     * @param int $idFrom  Lowest id of rows to delete.
-     * @param int $idTo    Highest id of rows to delete.
-     *
-     * @return int Number of rows deleted
-     */
-    public function deleteExpired($daysOld = 2, $idFrom = null, $idTo = null)
-    {
-        // Determine the expiration date:
-        $expireDate = date('Y-m-d H:i:s', time() - $daysOld * 24 * 60 * 60);
-        $callback = function ($select) use ($expireDate, $idFrom, $idTo) {
-            $where = $select->where->lessThan('created', $expireDate)
-                ->equalTo('saved', 0);
-            if (null !== $idFrom) {
-                $where->and->greaterThanOrEqualTo('id', $idFrom);
-            }
-            if (null !== $idTo) {
-                $where->and->lessThanOrEqualTo('id', $idTo);
-            }
-        };
-        return $this->delete($callback);
-    }
-
-    /**
-     * Get the lowest id and highest id for expired searches.
-     *
-     * @param int $daysOld Age in days of an "expired" search.
-     *
-     * @return array|bool Array of lowest id and highest id or false if no expired
-     * records found
-     */
-    public function getExpiredIdRange($daysOld = 2)
-    {
-        // Determine the expiration date:
-        $expireDate = date('Y-m-d H:i:s', time() - $daysOld * 24 * 60 * 60);
-        $callback = function ($select) use ($expireDate) {
-            $select->where->lessThan('created', $expireDate)->equalTo('saved', 0);
-        };
-        $select = $this->getSql()->select();
-        $select->columns(
-            [
-                'id' => new Expression('1'), // required for TableGateway
-                'minId' => new Expression('MIN(id)'),
-                'maxId' => new Expression('MAX(id)'),
-            ]
-        );
-        $select->where($callback);
-        $result = $this->selectWith($select)->current();
-        if (null === $result->minId) {
-            return false;
-        }
-        return [$result->minId, $result->maxId];
-    }
-
     /**
      * Get a query representing expired searches (this can be passed
      * to select() or delete() for further processing).
@@ -261,7 +211,7 @@ class Search extends Gateway
      * @param string                               $sessionId Current session ID
      * @param int|null                             $userId    Current user ID
      *
-     * @return void
+     * @return \VuFind\Db\Row\Search
      */
     public function saveSearch(\VuFind\Search\Results\PluginManager $manager,
         $newSearch, $sessionId, $userId
@@ -308,7 +258,7 @@ class Search extends Gateway
                 }
                 // Update the new search from the existing one
                 $newSearch->updateSaveStatus($oldSearch);
-                return;
+                return $oldSearch;
             }
         }
 
@@ -326,5 +276,30 @@ class Search extends Gateway
         $row->session_id = $sessionId;
         $row->search_object = serialize(new minSO($newSearch));
         $row->save();
+        return $row;
+    }
+
+    /**
+     * Update the select statement to find records to delete.
+     *
+     * @param Select $select  Select clause
+     * @param int    $daysOld Age in days of an "expired" record.
+     * @param int    $idFrom  Lowest id of rows to delete.
+     * @param int    $idTo    Highest id of rows to delete.
+     *
+     * @return void
+     */
+    protected function expirationCallback($select, $daysOld, $idFrom = null,
+        $idTo = null
+    ) {
+        $expireDate = date('Y-m-d H:i:s', time() - $daysOld * 24 * 60 * 60);
+        $where = $select->where->lessThan('created', $expireDate)
+            ->equalTo('saved', 0);
+        if (null !== $idFrom) {
+            $where->and->greaterThanOrEqualTo('id', $idFrom);
+        }
+        if (null !== $idTo) {
+            $where->and->lessThanOrEqualTo('id', $idTo);
+        }
     }
 }
diff --git a/module/VuFind/src/VuFind/Db/Table/Session.php b/module/VuFind/src/VuFind/Db/Table/Session.php
index c6449ad23e4fa9fecb5c057175183bc41acecb61..9be95feadef88f5dfeb6adcf2cb35eddeacbb3e2 100644
--- a/module/VuFind/src/VuFind/Db/Table/Session.php
+++ b/module/VuFind/src/VuFind/Db/Table/Session.php
@@ -28,8 +28,9 @@
  * @link     https://vufind.org Main Page
  */
 namespace VuFind\Db\Table;
+use VuFind\Db\Row\RowGateway;
 use VuFind\Exception\SessionExpired as SessionExpiredException;
-use Zend\Db\Sql\Expression;
+use Zend\Db\Adapter\Adapter;
 
 /**
  * Table Definition for session
@@ -43,12 +44,21 @@ use Zend\Db\Sql\Expression;
  */
 class Session extends Gateway
 {
+    use ExpirationTrait;
+
     /**
      * Constructor
+     *
+     * @param Adapter       $adapter Database adapter
+     * @param PluginManager $tm      Table manager
+     * @param array         $cfg     Zend Framework configuration
+     * @param RowGateway    $rowObj  Row prototype object (null for default)
+     * @param string        $table   Name of database table to interface with
      */
-    public function __construct()
-    {
-        parent::__construct('session', 'VuFind\Db\Row\Session');
+    public function __construct(Adapter $adapter, PluginManager $tm, $cfg,
+        RowGateway $rowObj = null, $table = 'session'
+    ) {
+        parent::__construct($adapter, $tm, $cfg, $rowObj, $table);
     }
 
     /**
@@ -144,75 +154,43 @@ class Session extends Gateway
     }
 
     /**
-     * Delete expired sessions. Allows setting of 'from' and 'to' ID's so that rows
-     * can be deleted in small batches.
-     *
-     * @param int $daysOld Age in days of an "expired" session.
-     * @param int $idFrom  Lowest id of rows to delete.
-     * @param int $idTo    Highest id of rows to delete.
-     *
-     * @return int Number of rows deleted
-     */
-    public function deleteExpired($daysOld = 2, $idFrom = null, $idTo = null)
-    {
-        $expireDate = time() - $daysOld * 24 * 60 * 60;
-        $callback = function ($select) use ($expireDate, $idFrom, $idTo) {
-            $where = $select->where->lessThan('last_used', $expireDate);
-            if (null !== $idFrom) {
-                $where->and->greaterThanOrEqualTo('id', $idFrom);
-            }
-            if (null !== $idTo) {
-                $where->and->lessThanOrEqualTo('id', $idTo);
-            }
-        };
-        return $this->delete($callback);
-    }
-
-    /**
-     * Get the lowest id and highest id for expired sessions.
+     * Get a query representing expired sessions (this can be passed
+     * to select() or delete() for further processing).
      *
      * @param int $daysOld Age in days of an "expired" session.
      *
-     * @return array|bool Array of lowest id and highest id or false if no expired
-     * records found
+     * @return function
      */
-    public function getExpiredIdRange($daysOld = 2)
+    public function getExpiredQuery($daysOld = 2)
     {
+        // Determine the expiration date:
         $expireDate = time() - $daysOld * 24 * 60 * 60;
         $callback = function ($select) use ($expireDate) {
             $select->where->lessThan('last_used', $expireDate);
         };
-        $select = $this->getSql()->select();
-        $select->columns(
-            [
-                'id' => new Expression('1'), // required for TableGateway
-                'minId' => new Expression('MIN(id)'),
-                'maxId' => new Expression('MAX(id)'),
-            ]
-        );
-        $select->where($callback);
-        $result = $this->selectWith($select)->current();
-        if (null === $result->minId) {
-            return false;
-        }
-        return [$result->minId, $result->maxId];
+        return $callback;
     }
 
     /**
-     * Get a query representing expired sessions (this can be passed
-     * to select() or delete() for further processing).
+     * Update the select statement to find records to delete.
      *
-     * @param int $daysOld Age in days of an "expired" session.
+     * @param Select $select  Select clause
+     * @param int    $daysOld Age in days of an "expired" record.
+     * @param int    $idFrom  Lowest id of rows to delete.
+     * @param int    $idTo    Highest id of rows to delete.
      *
-     * @return function
+     * @return void
      */
-    public function getExpiredQuery($daysOld = 2)
-    {
-        // Determine the expiration date:
+    protected function expirationCallback($select, $daysOld, $idFrom = null,
+        $idTo = null
+    ) {
         $expireDate = time() - $daysOld * 24 * 60 * 60;
-        $callback = function ($select) use ($expireDate) {
-            $select->where->lessThan('last_used', $expireDate);
-        };
-        return $callback;
+        $where = $select->where->lessThan('last_used', $expireDate);
+        if (null !== $idFrom) {
+            $where->and->greaterThanOrEqualTo('id', $idFrom);
+        }
+        if (null !== $idTo) {
+            $where->and->lessThanOrEqualTo('id', $idTo);
+        }
     }
 }
diff --git a/module/VuFind/src/VuFind/Db/Table/Tags.php b/module/VuFind/src/VuFind/Db/Table/Tags.php
index 1992d7a3c5db381767a293a0db46b9b6bc1e61e0..94b09ffd4ffb65221a192b8932c75bc1302ca984 100644
--- a/module/VuFind/src/VuFind/Db/Table/Tags.php
+++ b/module/VuFind/src/VuFind/Db/Table/Tags.php
@@ -26,9 +26,11 @@
  * @link     https://vufind.org Main Site
  */
 namespace VuFind\Db\Table;
-use Zend\Db\Sql\Expression,
-    Zend\Db\Sql\Predicate\Predicate,
-    Zend\Db\Sql\Select;
+use VuFind\Db\Row\RowGateway;
+use Zend\Db\Adapter\Adapter;
+use Zend\Db\Sql\Expression;
+use Zend\Db\Sql\Predicate\Predicate;
+use Zend\Db\Sql\Select;
 
 /**
  * Table Definition for tags
@@ -51,12 +53,18 @@ class Tags extends Gateway
     /**
      * Constructor
      *
-     * @param bool $caseSensitive Are tags case sensitive?
+     * @param Adapter       $adapter       Database adapter
+     * @param PluginManager $tm            Table manager
+     * @param array         $cfg           Zend Framework configuration
+     * @param RowGateway    $rowObj        Row prototype object (null for default)
+     * @param bool          $caseSensitive Are tags case sensitive?
+     * @param string        $table         Name of database table to interface with
      */
-    public function __construct($caseSensitive = false)
-    {
-        parent::__construct('tags', 'VuFind\Db\Row\Tags');
+    public function __construct(Adapter $adapter, PluginManager $tm, $cfg,
+        RowGateway $rowObj = null, $caseSensitive = false, $table = 'tags'
+    ) {
         $this->caseSensitive = $caseSensitive;
+        parent::__construct($adapter, $tm, $cfg, $rowObj, $table);
     }
 
     /**
diff --git a/module/VuFind/src/VuFind/Db/Table/User.php b/module/VuFind/src/VuFind/Db/Table/User.php
index f09907a5ba182f39b50d27c95ee3d431292067a4..c971b5b6abc3095337a9b0ffe800ed1cce27e11a 100644
--- a/module/VuFind/src/VuFind/Db/Table/User.php
+++ b/module/VuFind/src/VuFind/Db/Table/User.php
@@ -26,7 +26,10 @@
  * @link     https://vufind.org Main Site
  */
 namespace VuFind\Db\Table;
-use Zend\Config\Config, Zend\Session\Container;
+use VuFind\Db\Row\RowGateway;
+use Zend\Config\Config;
+use Zend\Db\Adapter\Adapter;
+use Zend\Session\Container;
 
 /**
  * Table Definition for user
@@ -56,23 +59,28 @@ class User extends Gateway
     /**
      * Constructor
      *
-     * @param Config    $config   VuFind configuration
-     * @param string    $rowClass Name of class for representing rows
-     * @param Container $session  Session container to inject into rows (optional;
-     * used for privacy mode)
+     * @param Adapter       $adapter Database adapter
+     * @param PluginManager $tm      Table manager
+     * @param array         $cfg     Zend Framework configuration
+     * @param RowGateway    $rowObj  Row prototype object (null for default)
+     * @param Config        $config  VuFind configuration
+     * @param Container     $session Session container to inject into rows
+     * (optional; used for privacy mode)
+     * @param string        $table   Name of database table to interface with
      */
-    public function __construct(Config $config, $rowClass = 'VuFind\Db\Row\User',
-        Container $session = null
+    public function __construct(Adapter $adapter, PluginManager $tm, $cfg,
+        RowGateway $rowObj, Config $config, Container $session = null,
+        $table = 'user'
     ) {
-        parent::__construct('user', $rowClass);
         $this->config = $config;
         $this->session = $session;
+        parent::__construct($adapter, $tm, $cfg, $rowObj, $table);
     }
 
     /**
      * Create a row for the specified username.
      *
-     * @param string $username Username to use for retrieval.
+     * @param string $username Username
      *
      * @return UserRow
      */
@@ -84,6 +92,18 @@ class User extends Gateway
         return $row;
     }
 
+    /**
+     * Retrieve a user object from the database based on catalog ID.
+     *
+     * @param string $catId Catalog ID.
+     *
+     * @return UserRow
+     */
+    public function getByCatalogId($catId)
+    {
+        return $this->select(['cat_id' => $catId])->current();
+    }
+
     /**
      * Retrieve a user object from the database based on username; when requested,
      * create a new row if no existing match is found.
@@ -128,21 +148,6 @@ class User extends Gateway
         return $this->select($callback);
     }
 
-    /**
-     * Construct the prototype for rows.
-     *
-     * @return object
-     */
-    protected function initializeRowPrototype()
-    {
-        $prototype = parent::initializeRowPrototype();
-        $prototype->setConfig($this->config);
-        if (null !== $this->session && is_callable([$prototype, 'setSession'])) {
-            $prototype->setSession($this->session);
-        }
-        return $prototype;
-    }
-
     /**
      * Return a row by a verification hash
      *
diff --git a/module/VuFind/src/VuFind/Db/Table/UserCard.php b/module/VuFind/src/VuFind/Db/Table/UserCard.php
index 590117406ff013c04540e2e46f6ea67f579b8f26..53fdd329e499e61a0a6ca7badbe23003efc45d96 100644
--- a/module/VuFind/src/VuFind/Db/Table/UserCard.php
+++ b/module/VuFind/src/VuFind/Db/Table/UserCard.php
@@ -26,6 +26,8 @@
  * @link     https://vufind.org Main Page
  */
 namespace VuFind\Db\Table;
+use VuFind\Db\Row\RowGateway;
+use Zend\Db\Adapter\Adapter;
 
 /**
  * Table Definition for user_card
@@ -40,9 +42,16 @@ class UserCard extends Gateway
 {
     /**
      * Constructor
+     *
+     * @param Adapter       $adapter Database adapter
+     * @param PluginManager $tm      Table manager
+     * @param array         $cfg     Zend Framework configuration
+     * @param RowGateway    $rowObj  Row prototype object (null for default)
+     * @param string        $table   Name of database table to interface with
      */
-    public function __construct()
-    {
-        parent::__construct('user_card', 'VuFind\Db\Row\UserCard');
+    public function __construct(Adapter $adapter, PluginManager $tm, $cfg,
+        RowGateway $rowObj = null, $table = 'user_card'
+    ) {
+        parent::__construct($adapter, $tm, $cfg, $rowObj, $table);
     }
 }
diff --git a/module/VuFind/src/VuFind/Db/Table/UserList.php b/module/VuFind/src/VuFind/Db/Table/UserList.php
index ced6dce5e776791aba1b128a956b328d15926f4f..718504e5be679316e9bd11d5e9300bb74314ccaf 100644
--- a/module/VuFind/src/VuFind/Db/Table/UserList.php
+++ b/module/VuFind/src/VuFind/Db/Table/UserList.php
@@ -26,9 +26,12 @@
  * @link     https://vufind.org Main Page
  */
 namespace VuFind\Db\Table;
-use VuFind\Exception\LoginRequired as LoginRequiredException,
-    VuFind\Exception\RecordMissing as RecordMissingException,
-    Zend\Db\Sql\Expression;
+use VuFind\Db\Row\RowGateway;
+use VuFind\Exception\LoginRequired as LoginRequiredException;
+use VuFind\Exception\RecordMissing as RecordMissingException;
+use Zend\Db\Adapter\Adapter;
+use Zend\Db\Sql\Expression;
+use Zend\Session\Container;
 
 /**
  * Table Definition for user_list
@@ -44,20 +47,26 @@ class UserList extends Gateway
     /**
      * Session container for last list information.
      *
-     * @var \Zend\Session\Container
+     * @var Container
      */
     protected $session;
 
     /**
      * Constructor
      *
-     * @param \Zend\Session\Container $session Session container (must use same
+     * @param Adapter       $adapter Database adapter
+     * @param PluginManager $tm      Table manager
+     * @param array         $cfg     Zend Framework configuration
+     * @param RowGateway    $rowObj  Row prototype object (null for default)
+     * @param Container     $session Session container (must use same
      * namespace as container provided to \VuFind\View\Helper\Root\UserList).
+     * @param string        $table   Name of database table to interface with
      */
-    public function __construct(\Zend\Session\Container $session)
-    {
-        parent::__construct('user_list', 'VuFind\Db\Row\UserList');
+    public function __construct(Adapter $adapter, PluginManager $tm, $cfg,
+        RowGateway $rowObj = null, Container $session = null, $table = 'user_list'
+    ) {
         $this->session = $session;
+        parent::__construct($adapter, $tm, $cfg, $rowObj, $table);
     }
 
     /**
@@ -138,16 +147,4 @@ class UserList extends Gateway
         };
         return $this->select($callback);
     }
-
-    /**
-     * Construct the prototype for rows.
-     *
-     * @return object
-     */
-    protected function initializeRowPrototype()
-    {
-        $prototype = parent::initializeRowPrototype();
-        $prototype->setSession($this->session);
-        return $prototype;
-    }
 }
diff --git a/module/VuFind/src/VuFind/Db/Table/UserResource.php b/module/VuFind/src/VuFind/Db/Table/UserResource.php
index 00e4d946fc74ea1a1fac4c43262d6d1de17447ae..7552f769c819995e84d85cd1ea49838102fb2300 100644
--- a/module/VuFind/src/VuFind/Db/Table/UserResource.php
+++ b/module/VuFind/src/VuFind/Db/Table/UserResource.php
@@ -26,6 +26,8 @@
  * @link     https://vufind.org Main Page
  */
 namespace VuFind\Db\Table;
+use VuFind\Db\Row\RowGateway;
+use Zend\Db\Adapter\Adapter;
 use Zend\Db\Sql\Expression;
 
 /**
@@ -41,10 +43,17 @@ class UserResource extends Gateway
 {
     /**
      * Constructor
+     *
+     * @param Adapter       $adapter Database adapter
+     * @param PluginManager $tm      Table manager
+     * @param array         $cfg     Zend Framework configuration
+     * @param RowGateway    $rowObj  Row prototype object (null for default)
+     * @param string        $table   Name of database table to interface with
      */
-    public function __construct()
-    {
-        parent::__construct('user_resource', 'VuFind\Db\Row\UserResource');
+    public function __construct(Adapter $adapter, PluginManager $tm, $cfg,
+        RowGateway $rowObj = null, $table = 'user_resource'
+    ) {
+        parent::__construct($adapter, $tm, $cfg, $rowObj, $table);
     }
 
     /**
@@ -101,7 +110,7 @@ class UserResource extends Gateway
      * @param string $list_id     ID of list to link up
      * @param string $notes       Notes to associate with link
      *
-     * @return void
+     * @return \VuFind\Db\Row\UserResource
      */
     public function createOrUpdateLink($resource_id, $user_id, $list_id,
         $notes = ''
@@ -123,6 +132,7 @@ class UserResource extends Gateway
         // Update the notes:
         $result->notes = $notes;
         $result->save();
+        return $result;
     }
 
     /**
diff --git a/module/VuFind/src/VuFind/Db/Table/UserStats.php b/module/VuFind/src/VuFind/Db/Table/UserStats.php
deleted file mode 100644
index ea4203eb69204adb1d14962e9dd073a1513e7117..0000000000000000000000000000000000000000
--- a/module/VuFind/src/VuFind/Db/Table/UserStats.php
+++ /dev/null
@@ -1,101 +0,0 @@
-<?php
-/**
- * Table Definition for statistics (user data)
- *
- * PHP version 5
- *
- * Copyright (C) Villanova University 2010.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- *
- * @category VuFind
- * @package  Db_Table
- * @author   Demian Katz <demian.katz@villanova.edu>
- * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
- * @link     https://vufind.org Main Site
- */
-namespace VuFind\Db\Table;
-
-use Zend\Db\Sql\Expression;
-
-/**
- * Table Definition for user statistics
- *
- * @category VuFind
- * @package  Db_Table
- * @author   Chris Hallberg <challber@villanova.edu>
- * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
- * @link     https://vufind.org Main Site
- */
-class UserStats extends Gateway
-{
-    /**
-     * Constructor
-     */
-    public function __construct()
-    {
-        parent::__construct('user_stats');
-    }
-
-    /**
-     * Returns the list of most popular browsers with use counts
-     *
-     * @param bool $withVersions Include browser version numbers?
-     * True = versions (Firefox 12.0) False = names only (Firefox).
-     * @param int  $limit        How many to return
-     *
-     * @return array
-     */
-    public function getBrowserStats($withVersions = false, $limit = 5)
-    {
-        $callback = function ($select) use ($withVersions, $limit) {
-            if ($withVersions) {
-                $select->columns(
-                    [
-                        'browserName' => new Expression(
-                            'CONCAT_WS(" ",?,?)',
-                            ['browser', 'browserVersion'],
-                            [
-                                Expression::TYPE_IDENTIFIER,
-                                Expression::TYPE_IDENTIFIER
-                            ]
-                        ),
-                        'count' => new Expression(
-                            'COUNT(DISTINCT (?))',
-                            ['session'],
-                            [Expression::TYPE_IDENTIFIER]
-                        )
-                    ]
-                );
-                $select->group('browserName');
-            } else {
-                $select->columns(
-                    [
-                        'browserName' => 'browser',
-                        'count' => new Expression(
-                            'COUNT(DISTINCT (?))',
-                            ['session'],
-                            [Expression::TYPE_IDENTIFIER]
-                        )
-                    ]
-                );
-                $select->group('browser');
-            }
-            $select->limit($limit);
-            $select->order('count DESC');
-        };
-        
-        return $this->select($callback)->toArray();
-    }
-}
diff --git a/module/VuFind/src/VuFind/Db/Table/UserStatsFields.php b/module/VuFind/src/VuFind/Db/Table/UserStatsFields.php
deleted file mode 100644
index 3a833e0872191fa0ecf9e594da876b3db49f47e9..0000000000000000000000000000000000000000
--- a/module/VuFind/src/VuFind/Db/Table/UserStatsFields.php
+++ /dev/null
@@ -1,114 +0,0 @@
-<?php
-/**
- * Table Definition for statistics
- *
- * PHP version 5
- *
- * Copyright (C) Villanova University 2010.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- *
- * @category VuFind
- * @package  Db_Table
- * @author   Demian Katz <demian.katz@villanova.edu>
- * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
- * @link     https://vufind.org Main Site
- */
-namespace VuFind\Db\Table;
-
-/**
- * Table Definition for statistics
- *
- * @category VuFind
- * @package  Db_Table
- * @author   Chris Hallberg <challber@villanova.edu>
- * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
- * @link     https://vufind.org Main Site
- */
-class UserStatsFields extends Gateway
-{
-    /**
-     * Constructor
-     */
-    public function __construct()
-    {
-        parent::__construct('user_stats_fields');
-    }
-
-    /**
-     * Save data to the DB, data to statistics, user data in user_stats
-     *
-     * @param array $stats    data indexed by column name
-     * @param array $userData data indexed by
-     * id, timestamp, browser, ipaddress, referrer, url
-     *
-     * @return null
-     */
-    public function save($stats, $userData)
-    {
-        // Statistics data
-        foreach ($stats as $field => $value) {
-            if (gettype($value) == "boolean") {
-                $value = ($value) ? "true" : "false";
-            }
-            $this->insert(
-                [
-                    'id'    => $userData['id'],
-                    'field' => $field . "",
-                    'value' => $value . "",
-                ]
-            );
-        }
-        // User data
-        $userStats = $this->getDbTable('UserStats');
-        $userStats->insert($userData);
-    }
-
-    /**
-     * Get data for these fields
-     *
-     * @param array $fields What fields of data are we researching?
-     * @param array $values Values to match while we search
-     *
-     * @return associative array
-     */
-    public function getFields($fields, $values = [])
-    {
-        if (empty($fields)) {
-            return null;
-        }
-        if (!is_array($fields)) {
-            $fields = [$fields];
-        }
-        $callback = function ($select) use ($fields, $values) {
-            $select->columns(
-                [$fields[0] => 'value']
-            );
-            $select->where->equalTo('field', $fields[0]);
-            for ($i = 1;$i < count($fields);$i++) {
-                $select->where->equalTo('field' . $i . '.field', $fields[$i]);
-                $select->join(
-                    ['field' . $i => 'user_stats_fields'],
-                    'user_stats_fields.id=field' . $i . '.id',
-                    [$fields[$i] => 'field' . $i . '.value']
-                );
-            }
-            foreach ($values as $key => $value) {
-                $select->where->equalTo($key, $value);
-            }
-        };
-        
-        return $this->select($callback);
-    }
-}
diff --git a/module/VuFind/src/VuFind/Exception/BadRequest.php b/module/VuFind/src/VuFind/Exception/BadRequest.php
new file mode 100644
index 0000000000000000000000000000000000000000..defff0e7c15bf7a85a911e50485a781c037e177c
--- /dev/null
+++ b/module/VuFind/src/VuFind/Exception/BadRequest.php
@@ -0,0 +1,50 @@
+<?php
+/**
+ * "Bad Request" Exception
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2016.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * @category VuFind
+ * @package  Exceptions
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development Wiki
+ */
+namespace VuFind\Exception;
+
+/**
+ * "Bad Request" Exception
+ *
+ * @category VuFind
+ * @package  Exceptions
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development Wiki
+ */
+class BadRequest extends \Exception implements HttpStatusInterface
+{
+    /**
+     * Get HTTP status associated with this exception.
+     *
+     * @return int
+     */
+    public function getHttpStatus()
+    {
+        return 400;
+    }
+}
diff --git a/module/VuFind/src/VuFind/Favorites/FavoritesService.php b/module/VuFind/src/VuFind/Favorites/FavoritesService.php
new file mode 100644
index 0000000000000000000000000000000000000000..86778ea93e34ea402dac177a2c934bf664e73ddf
--- /dev/null
+++ b/module/VuFind/src/VuFind/Favorites/FavoritesService.php
@@ -0,0 +1,174 @@
+<?php
+/**
+ * Favorites service
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2016.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * @category VuFind
+ * @package  Favorites
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org Main Page
+ */
+namespace VuFind\Favorites;
+use VuFind\Record\Cache as RecordCache;
+use VuFind\RecordDriver\AbstractBase as RecordDriver;
+use VuFind\Db\Table\Resource as ResourceTable;
+use VuFind\Db\Table\UserList as UserListTable;
+
+/**
+ * Favorites service
+ *
+ * @category VuFind
+ * @package  Favorites
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org Main Page
+ */
+class FavoritesService implements \VuFind\I18n\Translator\TranslatorAwareInterface
+{
+    use \VuFind\I18n\Translator\TranslatorAwareTrait;
+
+    /**
+     * Record cache
+     *
+     * @var RecordCache
+     */
+    protected $recordCache = null;
+
+    /**
+     * Resource database table
+     *
+     * @var ResourceTable
+     */
+    protected $resourceTable;
+
+    /**
+     * UserList database table
+     *
+     * @var UserListTable
+     */
+    protected $userListTable;
+
+    /**
+     * Constructor
+     *
+     * @param UserListTable $userList UserList table object
+     * @param ResourceTable $resource Resource table object
+     * @param RecordCache   $cache    Record cache
+     */
+    public function __construct(UserListTable $userList, ResourceTable $resource,
+        RecordCache $cache = null
+    ) {
+        $this->recordCache = $cache;
+        $this->userListTable = $userList;
+        $this->resourceTable = $resource;
+    }
+
+    /**
+     * Get a list object for the specified ID (or 'NEW' to create a new list).
+     *
+     * @param string              $listId List ID (or 'NEW')
+     * @param \VuFind\Db\Row\User $user   The user saving the record
+     *
+     * @return \VuFind\Db\Row\UserList
+     *
+     * @throws \VuFind\Exception\ListPermission
+     */
+    protected function getListObject($listId, \VuFind\Db\Row\User $user)
+    {
+        if (empty($listId) || $listId == 'NEW') {
+            $list = $this->userListTable->getNew($user);
+            $list->title = $this->translate('My Favorites');
+            $list->save($user);
+        } else {
+            $list = $this->userListTable->getExisting($listId);
+            // Validate incoming list ID:
+            if (!$list->editAllowed($user)) {
+                throw new \VuFind\Exception\ListPermission('Access denied.');
+            }
+            $list->rememberLastUsed(); // handled by save() in other case
+        }
+        return $list;
+    }
+
+    /**
+     * Persist a resource to the record cache (if applicable).
+     *
+     * @param RecordDriver            $driver   Record driver to persist
+     * @param \VuFind\Db\Row\Resource $resource Resource row
+     *
+     * @return void
+     */
+    protected function persistToCache(RecordDriver $driver,
+        \VuFind\Db\Row\Resource $resource
+    ) {
+        if ($this->recordCache) {
+            $this->recordCache->setContext(RecordCache::CONTEXT_FAVORITE);
+            $this->recordCache->createOrUpdate(
+                $resource->record_id, $resource->source,
+                $driver->getRawData()
+            );
+        }
+    }
+
+    /**
+     * Save this record to the user's favorites.
+     *
+     * @param array               $params Array with some or all of these keys:
+     *  <ul>
+     *    <li>mytags - Tag array to associate with record (optional)</li>
+     *    <li>notes - Notes to associate with record (optional)</li>
+     *    <li>list - ID of list to save record into (omit to create new list)</li>
+     *  </ul>
+     * @param \VuFind\Db\Row\User $user   The user saving the record
+     * @param RecordDriver        $driver Record driver for record being saved
+     *
+     * @return array list information
+     */
+    public function save(array $params, \VuFind\Db\Row\User $user,
+        RecordDriver $driver
+    ) {
+        // Validate incoming parameters:
+        if (!$user) {
+            throw new LoginRequiredException('You must be logged in first');
+        }
+
+        // Get or create a list object as needed:
+        $list = $this->getListObject(
+            isset($params['list']) ? $params['list'] : '',
+            $user
+        );
+
+        // Get or create a resource object as needed:
+        $resource = $this->resourceTable->findResource(
+            $driver->getUniqueId(), $driver->getSourceIdentifier(), true, $driver
+        );
+
+        // Persist record in the database for "offline" use
+        $this->persistToCache($driver, $resource);
+
+        // Add the information to the user's account:
+        $user->saveResource(
+            $resource, $list,
+            isset($params['mytags']) ? $params['mytags'] : [],
+            isset($params['notes']) ? $params['notes'] : ''
+        );
+        return ['listId' => $list->id];
+    }
+}
diff --git a/module/VuFind/src/VuFind/Favorites/FavoritesServiceFactory.php b/module/VuFind/src/VuFind/Favorites/FavoritesServiceFactory.php
new file mode 100644
index 0000000000000000000000000000000000000000..9d73aa12bc72e2a769b92d6d4f23c3d4b55e3e1b
--- /dev/null
+++ b/module/VuFind/src/VuFind/Favorites/FavoritesServiceFactory.php
@@ -0,0 +1,60 @@
+<?php
+/**
+ * Favorites service factory
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2016.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * @category VuFind
+ * @package  Favorites
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org Main Page
+ */
+namespace VuFind\Favorites;
+use Zend\ServiceManager\ServiceLocatorInterface;
+
+/**
+ * Favorites service
+ *
+ * @category VuFind
+ * @package  Favorites
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org Main Page
+ *
+ * @codeCoverageIgnore
+ */
+class FavoritesServiceFactory implements \Zend\ServiceManager\FactoryInterface
+{
+    /**
+     * Create service
+     *
+     * @param ServiceLocatorInterface $sm Service manager
+     *
+     * @return mixed
+     */
+    public function createService(ServiceLocatorInterface $sm)
+    {
+        $tableManager = $sm->get('VuFind\DbTablePluginManager');
+        return new FavoritesService(
+            $tableManager->get('userlist'),
+            $tableManager->get('resource'),
+            $sm->get('VuFind\RecordCache')
+        );
+    }
+}
diff --git a/module/VuFind/src/VuFind/Hierarchy/TreeDataSource/Solr.php b/module/VuFind/src/VuFind/Hierarchy/TreeDataSource/Solr.php
index 3b6c965fea97bc7672be5869637ad08d4a18b348..7668c44e11895b1fc60ad63cbebcc5caff91a450 100644
--- a/module/VuFind/src/VuFind/Hierarchy/TreeDataSource/Solr.php
+++ b/module/VuFind/src/VuFind/Hierarchy/TreeDataSource/Solr.php
@@ -111,11 +111,12 @@ class Solr extends AbstractBase
      * Search Solr.
      *
      * @param string $q    Search query
-     * @param int    $rows Max rows to retrieve (default = int max)
+     * @param int    $rows Max rows to retrieve (default = int max / 2 since Solr
+     * may choke with higher values)
      *
      * @return array
      */
-    protected function searchSolr($q, $rows = 2147483647)
+    protected function searchSolr($q, $rows = 1073741823)
     {
         $params = new ParamBag(
             [
diff --git a/module/VuFind/src/VuFind/ILS/Connection.php b/module/VuFind/src/VuFind/ILS/Connection.php
index 8cc116c4add3b4b58247d0bea0324ddee43d4c18..31dc2b086695fc112b1c00ea2b511a7d799dda97 100644
--- a/module/VuFind/src/VuFind/ILS/Connection.php
+++ b/module/VuFind/src/VuFind/ILS/Connection.php
@@ -65,7 +65,7 @@ class Connection implements TranslatorAwareInterface, LoggerAwareInterface
      *
      * @var object
      */
-    protected $driver;
+    protected $driver = null;
 
     /**
      * ILS configuration
@@ -88,6 +88,13 @@ class Connection implements TranslatorAwareInterface, LoggerAwareInterface
      */
     protected $titleHoldsMode = 'disabled';
 
+    /**
+     * Driver plugin manager
+     *
+     * @var \VuFind\ILS\Driver\PluginManager
+     */
+    protected $driverManager;
+
     /**
      * Configuration loader
      *
@@ -95,6 +102,13 @@ class Connection implements TranslatorAwareInterface, LoggerAwareInterface
      */
     protected $configReader;
 
+    /**
+     * Is the current ILS driver failing?
+     *
+     * @var bool
+     */
+    protected $failing = false;
+
     /**
      * Constructor
      *
@@ -107,28 +121,15 @@ class Connection implements TranslatorAwareInterface, LoggerAwareInterface
         \VuFind\ILS\Driver\PluginManager $driverManager,
         \VuFind\Config\PluginManager $configReader
     ) {
-        $this->config = $config;
-        $this->configReader = $configReader;
-        if (!isset($this->config->driver)) {
+        if (!isset($config->driver)) {
             throw new \Exception('ILS driver setting missing.');
         }
-        $service = $this->config->driver;
-        if (!$driverManager->has($service)) {
-            throw new \Exception('ILS driver missing: ' . $service);
-        }
-        $this->setDriver($driverManager->get($service));
-
-        // If we're configured to fail over to the NoILS driver, we need
-        // to test if the main driver is working.
-        if (isset($this->config->loadNoILSOnFailure)
-            && $this->config->loadNoILSOnFailure
-        ) {
-            try {
-                $this->getDriver();
-            } catch (\Exception $e) {
-                $this->setDriver($driverManager->get('NoILS'));
-            }
+        if (!$driverManager->has($config->driver)) {
+            throw new \Exception('ILS driver missing: ' . $config->driver);
         }
+        $this->config = $config;
+        $this->configReader = $configReader;
+        $this->driverManager = $driverManager;
     }
 
     /**
@@ -152,24 +153,78 @@ class Connection implements TranslatorAwareInterface, LoggerAwareInterface
      */
     public function getDriverClass()
     {
-        return get_class($this->driver);
+        return get_class($this->getDriver(false));
+    }
+
+    /**
+     * Initialize the ILS driver.
+     *
+     * @return void
+     */
+    protected function initializeDriver()
+    {
+        $this->driver->setConfig($this->getDriverConfig());
+        $this->driver->init();
+        $this->driverInitialized = true;
+    }
+
+    /**
+     * Are we configured to fail over to the NoILS driver on error?
+     *
+     * @return bool
+     */
+    protected function hasNoILSFailover()
+    {
+        // If we're configured to fail over to the NoILS driver, do so now:
+        return isset($this->config->loadNoILSOnFailure)
+            && $this->config->loadNoILSOnFailure;
+    }
+
+    /**
+     * If configured, fail over to the NoILS driver and return true; otherwise,
+     * return false.
+     *
+     * @return bool
+     */
+    protected function failOverToNoILS()
+    {
+        $this->failing = true;
+
+        // Only fail over if we're configured to allow it and we haven't already
+        // done so!
+        if ($this->hasNoILSFailover()) {
+            $noILS = $this->driverManager->get('NoILS');
+            if (get_class($noILS) != $this->getDriverClass()) {
+                $this->setDriver($noILS);
+                $this->initializeDriver();
+                return true;
+            }
+        }
+        return false;
     }
 
     /**
      * Get access to the driver object.
      *
+     * @param bool $init Should we initialize the driver (if necessary), or load it
+     * "as-is"?
+     *
      * @throws \Exception
      * @return object
      */
-    public function getDriver()
+    public function getDriver($init = true)
     {
-        if (!$this->driverInitialized) {
-            if (!is_object($this->driver)) {
-                throw new \Exception('ILS driver missing.');
+        if (null === $this->driver) {
+            $this->setDriver($this->driverManager->get($this->config->driver));
+        }
+        if (!$this->driverInitialized && $init) {
+            try {
+                $this->initializeDriver();
+            } catch (\Exception $e) {
+                if (!$this->failOverToNoILS()) {
+                    throw $e;
+                }
             }
-            $this->driver->setConfig($this->getDriverConfig());
-            $this->driver->init();
-            $this->driverInitialized = true;
         }
         return $this->driver;
     }
@@ -586,10 +641,16 @@ class Connection implements TranslatorAwareInterface, LoggerAwareInterface
      */
     public function checkRequestIsValid($id, $data, $patron)
     {
-        if ($this->checkCapability(
-            'checkRequestIsValid', [$id, $data, $patron]
-        )) {
-            return $this->getDriver()->checkRequestIsValid($id, $data, $patron);
+        try {
+            $params = [$id, $data, $patron];
+            if ($this->checkCapability('checkRequestIsValid', $params)) {
+                return $this->getDriver()->checkRequestIsValid($id, $data, $patron);
+            }
+        } catch (\Exception $e) {
+            if ($this->failOverToNoILS()) {
+                return call_user_func_array([$this, __METHOD__], func_get_args());
+            }
+            throw $e;
         }
         // If the driver has no checkRequestIsValid method, we will assume that
         // all requests are valid - failure can be handled later after the user
@@ -611,12 +672,20 @@ class Connection implements TranslatorAwareInterface, LoggerAwareInterface
      */
     public function checkStorageRetrievalRequestIsValid($id, $data, $patron)
     {
-        if ($this->checkCapability(
-            'checkStorageRetrievalRequestIsValid', [$id, $data, $patron]
-        )) {
-            return $this->getDriver()->checkStorageRetrievalRequestIsValid(
-                $id, $data, $patron
+        try {
+            $check = $this->checkCapability(
+                'checkStorageRetrievalRequestIsValid', [$id, $data, $patron]
             );
+            if ($check) {
+                return $this->getDriver()->checkStorageRetrievalRequestIsValid(
+                    $id, $data, $patron
+                );
+            }
+        } catch (\Exception $e) {
+            if ($this->failOverToNoILS()) {
+                return call_user_func_array([$this, __METHOD__], func_get_args());
+            }
+            throw $e;
         }
         // If the driver has no checkStorageRetrievalRequestIsValid method, we
         // will assume that the request is not valid
@@ -637,12 +706,18 @@ class Connection implements TranslatorAwareInterface, LoggerAwareInterface
      */
     public function checkILLRequestIsValid($id, $data, $patron)
     {
-        if ($this->checkCapability(
-            'checkILLRequestIsValid', [$id, $data, $patron]
-        )) {
-            return $this->getDriver()->checkILLRequestIsValid(
-                $id, $data, $patron
-            );
+        try {
+            $params = [$id, $data, $patron];
+            if ($this->checkCapability('checkILLRequestIsValid', $params)) {
+                return $this->getDriver()->checkILLRequestIsValid(
+                    $id, $data, $patron
+                );
+            }
+        } catch (\Exception $e) {
+            if ($this->failOverToNoILS()) {
+                return call_user_func_array([$this, __METHOD__], func_get_args());
+            }
+            throw $e;
         }
         // If the driver has no checkILLRequestIsValid method, we
         // will assume that the request is not valid
@@ -666,14 +741,33 @@ class Connection implements TranslatorAwareInterface, LoggerAwareInterface
      *
      * This is responsible for returning the offline mode
      *
+     * @param bool $healthCheck Perform a health check in addition to consulting
+     * the ILS status?
+     *
      * @return string|bool "ils-offline" for systems where the main ILS is offline,
      * "ils-none" for systems which do not use an ILS, false for online systems.
      */
-    public function getOfflineMode()
+    public function getOfflineMode($healthCheck = false)
     {
+        // If we have NoILS failover configured, force driver initialization so
+        // we can know we are checking the offline mode against the correct driver.
+        if ($this->hasNoILSFailover()) {
+            $this->getDriver();
+        }
+
+        // If we need to perform a health check, try to do a random item lookup
+        // before proceeding.
+        if ($healthCheck) {
+            $this->getStatus('1');
+        }
+
+        // If we're encountering failures, let's go into ils-offline mode if
+        // the ILS driver does not natively support getOfflineMode().
+        $default = $this->failing ? 'ils-offline' : false;
+
         // Graceful degradation -- return false if no method supported.
         return $this->checkCapability('getOfflineMode')
-            ? $this->getDriver()->getOfflineMode() : false;
+            ? $this->getDriver()->getOfflineMode() : $default;
     }
 
     /**
@@ -700,8 +794,15 @@ class Connection implements TranslatorAwareInterface, LoggerAwareInterface
     public function hasHoldings($id)
     {
         // Graceful degradation -- return true if no method supported.
-        return $this->checkCapability('hasHoldings', [$id])
-            ? $this->getDriver()->hasHoldings($id) : true;
+        try {
+            return $this->checkCapability('hasHoldings', [$id])
+                ? $this->getDriver()->hasHoldings($id) : true;
+        } catch (\Exception $e) {
+            if ($this->failOverToNoILS()) {
+                return call_user_func_array([$this, __METHOD__], func_get_args());
+            }
+            throw $e;
+        }
     }
 
     /**
@@ -714,8 +815,15 @@ class Connection implements TranslatorAwareInterface, LoggerAwareInterface
     public function loginIsHidden()
     {
         // Graceful degradation -- return false if no method supported.
-        return $this->checkCapability('loginIsHidden')
-            ? $this->getDriver()->loginIsHidden() : false;
+        try {
+            return $this->checkCapability('loginIsHidden')
+                ? $this->getDriver()->loginIsHidden() : false;
+        } catch (\Exception $e) {
+            if ($this->failOverToNoILS()) {
+                return call_user_func_array([$this, __METHOD__], func_get_args());
+            }
+            throw $e;
+        }
     }
 
     /**
@@ -732,13 +840,19 @@ class Connection implements TranslatorAwareInterface, LoggerAwareInterface
     public function checkCapability($method, $params = [], $throw = false)
     {
         try {
-            // First check that the function is callable without the expense of
-            // initializing the driver:
-            if (is_callable([$this->getDriverClass(), $method])) {
+            // If we have NoILS failover disabled, we can check capabilities of
+            // the driver class without wasting time initializing it; if NoILS
+            // failover is enabled, we have to initialize the driver object now
+            // to be sure we are checking capabilities on the appropriate class.
+            $driverToCheck = $this->hasNoILSFailover()
+                ? $this->getDriver() : $this->getDriverClass();
+
+            // First check that the function is callable:
+            if (is_callable([$driverToCheck, $method])) {
                 // At least drivers implementing the __call() magic method must also
                 // implement supportsMethod() to verify that the method is actually
                 // usable:
-                if (method_exists($this->getDriverClass(), 'supportsMethod')) {
+                if (method_exists($driverToCheck, 'supportsMethod')) {
                     return $this->getDriver()->supportsMethod($method, $params);
                 }
                 return true;
@@ -799,10 +913,17 @@ class Connection implements TranslatorAwareInterface, LoggerAwareInterface
      */
     public function __call($methodName, $params)
     {
-        if ($this->checkCapability($methodName, $params)) {
-            return call_user_func_array(
-                [$this->getDriver(), $methodName], $params
-            );
+        try {
+            if ($this->checkCapability($methodName, $params)) {
+                return call_user_func_array(
+                    [$this->getDriver(), $methodName], $params
+                );
+            }
+        } catch (\Exception $e) {
+            if ($this->failOverToNoILS()) {
+                return call_user_func_array([$this, __METHOD__], func_get_args());
+            }
+            throw $e;
         }
         throw new ILSException(
             'Cannot call method: ' . $this->getDriverClass() . '::' . $methodName
diff --git a/module/VuFind/src/VuFind/ILS/Driver/Aleph.php b/module/VuFind/src/VuFind/ILS/Driver/Aleph.php
index fe69cf8b4c78a0d8bae4b7e5693f82a38bffc225..4a251de393d6052b68b9934431c44f0b2384edbe 100644
--- a/module/VuFind/src/VuFind/ILS/Driver/Aleph.php
+++ b/module/VuFind/src/VuFind/ILS/Driver/Aleph.php
@@ -781,14 +781,12 @@ class Aleph extends AbstractBase implements \Zend\Log\LoggerAwareInterface,
                 $addLink = ($hold_request[0] == 'Y');
             }
             $matches = [];
-            if (preg_match(
-                "/([0-9]*\\/[a-zA-Z]*\\/[0-9]*);([a-zA-Z ]*)/", $status, $matches
-            )) {
+            $dueDateWithStatusRegEx = "/([0-9]*\\/[a-zA-Z]*\\/[0-9]*);([a-zA-Z ]*)/";
+            $dueDateRegEx = "/([0-9]*\\/[a-zA-Z]*\\/[0-9]*)/";
+            if (preg_match($dueDateWithStatusRegEx, $status, $matches)) {
                 $duedate = $this->parseDate($matches[1]);
                 $requested = (trim($matches[2]) == "Requested");
-            } else if (preg_match(
-                "/([0-9]*\\/[a-zA-Z]*\\/[0-9]*)/", $status, $matches
-            )) {
+            } else if (preg_match($dueDateRegEx, $status, $matches)) {
                 $duedate = $this->parseDate($matches[1]);
             } else {
                 $duedate = null;
diff --git a/module/VuFind/src/VuFind/ILS/Driver/DAIA.php b/module/VuFind/src/VuFind/ILS/Driver/DAIA.php
index 784cdaee4db7b53a7f2f43fa82e7ca29389efd4c..0a0b8287c88be94f2138f4eb3bf1e9462f5c8828 100644
--- a/module/VuFind/src/VuFind/ILS/Driver/DAIA.php
+++ b/module/VuFind/src/VuFind/ILS/Driver/DAIA.php
@@ -654,7 +654,8 @@ class DAIA extends AbstractBase implements
                         || (in_array(
                             $domNode->nodeName,
                             ['storage', 'limitation', 'department', 'institution']
-                        ) && strlen($domNode->nodeValue))) {
+                        ) && strlen($domNode->nodeValue))
+                    ) {
                         if (trim($node->textContent)) {
                             $domNode->setAttribute('content', $node->textContent);
                             $node->nodeValue = '';
@@ -790,7 +791,6 @@ class DAIA extends AbstractBase implements
     protected function getItemStatus($item)
     {
         $availability = false;
-        $status = ''; // status cannot be null as this will crash the translator
         $duedate = null;
         $serviceLink = '';
         $queue = '';
diff --git a/module/VuFind/src/VuFind/ILS/Driver/Demo.php b/module/VuFind/src/VuFind/ILS/Driver/Demo.php
index 520b5172024a4b2f1734507009090e396210f46e..ad8eb819fbd0de3eb16f13251930025bc4bcd59a 100644
--- a/module/VuFind/src/VuFind/ILS/Driver/Demo.php
+++ b/module/VuFind/src/VuFind/ILS/Driver/Demo.php
@@ -163,6 +163,7 @@ class Demo extends AbstractBase
                 }
             }
         }
+        $this->checkIntermittentFailure();
     }
 
     /**
@@ -292,43 +293,58 @@ class Demo extends AbstractBase
     }
 
     /**
-     * Are renewals blocked?
+     * Should we simulate a system failure?
      *
-     * @return bool
+     * @return void
+     * @throws ILSException
      */
-    protected function checkRenewBlock()
+    protected function checkIntermittentFailure()
     {
-        return $this->isFailing(__METHOD__, 25);
+        if ($this->isFailing(__METHOD__, 0)) {
+            throw new ILSException('Simulating low-level system failure');
+        }
     }
 
     /**
-     * Are holds/recalls blocked?
+     * Are renewals blocked?
      *
      * @return bool
      */
-    protected function checkRequestBlock()
+    protected function checkRenewBlock()
     {
-        return $this->isFailing(__METHOD__, 10);
+        return $this->isFailing(__METHOD__, 25);
     }
 
     /**
-     * Are ILL requests blocked?
+     * Check whether the patron is blocked from placing requests (holds/ILL/SRR).
      *
-     * @return bool
+     * @param array $patron Patron data from patronLogin().
+     *
+     * @return mixed A boolean false if no blocks are in place and an array
+     * of block reasons if blocks are in place
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
-    protected function checkILLRequestBlock()
+    public function getRequestBlocks($patron)
     {
-        return $this->isFailing(__METHOD__, 10);
+        return $this->isFailing(__METHOD__, 10)
+            ? ['simulated request block'] : false;
     }
 
     /**
-     * Are storage retrieval requests blocked?
+     * Check whether the patron has any blocks on their account.
      *
-     * @return bool
+     * @param array $patron Patron data from patronLogin().
+     *
+     * @return mixed A boolean false if no blocks are in place and an array
+     * of block reasons if blocks are in place
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
-    protected function checkStorageRetrievalRequestBlock()
+    public function getAccountBlocks($patron)
     {
-        return $this->isFailing(__METHOD__, 10);
+        return $this->isFailing(__METHOD__, 10)
+            ? ['simulated account block'] : false;
     }
 
     /**
@@ -359,16 +375,12 @@ class Demo extends AbstractBase
             'callnumber'   => $this->getFakeCallNum(),
             'duedate'      => '',
             'is_holdable'  => true,
-            'addLink'      => $patron
-                ? $this->checkRequestBlock() ? 'block' : true : false,
+            'addLink'      => $patron ? true : false,
             'level'        => 'copy',
             'storageRetrievalRequest' => 'auto',
-            'addStorageRetrievalRequestLink' => $patron
-                ? $this->checkStorageRetrievalRequestBlock() ? 'block' : 'check'
-                : false,
+            'addStorageRetrievalRequestLink' => $patron ? 'check' : false,
             'ILLRequest'   => 'auto',
-            'addILLRequestLink' => $patron
-                ? $this->checkILLRequestBlock() ? 'block' : 'check' : false,
+            'addILLRequestLink' => $patron ? 'check' : false,
             'services'     => $status == 'Available' ? $this->getFakeServices() : []
         ];
     }
@@ -586,6 +598,7 @@ class Demo extends AbstractBase
      */
     public function getStatuses($ids)
     {
+        $this->checkIntermittentFailure();
         return array_map([$this, 'getStatus'], $ids);
     }
 
@@ -604,6 +617,8 @@ class Demo extends AbstractBase
      */
     public function getHolding($id, array $patron = null)
     {
+        $this->checkIntermittentFailure();
+
         // Get basic status info:
         $status = $this->getSimulatedStatus($id, $patron);
 
@@ -640,6 +655,7 @@ class Demo extends AbstractBase
      */
     public function getPurchaseHistory($id)
     {
+        $this->checkIntermittentFailure();
         $issues = rand(0, 3);
         $retval = [];
         for ($i = 0; $i < $issues; $i++) {
@@ -662,6 +678,7 @@ class Demo extends AbstractBase
      */
     public function patronLogin($barcode, $password)
     {
+        $this->checkIntermittentFailure();
         if (isset($this->config['Users'])) {
             if (!isset($this->config['Users'][$barcode])
                 || $password !== $this->config['Users'][$barcode]
@@ -694,6 +711,7 @@ class Demo extends AbstractBase
      */
     public function getMyProfile($patron)
     {
+        $this->checkIntermittentFailure();
         $patron = [
             'firstname' => 'Lib-' . $patron['cat_username'],
             'lastname'  => 'Rarian',
@@ -721,6 +739,7 @@ class Demo extends AbstractBase
      */
     public function getMyFines($patron)
     {
+        $this->checkIntermittentFailure();
         $session = $this->getSession();
         if (!isset($session->fines)) {
             // How many items are there? %20 - 2 = 10% chance of none,
@@ -777,6 +796,7 @@ class Demo extends AbstractBase
      */
     public function getMyHolds($patron)
     {
+        $this->checkIntermittentFailure();
         $session = $this->getSession();
         if (!isset($session->holds)) {
             $session->holds = $this->createRequestList('Holds');
@@ -797,6 +817,7 @@ class Demo extends AbstractBase
      */
     public function getMyStorageRetrievalRequests($patron)
     {
+        $this->checkIntermittentFailure();
         $session = $this->getSession();
         if (!isset($session->storageRetrievalRequests)) {
             $session->storageRetrievalRequests
@@ -818,6 +839,7 @@ class Demo extends AbstractBase
      */
     public function getMyILLRequests($patron)
     {
+        $this->checkIntermittentFailure();
         $session = $this->getSession();
         if (!isset($session->ILLRequests)) {
             $session->ILLRequests = $this->createRequestList('ILLRequests');
@@ -833,6 +855,7 @@ class Demo extends AbstractBase
      */
     protected function getTransactionList()
     {
+        $this->checkIntermittentFailure();
         // If Demo.ini includes a fixed set of transactions, load those; otherwise
         // build some random ones.
         return isset($this->config['Records']['transactions'])
@@ -918,8 +941,8 @@ class Demo extends AbstractBase
                     $transList[$i]['title'] = 'Demo Title ' . $i;
                 }
             }
-            return $transList;
         }
+        return $transList;
     }
 
     /**
@@ -936,6 +959,7 @@ class Demo extends AbstractBase
      */
     public function getMyTransactions($patron)
     {
+        $this->checkIntermittentFailure();
         $session = $this->getSession();
         if (!isset($session->transactions)) {
             $session->transactions = $this->getTransactionList();
@@ -964,6 +988,7 @@ class Demo extends AbstractBase
      */
     public function getPickUpLocations($patron = false, $holdDetails = null)
     {
+        $this->checkIntermittentFailure();
         return [
             [
                 'locationID' => 'A',
@@ -993,6 +1018,7 @@ class Demo extends AbstractBase
      */
     public function getHoldDefaultRequiredDate($patron, $holdInfo)
     {
+        $this->checkIntermittentFailure();
         // 5 years in the future (but similate intermittent failure):
         return !$this->isFailing(__METHOD__, 50)
             ? mktime(0, 0, 0, date('m'), date('d'), date('Y') + 5) : null;
@@ -1016,6 +1042,7 @@ class Demo extends AbstractBase
      */
     public function getDefaultPickUpLocation($patron = false, $holdDetails = null)
     {
+        $this->checkIntermittentFailure();
         $locations = $this->getPickUpLocations($patron);
         return $locations[0]['locationID'];
     }
@@ -1038,6 +1065,7 @@ class Demo extends AbstractBase
      */
     public function getDefaultRequestGroup($patron = false, $holdDetails = null)
     {
+        $this->checkIntermittentFailure();
         if ($this->isFailing(__METHOD__, 50)) {
             return false;
         }
@@ -1048,17 +1076,23 @@ class Demo extends AbstractBase
     /**
      * Get request groups
      *
-     * @param int   $bibId  BIB ID
-     * @param array $patron Patron information returned by the patronLogin
+     * @param int   $bibId       BIB ID
+     * @param array $patron      Patron information returned by the patronLogin
      * method.
+     * @param array $holdDetails Optional array, only passed in when getting a list
+     * in the context of placing a hold; contains most of the same values passed to
+     * placeHold, minus the patron data.  May be used to limit the request group
+     * options or may be ignored.
      *
      * @return array  False if request groups not in use or an array of
      * associative arrays with id and name keys
      *
      * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
-    public function getRequestGroups($bibId = null, $patron = null)
-    {
+    public function getRequestGroups($bibId = null, $patron = null,
+        $holdDetails = null
+    ) {
+        $this->checkIntermittentFailure();
         return [
             [
                 'id' => 1,
@@ -1080,6 +1114,7 @@ class Demo extends AbstractBase
      */
     public function getFunds()
     {
+        $this->checkIntermittentFailure();
         return ["Fund A", "Fund B", "Fund C"];
     }
 
@@ -1092,6 +1127,7 @@ class Demo extends AbstractBase
      */
     public function getDepartments()
     {
+        $this->checkIntermittentFailure();
         return ["Dept. A", "Dept. B", "Dept. C"];
     }
 
@@ -1104,6 +1140,7 @@ class Demo extends AbstractBase
      */
     public function getInstructors()
     {
+        $this->checkIntermittentFailure();
         return ["Instructor A", "Instructor B", "Instructor C"];
     }
 
@@ -1116,6 +1153,7 @@ class Demo extends AbstractBase
      */
     public function getCourses()
     {
+        $this->checkIntermittentFailure();
         return ["Course A", "Course B", "Course C"];
     }
 
@@ -1140,6 +1178,7 @@ class Demo extends AbstractBase
      */
     public function getNewItems($page, $limit, $daysOld, $fundId = null)
     {
+        $this->checkIntermittentFailure();
         // Pick a random number of results to return -- don't exceed limit or 30,
         // whichever is smaller (this can be pretty slow due to the random ID code).
         $count = rand(0, $limit > 30 ? 30 : $limit);
@@ -1174,6 +1213,7 @@ class Demo extends AbstractBase
      */
     public function findReserves($course, $inst, $dept)
     {
+        $this->checkIntermittentFailure();
         // Pick a random number of results to return -- don't exceed 30.
         $count = rand(0, 30);
         $results = [];
@@ -1206,6 +1246,7 @@ class Demo extends AbstractBase
      */
     public function cancelHolds($cancelDetails)
     {
+        $this->checkIntermittentFailure();
         // Rewrite the holds in the session, removing those the user wants to
         // cancel.
         $newHolds = new ArrayObject();
@@ -1269,6 +1310,7 @@ class Demo extends AbstractBase
      */
     public function cancelStorageRetrievalRequests($cancelDetails)
     {
+        $this->checkIntermittentFailure();
         // Rewrite the items in the session, removing those the user wants to
         // cancel.
         $newRequests = new ArrayObject();
@@ -1331,6 +1373,7 @@ class Demo extends AbstractBase
      */
     public function renewMyItems($renewDetails)
     {
+        $this->checkIntermittentFailure();
         // Simulate an account block at random.
         if ($this->checkRenewBlock()) {
             return [
@@ -1413,13 +1456,26 @@ class Demo extends AbstractBase
      * @param array  $data   An Array of item data
      * @param patron $patron An array of patron data
      *
-     * @return bool True if request is valid, false if not
+     * @return mixed An array of data on the request including
+     * whether or not it is valid and a status message. Alternatively a boolean
+     * true if request is valid, false if not.
      *
      * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function checkRequestIsValid($id, $data, $patron)
     {
-        return !$this->isFailing(__METHOD__, 10);
+        $this->checkIntermittentFailure();
+        if ($this->isFailing(__METHOD__, 10)) {
+            return [
+                'valid' => false,
+                'status' => rand() % 3 != 0
+                    ? 'hold_error_blocked' : 'Demonstrating a custom failure'
+            ];
+        }
+        return [
+            'valid' => true,
+            'status' => 'request_place_text'
+        ];
     }
 
     /**
@@ -1435,6 +1491,7 @@ class Demo extends AbstractBase
      */
     public function placeHold($holdDetails)
     {
+        $this->checkIntermittentFailure();
         // Simulate failure:
         if ($this->isFailing(__METHOD__, 50)) {
             return [
@@ -1514,16 +1571,27 @@ class Demo extends AbstractBase
      * @param array  $data   An Array of item data
      * @param patron $patron An array of patron data
      *
-     * @return bool True if request is valid, false if not
+     * @return mixed An array of data on the request including
+     * whether or not it is valid and a status message. Alternatively a boolean
+     * true if request is valid, false if not.
      *
      * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function checkStorageRetrievalRequestIsValid($id, $data, $patron)
     {
+        $this->checkIntermittentFailure();
         if (!$this->storageRetrievalRequests || $this->isFailing(__METHOD__, 10)) {
-            return false;
+            return [
+                'valid' => false,
+                'status' => rand() % 3 != 0
+                    ? 'storage_retrieval_request_error_blocked'
+                    : 'Demonstrating a custom failure'
+            ];
         }
-        return true;
+        return [
+            'valid' => true,
+            'status' => 'storage_retrieval_request_place_text'
+        ];
     }
 
     /**
@@ -1539,6 +1607,7 @@ class Demo extends AbstractBase
      */
     public function placeStorageRetrievalRequest($details)
     {
+        $this->checkIntermittentFailure();
         if (!$this->storageRetrievalRequests) {
             return [
                 "success" => false,
@@ -1617,16 +1686,26 @@ class Demo extends AbstractBase
      * @param array  $data   An Array of item data
      * @param patron $patron An array of patron data
      *
-     * @return bool True if request is valid, false if not
+     * @return mixed An array of data on the request including
+     * whether or not it is valid and a status message. Alternatively a boolean
+     * true if request is valid, false if not.
      *
      * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function checkILLRequestIsValid($id, $data, $patron)
     {
+        $this->checkIntermittentFailure();
         if (!$this->ILLRequests || $this->isFailing(__METHOD__, 10)) {
-            return false;
+            return [
+                'valid' => false,
+                'status' => rand() % 3 != 0
+                    ? 'ill_request_error_blocked' : 'Demonstrating a custom failure'
+            ];
         }
-        return true;
+        return [
+            'valid' => true,
+            'status' => 'ill_request_place_text'
+        ];
     }
 
     /**
@@ -1642,6 +1721,7 @@ class Demo extends AbstractBase
      */
     public function placeILLRequest($details)
     {
+        $this->checkIntermittentFailure();
         if (!$this->ILLRequests) {
             return [
                 'success' => false,
@@ -1746,6 +1826,7 @@ class Demo extends AbstractBase
      */
     public function getILLPickupLibraries($id, $patron)
     {
+        $this->checkIntermittentFailure();
         if (!$this->ILLRequests) {
             return false;
         }
@@ -1782,6 +1863,7 @@ class Demo extends AbstractBase
      */
     public function getILLPickupLocations($id, $pickupLib, $patron)
     {
+        $this->checkIntermittentFailure();
         switch ($pickupLib) {
         case 1:
             return [
@@ -1827,6 +1909,7 @@ class Demo extends AbstractBase
      */
     public function cancelILLRequests($cancelDetails)
     {
+        $this->checkIntermittentFailure();
         // Rewrite the items in the session, removing those the user wants to
         // cancel.
         $newRequests = new ArrayObject();
@@ -1889,6 +1972,7 @@ class Demo extends AbstractBase
      */
     public function changePassword($details)
     {
+        $this->checkIntermittentFailure();
         if (!$this->isFailing(__METHOD__, 33)) {
             return ['success' => true, 'status' => 'change_password_ok'];
         }
@@ -1912,6 +1996,7 @@ class Demo extends AbstractBase
      */
     public function getConfig($function, $params = null)
     {
+        $this->checkIntermittentFailure();
         if ($function == 'Holds') {
             return [
                 'HMACKeys' => 'id:item_id:level',
diff --git a/module/VuFind/src/VuFind/ILS/Driver/Factory.php b/module/VuFind/src/VuFind/ILS/Driver/Factory.php
index 8d6cdd8a21a76821be74ff9ff1b560220b768e7c..fbc4bde0ac8023372a5e10b7d75364a78a5b4d2f 100644
--- a/module/VuFind/src/VuFind/ILS/Driver/Factory.php
+++ b/module/VuFind/src/VuFind/ILS/Driver/Factory.php
@@ -146,7 +146,8 @@ class Factory
     {
         return new MultiBackend(
             $sm->getServiceLocator()->get('VuFind\Config'),
-            $sm->getServiceLocator()->get('VuFind\ILSAuthenticator')
+            $sm->getServiceLocator()->get('VuFind\ILSAuthenticator'),
+            $sm
         );
     }
 
@@ -192,7 +193,26 @@ class Factory
      */
     public static function getKohaILSDI(ServiceManager $sm)
     {
-        return new KohaILSDI($sm->getServiceLocator()->get('VuFind\DateConverter'));
+        $koha = new KohaILSDI($sm->getServiceLocator()->get('VuFind\DateConverter'));
+        $koha->setCacheStorage(
+            $sm->getServiceLocator()->get('VuFind\CacheManager')->getCache('object')
+        );
+        return $koha;
+    }
+
+    /**
+     * Factory for Symphony driver.
+     *
+     * @param ServiceManager $sm Service manager.
+     *
+     * @return Symphony
+     */
+    public static function getSymphony(ServiceManager $sm)
+    {
+        return new Symphony(
+            $sm->getServiceLocator()->get('VuFind\RecordLoader'),
+            $sm->getServiceLocator()->get('VuFind\CacheManager')
+        );
     }
 
     /**
diff --git a/module/VuFind/src/VuFind/ILS/Driver/Innovative.php b/module/VuFind/src/VuFind/ILS/Driver/Innovative.php
index 4f20df3c3253976704403dd245ef57cd5ce6d6cf..f4bee878da18588f75181680578757a75f9ae48b 100644
--- a/module/VuFind/src/VuFind/ILS/Driver/Innovative.php
+++ b/module/VuFind/src/VuFind/ILS/Driver/Innovative.php
@@ -105,7 +105,7 @@ class Innovative extends AbstractBase implements
         } else {
             // Return digits only.
             $id_ = substr($id, 1);
-        };
+        }
         return $id_;
     }
 
diff --git a/module/VuFind/src/VuFind/ILS/Driver/KohaILSDI.php b/module/VuFind/src/VuFind/ILS/Driver/KohaILSDI.php
index 81410180af61e2b6ff30cbb4c18fb865c9d2aa2c..52213208d6347b37d1b111b9c11dfe73cc625f98 100644
--- a/module/VuFind/src/VuFind/ILS/Driver/KohaILSDI.php
+++ b/module/VuFind/src/VuFind/ILS/Driver/KohaILSDI.php
@@ -29,7 +29,6 @@
 namespace VuFind\ILS\Driver;
 use PDO, PDOException;
 use VuFind\Exception\ILS as ILSException;
-use VuFindHttp\HttpServiceInterface;
 use Zend\Log\LoggerInterface;
 use VuFind\Exception\Date as DateException;
 
@@ -48,6 +47,9 @@ use VuFind\Exception\Date as DateException;
 class KohaILSDI extends \VuFind\ILS\Driver\AbstractBase implements
     \VuFindHttp\HttpServiceAwareInterface, \Zend\Log\LoggerAwareInterface
 {
+    use \VuFindHttp\HttpServiceAwareTrait;
+    use \VuFind\Log\LoggerAwareTrait;
+
     /**
      * Web services host
      *
@@ -107,57 +109,22 @@ class KohaILSDI extends \VuFind\ILS\Driver\AbstractBase implements
     protected $logger = false;
 
     /**
-     * Set the logger
-     *
-     * @param LoggerInterface $logger Logger to use.
-     *
-     * @return void
-     */
-    public function setLogger(LoggerInterface $logger)
-    {
-        $this->logger = $logger;
-    }
-
-    /**
-     * Show a debug message.
-     *
-     * @param string $msg Debug message.
-     *
-     * @return void
-     */
-    protected function debug($msg)
-    {
-        if ($this->logger) {
-            $this->logger->debug($msg);
-        }
-    }
-
-    /**
-     * HTTP service
+     * Date converter object
      *
-     * @var \VuFindHttp\HttpServiceInterface
+     * @var \VuFind\Date\Converter
      */
-    protected $httpService = null;
+    protected $dateConverter;
 
     /**
-     * Set the HTTP service to be used for HTTP requests.
-     *
-     * @param HttpServiceInterface $service HTTP service
+     * Constructor
      *
-     * @return void
+     * @param \VuFind\Date\Converter $dateConverter Date converter object
      */
-    public function setHttpService(HttpServiceInterface $service)
+    public function __construct(\VuFind\Date\Converter $dateConverter)
     {
-        $this->httpService = $service;
+        $this->dateConverter = $dateConverter;
     }
 
-    /**
-     * Date converter object
-     *
-     * @var \VuFind\Date\Converter
-     */
-    protected $dateConverter;
-
     /**
      * Initialize the driver.
      *
@@ -195,9 +162,6 @@ class KohaILSDI extends \VuFind\ILS\Driver\AbstractBase implements
             = isset($this->config['Other']['availableLocations'])
             ? $this->config['Other']['availableLocations'] : [];
 
-        // Create a dateConverter
-        $this->dateConverter = new \VuFind\Date\Converter;
-
         $this->debug("Config Summary:");
         $this->debug("DB Host: " . $this->host);
         $this->debug("ILS URL: " . $this->ilsBaseUrl);
@@ -239,12 +203,64 @@ class KohaILSDI extends \VuFind\ILS\Driver\AbstractBase implements
             $this->db->exec("SET NAMES utf8");
         } catch (PDOException $e) {
             $this->debug('Connection failed: ' . $e->getMessage());
-            throw new ILSException($e->getMessage);
+            throw new ILSException($e->getMessage());
         }
 
         $this->debug('Connected to DB');
     }
 
+    /**
+     * Check if a table exists in the current database.
+     *
+     * @param string $table Table to search for.
+     *
+     * @return bool
+     */
+    protected function tableExists($table)
+    {
+        $cacheKey = "kohailsdi-tables-$table";
+        $cachedValue = $this->getCachedData($cacheKey);
+        if ($cachedValue !== null) {
+            return $cachedValue;
+        }
+
+        if (!$this->db) {
+            $this->initDb();
+        }
+
+        $returnValue = false;
+
+        // Try a select statement against the table
+        // Run it in try/catch in case PDO is in ERRMODE_EXCEPTION.
+        try {
+            $result = $this->db->query("SELECT 1 FROM $table LIMIT 1");
+            // Result is FALSE (no table found) or PDOStatement Object (table found)
+            $returnValue = $result !== false;
+        } catch (PDOException $e) {
+            // We got an exception == table not found
+            $returnValue = false;
+        }
+
+        $this->putCachedData($cacheKey, $returnValue);
+        return $returnValue;
+    }
+
+    /**
+     * Koha ILS-DI driver specific override of method to ensure uniform cache keys
+     * for cached VuFind objects.
+     *
+     * @param string|null $suffix Optional suffix that will get appended to the
+     * object class name calling getCacheKey()
+     *
+     * @return string
+     */
+    protected function getCacheKey($suffix = null)
+    {
+        return \VuFind\ILS\Driver\AbstractBase::getCacheKey(
+            md5($this->ilsBaseUrl) . $suffix
+        );
+    }
+
     /**
      * Get Field
      *
@@ -310,7 +326,7 @@ class KohaILSDI extends \VuFind\ILS\Driver\AbstractBase implements
             $this->debug("XML is not valid, URL: $url");
 
             throw new ILSException(
-                "XML is not valid, URL: $url method: $method answer: $answer."
+                "XML is not valid, URL: $url method: $http_method answer: $answer."
             );
         }
         return $result;
@@ -463,6 +479,45 @@ class KohaILSDI extends \VuFind\ILS\Driver\AbstractBase implements
             if (!$this->db) {
                 $this->initDb();
             }
+            if (!$this->pickupEnableBranchcodes) {
+                // No defaultPickupLocation is defined in config
+                // AND no pickupLocations are defined either
+                if (isset($holdDetails['item_id']) && (empty($holdDetails['level'])
+                    || $holdDetails['level'] == 'item')
+                ) {
+                    // We try to get the actual branchcode the item is found at
+                    $item_id = $holdDetails['item_id'];
+                    $sql = "SELECT holdingbranch
+                            FROM items
+                            WHERE itemnumber=($item_id)";
+                    try {
+                        $sqlSt = $this->db->prepare($sql);
+                        $sqlSt->execute();
+                        $this->pickupEnableBranchcodes = $sqlSt->fetch();
+                    } catch (PDOException $e) {
+                            $this->debug('Connection failed: ' . $e->getMessage());
+                            throw new ILSException($e->getMessage());
+                    }
+                } elseif (!empty($holdDetails['level'])
+                    && $holdDetails['level'] == 'title'
+                ) {
+                    // We try to get the actual branchcodes the title is found at
+                    $id = $holdDetails['id'];
+                    $sql = "SELECT DISTINCT holdingbranch
+                            FROM items
+                            WHERE biblionumber=($id)";
+                    try {
+                        $sqlSt = $this->db->prepare($sql);
+                        $sqlSt->execute();
+                        foreach ($sqlSt->fetchAll() as $row) {
+                            $this->pickupEnableBranchcodes[] = $row['holdingbranch'];
+                        }
+                    } catch (PDOException $e) {
+                            $this->debug('Connection failed: ' . $e->getMessage());
+                            throw new ILSException($e->getMessage());
+                    }
+                }
+            }
             $branchcodes = "'" . implode(
                 "','", $this->pickupEnableBranchcodes
             ) . "'";
@@ -530,7 +585,6 @@ class KohaILSDI extends \VuFind\ILS\Driver\AbstractBase implements
      */
     public function placeHold($holdDetails)
     {
-        $rsvLst             = [];
         $patron             = $holdDetails['patron'];
         $patron_id          = $patron['id'];
         $request_location   = isset($patron['ip']) ? $patron['ip'] : "127.0.0.1";
@@ -565,6 +619,22 @@ class KohaILSDI extends \VuFind\ILS\Driver\AbstractBase implements
         $this->debug("Needed before date: " . $needed_before_date);
         $this->debug("Level: " . $level);
 
+        // The following check is mainly required for certain old buggy Koha versions
+        // that allowed multiple holds from the same user to the same item
+        $sql = "select count(*) as RCOUNT from reserves where borrowernumber = :rid "
+            . "and itemnumber = :iid";
+        $reservesSqlStmt = $this->db->prepare($sql);
+        $reservesSqlStmt->execute([':rid' => $patron_id, ':iid' => $item_id]);
+        $reservesCount = $reservesSqlStmt->fetch()["RCOUNT"];
+
+        if ($reservesCount > 0) {
+            $this->debug("Fatal error: Patron has already reserved this item.");
+            return [
+                "success" => false,
+                "sysMessage" => "It seems you have already reserved this item."
+            ];
+        }
+
         if ($level == "title") {
             $rqString = "HoldTitle&patron_id=$patron_id&bib_id=$bib_id"
                 . "&request_location=$request_location"
@@ -648,8 +718,7 @@ class KohaILSDI extends \VuFind\ILS\Driver\AbstractBase implements
         $holding = [];
         $available = true;
         $duedate = $status = '';
-        $loc = $shelf = '';
-        $reserves = "N";
+        $loc = '';
 
         $sql = "select i.itemnumber as ITEMNO, i.location,
             COALESCE(av.lib_opac,av.lib,av.authorised_value,i.location) AS LOCATION,
@@ -670,10 +739,16 @@ class KohaILSDI extends \VuFind\ILS\Driver\AbstractBase implements
             . "WHERE biblionumber = :id AND found IS NULL";
         $sqlWaitingReserve = "select count(*) as WAITING from reserves "
             . "WHERE itemnumber = :item_id and found = 'W'";
-        $sqlHoldings = "SELECT ExtractValue(( SELECT marcxml FROM biblioitems "
-            . "WHERE biblionumber = :id), "
-            . "'//datafield[@tag=\"866\"]/subfield[@code=\"a\"]') AS MFHD;";
-
+        if ($this->tableExists("biblio_metadata")) {
+            $sqlHoldings = "SELECT "
+                . "ExtractValue(( SELECT metadata FROM biblio_metadata "
+                . "WHERE biblionumber = :id AND format='marcxml'), "
+                . "'//datafield[@tag=\"866\"]/subfield[@code=\"a\"]') AS MFHD;";
+        } else {
+            $sqlHoldings = "SELECT ExtractValue(( SELECT marcxml FROM biblioitems "
+                . "WHERE biblionumber = :id), "
+               . "'//datafield[@tag=\"866\"]/subfield[@code=\"a\"]') AS MFHD;";
+        }
         if (!$this->db) {
             $this->initDb();
         }
@@ -838,16 +913,15 @@ class KohaILSDI extends \VuFind\ILS\Driver\AbstractBase implements
     /**
      * This method queries the ILS for new items
      *
-     * Comment for $fundID: (use a value returned by getFunds, or exclude for no
-     * limit); note that ?fund? may be a misnomer ? if funds are not an
-     * appropriate way to limit your new item results, you can return a different
-     * set of values from getFunds. The important thing is that this parameter
-     * supports an ID returned by getFunds, whatever that may mean.
-     *
-     * @param unknown $page    - page number of results to retrieve (starts at 1)
-     * @param unknown $limit   - the size of each page of results to retrieve
-     * @param unknown $daysOld - the maxi age of records to retrieve in days  -max 30
-     * @param string  $fundId  - optional fund ID to use for limiting results
+     * @param int $page    Page number of results to retrieve (counting starts at 1)
+     * @param int $limit   The size of each page of results to retrieve
+     * @param int $daysOld The maximum age of records to retrieve in days (max. 30)
+     * @param int $fundId  optional fund ID to use for limiting results (use a value
+     * returned by getFunds, or exclude for no limit); note that "fund" may be a
+     * misnomer - if funds are not an appropriate way to limit your new item
+     * results, you can return a different set of values from getFunds. The
+     * important thing is that this parameter supports an ID returned by getFunds,
+     * whatever that may mean.
      *
      * @return array provides a count and the results of new items.
      */
@@ -1410,12 +1484,23 @@ class KohaILSDI extends \VuFind\ILS\Driver\AbstractBase implements
             if (!$this->db) {
                 $this->initDb();
             }
-            $sql = "SELECT biblio.biblionumber AS biblionumber
+
+            if ($this->tableExists("biblio_metadata")) {
+                $sql = "SELECT biblio.biblionumber AS biblionumber
+                      FROM biblio
+                      JOIN biblio_metadata USING (biblionumber)
+                      WHERE ExtractValue(
+                        metadata, '//datafield[@tag=\"942\"]/subfield[@code=\"n\"]' )
+                        IN ('Y', '1')
+                      AND biblio_metadata.format = 'marcxml'";
+            } else {
+                $sql = "SELECT biblio.biblionumber AS biblionumber
                       FROM biblioitems
                       JOIN biblio USING (biblionumber)
                       WHERE ExtractValue(
-                         marcxml, '//datafield[@tag=\"942\"]/subfield[@code=\"n\"]' )
-                      IN ('Y', '1')";
+                        marcxml, '//datafield[@tag=\"942\"]/subfield[@code=\"n\"]' )
+                        IN ('Y', '1')";
+            }
             $sqlStmt = $this->db->prepare($sql);
             $sqlStmt->execute();
             $result = [];
@@ -1448,7 +1533,6 @@ class KohaILSDI extends \VuFind\ILS\Driver\AbstractBase implements
             }
             $sqlStmt = $this->db->prepare($sql);
             $sqlStmt->execute();
-            $result = [];
             foreach ($sqlStmt->fetchAll() as $rowItem) {
                 $deptList[$rowItem["abv"]] = $rowItem["DEPARTMENT"];
             }
@@ -1479,7 +1563,6 @@ class KohaILSDI extends \VuFind\ILS\Driver\AbstractBase implements
             }
             $sqlStmt = $this->db->prepare($sql);
             $sqlStmt->execute();
-            $result = [];
             foreach ($sqlStmt->fetchAll() as $rowItem) {
                 $instList[$rowItem["borrowernumber"]] = $rowItem["name"];
             }
@@ -1509,7 +1592,6 @@ class KohaILSDI extends \VuFind\ILS\Driver\AbstractBase implements
             }
             $sqlStmt = $this->db->prepare($sql);
             $sqlStmt->execute();
-            $result = [];
             foreach ($sqlStmt->fetchAll() as $rowItem) {
                 $courseList[$rowItem["course_id"]] = $rowItem["course"];
             }
@@ -1537,7 +1619,6 @@ class KohaILSDI extends \VuFind\ILS\Driver\AbstractBase implements
      */
     public function findReserves($course, $inst, $dept)
     {
-        $recordList = [];
         $reserveWhere = [];
         $bindParams = [];
         if ($course != '') {
@@ -1596,8 +1677,6 @@ class KohaILSDI extends \VuFind\ILS\Driver\AbstractBase implements
      */
     public function patronLogin($username, $password)
     {
-        $patron = [];
-
         //       $idObj = $this->makeRequest(
         //         "AuthenticatePatron" . "&username=" . $username
         //       . "&password=" . $password
diff --git a/module/VuFind/src/VuFind/ILS/Driver/MultiBackend.php b/module/VuFind/src/VuFind/ILS/Driver/MultiBackend.php
index 19dc073a2fabbf9656b8ad44ff79431267ea4e15..70c96e49a26167ab446ed939566681ebb3ca4f9f 100644
--- a/module/VuFind/src/VuFind/ILS/Driver/MultiBackend.php
+++ b/module/VuFind/src/VuFind/ILS/Driver/MultiBackend.php
@@ -4,7 +4,7 @@
  *
  * PHP version 5
  *
- * Copyright (C) The National Library of Finland 2012-2016.
+ * Copyright (C) The National Library of Finland 2012-2017.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2,
@@ -28,9 +28,7 @@
  */
 namespace VuFind\ILS\Driver;
 
-use VuFind\Exception\ILS as ILSException,
-    Zend\ServiceManager\ServiceLocatorAwareInterface,
-    Zend\ServiceManager\ServiceLocatorInterface;
+use VuFind\Exception\ILS as ILSException;
 
 /**
  * Multiple Backend Driver.
@@ -44,14 +42,11 @@ use VuFind\Exception\ILS as ILSException,
  * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
  * @link     https://vufind.org/wiki/development:plugins:ils_drivers Wiki
  */
-class MultiBackend extends AbstractBase
-    implements ServiceLocatorAwareInterface, \Zend\Log\LoggerAwareInterface
+class MultiBackend extends AbstractBase implements \Zend\Log\LoggerAwareInterface
 {
     use \VuFind\Log\LoggerAwareTrait {
         logError as error;
     }
-    use \Zend\ServiceManager\ServiceLocatorAwareTrait;
-
     /**
      * The array of configured driver names.
      *
@@ -97,21 +92,30 @@ class MultiBackend extends AbstractBase
     /**
      * ILS authenticator
      *
-     * @param \VuFind\Auth\ILSAuthenticator
+     * @var \VuFind\Auth\ILSAuthenticator
      */
     protected $ilsAuth;
 
+    /**
+     * ILS driver manager
+     *
+     * @var PluginManager
+     */
+    protected $driverManager;
+
     /**
      * Constructor
      *
      * @param \VuFind\Config\PluginManager  $configLoader Configuration loader
      * @param \VuFind\Auth\ILSAuthenticator $ilsAuth      ILS authenticator
+     * @param PluginManager                 $dm           ILS driver manager
      */
     public function __construct(\VuFind\Config\PluginManager $configLoader,
-        \VuFind\Auth\ILSAuthenticator $ilsAuth
+        \VuFind\Auth\ILSAuthenticator $ilsAuth, PluginManager $dm
     ) {
         $this->configLoader = $configLoader;
         $this->ilsAuth = $ilsAuth;
+        $this->driverManager = $dm;
     }
 
     /**
@@ -211,6 +215,12 @@ class MultiBackend extends AbstractBase
         $source = $this->getSource($id);
         $driver = $this->getDriver($source);
         if ($driver) {
+            // If the patron belongs to another source, just pass on an empty array
+            // to indicate that the patron has logged in but is not available for the
+            // current catalog.
+            if ($patron && $this->getSource($patron['cat_username']) !== $source) {
+                $patron = [];
+            }
             $holdings = $driver->getHolding(
                 $this->getLocalId($id),
                 $this->stripIdPrefixes($patron, $source)
@@ -550,9 +560,10 @@ class MultiBackend extends AbstractBase
         $source = $this->getSource($patron['cat_username']);
         $driver = $this->getDriver($source);
         if ($driver) {
-            if (!$this->methodSupported(
+            $supported = $this->methodSupported(
                 $driver, 'getMyStorageRetrievalRequests', compact('patron')
-            )) {
+            );
+            if (!$supported) {
                 // Return empty array if not supported by the driver
                 return [];
             }
@@ -573,7 +584,9 @@ class MultiBackend extends AbstractBase
      * @param array  $data   An Array of item data
      * @param patron $patron An array of patron data
      *
-     * @return bool True if request is valid, false if not
+     * @return mixed An array of data on the request including
+     * whether or not it is valid and a status message. Alternatively a boolean
+     * true if request is valid, false if not.
      */
     public function checkRequestIsValid($id, $data, $patron)
     {
@@ -604,7 +617,9 @@ class MultiBackend extends AbstractBase
      * @param array  $data   An Array of item data
      * @param patron $patron An array of patron data
      *
-     * @return bool True if request is valid, false if not
+     * @return mixed An array of data on the request including
+     * whether or not it is valid and a status message. Alternatively a boolean
+     * true if request is valid, false if not.
      */
     public function checkStorageRetrievalRequestIsValid($id, $data, $patron)
     {
@@ -701,21 +716,27 @@ class MultiBackend extends AbstractBase
     /**
      * Get request groups
      *
-     * @param int   $id     BIB ID
-     * @param array $patron Patron information returned by the patronLogin
+     * @param int   $id          BIB ID
+     * @param array $patron      Patron information returned by the patronLogin
      * method.
+     * @param array $holdDetails Optional array, only passed in when getting a list
+     * in the context of placing a hold; contains most of the same values passed to
+     * placeHold, minus the patron data.  May be used to limit the request group
+     * options or may be ignored.
      *
      * @return array  An array of associative arrays with requestGroupId and
      * name keys
      */
-    public function getRequestGroups($id, $patron)
+    public function getRequestGroups($id, $patron, $holdDetails = null)
     {
         $source = $this->getSource($id);
         $driver = $this->getDriver($source);
         if ($driver) {
             if ($this->getSource($patron['cat_username']) != $source
                 || !$this->methodSupported(
-                    $driver, 'getRequestGroups', compact('id', 'patron')
+                    $driver,
+                    'getRequestGroups',
+                    compact('id', 'patron', 'holdDetails')
                 )
             ) {
                 // Return empty array since the sources don't match or the method
@@ -724,7 +745,8 @@ class MultiBackend extends AbstractBase
             }
             $groups = $driver->getRequestGroups(
                 $this->stripIdPrefixes($id, $source),
-                $this->stripIdPrefixes($patron, $source)
+                $this->stripIdPrefixes($patron, $source),
+                $this->stripIdPrefixes($holdDetails, $source)
             );
             return $groups;
         }
@@ -942,7 +964,9 @@ class MultiBackend extends AbstractBase
      * @param array  $data   An Array of item data
      * @param patron $patron An array of patron data
      *
-     * @return bool True if request is valid, false if not
+     * @return mixed An array of data on the request including
+     * whether or not it is valid and a status message. Alternatively a boolean
+     * true if request is valid, false if not.
      */
     public function checkILLRequestIsValid($id, $data, $patron)
     {
@@ -1065,9 +1089,10 @@ class MultiBackend extends AbstractBase
         $source = $this->getSource($patron['cat_username']);
         $driver = $this->getDriver($source);
         if ($driver) {
-            if (!$this->methodSupported(
+            $supported = $this->methodSupported(
                 $driver, 'getMyILLRequests', compact('patron')
-            )) {
+            );
+            if (!$supported) {
                 // Return empty array if not supported by the driver
                 return [];
             }
@@ -1163,6 +1188,58 @@ class MultiBackend extends AbstractBase
         throw new ILSException('No suitable backend driver found');
     }
 
+    /**
+     * Check whether the patron is blocked from placing requests (holds/ILL/SRR).
+     *
+     * @param array $patron Patron data from patronLogin().
+     *
+     * @return mixed A boolean false if no blocks are in place and an array
+     * of block reasons if blocks are in place
+     */
+    public function getRequestBlocks($patron)
+    {
+        $source = $this->getSource($patron['cat_username']);
+        $driver = $this->getDriver($source);
+        if ($driver) {
+            $supported = $this->methodSupported(
+                $driver, 'getRequestBlocks', compact('patron')
+            );
+            if (!$supported) {
+                return false;
+            }
+            return $driver->getRequestBlocks(
+                $this->stripIdPrefixes($patron, $source)
+            );
+        }
+        throw new ILSException('No suitable backend driver found');
+    }
+
+    /**
+     * Check whether the patron has any blocks on their account.
+     *
+     * @param array $patron Patron data from patronLogin().
+     *
+     * @return mixed A boolean false if no blocks are in place and an array
+     * of block reasons if blocks are in place
+     */
+    public function getAccountBlocks($patron)
+    {
+        $source = $this->getSource($patron['cat_username']);
+        $driver = $this->getDriver($source);
+        if ($driver) {
+            $supported = $this->methodSupported(
+                $driver, 'getAccountBlocks', compact('patron')
+            );
+            if (!$supported) {
+                return false;
+            }
+            return $driver->getAccountBlocks(
+                $this->stripIdPrefixes($patron, $source)
+            );
+        }
+        throw new ILSException('No suitable backend driver found');
+    }
+
     /**
      * Function which specifies renew, hold and cancel settings.
      *
@@ -1254,7 +1331,7 @@ class MultiBackend extends AbstractBase
      *
      * @param string $id The id to be split
      *
-     * @return string  Source
+     * @return string Source
      */
     protected function getSource($id)
     {
@@ -1263,7 +1340,6 @@ class MultiBackend extends AbstractBase
             return substr($id, 0, $pos);
         }
 
-        $this->debug("Could not find source id in '$id'");
         return '';
     }
 
@@ -1296,9 +1372,6 @@ class MultiBackend extends AbstractBase
                 return $source;
             }
         }
-        $this->debug(
-            'Could not find source id in params: ' . print_r($params, true)
-        );
         return '';
     }
 
@@ -1350,7 +1423,7 @@ class MultiBackend extends AbstractBase
             $this->error("No configuration found for source '$source'");
             return null;
         }
-        $driverInst = clone($this->getServiceLocator()->get($driver));
+        $driverInst = clone($this->driverManager->get($driver));
         $driverInst->setConfig($config);
         $driverInst->init();
         return $driverInst;
diff --git a/module/VuFind/src/VuFind/ILS/Driver/NoILS.php b/module/VuFind/src/VuFind/ILS/Driver/NoILS.php
index 523ff210a03930419671cd6ce0d6f475f9e27887..f577f618c08a4ed921f77304ff2129725e2d5b61 100644
--- a/module/VuFind/src/VuFind/ILS/Driver/NoILS.php
+++ b/module/VuFind/src/VuFind/ILS/Driver/NoILS.php
@@ -379,4 +379,84 @@ class NoILS extends AbstractBase implements TranslatorAwareInterface
         // Block authentication:
         return null;
     }
+
+    /**
+     * Get Funds
+     *
+     * Return a list of funds which may be used to limit the getNewItems list.
+     *
+     * @throws ILSException
+     * @return array An associative array with key = fund ID, value = fund name.
+     */
+    public function getFunds()
+    {
+        // Does not work while ILS offline:
+        return [];
+    }
+
+    /**
+     * Get Departments
+     *
+     * Obtain a list of departments for use in limiting the reserves list.
+     *
+     * @throws ILSException
+     * @return array An associative array with key = dept. ID, value = dept. name.
+     */
+    public function getDepartments()
+    {
+        // Does not work while ILS offline:
+        return [];
+    }
+
+    /**
+     * Get Instructors
+     *
+     * Obtain a list of instructors for use in limiting the reserves list.
+     *
+     * @throws ILSException
+     * @return array An associative array with key = ID, value = name.
+     */
+    public function getInstructors()
+    {
+        // Does not work while ILS offline:
+        return [];
+    }
+
+    /**
+     * Get Courses
+     *
+     * Obtain a list of courses for use in limiting the reserves list.
+     *
+     * @throws ILSException
+     * @return array An associative array with key = ID, value = name.
+     */
+    public function getCourses()
+    {
+        // Does not work while ILS offline:
+        return [];
+    }
+
+    /**
+     * Find Reserves
+     *
+     * Obtain information on course reserves.
+     *
+     * This version of findReserves was contributed by Matthew Hooper and includes
+     * support for electronic reserves (though eReserve support is still a work in
+     * progress).
+     *
+     * @param string $course ID from getCourses (empty string to match all)
+     * @param string $inst   ID from getInstructors (empty string to match all)
+     * @param string $dept   ID from getDepartments (empty string to match all)
+     *
+     * @throws ILSException
+     * @return array An array of associative arrays representing reserve items.
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+     */
+    public function findReserves($course, $inst, $dept)
+    {
+        // Does not work while ILS offline:
+        return [];
+    }
 }
diff --git a/module/VuFind/src/VuFind/ILS/Driver/PAIA.php b/module/VuFind/src/VuFind/ILS/Driver/PAIA.php
index 31712d4e294b582f0541dfaeeeeeb46cef36900d..cef4b639b75a0a732cbc9c7483684a1729545348 100644
--- a/module/VuFind/src/VuFind/ILS/Driver/PAIA.php
+++ b/module/VuFind/src/VuFind/ILS/Driver/PAIA.php
@@ -335,7 +335,9 @@ class PAIA extends DAIA
                     isset($array_response['error_description'])
                         ? $array_response['error_description'] : ' '
             ];
-        } elseif ($array_response['patron'] === $post_data['patron']) {
+        } elseif (isset($array_response['patron'])
+            && $array_response['patron'] === $post_data['patron']
+        ) {
             // on success patron_id is returned
             $details = [
                 'success' => true,
@@ -624,9 +626,10 @@ class PAIA extends DAIA
     protected function getAdditionalFeeData($fee, $patron = null)
     {
         $additionalData = [];
-        // Add the item title using the about field,
-        // but only if this fee is caused by some item
-        if (isset($fee['item'])) {
+        // The title is always displayed to the user in fines view if no record can
+        // be found for current fee. So always populate the title with content of
+        // about field.
+        if (isset($fee['about'])) {
             $additionalData['title'] = $fee['about'];
         }
 
@@ -641,8 +644,6 @@ class PAIA extends DAIA
             ? $fee['about'] : null);
         $additionalData['item']       = (isset($fee['item'])
             ? $fee['item'] : null);
-        $additionalData['title']      = (isset($fee['title'])
-            ? $fee['title'] : null);
 
         return $additionalData;
     }
@@ -1230,6 +1231,86 @@ class PAIA extends DAIA
         return [];
     }
 
+    /**
+     * Map a PAIA document to an array for use in generating a VuFind request
+     * (holds, storage retrieval, etc).
+     *
+     * @param array $doc Array of PAIA document to be mapped.
+     *
+     * @return array
+     */
+    protected function getBasicDetails($doc)
+    {
+        $result = [];
+
+        // item (0..1) URI of a particular copy
+        $result['item_id'] = (isset($doc['item']) ? $doc['item'] : '');
+
+        $result['cancel_details']
+            = (isset($doc['cancancel']) && $doc['cancancel'])
+            ? $result['item_id'] : '';
+
+        // edition (0..1) URI of a the document (no particular copy)
+        // hook for retrieving alternative ItemId in case PAIA does not
+        // the needed id
+        $result['id'] = (isset($doc['edition'])
+            ? $this->getAlternativeItemId($doc['edition']) : '');
+
+        $result['type'] = $this->paiaStatusString($doc['status']);
+
+        // storage (0..1) textual description of location of the document
+        $result['location'] = (isset($doc['storage']) ? $doc['storage'] : null);
+
+        // queue (0..1) number of waiting requests for the document or item
+        $result['position'] =  (isset($doc['queue']) ? $doc['queue'] : null);
+
+        // only true if status == 4
+        $result['available'] = false;
+
+        // about (0..1) textual description of the document
+        $result['title'] = (isset($doc['about']) ? $doc['about'] : null);
+
+        // PAIA custom field
+        // label (0..1) call number, shelf mark or similar item label
+        $result['callnumber'] = $this->getCallNumber($doc);
+
+        /*
+         * meaning of starttime and endtime depends on status:
+         *
+         * status | starttime
+         *        | endtime
+         * -------+--------------------------------
+         * 0      | -
+         *        | -
+         * 1      | when the document was reserved
+         *        | when the reserved document is expected to be available
+         * 2      | when the document was ordered
+         *        | when the ordered document is expected to be available
+         * 3      | when the document was lend
+         *        | when the loan period ends or ended (due)
+         * 4      | when the document is provided
+         *        | when the provision will expire
+         * 5      | when the request was rejected
+         *        | -
+         */
+
+        $result['create'] = (isset($doc['starttime'])
+            ? $this->convertDatetime($doc['starttime']) : '');
+
+        // Optional VuFind fields
+        /*
+        $result['reqnum'] = null;
+        $result['volume'] =  null;
+        $result['publication_year'] = null;
+        $result['isbn'] = null;
+        $result['issn'] = null;
+        $result['oclc'] = null;
+        $result['upc'] = null;
+        */
+
+        return $result;
+    }
+
     /**
      * This PAIA helper function allows custom overrides for mapping of PAIA response
      * to getMyHolds data structure.
@@ -1243,61 +1324,7 @@ class PAIA extends DAIA
         $results = [];
 
         foreach ($items as $doc) {
-            $result = [];
-
-            // item (0..1) URI of a particular copy
-            $result['item_id'] = (isset($doc['item']) ? $doc['item'] : '');
-
-            $result['cancel_details']
-                = (isset($doc['cancancel']) && $doc['cancancel'])
-                ? $result['item_id'] : '';
-
-            // edition (0..1) URI of a the document (no particular copy)
-            // hook for retrieving alternative ItemId in case PAIA does not
-            // the needed id
-            $result['id'] = (isset($doc['edition'])
-                ? $this->getAlternativeItemId($doc['edition']) : '');
-
-            $result['type'] = $this->paiaStatusString($doc['status']);
-
-            // storage (0..1) textual description of location of the document
-            $result['location'] = (isset($doc['storage']) ? $doc['storage'] : null);
-
-            // queue (0..1) number of waiting requests for the document or item
-            $result['position'] =  (isset($doc['queue']) ? $doc['queue'] : null);
-
-            // only true if status == 4
-            $result['available'] = false;
-
-            // about (0..1) textual description of the document
-            $result['title'] = (isset($doc['about']) ? $doc['about'] : null);
-
-            // PAIA custom field
-            // label (0..1) call number, shelf mark or similar item label
-            $result['callnumber'] = $this->getCallNumber($doc);
-
-            /*
-             * meaning of starttime and endtime depends on status:
-             *
-             * status | starttime
-             *        | endtime
-             * -------+--------------------------------
-             * 0      | -
-             *        | -
-             * 1      | when the document was reserved
-             *        | when the reserved document is expected to be available
-             * 2      | when the document was ordered
-             *        | when the ordered document is expected to be available
-             * 3      | when the document was lend
-             *        | when the loan period ends or ended (due)
-             * 4      | when the document is provided
-             *        | when the provision will expire
-             * 5      | when the request was rejected
-             *        | -
-             */
-
-            $result['create'] = (isset($doc['starttime'])
-                ? $this->convertDatetime($doc['starttime']) : '');
+            $result = $this->getBasicDetails($doc);
 
             if ($doc['status'] == '4') {
                 $result['expire'] = (isset($doc['endtime'])
@@ -1310,23 +1337,11 @@ class PAIA extends DAIA
             // status: provided (the document is ready to be used by the patron)
             $result['available'] = $doc['status'] == 4 ? true : false;
 
-            // Optional VuFind fields
-            /*
-            $result['reqnum'] = null;
-            $result['volume'] =  null;
-            $result['publication_year'] = null;
-            $result['isbn'] = null;
-            $result['issn'] = null;
-            $result['oclc'] = null;
-            $result['upc'] = null;
-            */
-
             $results[] = $result;
 
         }
         return $results;
     }
-
     /**
      * This PAIA helper function allows custom overrides for mapping of PAIA response
      * to getMyStorageRetrievalRequests data structure.
@@ -1340,52 +1355,7 @@ class PAIA extends DAIA
         $results = [];
 
         foreach ($items as $doc) {
-            $result = [];
-
-            // item (0..1) URI of a particular copy
-            $result['item_id'] = (isset($doc['item']) ? $doc['item'] : '');
-
-            $result['cancel_details']
-                = (isset($doc['cancancel']) && $doc['cancancel'])
-                ? $result['item_id'] : '';
-
-            // edition (0..1) URI of a the document (no particular copy)
-            // hook for retrieving alternative ItemId in case PAIA does not
-            // the needed id
-            $result['id'] = (isset($doc['edition'])
-                ? $this->getAlternativeItemId($doc['edition']) : '');
-
-            $result['type'] = $this->paiaStatusString($doc['status']);
-
-            // storage (0..1) textual description of location of the document
-            $result['location'] = (isset($doc['storage']) ? $doc['storage'] : null);
-
-            // queue (0..1) number of waiting requests for the document or item
-            $result['position'] =  (isset($doc['queue']) ? $doc['queue'] : null);
-
-            // only true if status == 4
-            $result['available'] = false;
-
-            // about (0..1) textual description of the document
-            $result['title'] = (isset($doc['about']) ? $doc['about'] : null);
-
-            // PAIA custom field
-            // label (0..1) call number, shelf mark or similar item label
-            $result['callnumber'] = $this->getCallNumber($doc);
-
-            $result['create'] = (isset($doc['starttime'])
-                ? $this->convertDatetime($doc['starttime']) : '');
-
-            // Optional VuFind fields
-            /*
-            $result['reqnum'] = null;
-            $result['volume'] =  null;
-            $result['publication_year'] = null;
-            $result['isbn'] = null;
-            $result['issn'] = null;
-            $result['oclc'] = null;
-            $result['upc'] = null;
-            */
+            $result = $this->getBasicDetails($doc);
 
             $results[] = $result;
 
diff --git a/module/VuFind/src/VuFind/ILS/Driver/Symphony.php b/module/VuFind/src/VuFind/ILS/Driver/Symphony.php
index e34f7f06b7de727c846d89d2e8b98ba0575a7fb8..50235a8eba16e2a6c5c59868a728ea1ada6b1f5d 100644
--- a/module/VuFind/src/VuFind/ILS/Driver/Symphony.php
+++ b/module/VuFind/src/VuFind/ILS/Driver/Symphony.php
@@ -27,9 +27,12 @@
  * @link     https://vufind.org/wiki/development:plugins:ils_drivers Wiki
  */
 namespace VuFind\ILS\Driver;
-use SoapClient, SoapFault, SoapHeader, VuFind\Exception\ILS as ILSException,
-    Zend\ServiceManager\ServiceLocatorAwareInterface,
-    Zend\ServiceManager\ServiceLocatorInterface;
+use SoapClient;
+use SoapFault;
+use SoapHeader;
+use VuFind\Cache\Manager as CacheManager;
+use VuFind\Exception\ILS as ILSException;
+use VuFind\Record\Loader;
 use Zend\Log\LoggerAwareInterface;
 
 /**
@@ -42,11 +45,9 @@ use Zend\Log\LoggerAwareInterface;
  * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
  * @link     https://vufind.org/wiki/development:plugins:ils_drivers Wiki
  */
-class Symphony extends AbstractBase
-    implements ServiceLocatorAwareInterface, LoggerAwareInterface
+class Symphony extends AbstractBase implements LoggerAwareInterface
 {
     use \VuFind\Log\LoggerAwareTrait;
-    use \Zend\ServiceManager\ServiceLocatorAwareTrait;
 
     /**
      * Cache for policy information
@@ -62,6 +63,32 @@ class Symphony extends AbstractBase
      */
     protected $policies;
 
+    /**
+     * Cache manager
+     *
+     * @var CacheManager
+     */
+    protected $cacheManager;
+
+    /**
+     * Record loader
+     *
+     * @var Loader
+     */
+    protected $recordLoader;
+
+    /**
+     * Constructor
+     *
+     * @param Loader       $loader       Record loader
+     * @param CacheManager $cacheManager Cache manager (optional)
+     */
+    public function __construct(Loader $loader, CacheManager $cacheManager = null)
+    {
+        $this->recordLoader = $loader;
+        $this->cacheManager = $cacheManager;
+    }
+
     /**
      * Initialize the driver.
      *
@@ -120,13 +147,11 @@ class Symphony extends AbstractBase
         ];
 
         // Initialize cache manager.
-        if (isset($configArray['PolicyCache']['type'])) {
-            $serviceManager = $this->getServiceLocator()->getServiceLocator();
-            if ($serviceManager->has('VuFind\CacheManager')) {
-                $manager = $serviceManager->get('VuFind\CacheManager');
-                $this->policyCache
-                    = $manager->getCache($configArray['PolicyCache']['type']);
-            }
+        if (isset($configArray['PolicyCache']['type'])
+            && $this->cacheManager
+        ) {
+            $this->policyCache = $this->cacheManager
+                ->getCache($configArray['PolicyCache']['type']);
         }
     }
 
@@ -375,8 +400,7 @@ class Symphony extends AbstractBase
 
         $entryNumber = $this->config['999Holdings']['entry_number'];
 
-        $records = $this->getServiceLocator()->getServiceLocator()
-            ->get('VuFind\RecordLoader')->loadBatch($ids);
+        $records = $this->recordLoader->loadBatch($ids);
         foreach ($records as $record) {
             $results = $record->getFormattedMarcDetails($entryNumber, $marcMap);
             foreach ($results as $result) {
diff --git a/module/VuFind/src/VuFind/ILS/Driver/Virtua.php b/module/VuFind/src/VuFind/ILS/Driver/Virtua.php
index 2f56a89a8e20dda275f7fd397111c7f359fa40c6..a9377aca46d088ab1630c4feaa2c810fe03f7bb9 100644
--- a/module/VuFind/src/VuFind/ILS/Driver/Virtua.php
+++ b/module/VuFind/src/VuFind/ILS/Driver/Virtua.php
@@ -589,11 +589,9 @@ class Virtua extends AbstractBase implements \VuFindHttp\HttpServiceAwareInterfa
                         ) {
                             // ... can this user borrow on loan items at this
                             // location?
-                            if (in_array(
+                            $can_req = in_array(
                                 $location, $unavailable_locs[$item_loc_code]
-                            )) {
-                                $can_req = true;
-                            }
+                            );
                         }
                     } else {
                         // The item is NOT on loan ...
@@ -601,9 +599,8 @@ class Virtua extends AbstractBase implements \VuFindHttp\HttpServiceAwareInterfa
                         // ... and has a requestable status ...
                         if (in_array($item_stat_code, $status_list)) {
                             // ... can the user borrow status items at this location?
-                            if (in_array($location, $status_locs[$item_loc_code])) {
-                                $can_req = true;
-                            }
+                            $can_req
+                                = in_array($location, $status_locs[$item_loc_code]);
                         } else {
                             // ... and DOESN'T have a requestable status ...
                             if ($item_stat_code !== null) {
@@ -611,11 +608,9 @@ class Virtua extends AbstractBase implements \VuFindHttp\HttpServiceAwareInterfa
                             } else {
                                 // ... can the user borrow available items at this
                                 // location?
-                                if (in_array(
+                                $can_req = in_array(
                                     $location, $available_locs[$item_loc_code]
-                                )) {
-                                    $can_req = true;
-                                }
+                                );
                             }
                         }
                     }
diff --git a/module/VuFind/src/VuFind/ILS/Driver/Voyager.php b/module/VuFind/src/VuFind/ILS/Driver/Voyager.php
index 4d786a048df21739590b8eeb9aaa3723757d04b8..4f915b741354db7099eb4ccf36ad8759889c4deb 100644
--- a/module/VuFind/src/VuFind/ILS/Driver/Voyager.php
+++ b/module/VuFind/src/VuFind/ILS/Driver/Voyager.php
@@ -55,11 +55,11 @@ class Voyager extends AbstractBase
     }
 
     /**
-     * Database connection
+     * Lazily instantiated database connection. Use getDb() to access it.
      *
      * @var Oci8
      */
-    protected $db;
+    protected $lazyDb;
 
     /**
      * Name of database
@@ -138,43 +138,56 @@ class Voyager extends AbstractBase
         // Define Database Name
         $this->dbName = $this->config['Catalog']['database'];
 
-        // Based on the configuration file, use either "SID" or "SERVICE_NAME"
-        // to connect (correct value varies depending on Voyager's Oracle setup):
-        $connectType = isset($this->config['Catalog']['connect_with_sid']) &&
-            $this->config['Catalog']['connect_with_sid'] ?
-            'SID' : 'SERVICE_NAME';
-
-        $tns = '(DESCRIPTION=' .
-                 '(ADDRESS_LIST=' .
-                   '(ADDRESS=' .
-                     '(PROTOCOL=TCP)' .
-                     '(HOST=' . $this->config['Catalog']['host'] . ')' .
-                     '(PORT=' . $this->config['Catalog']['port'] . ')' .
-                   ')' .
-                 ')' .
-                 '(CONNECT_DATA=' .
-                   "({$connectType}={$this->config['Catalog']['service']})" .
-                 ')' .
-               ')';
-        try {
-            $this->db = new Oci8(
-                "oci:dbname=$tns;charset=US_ASCII",
-                $this->config['Catalog']['user'],
-                $this->config['Catalog']['password']
-            );
-            $this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
-        } catch (PDOException $e) {
-            $this->error(
-                "PDO Connection failed ($this->dbName): " . $e->getMessage()
-            );
-            throw new ILSException($e->getMessage());
-        }
-
         $this->useHoldingsSortGroups
             = isset($this->config['Holdings']['use_sort_groups'])
             ? $this->config['Holdings']['use_sort_groups'] : true;
     }
 
+    /**
+     * Initialize database connection if necessary and return it.
+     *
+     * @throws ILSException
+     * @return \PDO
+     */
+    protected function getDb()
+    {
+        if (null === $this->lazyDb) {
+            // Based on the configuration file, use either "SID" or "SERVICE_NAME"
+            // to connect (correct value varies depending on Voyager's Oracle setup):
+            $connectType = isset($this->config['Catalog']['connect_with_sid']) &&
+                $this->config['Catalog']['connect_with_sid'] ?
+                'SID' : 'SERVICE_NAME';
+
+            $tns = '(DESCRIPTION=' .
+                     '(ADDRESS_LIST=' .
+                       '(ADDRESS=' .
+                         '(PROTOCOL=TCP)' .
+                         '(HOST=' . $this->config['Catalog']['host'] . ')' .
+                         '(PORT=' . $this->config['Catalog']['port'] . ')' .
+                       ')' .
+                     ')' .
+                     '(CONNECT_DATA=' .
+                       "({$connectType}={$this->config['Catalog']['service']})" .
+                     ')' .
+                   ')';
+            try {
+                $this->lazyDb = new Oci8(
+                    "oci:dbname=$tns;charset=US7ASCII",
+                    $this->config['Catalog']['user'],
+                    $this->config['Catalog']['password']
+                );
+                $this->lazyDb
+                    ->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+            } catch (PDOException $e) {
+                $this->error(
+                    "PDO Connection failed ($this->dbName): " . $e->getMessage()
+                );
+                throw new ILSException($e->getMessage());
+            }
+        }
+        return $this->lazyDb;
+    }
+
     /**
      * Protected support method for building sql strings.
      *
@@ -336,7 +349,7 @@ class Voyager extends AbstractBase
     {
         // Expressions
         $sqlExpressions = [
-            "BIB_ITEM.BIB_ID", "ITEM.ITEM_ID",
+            "BIB_ITEM.BIB_ID", "ITEM.ITEM_ID",  "MFHD_MASTER.MFHD_ID",
             "ITEM.ON_RESERVE", "ITEM_STATUS_DESC as status",
             "NVL(LOCATION.LOCATION_DISPLAY_NAME, " .
                 "LOCATION.LOCATION_NAME) as location",
@@ -393,7 +406,7 @@ class Voyager extends AbstractBase
         // Expressions
         $sqlExpressions = [
             "BIB_MFHD.BIB_ID",
-            "1 as ITEM_ID", "'N' as ON_RESERVE",
+            "null as ITEM_ID", "MFHD_MASTER.MFHD_ID", "'N' as ON_RESERVE",
             "'No information available' as status",
             "NVL(LOCATION.LOCATION_DISPLAY_NAME, " .
                 "LOCATION.LOCATION_NAME) as location",
@@ -445,8 +458,10 @@ class Voyager extends AbstractBase
         $data = [];
 
         foreach ($sqlRows as $row) {
-            if (!isset($data[$row['ITEM_ID']])) {
-                $data[$row['ITEM_ID']] = [
+            $rowId = null !== $row['ITEM_ID']
+                ? $row['ITEM_ID'] : 'MFHD' . $row['MFHD_ID'];
+            if (!isset($data[$rowId])) {
+                $data[$rowId] = [
                     'id' => $row['BIB_ID'],
                     'status' => $row['STATUS'],
                     'status_array' => [$row['STATUS']],
@@ -461,10 +476,11 @@ class Voyager extends AbstractBase
                         : PHP_INT_MAX
                 ];
             } else {
-                if (!in_array(
-                    $row['STATUS'], $data[$row['ITEM_ID']]['status_array']
-                )) {
-                    $data[$row['ITEM_ID']]['status_array'][] = $row['STATUS'];
+                $statusFound = in_array(
+                    $row['STATUS'], $data[$rowId]['status_array']
+                );
+                if (!$statusFound) {
+                    $data[$rowId]['status_array'][] = $row['STATUS'];
                 }
             }
         }
@@ -590,6 +606,13 @@ class Voyager extends AbstractBase
     protected function getHoldingItemsSQL($id)
     {
         // Expressions
+        $returnDate = <<<EOT
+CASE WHEN ITEM_STATUS_TYPE.ITEM_STATUS_DESC = 'Discharged' THEN (
+  SELECT TO_CHAR(MAX(CIRC_TRANS_ARCHIVE.DISCHARGE_DATE), 'MM-DD-YY HH24:MI')
+    FROM $this->dbName.CIRC_TRANS_ARCHIVE
+    WHERE CIRC_TRANS_ARCHIVE.ITEM_ID = ITEM.ITEM_ID
+) ELSE NULL END RETURNDATE
+EOT;
         $sqlExpressions = [
             "BIB_ITEM.BIB_ID", "MFHD_ITEM.MFHD_ID",
             "ITEM_BARCODE.ITEM_BARCODE", "ITEM.ITEM_ID",
@@ -603,9 +626,7 @@ class Voyager extends AbstractBase
             "ITEM.PERM_LOCATION",
             "MFHD_MASTER.DISPLAY_CALL_NO as callnumber",
             "to_char(CIRC_TRANSACTIONS.CURRENT_DUE_DATE, 'MM-DD-YY') as duedate",
-            "(SELECT TO_CHAR(MAX(CIRC_TRANS_ARCHIVE.DISCHARGE_DATE), " .
-            "'MM-DD-YY HH24:MI') FROM $this->dbName.CIRC_TRANS_ARCHIVE " .
-            "WHERE CIRC_TRANS_ARCHIVE.ITEM_ID = ITEM.ITEM_ID) RETURNDATE",
+            $returnDate,
             "ITEM.ITEM_SEQUENCE_NUMBER",
             $this->getItemSortSequenceSQL('ITEM.PERM_LOCATION')
         ];
@@ -674,7 +695,7 @@ class Voyager extends AbstractBase
                 "LOCATION.LOCATION_NAME) as location",
             "MFHD_MASTER.DISPLAY_CALL_NO as callnumber",
             "BIB_MFHD.BIB_ID", "MFHD_MASTER.MFHD_ID",
-            "null as duedate", "0 AS TEMP_LOCATION",
+            "null as duedate", "null as RETURNDATE", "0 AS TEMP_LOCATION",
             "0 as PERM_LOCATION",
             "0 as ITEM_SEQUENCE_NUMBER",
             $this->getItemSortSequenceSQL('LOCATION.LOCATION_ID')
@@ -735,7 +756,8 @@ class Voyager extends AbstractBase
 
             // Concat wrapped rows (MARC data more than 300 bytes gets split
             // into multiple rows)
-            $rowId = isset($row['ITEM_ID']) ? $row['ITEM_ID'] : $row['MFHD_ID'];
+            $rowId = isset($row['ITEM_ID'])
+                ? $row['ITEM_ID'] : 'MFHD' . $row['MFHD_ID'];
             if (isset($data[$rowId][$number])) {
                 // We don't want to concatenate the same MARC information to
                 // itself over and over due to a record with multiple status
@@ -747,11 +769,14 @@ class Voyager extends AbstractBase
                 }
 
                 // If we've encountered a new status code, we should track it:
-                if (!in_array(
-                    $row['STATUS'], $record['STATUS_ARRAY']
-                )) {
+                if (!in_array($row['STATUS'], $record['STATUS_ARRAY'])) {
                     $record['STATUS_ARRAY'][] = $row['STATUS'];
                 }
+
+                // If we have a return date for this status, take it
+                if (null !== $row['RETURNDATE']) {
+                    $record['RETURNDATE'] = $row['RETURNDATE'];
+                }
             } else {
                 // This is the first time we've encountered this row number --
                 // initialize the row and start an array of statuses.
@@ -994,7 +1019,7 @@ class Voyager extends AbstractBase
      *
      * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
-    protected function processHoldingData($data, $id, $patron = false)
+    protected function processHoldingData($data, $id, $patron = null)
     {
         $holding = [];
 
@@ -1027,18 +1052,11 @@ class Voyager extends AbstractBase
                 }
                 $returnDate = false;
                 if (!empty($row['RETURNDATE'])) {
-                    $returnDate = $this->dateFormat->convertToDisplayDate(
-                        "m-d-y H:i", $row['RETURNDATE']
+                    $returnDate = $this->dateFormat->convertToDisplayDateAndTime(
+                        'm-d-y H:i', $row['RETURNDATE']
                     );
-                    $returnTime = $this->dateFormat->convertToDisplayTime(
-                        "m-d-y H:i", $row['RETURNDATE']
-                    );
-                    $returnDate .=  " " . $returnTime;
                 }
 
-                $returnDate = (in_array("Discharged", $row['STATUS_ARRAY']))
-                    ? $returnDate : false;
-
                 $requests_placed = isset($row['HOLDS_PLACED'])
                     ? $row['HOLDS_PLACED'] : 0;
                 if (isset($row['RECALLS_PLACED'])) {
@@ -1214,6 +1232,20 @@ class Voyager extends AbstractBase
                "WHERE PATRON.PATRON_ID = PATRON_BARCODE.PATRON_ID AND " .
                "lower(PATRON_BARCODE.PATRON_BARCODE) = :barcode";
 
+        // Limit the barcode statuses that allow logging in. By default only
+        // 1 (active) and 4 (expired) are allowed.
+        $allowedStatuses = preg_replace(
+            '/[^:\d]*/',
+            '',
+            isset($this->config['Catalog']['allowed_barcode_statuses'])
+                ? $this->config['Catalog']['allowed_barcode_statuses']
+                : '1:4'
+        );
+        if ($allowedStatuses) {
+            $sql .= ' AND PATRON_BARCODE.BARCODE_STATUS IN ('
+                . str_replace(':', ',', $allowedStatuses) . ')';
+        }
+
         try {
             $bindBarcode = strtolower(utf8_decode($barcode));
             $compareLogin = mb_strtolower($login, 'UTF-8');
@@ -2053,22 +2085,6 @@ class Voyager extends AbstractBase
         $limit = ($limit) ? $limit : 20;
         $bindParams[':startRow'] = (($page - 1) * $limit) + 1;
         $bindParams[':endRow'] = ($page * $limit);
-        /*
-        $sql = "select * from " .
-               "(select a.*, rownum rnum from " .
-               "(select LINE_ITEM.BIB_ID, BIB_TEXT.TITLE, FUND.FUND_NAME, " .
-               "LINE_ITEM.CREATE_DATE, LINE_ITEM_STATUS.LINE_ITEM_STATUS_DESC " .
-               "from $this->dbName.BIB_TEXT, $this->dbName.LINE_ITEM, " .
-               "$this->dbName.LINE_ITEM_COPY_STATUS, " .
-               "$this->dbName.LINE_ITEM_STATUS, $this->dbName.LINE_ITEM_FUNDS, " .
-               "$this->dbName.FUND " .
-               "where BIB_TEXT.BIB_ID = LINE_ITEM.BIB_ID " .
-               "and LINE_ITEM.LINE_ITEM_ID = LINE_ITEM_COPY_STATUS.LINE_ITEM_ID " .
-               "and LINE_ITEM_COPY_STATUS.COPY_ID = LINE_ITEM_FUNDS.COPY_ID " .
-               "and LINE_ITEM_STATUS.LINE_ITEM_STATUS = " .
-               "LINE_ITEM_COPY_STATUS.LINE_ITEM_STATUS " .
-               "and LINE_ITEM_FUNDS.FUND_ID = FUND.FUND_ID ";
-        */
         $sql = "select * from " .
                "(select a.*, rownum rnum from " .
                "(select LINE_ITEM.BIB_ID, LINE_ITEM.CREATE_DATE " .
@@ -2446,7 +2462,7 @@ class Voyager extends AbstractBase
             list(, $caller) = debug_backtrace(false);
             $this->debugSQL($caller['function'], $sql, $bind);
         }
-        $sqlStmt = $this->db->prepare($sql);
+        $sqlStmt = $this->getDb()->prepare($sql);
         $sqlStmt->execute($bind);
 
         return $sqlStmt;
diff --git a/module/VuFind/src/VuFind/ILS/Driver/VoyagerRestful.php b/module/VuFind/src/VuFind/ILS/Driver/VoyagerRestful.php
index 293258fe4b6ed37df6cf670dc350650ee3e02c09..bbae414af17e8c82dd0eb4d0ceee10c42de20c16 100644
--- a/module/VuFind/src/VuFind/ILS/Driver/VoyagerRestful.php
+++ b/module/VuFind/src/VuFind/ILS/Driver/VoyagerRestful.php
@@ -253,10 +253,10 @@ class VoyagerRestful extends Voyager implements \VuFindHttp\HttpServiceAwareInte
         }
         $this->holdCheckLimit
             = isset($this->config['Holds']['holdCheckLimit'])
-            ? $this->config['Holds']['holdCheckLimit'] : "15";
+            ? $this->config['Holds']['holdCheckLimit'] : '15';
         $this->callSlipCheckLimit
             = isset($this->config['StorageRetrievalRequests']['checkLimit'])
-            ? $this->config['StorageRetrievalRequests']['checkLimit'] : "15";
+            ? $this->config['StorageRetrievalRequests']['checkLimit'] : '15';
 
         $this->recallsEnabled
             = isset($this->config['Holds']['enableRecalls'])
@@ -354,7 +354,7 @@ class VoyagerRestful extends Voyager implements \VuFindHttp\HttpServiceAwareInte
 
         if (isset($this->config['Holds']['valid_hold_statuses'])) {
             $valid_hold_statuses_array
-                = explode(":", $this->config['Holds']['valid_hold_statuses']);
+                = explode(':', $this->config['Holds']['valid_hold_statuses']);
 
             if (count($valid_hold_statuses_array > 0)) {
                 foreach ($statusArray as $status) {
@@ -452,8 +452,8 @@ class VoyagerRestful extends Voyager implements \VuFindHttp\HttpServiceAwareInte
     protected function getHoldingItemsSQL($id)
     {
         $sqlArray = parent::getHoldingItemsSQL($id);
-        $sqlArray['expressions'][] = "ITEM.ITEM_TYPE_ID";
-        $sqlArray['expressions'][] = "ITEM.TEMP_ITEM_TYPE_ID";
+        $sqlArray['expressions'][] = 'ITEM.ITEM_TYPE_ID';
+        $sqlArray['expressions'][] = 'ITEM.TEMP_ITEM_TYPE_ID';
 
         return $sqlArray;
     }
@@ -477,11 +477,11 @@ class VoyagerRestful extends Voyager implements \VuFindHttp\HttpServiceAwareInte
      *
      * @param array  $data   Item Data
      * @param string $id     The BIB record id
-     * @param mixed  $patron Patron Data or boolean false
+     * @param array  $patron Patron Data
      *
      * @return array Keyed data
      */
-    protected function processHoldingData($data, $id, $patron = false)
+    protected function processHoldingData($data, $id, $patron = null)
     {
         $holding = parent::processHoldingData($data, $id, $patron);
 
@@ -510,26 +510,26 @@ class VoyagerRestful extends Voyager implements \VuFindHttp\HttpServiceAwareInte
             if ($is_holdable) {
                 // Hold Type - If we have patron data, we can use it to determine if
                 // a hold link should be shown
-                if ($patron && $this->holdsMode == "driver") {
+                if ($patron && $this->holdsMode == 'driver') {
                     // This limit is set as the api is slow to return results
-                    if ($i < $this->holdCheckLimit && $this->holdCheckLimit != "0") {
+                    if ($i < $this->holdCheckLimit && $this->holdCheckLimit != '0') {
                         $holdType = $this->determineHoldType(
                             $patron['id'], $row['id'], $row['item_id']
                         );
                         $addLink = $holdType ? $holdType : false;
                     } else {
-                        $holdType = "auto";
-                        $addLink = "check";
+                        $holdType = 'auto';
+                        $addLink = 'check';
                     }
                 } else {
-                    $holdType = "auto";
+                    $holdType = 'auto';
                 }
             }
 
             if ($isStorageRetrievalRequestAllowed) {
                 if ($patron) {
                     if ($i < $this->callSlipCheckLimit
-                        && $this->callSlipCheckLimit != "0"
+                        && $this->callSlipCheckLimit != '0'
                     ) {
                         $storageRetrieval = $this->checkItemRequests(
                             $patron['id'],
@@ -541,17 +541,18 @@ class VoyagerRestful extends Voyager implements \VuFindHttp\HttpServiceAwareInte
                             ? true
                             : false;
                     } else {
-                        $storageRetrieval = "auto";
-                        $addStorageRetrievalLink = "check";
+                        $storageRetrieval = 'auto';
+                        $addStorageRetrievalLink = 'check';
                     }
                 } else {
-                    $storageRetrieval = "auto";
+                    $storageRetrieval = 'auto';
                 }
             }
 
             $ILLRequest = '';
             $addILLRequestLink = false;
-            if ($patron && $isILLRequestAllowed) {
+            // Check only that a patron has logged in
+            if (null !== $patron && $isILLRequestAllowed) {
                 $ILLRequest = 'auto';
                 $addILLRequestLink = 'check';
             }
@@ -560,7 +561,7 @@ class VoyagerRestful extends Voyager implements \VuFindHttp\HttpServiceAwareInte
                 'is_holdable' => $is_holdable,
                 'holdtype' => $holdType,
                 'addLink' => $addLink,
-                'level' => "copy",
+                'level' => 'copy',
                 'storageRetrievalRequest' => $storageRetrieval,
                 'addStorageRetrievalRequestLink' => $addStorageRetrievalLink,
                 'ILLRequest' => $ILLRequest,
@@ -584,13 +585,13 @@ class VoyagerRestful extends Voyager implements \VuFindHttp\HttpServiceAwareInte
      */
     public function checkRequestIsValid($id, $data, $patron)
     {
-        $holdType = isset($data['holdtype']) ? $data['holdtype'] : "auto";
-        $level = isset($data['level']) ? $data['level'] : "copy";
-        $mode = ("title" == $level) ? $this->titleHoldsMode : $this->holdsMode;
-        if ("driver" == $mode && "auto" == $holdType) {
+        $holdType = isset($data['holdtype']) ? $data['holdtype'] : 'auto';
+        $level = isset($data['level']) ? $data['level'] : 'copy';
+        $mode = ('title' == $level) ? $this->titleHoldsMode : $this->holdsMode;
+        if ('driver' == $mode && 'auto' == $holdType) {
             $itemID = isset($data['item_id']) ? $data['item_id'] : false;
             $result = $this->determineHoldType($patron['id'], $id, $itemID);
-            if (!$result || $result == 'block') {
+            if (!$result) {
                 return false;
             }
         }
@@ -624,7 +625,7 @@ class VoyagerRestful extends Voyager implements \VuFindHttp\HttpServiceAwareInte
             return false;
         }
 
-        $level = isset($data['level']) ? $data['level'] : "copy";
+        $level = isset($data['level']) ? $data['level'] : 'copy';
         $itemID = ($level != 'title' && isset($data['item_id']))
             ? $data['item_id']
             : false;
@@ -733,8 +734,8 @@ class VoyagerRestful extends Voyager implements \VuFindHttp\HttpServiceAwareInte
             // Read results
             while ($row = $sqlStmt->fetch(PDO::FETCH_ASSOC)) {
                 $pickResponse[] = [
-                    "locationID" => $row['LOCATION_ID'],
-                    "locationDisplay" => utf8_encode($row['LOCATION_NAME'])
+                    'locationID' => $row['LOCATION_ID'],
+                    'locationDisplay' => utf8_encode($row['LOCATION_NAME'])
                 ];
             }
         }
@@ -840,113 +841,73 @@ class VoyagerRestful extends Voyager implements \VuFindHttp\HttpServiceAwareInte
     /**
      * Get request groups
      *
-     * @param int   $bibId  BIB ID
-     * @param array $patron Patron information returned by the patronLogin
+     * @param int   $bibId       BIB ID
+     * @param array $patron      Patron information returned by the patronLogin
      * method.
+     * @param array $holdDetails Optional array, only passed in when getting a list
+     * in the context of placing a hold; contains most of the same values passed to
+     * placeHold, minus the patron data.  May be used to limit the request group
+     * options or may be ignored.
      *
      * @return array False if request groups not in use or an array of
      * associative arrays with id and name keys
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
-    public function getRequestGroups($bibId, $patron)
+    public function getRequestGroups($bibId, $patron, $holdDetails = null)
     {
         if (!$this->requestGroupsEnabled) {
             return false;
         }
 
-        if ($this->checkItemsExist) {
-            // First get hold information for the list of items Voyager
-            // thinks are holdable
-            $request = $this->determineHoldType($patron['id'], $bibId);
-            if ($request != 'hold' && $request != 'recall') {
-                return false;
-            }
-
-            $hierarchy = [];
-
-            // Build Hierarchy
-            $hierarchy['record'] = $bibId;
-            $hierarchy[$request] = false;
-
-            // Add Required Params
-            $params = [
-                "patron" => $patron['id'],
-                "patron_homedb" => $this->ws_patronHomeUbId,
-                "view" => "full"
-            ];
-
-            $results = $this->makeRequest($hierarchy, $params, "GET", false);
-
-            if ($results === false) {
-                throw new ILSException('Could not fetch hold information');
-            }
+        $sqlExpressions = [
+            'rg.GROUP_ID',
+            'rg.GROUP_NAME',
+        ];
+        $sqlFrom = [
+            "$this->dbName.REQUEST_GROUP rg"
 
-            $items = [];
-            foreach ($results->$request as $hold) {
-                foreach ($hold->items->item as $item) {
-                    $items[(string)$item->item_id] = 1;
-                }
-            }
+        ];
+        $sqlWhere = [];
+        $sqlBind = [];
+
+        if ($this->pickupLocationsInRequestGroup) {
+            // Limit to request groups that have valid pickup locations
+            $sqlWhere[] = <<<EOT
+rg.GROUP_ID IN (
+  SELECT rgl.GROUP_ID
+  FROM $this->dbName.REQUEST_GROUP_LOCATION rgl
+  WHERE rgl.LOCATION_ID IN (
+    SELECT cpl.LOCATION_ID
+    FROM $this->dbName.CIRC_POLICY_LOCS cpl
+    WHERE cpl.PICKUP_LOCATION='Y'
+  )
+)
+EOT;
         }
 
-        // Find request groups (with items if item check is enabled)
         if ($this->checkItemsExist) {
-            $sqlExpressions = [
-                'rg.GROUP_ID',
-                'rg.GROUP_NAME',
-                'bi.ITEM_ID'
-            ];
-
-            $sqlFrom = [
-                "$this->dbName.BIB_ITEM bi",
-                "$this->dbName.MFHD_ITEM mi",
-                "$this->dbName.MFHD_MASTER mm",
-                "$this->dbName.REQUEST_GROUP rg",
-                "$this->dbName.REQUEST_GROUP_LOCATION rgl",
-            ];
-
-            $sqlWhere = [
-                'bi.BIB_ID=:bibId',
-                'mi.ITEM_ID=bi.ITEM_ID',
-                'mm.MFHD_ID=mi.MFHD_ID',
-                'rgl.LOCATION_ID=mm.LOCATION_ID',
-                'rg.GROUP_ID=rgl.GROUP_ID'
-            ];
-
-            $sqlBind = [
-                'bibId' => $bibId
-            ];
-        } else {
-            $sqlExpressions = [
-                'rg.GROUP_ID',
-                'rg.GROUP_NAME',
-            ];
-
-            $sqlFrom = [
-                "$this->dbName.REQUEST_GROUP rg",
-                "$this->dbName.REQUEST_GROUP_LOCATION rgl"
-            ];
-
-            $sqlWhere = [
-                'rg.GROUP_ID=rgl.GROUP_ID'
-            ];
-
-            $sqlBind = [
-            ];
-
-            if ($this->pickupLocationsInRequestGroup) {
-                // Limit to request groups that have valid pickup locations
-                $sqlFrom[] = "$this->dbName.REQUEST_GROUP_LOCATION rgl";
-                $sqlFrom[] = "$this->dbName.CIRC_POLICY_LOCS cpl";
-
-                $sqlWhere[] = "rgl.GROUP_ID=rg.GROUP_ID";
-                $sqlWhere[] = "cpl.LOCATION_ID=rgl.LOCATION_ID";
-                $sqlWhere[] = "cpl.PICKUP_LOCATION='Y'";
-            }
+            $sqlWhere[] = <<<EOT
+rg.GROUP_ID IN (
+  SELECT rgl.GROUP_ID
+  FROM $this->dbName.REQUEST_GROUP_LOCATION rgl
+  WHERE rgl.LOCATION_ID IN (
+    SELECT mm.LOCATION_ID FROM $this->dbName.MFHD_MASTER mm
+    WHERE mm.SUPPRESS_IN_OPAC='N'
+    AND mm.MFHD_ID IN (
+      SELECT mi.MFHD_ID
+      FROM $this->dbName.MFHD_ITEM mi, $this->dbName.BIB_ITEM bi
+      WHERE mi.ITEM_ID = bi.ITEM_ID AND bi.BIB_ID=:bibId
+    )
+  )
+)
+EOT;
+            $sqlBind['bibId'] = $bibId;
         }
 
         if ($this->checkItemsNotAvailable) {
-
-            // Build inner query first
+            // Build first the inner query that return item statuses for all request
+            // groups
             $subExpressions = [
                 'sub_rgl.GROUP_ID',
                 'sub_i.ITEM_ID',
@@ -968,7 +929,8 @@ class VoyagerRestful extends Voyager implements \VuFindHttp\HttpServiceAwareInte
                 'sub_ist.ITEM_ID=sub_i.ITEM_ID',
                 'sub_mi.ITEM_ID=sub_i.ITEM_ID',
                 'sub_mm.MFHD_ID=sub_mi.MFHD_ID',
-                'sub_rgl.LOCATION_ID=sub_mm.LOCATION_ID'
+                'sub_rgl.LOCATION_ID=sub_mm.LOCATION_ID',
+                "sub_mm.SUPPRESS_IN_OPAC='N'"
             ];
 
             $subGroup = [
@@ -988,9 +950,28 @@ class VoyagerRestful extends Voyager implements \VuFindHttp\HttpServiceAwareInte
 
             $subSql = $this->buildSqlFromArray($subArray);
 
-            $sqlWhere[] = "not exists (select status.GROUP_ID from " .
-                "({$subSql['string']}) status where status.status=1 " .
-                "and status.GROUP_ID = rgl.GROUP_ID)";
+            $itemWhere = <<<EOT
+rg.GROUP_ID NOT IN (
+  SELECT status.GROUP_ID
+  FROM ({$subSql['string']}) status
+  WHERE status.status=1
+)
+EOT;
+
+            $key = 'disableAvailabilityCheckForRequestGroups';
+            if (isset($this->config['Holds'][$key])) {
+                $disabledGroups = array_map(
+                    function ($s) {
+                        return preg_replace('/[^\d]*/', '', $s);
+                    },
+                    explode(':', $this->config['Holds'][$key])
+                );
+                if ($disabledGroups) {
+                    $itemWhere = "($itemWhere OR rg.GROUP_ID IN ("
+                        . implode(',', $disabledGroups) . '))';
+                }
+            }
+            $sqlWhere[] = $itemWhere;
         }
 
         $sqlArray = [
@@ -1008,16 +989,12 @@ class VoyagerRestful extends Voyager implements \VuFindHttp\HttpServiceAwareInte
             throw new ILSException($e->getMessage());
         }
 
-        $groups = [];
-        while ($row = $sqlStmt->fetch(PDO::FETCH_ASSOC)) {
-            if (!$this->checkItemsExist || isset($items[$row['ITEM_ID']])) {
-                $groups[$row['GROUP_ID']] = utf8_encode($row['GROUP_NAME']);
-            }
-        }
-
         $results = [];
-        foreach ($groups as $groupId => $groupName) {
-            $results[] = ['id' => $groupId, 'name' => $groupName];
+        while ($row = $sqlStmt->fetch(PDO::FETCH_ASSOC)) {
+            $results[] = [
+                'id' => $row['GROUP_ID'],
+                'name' => utf8_encode($row['GROUP_NAME'])
+            ];
         }
 
         // Sort request groups
@@ -1040,7 +1017,7 @@ class VoyagerRestful extends Voyager implements \VuFindHttp\HttpServiceAwareInte
      * @throws ILSException
      * @return obj  A Simple XML Object loaded with the xml data returned by the API
      */
-    protected function makeRequest($hierarchy, $params = false, $mode = "GET",
+    protected function makeRequest($hierarchy, $params = false, $mode = 'GET',
         $xml = false
     ) {
         // Build Url Base
@@ -1049,20 +1026,20 @@ class VoyagerRestful extends Voyager implements \VuFindHttp\HttpServiceAwareInte
         // Add Hierarchy
         foreach ($hierarchy as $key => $value) {
             $hierarchyString[] = ($value !== false)
-                ? urlencode($key) . "/" . urlencode($value) : urlencode($key);
+                ? urlencode($key) . '/' . urlencode($value) : urlencode($key);
         }
 
         // Add Params
         $queryString = [];
         foreach ($params as $key => $param) {
-            $queryString[] = urlencode($key) . "=" . urlencode($param);
+            $queryString[] = urlencode($key) . '=' . urlencode($param);
         }
 
         // Build Hierarchy
-        $urlParams .= "/" . implode("/", $hierarchyString);
+        $urlParams .= '/' . implode('/', $hierarchyString);
 
         // Build Params
-        $urlParams .= "?" . implode("&", $queryString);
+        $urlParams .= '?' . implode('&', $queryString);
 
         // Create Proxy Request
         $client = $this->httpService->createClient($urlParams);
@@ -1085,7 +1062,15 @@ class VoyagerRestful extends Voyager implements \VuFindHttp\HttpServiceAwareInte
 
         // Send Request and Retrieve Response
         $startTime = microtime(true);
-        $result = $client->setMethod($mode)->send();
+        try {
+            $result = $client->setMethod($mode)->send();
+        } catch (\Exception $e) {
+            $this->error(
+                "$mode request for '$urlParams' with contents '$xml' failed: "
+                . $e->getMessage()
+            );
+            throw new ILSException('Problem with RESTful API.');
+        }
         if (!$result->isSuccess()) {
             $this->error(
                 "$mode request for '$urlParams' with contents '$xml' failed: "
@@ -1128,7 +1113,7 @@ class VoyagerRestful extends Voyager implements \VuFindHttp\HttpServiceAwareInte
      */
     protected function encodeXML($string)
     {
-        return htmlspecialchars($string, ENT_COMPAT, "UTF-8");
+        return htmlspecialchars($string, ENT_COMPAT, 'UTF-8');
     }
 
     /**
@@ -1142,22 +1127,22 @@ class VoyagerRestful extends Voyager implements \VuFindHttp\HttpServiceAwareInte
      */
     protected function buildBasicXML($xml)
     {
-        $xmlString = "";
+        $xmlString = '';
 
         foreach ($xml as $root => $nodes) {
-            $xmlString .= "<" . $root . ">";
+            $xmlString .= '<' . $root . '>';
 
             foreach ($nodes as $nodeName => $nodeValue) {
-                $xmlString .= "<" . $nodeName . ">";
+                $xmlString .= '<' . $nodeName . '>';
                 $xmlString .= $this->encodeXML($nodeValue);
                 // Split out any attributes
                 $nodeName = strtok($nodeName, ' ');
-                $xmlString .= "</" . $nodeName . ">";
+                $xmlString .= '</' . $nodeName . '>';
             }
 
             // Split out any attributes
             $root = strtok($root, ' ');
-            $xmlString .= "</" . $root . ">";
+            $xmlString .= '</' . $root . '>';
         }
 
         $xmlComplete = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" . $xmlString;
@@ -1187,6 +1172,32 @@ class VoyagerRestful extends Voyager implements \VuFindHttp\HttpServiceAwareInte
         return $blockReason;
     }
 
+    /**
+     * Check whether the patron is blocked from placing requests (holds/ILL/SRR).
+     *
+     * @param array $patron Patron data from patronLogin().
+     *
+     * @return mixed A boolean false if no blocks are in place and an array
+     * of block reasons if blocks are in place
+     */
+    public function getRequestBlocks($patron)
+    {
+        return $this->checkAccountBlocks($patron['id']);
+    }
+
+    /**
+     * Check whether the patron has any blocks on their account.
+     *
+     * @param array $patron Patron data from patronLogin().
+     *
+     * @return mixed A boolean false if no blocks are in place and an array
+     * of block reasons if blocks are in place
+     */
+    public function getAccountBlocks($patron)
+    {
+        return $this->checkAccountBlocks($patron['id']);
+    }
+
     /**
      * Check Account Blocks
      *
@@ -1205,19 +1216,19 @@ class VoyagerRestful extends Voyager implements \VuFindHttp\HttpServiceAwareInte
         if (null === $blockReason) {
             // Build Hierarchy
             $hierarchy = [
-                "patron" =>  $patronId,
-                "patronStatus" => "blocks"
+                'patron' =>  $patronId,
+                'patronStatus' => 'blocks'
             ];
 
             // Add Required Params
             $params = [
-                "patron_homedb" => $this->ws_patronHomeUbId,
-                "view" => "full"
+                'patron_homedb' => $this->ws_patronHomeUbId,
+                'view' => 'full'
             ];
 
             $blocks = $this->makeRequest($hierarchy, $params);
             if ($blocks
-                && (string)$blocks->{'reply-text'} == "ok"
+                && (string)$blocks->{'reply-text'} == 'ok'
                 && isset($blocks->blocks->institution->borrowingBlock)
             ) {
                 $blockReason = $this->extractBlockReasons(
@@ -1372,7 +1383,7 @@ EOT;
                     $dueDate = (string)$chargedItem->dueDate;
                     try {
                         $newDate = $this->dateFormat->convertToDisplayDate(
-                            "Y-m-d H:i", $dueDate
+                            'Y-m-d H:i', $dueDate
                         );
                         $response['new_date'] = $newDate;
                     } catch (DateException $e) {
@@ -1381,7 +1392,7 @@ EOT;
                     }
                     try {
                         $newTime = $this->dateFormat->convertToDisplayTime(
-                            "Y-m-d H:i", $dueDate
+                            'Y-m-d H:i', $dueDate
                         );
                         $response['new_time'] = $newTime;
                     } catch (DateException $e) {
@@ -1429,24 +1440,24 @@ EOT;
 
             // Add Required Params
             $params = [
-                "patron" => $patronId,
-                "patron_homedb" => $this->ws_patronHomeUbId,
-                "view" => "full"
+                'patron' => $patronId,
+                'patron_homedb' => $this->ws_patronHomeUbId,
+                'view' => 'full'
             ];
 
-            $check = $this->makeRequest($hierarchy, $params, "GET", false);
+            $check = $this->makeRequest($hierarchy, $params, 'GET', false);
 
             if ($check) {
                 // Process
                 $check = $check->children();
-                $node = "reply-text";
+                $node = 'reply-text';
                 $reply = (string)$check->$node;
 
                 // Valid Response
-                if ($reply == "ok") {
+                if ($reply == 'ok') {
                     if ($check->$request) {
                         $requestAttributes = $check->$request->attributes();
-                        if ($requestAttributes['allowed'] == "Y") {
+                        if ($requestAttributes['allowed'] == 'Y') {
                             return true;
                         }
                     }
@@ -1473,7 +1484,7 @@ EOT;
         if (empty($patron) || empty($requestData) || empty($requestData['bibId'])
             || empty($type)
         ) {
-            return ['success' => false, 'status' => "hold_error_fail"];
+            return ['success' => false, 'status' => 'hold_error_fail'];
         }
 
         // Build request
@@ -1576,20 +1587,20 @@ EOT;
 
         // Check for account Blocks
         if ($this->checkAccountBlocks($patronId)) {
-            return "block";
+            return false;
         }
 
         // Check Recalls First
         if ($this->recallsEnabled) {
-            $recall = $this->checkItemRequests($patronId, "recall", $bibId, $itemId);
+            $recall = $this->checkItemRequests($patronId, 'recall', $bibId, $itemId);
             if ($recall) {
-                return "recall";
+                return 'recall';
             }
         }
         // Check Holds
-        $hold = $this->checkItemRequests($patronId, "hold", $bibId, $itemId);
+        $hold = $this->checkItemRequests($patronId, 'hold', $bibId, $itemId);
         if ($hold) {
-            return "hold";
+            return 'hold';
         }
         return false;
     }
@@ -1606,20 +1617,21 @@ EOT;
     protected function holdError($msg)
     {
         return [
-                    "success" => false,
-                    "sysMessage" => $msg
+            'success' => false,
+            'sysMessage' => $msg
         ];
     }
 
     /**
-     * Check whether the given patron has the given bib record on loan.
+     * Check whether the given patron has the given bib record or its item on loan.
      *
      * @param int $patronId Patron ID
-     * @param int $bibId    BIB ID
+     * @param int $bibId    Bib ID
+     * @param int $itemId   Item ID (optional)
      *
      * @return bool
      */
-    protected function isRecordOnLoan($patronId, $bibId)
+    protected function isRecordOnLoan($patronId, $bibId, $itemId = null)
     {
         $sqlExpressions = [
             'count(cta.ITEM_ID) CNT'
@@ -1644,10 +1656,16 @@ EOT;
             $sqlWhere[] = 'mi.ITEM_ID=cta.ITEM_ID';
             $sqlWhere[] = 'mm.MFHD_ID=mi.MFHD_ID';
             $sqlWhere[] = 'rgl.LOCATION_ID=mm.LOCATION_ID';
+            $sqlWhere[] = "mm.SUPPRESS_IN_OPAC='N'";
         }
 
         $sqlBind = ['patronId' => $patronId, 'bibId' => $bibId];
 
+        if (null !== $itemId) {
+            $sqlWhere[] = 'cta.ITEM_ID=:itemId';
+            $sqlBind['itemId'] = $itemId;
+        }
+
         $sqlArray = [
             'expressions' => $sqlExpressions,
             'from' => $sqlFrom,
@@ -1691,7 +1709,8 @@ EOT;
             'bi.BIB_ID=:bibId',
             'i.ITEM_ID=bi.ITEM_ID',
             'mi.ITEM_ID=i.ITEM_ID',
-            'mm.MFHD_ID=mi.MFHD_ID'
+            'mm.MFHD_ID=mi.MFHD_ID',
+            "mm.SUPPRESS_IN_OPAC='N'"
         ];
 
         if ($this->excludedItemLocations) {
@@ -1756,7 +1775,8 @@ EOT;
             'i.ITEM_ID=bi.ITEM_ID',
             'ist.ITEM_ID=i.ITEM_ID',
             'mi.ITEM_ID=i.ITEM_ID',
-            'mm.MFHD_ID=mi.MFHD_ID'
+            'mm.MFHD_ID=mi.MFHD_ID',
+            "mm.SUPPRESS_IN_OPAC='N'"
         ];
 
         if ($this->excludedItemLocations) {
@@ -1919,9 +1939,9 @@ EOT;
     {
         $patron = $holdDetails['patron'];
         $type = isset($holdDetails['holdtype']) && !empty($holdDetails['holdtype'])
-            ? $holdDetails['holdtype'] : "auto";
+            ? $holdDetails['holdtype'] : 'auto';
         $level = isset($holdDetails['level']) && !empty($holdDetails['level'])
-            ? $holdDetails['level'] : "copy";
+            ? $holdDetails['level'] : 'copy';
         $pickUpLocation = !empty($holdDetails['pickUpLocation'])
             ? $holdDetails['pickUpLocation'] : $this->defaultPickUpLocation;
         $itemId = isset($holdDetails['item_id']) ? $holdDetails['item_id'] : false;
@@ -1930,26 +1950,26 @@ EOT;
 
         // Request was initiated before patron was logged in -
         // Let's determine Hold Type now
-        if ($type == "auto") {
+        if ($type == 'auto') {
             $type = $this->determineHoldType($patron['id'], $bibId, $itemId);
-            if (!$type || $type == "block") {
-                return $this->holdError("hold_error_blocked");
+            if (!$type) {
+                return $this->holdError('hold_error_blocked');
             }
         }
 
         // Convert last interest date from Display Format to Voyager required format
         try {
             $lastInterestDate = $this->dateFormat->convertFromDisplayDate(
-                "Y-m-d", $holdDetails['requiredBy']
+                'Y-m-d', $holdDetails['requiredBy']
             );
         } catch (DateException $e) {
             // Hold Date is invalid
-            return $this->holdError("hold_date_invalid");
+            return $this->holdError('hold_date_invalid');
         }
 
         try {
             $checkTime =  $this->dateFormat->convertFromDisplayDate(
-                "U", $holdDetails['requiredBy']
+                'U', $holdDetails['requiredBy']
             );
             if (!is_numeric($checkTime)) {
                 throw new DateException('Result should be numeric');
@@ -1960,12 +1980,12 @@ EOT;
 
         if (time() > $checkTime) {
             // Hold Date is in the past
-            return $this->holdError("hold_date_past");
+            return $this->holdError('hold_date_past');
         }
 
         // Make Sure Pick Up Library is Valid
         if (!$this->pickUpLocationIsValid($pickUpLocation, $patron, $holdDetails)) {
-            return $this->holdError("hold_invalid_pickup");
+            return $this->holdError('hold_invalid_pickup');
         }
 
         if ($this->requestGroupsEnabled && !$itemId
@@ -2009,7 +2029,9 @@ EOT;
 
         // Optional check that the patron doesn't already have the bib on loan
         if ($this->checkLoans) {
-            if ($this->isRecordOnLoan($patron['id'], $bibId)) {
+            $checkItemId = $this->checkLoans === 'same-item' && $level == 'copy'
+                && $itemId ? $itemId : null;
+            if ($this->isRecordOnLoan($patron['id'], $bibId, $checkItemId)) {
                 return $this->holdError('hold_record_already_on_loan');
             }
         }
@@ -2033,7 +2055,7 @@ EOT;
             return $result;
         }
 
-        return $this->holdError("hold_error_blocked");
+        return $this->holdError('hold_error_blocked');
     }
 
     /**
@@ -2055,44 +2077,44 @@ EOT;
         $response = [];
 
         foreach ($details as $cancelDetails) {
-            list($itemId, $cancelCode) = explode("|", $cancelDetails);
+            list($itemId, $cancelCode) = explode('|', $cancelDetails);
 
              // Create Rest API Cancel Key
-            $cancelID = $this->ws_dbKey . "|" . $cancelCode;
+            $cancelID = $this->ws_dbKey . '|' . $cancelCode;
 
             // Build Hierarchy
             $hierarchy = [
-                "patron" => $patron['id'],
-                 "circulationActions" => "requests",
-                 "holds" => $cancelID
+                'patron' => $patron['id'],
+                 'circulationActions' => 'requests',
+                 'holds' => $cancelID
             ];
 
             // Add Required Params
             $params = [
-                "patron_homedb" => $this->ws_patronHomeUbId,
-                "view" => "full"
+                'patron_homedb' => $this->ws_patronHomeUbId,
+                'view' => 'full'
             ];
 
             // Get Data
-            $cancel = $this->makeRequest($hierarchy, $params, "DELETE");
+            $cancel = $this->makeRequest($hierarchy, $params, 'DELETE');
 
             if ($cancel) {
                 // Process Cancel
                 $cancel = $cancel->children();
-                $node = "reply-text";
+                $node = 'reply-text';
                 $reply = (string)$cancel->$node;
-                $count = ($reply == "ok") ? $count + 1 : $count;
+                $count = ($reply == 'ok') ? $count + 1 : $count;
 
                 $response[$itemId] = [
-                    'success' => ($reply == "ok") ? true : false,
-                    'status' => ($reply == "ok")
-                        ? "hold_cancel_success" : "hold_cancel_fail",
-                    'sysMessage' => ($reply == "ok") ? false : $reply,
+                    'success' => ($reply == 'ok') ? true : false,
+                    'status' => ($reply == 'ok')
+                        ? 'hold_cancel_success' : 'hold_cancel_fail',
+                    'sysMessage' => ($reply == 'ok') ? false : $reply,
                 ];
 
             } else {
                 $response[$itemId] = [
-                    'success' => false, 'status' => "hold_cancel_fail"
+                    'success' => false, 'status' => 'hold_cancel_fail'
                 ];
             }
         }
@@ -2168,8 +2190,8 @@ EOT;
 
         // Add Required Params
         $params = [
-            "patron_homedb" => $this->ws_patronHomeUbId,
-            "view" => "full"
+            'patron_homedb' => $this->ws_patronHomeUbId,
+            'view' => 'full'
         ];
 
         $results = $this->makeRequest($hierarchy, $params);
@@ -2274,8 +2296,8 @@ EOT;
 
         // Add Required Params
         $params = [
-            "patron_homedb" => $this->ws_patronHomeUbId,
-            "view" => "full"
+            'patron_homedb' => $this->ws_patronHomeUbId,
+            'view' => 'full'
         ];
 
         $results = $this->makeRequest($hierarchy, $params);
@@ -2340,14 +2362,17 @@ EOT;
     }
 
     /**
-     * Get Patron Remote Storage Retrieval Requests (Call Slips). Gets remote
-     * callslips via the API.
+     * Get Patron Storage Retrieval Requests (Call Slips). Gets callslips via
+     * the API. Returns only remote slips by default since more complete data
+     * can be retrieved directly from the local database; however, the $local
+     * parameter exists to support potential local customizations.
      *
      * @param array $patron The patron array from patronLogin
+     * @param bool  $local  Whether to include local callslips
      *
      * @return mixed        Array of the patron's storage retrieval requests.
      */
-    protected function getRemoteCallSlips($patron)
+    protected function getCallSlips($patron, $local = false)
     {
         // Build Hierarchy
         $hierarchy = [
@@ -2358,8 +2383,8 @@ EOT;
 
         // Add Required Params
         $params = [
-            "patron_homedb" => $this->ws_patronHomeUbId,
-            "view" => "full"
+            'patron_homedb' => $this->ws_patronHomeUbId,
+            'view' => 'full'
         ];
 
         $results = $this->makeRequest($hierarchy, $params);
@@ -2371,8 +2396,11 @@ EOT;
         $requests = [];
         if (isset($results->callslips->institution)) {
             foreach ($results->callslips->institution as $institution) {
-                if ($this->isLocalInst((string)$institution->attributes()->id)) {
-                    // Ignore local callslips, we have them already
+                if (!$local
+                    && $this->isLocalInst((string)$institution->attributes()->id)
+                ) {
+                    // Unless $local is set, ignore local callslips; we have them
+                    // already....
                     continue;
                 }
                 foreach ($institution->callslip as $callslip) {
@@ -2449,7 +2477,7 @@ EOT;
                 $details['pickUpLocation'], $patron, $details
             )
         ) {
-            return $this->holdError("hold_invalid_pickup");
+            return $this->holdError('hold_invalid_pickup');
         }
 
         // Attempt Request
@@ -2546,10 +2574,10 @@ EOT;
         $response = [];
 
         foreach ($details as $cancelDetails) {
-            list($dbKey, $itemId, $cancelCode) = explode("|", $cancelDetails);
+            list($dbKey, $itemId, $cancelCode) = explode('|', $cancelDetails);
 
              // Create Rest API Cancel Key
-            $cancelID = ($dbKey ? $dbKey : $this->ws_dbKey) . "|" . $cancelCode;
+            $cancelID = ($dbKey ? $dbKey : $this->ws_dbKey) . '|' . $cancelCode;
 
             // Build Hierarchy
             $hierarchy = [
@@ -2793,7 +2821,7 @@ EOT;
             case 'notNeededAfter':
                 $node = current($field->xpath('./req:text'));
                 $requiredByDate = $this->dateFormat->convertToDisplayDate(
-                    "Y-m-d H:i", (string)$node
+                    'Y-m-d H:i', (string)$node
                 );
                 break;
             }
@@ -2826,7 +2854,7 @@ EOT;
             return false;
         }
 
-        $level = isset($data['level']) ? $data['level'] : "copy";
+        $level = isset($data['level']) ? $data['level'] : 'copy';
         $itemID = ($level != 'title' && isset($data['item_id']))
             ? $data['item_id']
             : false;
@@ -3004,11 +3032,11 @@ EOT;
         // Convert last interest date from Display Format to Voyager required format
         try {
             $lastInterestDate = $this->dateFormat->convertFromDisplayDate(
-                "Y-m-d", $details['requiredBy']
+                'Y-m-d', $details['requiredBy']
             );
         } catch (DateException $e) {
             // Date is invalid
-            return $this->holdError("ill_request_date_invalid");
+            return $this->holdError('ill_request_date_invalid');
         }
 
         // Verify pickup library and location
@@ -3121,7 +3149,7 @@ EOT;
     {
         return array_merge(
             $this->getHoldsFromApi($patron, false),
-            $this->getRemoteCallSlips($patron)
+            $this->getCallSlips($patron, false) // remote only
         );
     }
 
@@ -3145,15 +3173,15 @@ EOT;
         $response = [];
 
         foreach ($details as $cancelDetails) {
-            list($dbKey, $itemId, $type, $cancelCode) = explode("|", $cancelDetails);
+            list($dbKey, $itemId, $type, $cancelCode) = explode('|', $cancelDetails);
 
              // Create Rest API Cancel Key
-            $cancelID = ($dbKey ? $dbKey : $this->ws_dbKey) . "|" . $cancelCode;
+            $cancelID = ($dbKey ? $dbKey : $this->ws_dbKey) . '|' . $cancelCode;
 
             // Build Hierarchy
             $hierarchy = [
-                "patron" => $patron['id'],
-                 "circulationActions" => 'requests'
+                'patron' => $patron['id'],
+                 'circulationActions' => 'requests'
             ];
             // An UB request is
             if ($type == 'C') {
@@ -3164,32 +3192,32 @@ EOT;
 
             // Add Required Params
             $params = [
-                "patron_homedb" => $this->ws_patronHomeUbId,
-                "view" => "full"
+                'patron_homedb' => $this->ws_patronHomeUbId,
+                'view' => 'full'
             ];
 
             // Get Data
-            $cancel = $this->makeRequest($hierarchy, $params, "DELETE");
+            $cancel = $this->makeRequest($hierarchy, $params, 'DELETE');
 
             if ($cancel) {
 
                 // Process Cancel
                 $cancel = $cancel->children();
-                $node = "reply-text";
+                $node = 'reply-text';
                 $reply = (string)$cancel->$node;
-                $count = ($reply == "ok") ? $count + 1 : $count;
+                $count = ($reply == 'ok') ? $count + 1 : $count;
 
                 $response[$itemId] = [
-                    'success' => ($reply == "ok") ? true : false,
-                    'status' => ($reply == "ok")
-                        ? "ill_request_cancel_success" : "ill_request_cancel_fail",
-                    'sysMessage' => ($reply == "ok") ? false : $reply,
+                    'success' => ($reply == 'ok') ? true : false,
+                    'status' => ($reply == 'ok')
+                        ? 'ill_request_cancel_success' : 'ill_request_cancel_fail',
+                    'sysMessage' => ($reply == 'ok') ? false : $reply,
                 ];
 
             } else {
                 $response[$itemId] = [
                     'success' => false,
-                    'status' => "ill_request_cancel_fail"
+                    'status' => 'ill_request_cancel_fail'
                 ];
             }
         }
diff --git a/module/VuFind/src/VuFind/ILS/Logic/Holds.php b/module/VuFind/src/VuFind/ILS/Logic/Holds.php
index 07f65072b3ecc3b3de4ba0d4bde45b230be868f3..88ebd73c4fa1cd319e4d7c8bed84a9c064f48393 100644
--- a/module/VuFind/src/VuFind/ILS/Logic/Holds.php
+++ b/module/VuFind/src/VuFind/ILS/Logic/Holds.php
@@ -115,9 +115,7 @@ class Holds
     {
         $retVal = [];
 
-        // Handle purchase history alongside other textual fields
         $textFieldNames = $this->catalog->getHoldingsTextFieldNames();
-        $textFieldNames[] = 'purchase_history';
 
         foreach ($holdings as $groupKey => $items) {
             $retVal[$groupKey] = [
@@ -156,6 +154,16 @@ class Holds
                         }
                     }
                 }
+
+                // Handle purchase history
+                if (!empty($item['purchase_history'])) {
+                    $targetRef = & $retVal[$groupKey]['purchase_history'];
+                    foreach ((array)$item['purchase_history'] as $field) {
+                        if (empty($targetRef) || !in_array($field, $targetRef)) {
+                            $targetRef[] = $field;
+                        }
+                    }
+                }
             }
         }
 
@@ -200,22 +208,32 @@ class Holds
                 $result = $this->catalog->getHolding($id, $patron ? $patron : null);
             }
 
+            $grb = 'getRequestBlocks'; // use variable to shorten line below:
+            $blocks
+                = $patron && $this->catalog->checkCapability($grb, compact($patron))
+                ? $this->catalog->getRequestBlocks($patron) : false;
+
             $mode = $this->catalog->getHoldsMode();
 
             if ($mode == "disabled") {
                 $holdings = $this->standardHoldings($result);
             } else if ($mode == "driver") {
-                $holdings = $this->driverHoldings($result, $config);
+                $holdings = $this->driverHoldings($result, $config, !empty($blocks));
             } else {
                 $holdings = $this->generateHoldings($result, $mode, $config);
             }
 
             $holdings = $this->processStorageRetrievalRequests(
-                $holdings, $id, $patron
+                $holdings, $id, $patron, !empty($blocks)
+            );
+            $holdings = $this->processILLRequests(
+                $holdings, $id, $patron, !empty($blocks)
             );
-            $holdings = $this->processILLRequests($holdings, $id, $patron);
         }
-        return $this->formatHoldings($holdings);
+        return [
+            'blocks' => $blocks,
+            'holdings' => $this->formatHoldings($holdings)
+        ];
     }
 
     /**
@@ -243,12 +261,13 @@ class Holds
     /**
      * Protected method for driver defined holdings
      *
-     * @param array $result     A result set returned from a driver
-     * @param array $holdConfig Hold configuration from driver
+     * @param array $result          A result set returned from a driver
+     * @param array $holdConfig      Hold configuration from driver
+     * @param bool  $requestsBlocked Are user requests blocked?
      *
      * @return array A sorted results set
      */
-    protected function driverHoldings($result, $holdConfig)
+    protected function driverHoldings($result, $holdConfig, $requestsBlocked)
     {
         $holdings = [];
 
@@ -258,17 +277,16 @@ class Holds
                 if ($show) {
                     if ($holdConfig) {
                         // Is this copy holdable / linkable
-                        if (isset($copy['addLink']) && $copy['addLink']) {
-                            // If the hold is blocked, link to an error page
-                            // instead of the hold form:
-                            $copy['link'] = $copy['addLink'] === 'block'
-                                ? $this->getBlockedDetails($copy)
-                                : $this->getRequestDetails(
-                                    $copy, $holdConfig['HMACKeys'], 'Hold'
-                                );
+                        if (!$requestsBlocked
+                            && isset($copy['addLink']) && $copy['addLink']
+                        ) {
+                            $copy['link'] = $this->getRequestDetails(
+                                $copy, $holdConfig['HMACKeys'], 'Hold'
+                            );
+                            $copy['linkLightbox'] = true;
                             // If we are unsure whether hold options are available,
                             // set a flag so we can check later via AJAX:
-                            $copy['check'] = $copy['addLink'] == 'check';
+                            $copy['check'] = $copy['addLink'] === 'check';
                         }
                     }
 
@@ -352,12 +370,16 @@ class Holds
                                     = $this->catalog->getHoldLink(
                                         $copy['id'], $copy
                                     );
+                                $holdings[$location_key][$copy_key]['linkLightbox']
+                                    = false;
                             } else {
                                 /* Build non-opac link */
                                 $holdings[$location_key][$copy_key]['link']
                                     = $this->getRequestDetails(
                                         $copy, $holdConfig['HMACKeys'], 'Hold'
                                     );
+                                $holdings[$location_key][$copy_key]['linkLightbox']
+                                    = true;
                             }
                         }
                     }
@@ -371,14 +393,16 @@ class Holds
      * Process storage retrieval request information in holdings and set the links
      * accordingly.
      *
-     * @param array  $holdings Holdings
-     * @param string $id       Record ID
-     * @param array  $patron   Patron
+     * @param array  $holdings        Holdings
+     * @param string $id              Record ID
+     * @param array  $patron          Patron
+     * @param bool   $requestsBlocked Are user requests blocked?
      *
      * @return array Modified holdings
      */
-    protected function processStorageRetrievalRequests($holdings, $id, $patron)
-    {
+    protected function processStorageRetrievalRequests($holdings, $id, $patron,
+        $requestsBlocked
+    ) {
         if (!is_array($holdings)) {
             return $holdings;
         }
@@ -397,22 +421,15 @@ class Holds
         foreach ($holdings as &$location) {
             foreach ($location as &$copy) {
                 // Is this copy requestable
-                if (isset($copy['addStorageRetrievalRequestLink'])
+                if (!$requestsBlocked
+                    && isset($copy['addStorageRetrievalRequestLink'])
                     && $copy['addStorageRetrievalRequestLink']
                 ) {
-                    // If the request is blocked, link to an error page
-                    // instead of the form:
-                    if ($copy['addStorageRetrievalRequestLink'] === 'block') {
-                        $copy['storageRetrievalRequestLink']
-                            = $this->getBlockedStorageRetrievalRequestDetails($copy);
-                    } else {
-                        $copy['storageRetrievalRequestLink']
-                            = $this->getRequestDetails(
-                                $copy,
-                                $requestConfig['HMACKeys'],
-                                'StorageRetrievalRequest'
-                            );
-                    }
+                    $copy['storageRetrievalRequestLink'] = $this->getRequestDetails(
+                        $copy,
+                        $requestConfig['HMACKeys'],
+                        'StorageRetrievalRequest'
+                    );
                     // If we are unsure whether request options are
                     // available, set a flag so we can check later via AJAX:
                     $copy['checkStorageRetrievalRequest']
@@ -426,13 +443,14 @@ class Holds
     /**
      * Process ILL request information in holdings and set the links accordingly.
      *
-     * @param array  $holdings Holdings
-     * @param string $id       Record ID
-     * @param array  $patron   Patron
+     * @param array  $holdings        Holdings
+     * @param string $id              Record ID
+     * @param array  $patron          Patron
+     * @param bool   $requestsBlocked Are user requests blocked?
      *
      * @return array Modified holdings
      */
-    protected function processILLRequests($holdings, $id, $patron)
+    protected function processILLRequests($holdings, $id, $patron, $requestsBlocked)
     {
         if (!is_array($holdings)) {
             return $holdings;
@@ -452,22 +470,14 @@ class Holds
         foreach ($holdings as &$location) {
             foreach ($location as &$copy) {
                 // Is this copy requestable
-                if (isset($copy['addILLRequestLink'])
+                if (!$requestsBlocked && isset($copy['addILLRequestLink'])
                     && $copy['addILLRequestLink']
                 ) {
-                    // If the request is blocked, link to an error page
-                    // instead of the form:
-                    if ($copy['addILLRequestLink'] === 'block') {
-                        $copy['ILLRequestLink']
-                            = $this->getBlockedILLRequestDetails($copy);
-                    } else {
-                        $copy['ILLRequestLink']
-                            = $this->getRequestDetails(
-                                $copy,
-                                $requestConfig['HMACKeys'],
-                                'ILLRequest'
-                            );
-                    }
+                    $copy['ILLRequestLink'] = $this->getRequestDetails(
+                        $copy,
+                        $requestConfig['HMACKeys'],
+                        'ILLRequest'
+                    );
                     // If we are unsure whether request options are
                     // available, set a flag so we can check later via AJAX:
                     $copy['checkILLRequest']
@@ -491,6 +501,9 @@ class Holds
      */
     protected function getRequestDetails($details, $HMACKeys, $action)
     {
+        // Include request type in the details
+        $details['requestType'] = $action;
+
         // Generate HMAC
         $HMACkey = $this->hmac->generate($HMACKeys, $details);
 
@@ -515,53 +528,6 @@ class Holds
         ];
     }
 
-    /**
-     * Returns a URL to display a "blocked hold" message.
-     *
-     * @param array $holdDetails An array of item data
-     *
-     * @return array             Details for generating URL
-     */
-    protected function getBlockedDetails($holdDetails)
-    {
-        // Build Params
-        return [
-            'action' => 'BlockedHold', 'record' => $holdDetails['id']
-        ];
-    }
-
-    /**
-     * Returns a URL to display a "blocked storage retrieval request" message.
-     *
-     * @param array $details An array of item data
-     *
-     * @return array         Details for generating URL
-     */
-    protected function getBlockedStorageRetrievalRequestDetails($details)
-    {
-        // Build Params
-        return [
-            'action' => 'BlockedStorageRetrievalRequest',
-            'record' => $details['id']
-        ];
-    }
-
-    /**
-     * Returns a URL to display a "blocked ILL request" message.
-     *
-     * @param array $details An array of item data
-     *
-     * @return array         Details for generating URL
-     */
-    protected function getBlockedILLRequestDetails($details)
-    {
-        // Build Params
-        return [
-            'action' => 'BlockedILLRequest',
-            'record' => $details['id']
-        ];
-    }
-
     /**
      * Get a grouping key for a holdings item
      *
@@ -571,9 +537,9 @@ class Holds
      */
     protected function getHoldingsGroupKey($copy)
     {
-        // Group by holdings id unless configured otherwise
+        // Group by holdings id and location unless configured otherwise
         $grouping = isset($this->config->Catalog->holdings_grouping)
-            ? $this->config->Catalog->holdings_grouping : 'holdings_id';
+            ? $this->config->Catalog->holdings_grouping : 'holdings_id,location';
 
         $groupKey = "";
 
diff --git a/module/VuFind/src/VuFind/ILS/Logic/TitleHolds.php b/module/VuFind/src/VuFind/ILS/Logic/TitleHolds.php
index 191baaed745d9b54eb5385d1555dccb887fbdfe5..3d8ed1c8a40803ddd887582a174b134448d849df 100644
--- a/module/VuFind/src/VuFind/ILS/Logic/TitleHolds.php
+++ b/module/VuFind/src/VuFind/ILS/Logic/TitleHolds.php
@@ -120,13 +120,13 @@ class TitleHolds
             } else if ($mode == 'driver') {
                 try {
                     $patron = $this->ilsAuth->storedCatalogLogin();
+                    if (!$patron) {
+                        return false;
+                    }
+                    return $this->driverHold($id, $patron);
                 } catch (ILSException $e) {
                     return false;
                 }
-                if (!$patron) {
-                    return false;
-                }
-                return $this->driverHold($id, $patron);
             } else {
                 try {
                     $patron = $this->ilsAuth->storedCatalogLogin();
@@ -205,14 +205,13 @@ class TitleHolds
         $checkHolds = $this->catalog->checkFunction(
             'Holds', compact('id', 'patron')
         );
-        $data = [
-            'id' => $id,
-            'level' => 'title'
-        ];
 
-        if ($checkHolds != false) {
-            $valid = $this->catalog->checkRequestIsValid($id, $data, $patron);
-            if ($valid) {
+        if (isset($checkHolds['HMACKeys'])) {
+            $data = ['id' => $id, 'level' => 'title'];
+            $result = $this->catalog->checkRequestIsValid($id, $data, $patron);
+            if ((is_array($result) && $result['valid'])
+                || (is_bool($result) && $result)
+            ) {
                 return $this->getHoldDetails($data, $checkHolds['HMACKeys']);
             }
         }
diff --git a/module/VuFind/src/VuFind/Log/Logger.php b/module/VuFind/src/VuFind/Log/Logger.php
index 9b97e58e1f4b76d43a7ad4c378477f5055cb8615..c3b3e40a4bb33cd287c6f5addace7ece9af47993 100644
--- a/module/VuFind/src/VuFind/Log/Logger.php
+++ b/module/VuFind/src/VuFind/Log/Logger.php
@@ -26,9 +26,7 @@
  * @link     https://vufind.org Main Site
  */
 namespace VuFind\Log;
-use Zend\Log\Logger as BaseLogger,
-    Zend\ServiceManager\ServiceLocatorAwareInterface,
-    Zend\ServiceManager\ServiceLocatorInterface;
+use Zend\Log\Logger as BaseLogger;
 
 /**
  * This class wraps the BaseLogger class to allow for log verbosity
@@ -39,10 +37,8 @@ use Zend\Log\Logger as BaseLogger,
  * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
  * @link     https://vufind.org Main Site
  */
-class Logger extends BaseLogger implements ServiceLocatorAwareInterface
+class Logger extends BaseLogger
 {
-    use \Zend\ServiceManager\ServiceLocatorAwareTrait;
-
     /**
      * Is debug logging enabled?
      *
@@ -50,221 +46,20 @@ class Logger extends BaseLogger implements ServiceLocatorAwareInterface
      */
     protected $debugNeeded = false;
 
-    /**
-     * Set configuration
-     *
-     * @param \Zend\Config\Config $config VuFind configuration
-     *
-     * @return void
-     */
-    public function setConfig($config)
-    {
-        // DEBUGGER
-        if (!$config->System->debug == false) {
-            $this->addDebugWriter($config->System->debug);
-        }
-
-        // Activate database logging, if applicable:
-        if (isset($config->Logging->database)) {
-            $parts = explode(':', $config->Logging->database);
-            $table_name = $parts[0];
-            $error_types = isset($parts[1]) ? $parts[1] : '';
-
-            $columnMapping = [
-                'priority' => 'priority',
-                'message' => 'message',
-                'logtime' => 'timestamp',
-                'ident' => 'ident'
-            ];
-
-            // Make Writers
-            $filters = explode(',', $error_types);
-            $writer = new Writer\Db(
-                $this->getServiceLocator()->get('VuFind\DbAdapter'),
-                $table_name, $columnMapping
-            );
-            $this->addWriters($writer, $filters);
-        }
-
-        // Activate file logging, if applicable:
-        if (isset($config->Logging->file)) {
-            $parts = explode(':', $config->Logging->file);
-            $file = $parts[0];
-            $error_types = isset($parts[1]) ? $parts[1] : '';
-
-            // Make Writers
-            $filters = explode(',', $error_types);
-            $writer = new Writer\Stream($file);
-            $this->addWriters($writer, $filters);
-        }
-
-        // Activate email logging, if applicable:
-        if (isset($config->Logging->email)) {
-            // Set up the logger's mailer to behave consistently with VuFind's
-            // general mailer:
-            $parts = explode(':', $config->Logging->email);
-            $email = $parts[0];
-            $error_types = isset($parts[1]) ? $parts[1] : '';
-
-            // use smtp
-            $mailer = $this->getServiceLocator()->get('VuFind\Mailer');
-            $msg = $mailer->getNewMessage()
-                ->addFrom($config->Site->email)
-                ->addTo($email)
-                ->setSubject('VuFind Log Message');
-
-            // Make Writers
-            $filters = explode(',', $error_types);
-            $writer = new Writer\Mail($msg, $mailer->getTransport());
-            $this->addWriters($writer, $filters);
-        }
-
-        // Activate slack logging, if applicable:
-        if (isset($config->Logging->slack) && isset($config->Logging->slackurl)) {
-            $options = [];
-            // Get config
-            list($channel, $error_types) = explode(':', $config->Logging->slack);
-            if ($error_types == null) {
-                $error_types = $channel;
-                $channel = null;
-            }
-            if ($channel) {
-                $options['channel'] = $channel;
-            }
-            if (isset($config->Logging->slackname)) {
-                $options['name'] = $config->Logging->slackname;
-            }
-            $filters = explode(',', $error_types);
-            // Make Writers
-            $writer = new Writer\Slack(
-                $config->Logging->slackurl,
-                $this->getServiceLocator()->get('VuFind\Http')->createClient(),
-                $options
-            );
-            $writer->setContentType('application/json');
-            $formatter = new \Zend\Log\Formatter\Simple(
-                "*%priorityName%*: %message%"
-            );
-            $writer->setFormatter($formatter);
-            $this->addWriters($writer, $filters);
-        }
-
-        // Null (no-op) writer to avoid errors
-        if (count($this->writers) == 0) {
-            $nullWriter = 'Zend\Log\Writer\Noop';
-            $this->addWriter(new $nullWriter());
-        }
-    }
-
-    /**
-     * Add the standard debug stream writer.
-     *
-     * @param bool|int $debug Debug mode/level
-     *
-     * @return void
-     */
-    public function addDebugWriter($debug)
-    {
-        // Only add debug writer ONCE!
-        static $hasDebugWriter = false;
-        if ($hasDebugWriter) {
-            return;
-        }
-
-        $hasDebugWriter = true;
-        $writer = new Writer\Stream('php://output');
-        $formatter = new \Zend\Log\Formatter\Simple(
-            '<pre>%timestamp% %priorityName%: %message%</pre>' . PHP_EOL
-        );
-        $writer->setFormatter($formatter);
-        $this->addWriters($writer, 'debug-' . (is_int($debug) ? $debug : '5'));
-    }
-
-    /**
-     * Applies an array of filters to a writer
-     *
-     * Filter keys: alert, error, notice, debug
-     *
-     * @param Zend\Log\Writer\WriterInterface $writer  The writer to apply the
-     * filters to
-     * @param string|array                    $filters An array or comma-separated
-     * string of
-     * logging levels
-     *
-     * @return void
-     */
-    protected function addWriters($writer, $filters)
-    {
-        if (!is_array($filters)) {
-            $filters = explode(',', $filters);
-        }
-
-        foreach ($filters as $filter) {
-            $parts = explode('-', $filter);
-            $priority = $parts[0];
-            $verbosity = isset($parts[1]) ? $parts[1] : false;
-
-            // VuFind's configuration provides four priority options, each
-            // combining two of the standard Zend levels.
-            switch(trim($priority)) {
-            case 'debug':
-                // Set static flag indicating that debug is turned on:
-                $this->debugNeeded = true;
-
-                $max = BaseLogger::INFO;  // Informational: informational messages
-                $min = BaseLogger::DEBUG; // Debug: debug messages
-                break;
-            case 'notice':
-                $max = BaseLogger::WARN;  // Warning: warning conditions
-                $min = BaseLogger::NOTICE;// Notice: normal but significant condition
-                break;
-            case 'error':
-                $max = BaseLogger::CRIT;  // Critical: critical conditions
-                $min = BaseLogger::ERR;   // Error: error conditions
-                break;
-            case 'alert':
-                $max = BaseLogger::EMERG; // Emergency: system is unusable
-                $min = BaseLogger::ALERT; // Alert: action must be taken immediately
-                break;
-            default:                    // INVALID FILTER
-                continue;
-            }
-
-            // Clone the submitted writer since we'll need a separate instance of the
-            // writer for each selected priority level.
-            $newWriter = clone($writer);
-
-            // verbosity
-            if ($verbosity) {
-                if (method_exists($newWriter, 'setVerbosity')) {
-                    $newWriter->setVerbosity($verbosity);
-                } else {
-                    throw new \Exception(
-                        get_class($newWriter) . ' does not support verbosity.'
-                    );
-                }
-            }
-
-            // filtering -- only log messages between the min and max priority levels
-            $filter1 = new \Zend\Log\Filter\Priority($min, '<=');
-            $filter2 = new \Zend\Log\Filter\Priority($max, '>=');
-            $newWriter->addFilter($filter1);
-            $newWriter->addFilter($filter2);
-
-            // add the writer
-            $this->addWriter($newWriter);
-        }
-    }
-
     /**
      * Is one of the log writers listening for debug messages?  (This is useful to
      * know, since some code can save time that would be otherwise wasted generating
      * debug messages if we know that no one is listening).
      *
+     * @param bool $newState New state (omit to leave current state unchanged)
+     *
      * @return bool
      */
-    public function debugNeeded()
+    public function debugNeeded($newState = null)
     {
+        if (null !== $newState) {
+            $this->debugNeeded = $newState;
+        }
         return $this->debugNeeded;
     }
 
@@ -410,7 +205,7 @@ class Logger extends BaseLogger implements ServiceLocatorAwareInterface
         if (is_int($arg) || is_float($arg)) {
             return (string)$arg;
         }
-        if (is_null($arg)) {
+        if (null === $arg) {
             return 'null';
         }
         return "'$arg'";
diff --git a/module/VuFind/src/VuFind/Log/LoggerFactory.php b/module/VuFind/src/VuFind/Log/LoggerFactory.php
new file mode 100644
index 0000000000000000000000000000000000000000..bcc6d393dd7bd84dfe262e0e43fcef5e6fbe97db
--- /dev/null
+++ b/module/VuFind/src/VuFind/Log/LoggerFactory.php
@@ -0,0 +1,336 @@
+<?php
+/**
+ * Factory for instantiating Logger
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2017.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * @category VuFind
+ * @package  Error_Logging
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development Wiki
+ */
+namespace VuFind\Log;
+use Zend\Config\Config;
+use Zend\Log\Writer\WriterInterface;
+use Zend\ServiceManager\ServiceLocatorInterface;
+
+/**
+ * Factory for instantiating Logger
+ *
+ * @category VuFind
+ * @package  Error_Logging
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development Wiki
+ *
+ * @codeCoverageIgnore
+ */
+class LoggerFactory implements \Zend\ServiceManager\FactoryInterface
+{
+    /**
+     * Configure database writers.
+     *
+     * @param Logger                  $logger Logger object
+     * @param ServiceLocatorInterface $sm     Service locator
+     * @param string                  $config Configuration
+     *
+     * @return void
+     */
+    protected function addDbWriters(Logger $logger, ServiceLocatorInterface $sm,
+        $config
+    ) {
+        $parts = explode(':', $config);
+        $table_name = $parts[0];
+        $error_types = isset($parts[1]) ? $parts[1] : '';
+
+        $columnMapping = [
+            'priority' => 'priority',
+            'message' => 'message',
+            'logtime' => 'timestamp',
+            'ident' => 'ident'
+        ];
+
+        // Make Writers
+        $filters = explode(',', $error_types);
+        $writer = new Writer\Db(
+            $sm->get('VuFind\DbAdapter'),
+            $table_name, $columnMapping
+        );
+        $this->addWriters($logger, $writer, $filters);
+    }
+
+    /**
+     * Configure email writers.
+     *
+     * @param Logger                  $logger Logger object
+     * @param ServiceLocatorInterface $sm     Service locator
+     * @param Config                  $config Configuration
+     *
+     * @return void
+     */
+    protected function addEmailWriters(Logger $logger, ServiceLocatorInterface $sm,
+        Config $config
+    ) {
+        // Set up the logger's mailer to behave consistently with VuFind's
+        // general mailer:
+        $parts = explode(':', $config->Logging->email);
+        $email = $parts[0];
+        $error_types = isset($parts[1]) ? $parts[1] : '';
+
+        // use smtp
+        $mailer = $sm->get('VuFind\Mailer');
+        $msg = $mailer->getNewMessage()
+            ->addFrom($config->Site->email)
+            ->addTo($email)
+            ->setSubject('VuFind Log Message');
+
+        // Make Writers
+        $filters = explode(',', $error_types);
+        $writer = new Writer\Mail($msg, $mailer->getTransport());
+        $this->addWriters($logger, $writer, $filters);
+    }
+
+    /**
+     * Configure File writers.
+     *
+     * @param Logger $logger Logger object
+     * @param string $config Configuration
+     *
+     * @return void
+     */
+    protected function addFileWriters(Logger $logger, $config)
+    {
+        $parts = explode(':', $config);
+        $file = $parts[0];
+        $error_types = isset($parts[1]) ? $parts[1] : '';
+
+        // Make Writers
+        $filters = explode(',', $error_types);
+        $writer = new Writer\Stream($file);
+        $this->addWriters($logger, $writer, $filters);
+    }
+
+    /**
+     * Configure Slack writers.
+     *
+     * @param Logger                  $logger Logger object
+     * @param ServiceLocatorInterface $sm     Service locator
+     * @param Config                  $config Configuration
+     *
+     * @return void
+     */
+    protected function addSlackWriters(Logger $logger, ServiceLocatorInterface $sm,
+        Config $config
+    ) {
+        $options = [];
+        // Get config
+        list($channel, $error_types) = explode(':', $config->Logging->slack);
+        if ($error_types == null) {
+            $error_types = $channel;
+            $channel = null;
+        }
+        if ($channel) {
+            $options['channel'] = $channel;
+        }
+        if (isset($config->Logging->slackname)) {
+            $options['name'] = $config->Logging->slackname;
+        }
+        $filters = explode(',', $error_types);
+        // Make Writers
+        $writer = new Writer\Slack(
+            $config->Logging->slackurl,
+            $sm->get('VuFind\Http')->createClient(),
+            $options
+        );
+        $writer->setContentType('application/json');
+        $formatter = new \Zend\Log\Formatter\Simple(
+            "*%priorityName%*: %message%"
+        );
+        $writer->setFormatter($formatter);
+        $this->addWriters($logger, $writer, $filters);
+    }
+
+    /**
+     * Set configuration
+     *
+     * @param ServiceLocatorInterface $sm     Service manager
+     * @param Logger                  $logger Logger to configure
+     *
+     * @return void
+     */
+    protected function configureLogger(ServiceLocatorInterface $sm, Logger $logger)
+    {
+        $config = $sm->get('VuFind\Config')->get('config');
+
+        $hasWriter = false;
+
+        // DEBUGGER
+        if (!$config->System->debug == false) {
+            $hasWriter = true;
+            $this->addDebugWriter($logger, $config->System->debug);
+        }
+
+        // Activate database logging, if applicable:
+        if (isset($config->Logging->database)) {
+            $hasWriter = true;
+            $this->addDbWriters($logger, $sm, $config->Logging->database);
+        }
+
+        // Activate file logging, if applicable:
+        if (isset($config->Logging->file)) {
+            $hasWriter = true;
+            $this->addFileWriters($logger, $config->Logging->file);
+        }
+
+        // Activate email logging, if applicable:
+        if (isset($config->Logging->email)) {
+            $hasWriter = true;
+            $this->addEmailWriters($logger, $sm, $config);
+        }
+
+        // Activate slack logging, if applicable:
+        if (isset($config->Logging->slack) && isset($config->Logging->slackurl)) {
+            $hasWriter = true;
+            $this->addSlackWriters($logger, $sm, $config);
+        }
+
+        // Null (no-op) writer to avoid errors
+        if (!$hasWriter) {
+            $logger->addWriter(new \Zend\Log\Writer\Noop());
+        }
+    }
+
+    /**
+     * Add the standard debug stream writer.
+     *
+     * @param Logger   $logger Logger object
+     * @param bool|int $debug  Debug mode/level
+     *
+     * @return void
+     */
+    protected function addDebugWriter(Logger $logger, $debug)
+    {
+        // Only add debug writer ONCE!
+        static $hasDebugWriter = false;
+        if ($hasDebugWriter) {
+            return;
+        }
+
+        $hasDebugWriter = true;
+        $writer = new Writer\Stream('php://output');
+        $formatter = new \Zend\Log\Formatter\Simple(
+            '<pre>%timestamp% %priorityName%: %message%</pre>' . PHP_EOL
+        );
+        $writer->setFormatter($formatter);
+        $this->addWriters(
+            $logger, $writer, 'debug-' . (is_int($debug) ? $debug : '5')
+        );
+    }
+
+    /**
+     * Applies an array of filters to a writer
+     *
+     * Filter keys: alert, error, notice, debug
+     *
+     * @param Logger          $logger  Logger object
+     * @param WriterInterface $writer  The writer to apply the
+     * filters to
+     * @param string|array    $filters An array or comma-separated
+     * string of
+     * logging levels
+     *
+     * @return void
+     */
+    protected function addWriters(Logger $logger, WriterInterface $writer, $filters)
+    {
+        if (!is_array($filters)) {
+            $filters = explode(',', $filters);
+        }
+
+        foreach ($filters as $filter) {
+            $parts = explode('-', $filter);
+            $priority = $parts[0];
+            $verbosity = isset($parts[1]) ? $parts[1] : false;
+
+            // VuFind's configuration provides four priority options, each
+            // combining two of the standard Zend levels.
+            switch(trim($priority)) {
+            case 'debug':
+                // Set static flag indicating that debug is turned on:
+                $logger->debugNeeded(true);
+
+                $max = Logger::INFO;  // Informational: informational messages
+                $min = Logger::DEBUG; // Debug: debug messages
+                break;
+            case 'notice':
+                $max = Logger::WARN;  // Warning: warning conditions
+                $min = Logger::NOTICE;// Notice: normal but significant condition
+                break;
+            case 'error':
+                $max = Logger::CRIT;  // Critical: critical conditions
+                $min = Logger::ERR;   // Error: error conditions
+                break;
+            case 'alert':
+                $max = Logger::EMERG; // Emergency: system is unusable
+                $min = Logger::ALERT; // Alert: action must be taken immediately
+                break;
+            default:                    // INVALID FILTER
+                continue;
+            }
+
+            // Clone the submitted writer since we'll need a separate instance of the
+            // writer for each selected priority level.
+            $newWriter = clone($writer);
+
+            // verbosity
+            if ($verbosity) {
+                if (method_exists($newWriter, 'setVerbosity')) {
+                    $newWriter->setVerbosity($verbosity);
+                } else {
+                    throw new \Exception(
+                        get_class($newWriter) . ' does not support verbosity.'
+                    );
+                }
+            }
+
+            // filtering -- only log messages between the min and max priority levels
+            $filter1 = new \Zend\Log\Filter\Priority($min, '<=');
+            $filter2 = new \Zend\Log\Filter\Priority($max, '>=');
+            $newWriter->addFilter($filter1);
+            $newWriter->addFilter($filter2);
+
+            // add the writer
+            $logger->addWriter($newWriter);
+        }
+    }
+
+    /**
+     * Create service
+     *
+     * @param ServiceLocatorInterface $sm Service manager
+     *
+     * @return mixed
+     */
+    public function createService(ServiceLocatorInterface $sm)
+    {
+        $logger = new Logger();
+        $this->configureLogger($sm, $logger);
+        return $logger;
+    }
+}
diff --git a/module/VuFind/src/VuFind/Log/Writer/Post.php b/module/VuFind/src/VuFind/Log/Writer/Post.php
index 178825edbeffd1d6eb7f5c8543ebf89279442d15..ab1cc838b03ecef472d4e2c0b5dcd42b8980762c 100644
--- a/module/VuFind/src/VuFind/Log/Writer/Post.php
+++ b/module/VuFind/src/VuFind/Log/Writer/Post.php
@@ -119,6 +119,6 @@ class Post extends \Zend\Log\Writer\AbstractWriter
         $this->client->setEncType($this->contentType);
         $this->client->setRawBody($this->getBody($this->applyVerbosity($event)));
         // Send
-        $response = $this->client->send();
+        $this->client->send();
     }
 }
diff --git a/module/VuFind/src/VuFind/Mailer/Mailer.php b/module/VuFind/src/VuFind/Mailer/Mailer.php
index d149369a801fc21ffd34ea514315b14c7138ec3e..333250be1ec84b54d49c9a58d7cf6d804cd41ec3 100644
--- a/module/VuFind/src/VuFind/Mailer/Mailer.php
+++ b/module/VuFind/src/VuFind/Mailer/Mailer.php
@@ -267,7 +267,7 @@ class Mailer implements \VuFind\I18n\Translator\TranslatorAwareInterface
     /**
      * Set the maximum number of email recipients
      *
-     * @param type $max Maximum
+     * @param int $max Maximum
      *
      * @return void
      */
diff --git a/module/VuFind/src/VuFind/OAI/Server.php b/module/VuFind/src/VuFind/OAI/Server.php
index a161e5dceed85c6e3985be4a2fed78808150430d..539cec5baa1d223a99cebcdc97007aceba64e923 100644
--- a/module/VuFind/src/VuFind/OAI/Server.php
+++ b/module/VuFind/src/VuFind/OAI/Server.php
@@ -369,9 +369,10 @@ class Server
 
         // Retrieve the record from the index
         if ($record = $this->loadRecord($this->params['identifier'])) {
-            if (!$this->attachNonDeleted(
+            $success = $this->attachNonDeleted(
                 $xml, $record, $this->params['metadataPrefix']
-            )) {
+            );
+            if (!$success) {
                 return $this->showError('cannotDisseminateFormat', 'Unknown Format');
             }
         } else {
diff --git a/module/VuFind/src/VuFind/Recommend/ResultGoogleMapAjax.php b/module/VuFind/src/VuFind/Recommend/AbstractResultsPassthrough.php
similarity index 66%
rename from module/VuFind/src/VuFind/Recommend/ResultGoogleMapAjax.php
rename to module/VuFind/src/VuFind/Recommend/AbstractResultsPassthrough.php
index 833c4f687c894a5b1f23ff6f7f525070e47b14dd..96ad5c783bddb29ecdac0678d4964b0a830bf4d2 100644
--- a/module/VuFind/src/VuFind/Recommend/ResultGoogleMapAjax.php
+++ b/module/VuFind/src/VuFind/Recommend/AbstractResultsPassthrough.php
@@ -1,10 +1,11 @@
 <?php
 /**
- * AuthorInfo Recommendations Module
+ * Simple abstract recommendation module that simply passes the Results object
+ * through to the template.
  *
  * PHP version 5
  *
- * Copyright (C) Villanova University 2010.
+ * Copyright (C) Villanova University 2017.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2,
@@ -21,6 +22,7 @@
  *
  * @category VuFind
  * @package  Recommendations
+ * @author   Demian Katz <demian.katz@villanova.edu>
  * @author   Chris Hallberg <challber@villanova.edu>
  * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
  * @link     https://vufind.org/wiki/development:plugins:recommendation_modules Wiki
@@ -28,44 +30,24 @@
 namespace VuFind\Recommend;
 
 /**
- * AuthorInfo Recommendations Module
- *
- * This class gathers information from the Wikipedia API and publishes the results
- * to a module at the top of an author's results page
+ * Simple abstract recommendation module that simply passes the Results object
+ * through to the template.
  *
  * @category VuFind
  * @package  Recommendations
- * @author   Lutz Biedinger <lutz.biedinger@gmail.com>
+ * @author   Demian Katz <demian.katz@villanova.edu>
  * @author   Chris Hallberg <challber@villanova.edu>
  * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
  * @link     https://vufind.org/wiki/development:plugins:recommendation_modules Wiki
- * @view     AuthorInfoFacets.phtml
  */
-class ResultGoogleMapAjax implements RecommendInterface
+class AbstractResultsPassthrough implements RecommendInterface
 {
     /**
-     * Saved search results
+     * Search results object.
      *
      * @var \VuFind\Search\Base\Results
      */
-    protected $searchObject;
-
-    /**
-     * Google Maps API key.
-     *
-     * @var string
-     */
-    protected $googleMapApiKey;
-
-    /**
-     * Constructor
-     *
-     * @param string $key API key
-     */
-    public function __construct($key)
-    {
-        $this->googleMapApiKey = $key;
-    }
+    protected $results;
 
     /**
      * Store the configuration of the recommendation module.
@@ -76,7 +58,7 @@ class ResultGoogleMapAjax implements RecommendInterface
      */
     public function setConfig($settings)
     {
-        // No special settings
+        // No settings used by default.
     }
 
     /**
@@ -93,7 +75,7 @@ class ResultGoogleMapAjax implements RecommendInterface
      */
     public function init($params, $request)
     {
-        // No action needed here.
+        // No initialization required by default.
     }
 
     /**
@@ -107,27 +89,16 @@ class ResultGoogleMapAjax implements RecommendInterface
      */
     public function process($results)
     {
-        $this->searchObject = $results;
-    }
-
-    /**
-     * Get the Google Maps API key.
-     *
-     * @return string
-     */
-    public function getGoogleMapApiKey()
-    {
-        return $this->googleMapApiKey;
+        $this->results = $results;
     }
 
     /**
-     * Get search parameters
+     * Get results stored in the object.
      *
-     * @return string of params
+     * @return \VuFind\Search\Base\Results
      */
-    public function getSearchParams()
+    public function getResults()
     {
-        // Get search parameters and return them minus the leading ?:
-        return substr($this->searchObject->getUrlQuery()->getParams(false), 1);
+        return $this->results;
     }
 }
diff --git a/module/VuFind/src/VuFind/Recommend/Channels.php b/module/VuFind/src/VuFind/Recommend/Channels.php
new file mode 100644
index 0000000000000000000000000000000000000000..264f09c216f3a21802243c3b15fda6ec3f544631
--- /dev/null
+++ b/module/VuFind/src/VuFind/Recommend/Channels.php
@@ -0,0 +1,43 @@
+<?php
+/**
+ * Channels Recommendations Module
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2017.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * @category VuFind
+ * @package  Recommendations
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @author   Chris Hallberg <challber@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development:plugins:recommendation_modules Wiki
+ */
+namespace VuFind\Recommend;
+
+/**
+ * Channels Recommendations Module
+ *
+ * @category VuFind
+ * @package  Recommendations
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @author   Chris Hallberg <challber@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development:plugins:recommendation_modules Wiki
+ */
+class Channels extends AbstractResultsPassthrough
+{
+}
diff --git a/module/VuFind/src/VuFind/Recommend/DOI.php b/module/VuFind/src/VuFind/Recommend/DOI.php
new file mode 100644
index 0000000000000000000000000000000000000000..f282a25dc5584a14710c368a8d32d901104af85f
--- /dev/null
+++ b/module/VuFind/src/VuFind/Recommend/DOI.php
@@ -0,0 +1,141 @@
+<?php
+/**
+ * DOI Recommendations Module
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2016.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * @category VuFind
+ * @package  Recommendations
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @author   Chris Hallberg <challber@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development:plugins:recommendation_modules Wiki
+ */
+namespace VuFind\Recommend;
+
+/**
+ * DOI Recommendations Module
+ *
+ * This class directs the user to a DOI resolver when appropriate.
+ *
+ * @category VuFind
+ * @package  Recommendations
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @author   Chris Hallberg <challber@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development:plugins:recommendation_modules Wiki
+ */
+class DOI implements RecommendInterface
+{
+    /**
+     * DOI found in search query (or null for none)
+     *
+     * @var string
+     */
+    protected $match = null;
+
+    /**
+     * URL prefix for resolving DOIs
+     *
+     * @var string
+     */
+    protected $prefix;
+
+    /**
+     * Does the DOI in $match exactly match the user's query?
+     *
+     * @var bool
+     */
+    protected $exact = false;
+
+    /**
+     * Store the configuration of the recommendation module.
+     *
+     * @param string $settings Settings from searches.ini.
+     *
+     * @return void
+     */
+    public function setConfig($settings)
+    {
+        $this->prefix = $settings;
+    }
+
+    /**
+     * Called at the end of the Search Params objects' initFromRequest() method.
+     * This method is responsible for setting search parameters needed by the
+     * recommendation module and for reading any existing search parameters that may
+     * be needed.
+     *
+     * @param \VuFind\Search\Base\Params $params  Search parameter object
+     * @param \Zend\StdLib\Parameters    $request Parameter object representing user
+     * request.
+     *
+     * @return void
+     */
+    public function init($params, $request)
+    {
+    }
+
+    /**
+     * Called after the Search Results object has performed its main search.  This
+     * may be used to extract necessary information from the Search Results object
+     * or to perform completely unrelated processing.
+     *
+     * @param \VuFind\Search\Base\Results $results Search results object
+     *
+     * @return void
+     */
+    public function process($results)
+    {
+        $query = $results->getParams()->getDisplayQuery();
+        preg_match('|10\.[^\s/]{4,}/[^\s]{1,}|', $query, $matches);
+        $this->match = isset($matches[0]) ? $matches[0] : null;
+        $this->exact = (null !== $this->match) && ($this->match === $query);
+    }
+
+    /**
+     * Get the matched DOI (or null if no match found)
+     *
+     * @return string
+     */
+    public function getDOI()
+    {
+        return $this->match;
+    }
+
+    /**
+     * Get the URL to resolve the matched DOI (or null if no match found)
+     *
+     * @return string
+     */
+    public function getURL()
+    {
+        return null === $this->match
+            ? null : $this->prefix . urlencode($this->match);
+    }
+
+    /**
+     * Is the DOI returned by getDOI a match to the user's full search query?
+     *
+     * @return bool
+     */
+    public function isFullMatch()
+    {
+        return $this->exact;
+    }
+}
diff --git a/module/VuFind/src/VuFind/Recommend/Factory.php b/module/VuFind/src/VuFind/Recommend/Factory.php
index 23b56b4aec8ca2a05232012058903d40b5824c30..908e115fc76a9e5d54334b611615dd92b5a5aa75 100644
--- a/module/VuFind/src/VuFind/Recommend/Factory.php
+++ b/module/VuFind/src/VuFind/Recommend/Factory.php
@@ -212,21 +212,6 @@ class Factory
         );
     }
 
-    /**
-     * Factory for ResultGoogleMapAjax Recommendations.
-     *
-     * @param ServiceManager $sm Service manager.
-     *
-     * @return ResultGoogleMapAjax
-     */
-    public static function getResultGoogleMapAjax(ServiceManager $sm)
-    {
-        $config = $sm->getServiceLocator()->get('VuFind\Config')->get('config');
-        $key = isset($config->Content->googleMapApiKey)
-            ? $config->Content->googleMapApiKey : null;
-        return new ResultGoogleMapAjax($key);
-    }
-
     /**
      * Factory for SideFacets module.
      *
diff --git a/module/VuFind/src/VuFind/Recommend/MapSelection.php b/module/VuFind/src/VuFind/Recommend/MapSelection.php
index 31a33758bacc5a94368f6ef68f07acd2b76df9fc..eb22e9ae122eae3ebcd02a1b6812f8582ae7ea8e 100644
--- a/module/VuFind/src/VuFind/Recommend/MapSelection.php
+++ b/module/VuFind/src/VuFind/Recommend/MapSelection.php
@@ -52,7 +52,7 @@ class MapSelection implements \VuFind\Recommend\RecommendInterface
      *
      * @var string
      */
-    protected $geoField = 'location_geo';
+    protected $geoField = 'long_lat';
 
     /**
      * Height of search map pane
@@ -234,9 +234,8 @@ class MapSelection implements \VuFind\Recommend\RecommendInterface
                     );
                     $this->selectedCoordinates = $reorder_coords;
                 }
-                $this->searchParams = $results->getUrlQuery()->removeFacet(
-                    $this->geoField, $value[0], false
-                );
+                $this->searchParams = $results->getUrlQuery()
+                    ->removeFacet($this->geoField, $value[0])->getParams(false);
             }
         }
         if ($this->searchParams == null) {
@@ -294,20 +293,6 @@ class MapSelection implements \VuFind\Recommend\RecommendInterface
         return $this->searchParams;
     }
 
-    /**
-     * GetSearchParams no question mark at end
-     *
-     * Return search params without leading question mark and colon.
-     * Copied from ResultGoogleMapAjax.php and chngd name to add NoQ.LMG
-     *
-     * @return string
-     */
-    public function getSearchParamsNoQ()
-    {
-        // Get search parameters and return them minus the leading ?:
-           return substr($this->searchObject->getUrlQuery()->getParams(false), 1);
-    }
-
     /**
      * GetGeoField
      *
diff --git a/module/VuFind/src/VuFind/Recommend/PluginManager.php b/module/VuFind/src/VuFind/Recommend/PluginManager.php
index 4a1270d29491a051d9aaccd967977e74c6743a8b..e340311211c8f9659a2c6f23587a13b6ff4737b7 100644
--- a/module/VuFind/src/VuFind/Recommend/PluginManager.php
+++ b/module/VuFind/src/VuFind/Recommend/PluginManager.php
@@ -26,7 +26,6 @@
  * @link     https://vufind.org/wiki/development:plugins:recommendation_modules Wiki
  */
 namespace VuFind\Recommend;
-use Zend\ServiceManager\ConfigInterface;
 
 /**
  * Recommendation module plugin manager
@@ -42,16 +41,20 @@ class PluginManager extends \VuFind\ServiceManager\AbstractPluginManager
     /**
      * Constructor
      *
-     * @param ConfigInterface $configuration Configuration settings (optional)
+     * Make sure plugins are properly initialized.
+     *
+     * @param mixed $configOrContainerInstance Configuration or container instance
+     * @param array $v3config                  If $configOrContainerInstance is a
+     * container, this value will be passed to the parent constructor.
      */
-    public function __construct(ConfigInterface $configuration = null)
-    {
-        // These plugins are not meant to be shared -- the same module may be used
-        // multiple times with different configurations, so we need to build a new
-        // copy each time the plugin is retrieved.
+    public function __construct($configOrContainerInstance = null,
+        array $v3config = []
+    ) {
+        // These objects are not meant to be shared -- every time we retrieve one,
+        // we are building a brand new object.
         $this->setShareByDefault(false);
 
-        parent::__construct($configuration);
+        parent::__construct($configOrContainerInstance, $v3config);
     }
 
     /**
diff --git a/module/VuFind/src/VuFind/Recommend/RemoveFilters.php b/module/VuFind/src/VuFind/Recommend/RemoveFilters.php
index 9253f8bd17d4f9da7f290b8d37e8579e1b51e841..8f921e9badf8c88ef44aeae8f446476a32c986f7 100644
--- a/module/VuFind/src/VuFind/Recommend/RemoveFilters.php
+++ b/module/VuFind/src/VuFind/Recommend/RemoveFilters.php
@@ -122,7 +122,7 @@ class RemoveFilters implements RecommendInterface
      */
     public function getFilterlessUrl()
     {
-        return $this->results->getUrlQuery()->removeAllFilters();
+        return $this->results->getUrlQuery()->removeAllFilters()->getParams();
     }
 
     /**
diff --git a/module/VuFind/src/VuFind/Recommend/SpellingSuggestions.php b/module/VuFind/src/VuFind/Recommend/SpellingSuggestions.php
index 23675c4f2b3d1c5c0615c0afad46fc6f36f12a43..bd343d2a160e9717f38ad8ecd4aad949d3826735 100644
--- a/module/VuFind/src/VuFind/Recommend/SpellingSuggestions.php
+++ b/module/VuFind/src/VuFind/Recommend/SpellingSuggestions.php
@@ -38,64 +38,6 @@ namespace VuFind\Recommend;
  * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
  * @link     https://vufind.org/wiki/development:plugins:recommendation_modules Wiki
  */
-class SpellingSuggestions implements RecommendInterface
+class SpellingSuggestions extends AbstractResultsPassthrough
 {
-    /**
-     * Search results object.
-     *
-     * @var \VuFind\Search\Base\Results
-     */
-    protected $results;
-
-    /**
-     * Store the configuration of the recommendation module.
-     *
-     * @param string $settings Settings from searches.ini.
-     *
-     * @return void
-     */
-    public function setConfig($settings)
-    {
-        // No settings used at present.
-    }
-
-    /**
-     * Called at the end of the Search Params objects' initFromRequest() method.
-     * This method is responsible for setting search parameters needed by the
-     * recommendation module and for reading any existing search parameters that may
-     * be needed.
-     *
-     * @param \VuFind\Search\Base\Params $params  Search parameter object
-     * @param \Zend\StdLib\Parameters    $request Parameter object representing user
-     * request.
-     *
-     * @return void
-     */
-    public function init($params, $request)
-    {
-    }
-
-    /**
-     * Called after the Search Results object has performed its main search.  This
-     * may be used to extract necessary information from the Search Results object
-     * or to perform completely unrelated processing.
-     *
-     * @param \VuFind\Search\Base\Results $results Search results object
-     *
-     * @return void
-     */
-    public function process($results)
-    {
-        $this->results = $results;
-    }
-
-    /**
-     * Get results stored in the object.
-     *
-     * @return \VuFind\Search\Base\Results
-     */
-    public function getResults()
-    {
-        return $this->results;
-    }
 }
diff --git a/module/VuFind/src/VuFind/Record/Loader.php b/module/VuFind/src/VuFind/Record/Loader.php
index 64aaf7264c0a40bba692c56a821707dc18a369d8..3cda3c8d728b852465f53108e8edf1bf876d16e9 100644
--- a/module/VuFind/src/VuFind/Record/Loader.php
+++ b/module/VuFind/src/VuFind/Record/Loader.php
@@ -43,8 +43,10 @@ use VuFind\Exception\RecordMissing as RecordMissingException,
  * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
  * @link     https://vufind.org Main Site
  */
-class Loader
+class Loader implements \Zend\Log\LoggerAwareInterface
 {
+    use \VuFind\Log\LoggerAwareTrait;
+
     /**
      * Record factory
      *
@@ -131,14 +133,18 @@ class Loader
      * Given an array of IDs and a record source, load a batch of records for
      * that source.
      *
-     * @param array  $ids    Record IDs
-     * @param string $source Record source
+     * @param array  $ids                       Record IDs
+     * @param string $source                    Record source
+     * @param bool   $tolerateBackendExceptions Whether to tolerate backend
+     * exceptions that may be caused by e.g. connection issues or changes in
+     * subcscriptions
      *
      * @throws \Exception
      * @return array
      */
-    public function loadBatchForSource($ids, $source = DEFAULT_SEARCH_BACKEND)
-    {
+    public function loadBatchForSource($ids, $source = DEFAULT_SEARCH_BACKEND,
+        $tolerateBackendExceptions = false
+    ) {
         $cachedRecords = [];
         if (null !== $this->recordCache && $this->recordCache->isPrimary($source)) {
             // Try to load records from cache if source is cachable
@@ -155,8 +161,18 @@ class Loader
         // Try to load the uncached records from the original $source
         $genuineRecords = [];
         if (!empty($ids)) {
-            $genuineRecords = $this->searchService->retrieveBatch($source, $ids)
-                ->getRecords();
+            try {
+                $genuineRecords = $this->searchService->retrieveBatch($source, $ids)
+                    ->getRecords();
+            } catch (\VuFindSearch\Backend\Exception\BackendException $e) {
+                if (!$tolerateBackendExceptions) {
+                    throw $e;
+                }
+                $this->logWarning(
+                    "Exception when trying to retrieve records from $source: "
+                    . $e->getMessage()
+                );
+            }
 
             foreach ($genuineRecords as $genuineRecord) {
                 $key = array_search($genuineRecord->getUniqueId(), $ids);
@@ -187,16 +203,19 @@ class Loader
      * separated source|id strings), load all of the requested records in the
      * requested order.
      *
-     * @param array $ids Array of associative arrays with id/source keys or
-     * strings in source|id format.  In associative array formats, there is
-     * also an optional "extra_fields" key which can be used to pass in data
+     * @param array $ids                       Array of associative arrays with
+     * id/source keys or strings in source|id format.  In associative array formats,
+     * there is also an optional "extra_fields" key which can be used to pass in data
      * formatted as if it belongs to the Solr schema; this is used to create
      * a mock driver object if the real data source is unavailable.
+     * @param bool  $tolerateBackendExceptions Whether to tolerate backend
+     * exceptions that may be caused by e.g. connection issues or changes in
+     * subcscriptions
      *
      * @throws \Exception
      * @return array     Array of record drivers
      */
-    public function loadBatch($ids)
+    public function loadBatch($ids, $tolerateBackendExceptions = false)
     {
         // Sort the IDs by source -- we'll create an associative array indexed by
         // source and record ID which points to the desired position of the indexed
@@ -216,7 +235,9 @@ class Loader
         // Retrieve the records and put them back in order:
         $retVal = [];
         foreach ($idBySource as $source => $details) {
-            $records = $this->loadBatchForSource(array_keys($details), $source);
+            $records = $this->loadBatchForSource(
+                array_keys($details), $source, $tolerateBackendExceptions
+            );
             foreach ($records as $current) {
                 $id = $current->getUniqueId();
                 // In theory, we should be able to assume that $details[$id] is
diff --git a/module/VuFind/src/VuFind/RecordDriver/AbstractBase.php b/module/VuFind/src/VuFind/RecordDriver/AbstractBase.php
index bc04d7bd132eec8df6b97fcef09b0a613a775921..3daa678495d598ab8927fdbcab3dfea058ff8c76 100644
--- a/module/VuFind/src/VuFind/RecordDriver/AbstractBase.php
+++ b/module/VuFind/src/VuFind/RecordDriver/AbstractBase.php
@@ -28,7 +28,6 @@
 namespace VuFind\RecordDriver;
 use VuFind\Exception\LoginRequired as LoginRequiredException,
     VuFind\XSLT\Import\VuFind as ArticleStripper;
-use VuFind\Record\Cache;
 
 /**
  * Abstract base record model.
@@ -43,12 +42,10 @@ use VuFind\Record\Cache;
  */
 abstract class AbstractBase implements \VuFind\Db\Table\DbTableAwareInterface,
     \VuFind\I18n\Translator\TranslatorAwareInterface,
-    \VuFindSearch\Response\RecordInterface,
-    \VuFind\Record\Cache\RecordCacheAwareInterface
+    \VuFindSearch\Response\RecordInterface
 {
     use \VuFind\Db\Table\DbTableAwareTrait;
     use \VuFind\I18n\Translator\TranslatorAwareTrait;
-    use \VuFind\Record\Cache\RecordCacheAwareTrait;
 
     /**
      * Used for identifying search backends
@@ -227,66 +224,6 @@ abstract class AbstractBase implements \VuFind\Db\Table\DbTableAwareInterface,
         }
     }
 
-    /**
-     * Save this record to the user's favorites.
-     *
-     * @param array               $params Array with some or all of these keys:
-     *  <ul>
-     *    <li>mytags - Tag array to associate with record (optional)</li>
-     *    <li>notes - Notes to associate with record (optional)</li>
-     *    <li>list - ID of list to save record into (omit to create new list)</li>
-     *  </ul>
-     * @param \VuFind\Db\Row\User $user   The user saving the record
-     *
-     * @return array list information
-     */
-    public function saveToFavorites($params, $user)
-    {
-        // Validate incoming parameters:
-        if (!$user) {
-            throw new LoginRequiredException('You must be logged in first');
-        }
-
-        // Get or create a list object as needed:
-        $listId = isset($params['list']) ? $params['list'] : '';
-        $table = $this->getDbTable('UserList');
-        if (empty($listId) || $listId == 'NEW') {
-            $list = $table->getNew($user);
-            $list->title = $this->translate('My Favorites');
-            $list->save($user);
-        } else {
-            $list = $table->getExisting($listId);
-            // Validate incoming list ID:
-            if (!$list->editAllowed($user)) {
-                throw new \VuFind\Exception\ListPermission('Access denied.');
-            }
-            $list->rememberLastUsed(); // handled by save() in other case
-        }
-
-        // Get or create a resource object as needed:
-        $resourceTable = $this->getDbTable('Resource');
-        $resource = $resourceTable->findResource(
-            $this->getUniqueId(), $this->getSourceIdentifier(), true, $this
-        );
-
-        // Persist record in the database for "offline" use
-        if ($recordCache = $this->getRecordCache()) {
-            $recordCache->setContext(Cache::CONTEXT_FAVORITE);
-            $recordCache->createOrUpdate(
-                $resource->record_id, $resource->source,
-                $this->getRawData()
-            );
-        }
-
-        // Add the information to the user's account:
-        $user->saveResource(
-            $resource, $list,
-            isset($params['mytags']) ? $params['mytags'] : [],
-            isset($params['notes']) ? $params['notes'] : ''
-        );
-        return ['listId' => $list->id];
-    }
-
     /**
      * Get notes associated with this record in user lists.
      *
@@ -495,15 +432,15 @@ abstract class AbstractBase implements \VuFind\Db\Table\DbTableAwareInterface,
      * useful for checking for the existence of get methods for particular types of
      * data without causing fatal errors.
      *
-     * @param string $method Name of method to call.
-     * @param array  $params Array of parameters to pass to method.
+     * @param string $method  Name of method to call.
+     * @param array  $params  Array of parameters to pass to method.
+     * @param mixed  $default A default value to return if the method is not
+     * callable
      *
      * @return mixed
      */
-    public function tryMethod($method, $params = [])
+    public function tryMethod($method, $params = [], $default = null)
     {
-        return is_callable([$this, $method])
-            ? call_user_func_array([$this, $method], $params)
-            : null;
+        return is_callable([$this, $method]) ? $this->$method(...$params) : $default;
     }
 }
diff --git a/module/VuFind/src/VuFind/RecordDriver/EDS.php b/module/VuFind/src/VuFind/RecordDriver/EDS.php
index c5c2689bd7323c59105cf6b55c4a1fd6e5fa1fe8..121ffc3c9341f8372842124136bc592feacd3009 100644
--- a/module/VuFind/src/VuFind/RecordDriver/EDS.php
+++ b/module/VuFind/src/VuFind/RecordDriver/EDS.php
@@ -269,7 +269,7 @@ class EDS extends SolrDefault
     {
         if (isset($this->fields['FullText']['Links'])) {
             foreach ($this->fields['FullText']['Links'] as $link) {
-                if (isset($link['Type'])
+                if (!empty($link['Type']) && !empty($link['Url'])
                     && in_array($link['Type'], $this->pdfTypes)
                 ) {
                     return $link['Url']; // return PDF link
diff --git a/module/VuFind/src/VuFind/RecordDriver/EIT.php b/module/VuFind/src/VuFind/RecordDriver/EIT.php
index 009d4d53f3b6a258a4b3d9043bb40ba4ee92377e..64b471f86924d224ce140fe4d1d6afd1121c56b4 100644
--- a/module/VuFind/src/VuFind/RecordDriver/EIT.php
+++ b/module/VuFind/src/VuFind/RecordDriver/EIT.php
@@ -83,9 +83,15 @@ class EIT extends SolrDefault
      * returned as an array of chunks, increasing from least specific to most
      * specific.
      *
+     * @param bool $extended Whether to return a keyed array with the following
+     * keys:
+     * - heading: the actual subject heading chunks
+     * - type: heading type
+     * - source: source vocabulary
+     *
      * @return array
      */
-    public function getAllSubjectHeadings()
+    public function getAllSubjectHeadings($extended = false)
     {
         $su = isset($this->controlInfo['artinfo']['su'])
             ? $this->controlInfo['artinfo']['su'] : [];
@@ -94,7 +100,9 @@ class EIT extends SolrDefault
         // format, so we'll just send each value as a single chunk.
         $retval = [];
         foreach ($su as $s) {
-            $retval[] = [$s];
+            $retval[] = $extended
+                ? ['heading' => [$s], 'type' => '', 'source' => '']
+                : [$s];
         }
         return $retval;
     }
diff --git a/module/VuFind/src/VuFind/RecordDriver/IlsAwareTrait.php b/module/VuFind/src/VuFind/RecordDriver/IlsAwareTrait.php
new file mode 100644
index 0000000000000000000000000000000000000000..b0a6cadc8aaee795c38f81d7566e139aa66d6196
--- /dev/null
+++ b/module/VuFind/src/VuFind/RecordDriver/IlsAwareTrait.php
@@ -0,0 +1,155 @@
+<?php
+/**
+ * ILS support for MARC and other types of records.
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2010.
+ * Copyright (C) The National Library of Finland 2015.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * @category VuFind
+ * @package  RecordDrivers
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @author   Ere Maijala <ere.maijala@helsinki.fi>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development:plugins:record_drivers Wiki
+ */
+namespace VuFind\RecordDriver;
+
+/**
+ * ILS support for MARC and other types of records.
+ *
+ * @category VuFind
+ * @package  RecordDrivers
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @author   Ere Maijala <ere.maijala@helsinki.fi>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development:plugins:record_drivers Wiki
+ */
+trait IlsAwareTrait
+{
+    /**
+     * ILS connection
+     *
+     * @var \VuFind\ILS\Connection
+     */
+    protected $ils = null;
+
+    /**
+     * Hold logic
+     *
+     * @var \VuFind\ILS\Logic\Holds
+     */
+    protected $holdLogic;
+
+    /**
+     * Title hold logic
+     *
+     * @var \VuFind\ILS\Logic\TitleHolds
+     */
+    protected $titleHoldLogic;
+
+    /**
+     * Attach an ILS connection and related logic to the driver
+     *
+     * @param \VuFind\ILS\Connection       $ils            ILS connection
+     * @param \VuFind\ILS\Logic\Holds      $holdLogic      Hold logic handler
+     * @param \VuFind\ILS\Logic\TitleHolds $titleHoldLogic Title hold logic handler
+     *
+     * @return void
+     */
+    public function attachILS(\VuFind\ILS\Connection $ils,
+        \VuFind\ILS\Logic\Holds $holdLogic,
+        \VuFind\ILS\Logic\TitleHolds $titleHoldLogic
+    ) {
+        $this->ils = $ils;
+        $this->holdLogic = $holdLogic;
+        $this->titleHoldLogic = $titleHoldLogic;
+    }
+
+    /**
+     * Do we have an attached ILS connection?
+     *
+     * @return bool
+     */
+    protected function hasILS()
+    {
+        return null !== $this->ils;
+    }
+
+    /**
+     * Get an array of information about record holdings, obtained in real-time
+     * from the ILS.
+     *
+     * @return array
+     */
+    public function getRealTimeHoldings()
+    {
+        return $this->hasILS() ? $this->holdLogic->getHoldings(
+            $this->getUniqueID(), $this->tryMethod('getConsortialIDs')
+        ) : [];
+    }
+
+    /**
+     * Get an array of information about record history, obtained in real-time
+     * from the ILS.
+     *
+     * @return array
+     */
+    public function getRealTimeHistory()
+    {
+        // Get Acquisitions Data
+        if (!$this->hasILS()) {
+            return [];
+        }
+        try {
+            return $this->ils->getPurchaseHistory($this->getUniqueID());
+        } catch (ILSException $e) {
+            return [];
+        }
+    }
+
+    /**
+     * Get a link for placing a title level hold.
+     *
+     * @return mixed A url if a hold is possible, boolean false if not
+     */
+    public function getRealTimeTitleHold()
+    {
+        if ($this->hasILS()) {
+            $biblioLevel = strtolower($this->tryMethod('getBibliographicLevel'));
+            if ("monograph" == $biblioLevel || strstr($biblioLevel, "part")) {
+                if ($this->ils->getTitleHoldsMode() != "disabled") {
+                    return $this->titleHoldLogic->getHold($this->getUniqueID());
+                }
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * Returns true if the record supports real-time AJAX status lookups.
+     *
+     * @return bool
+     */
+    public function supportsAjaxStatus()
+    {
+        // as AJAX status lookups are done via the ILS AJAX status lookup support is
+        // only given if the ILS is available for this record
+        return $this->hasILS();
+    }
+}
diff --git a/module/VuFind/src/VuFind/RecordDriver/PluginManager.php b/module/VuFind/src/VuFind/RecordDriver/PluginManager.php
index 31a36761fdab9ee1a5db110d18205b9ed2fe075c..e55ce0ab33d9e06691d99dec1b28235463b6eee0 100644
--- a/module/VuFind/src/VuFind/RecordDriver/PluginManager.php
+++ b/module/VuFind/src/VuFind/RecordDriver/PluginManager.php
@@ -26,7 +26,6 @@
  * @link     https://vufind.org/wiki/development:plugins:record_drivers Wiki
  */
 namespace VuFind\RecordDriver;
-use Zend\ServiceManager\ConfigInterface;
 
 /**
  * Record driver plugin manager
@@ -42,15 +41,20 @@ class PluginManager extends \VuFind\ServiceManager\AbstractPluginManager
     /**
      * Constructor
      *
-     * @param ConfigInterface $configuration Configuration settings (optional)
+     * Make sure plugins are properly initialized.
+     *
+     * @param mixed $configOrContainerInstance Configuration or container instance
+     * @param array $v3config                  If $configOrContainerInstance is a
+     * container, this value will be passed to the parent constructor.
      */
-    public function __construct(ConfigInterface $configuration = null)
-    {
-        // Record drivers are not meant to be shared -- every time we retrieve one,
+    public function __construct($configOrContainerInstance = null,
+        array $v3config = []
+    ) {
+        // These objects are not meant to be shared -- every time we retrieve one,
         // we are building a brand new object.
         $this->setShareByDefault(false);
 
-        parent::__construct($configuration);
+        parent::__construct($configOrContainerInstance, $v3config);
 
         // Add an initializer for setting up hierarchies
         $initializer = function ($instance, $manager) {
diff --git a/module/VuFind/src/VuFind/RecordDriver/Primo.php b/module/VuFind/src/VuFind/RecordDriver/Primo.php
index 3641155241c924bd18b0aa685c379593b3657ba5..fee58726efcf9589f245028bf0e25f587dbb5f5d 100644
--- a/module/VuFind/src/VuFind/RecordDriver/Primo.php
+++ b/module/VuFind/src/VuFind/RecordDriver/Primo.php
@@ -92,14 +92,23 @@ class Primo extends SolrDefault
      * Get an array of all subject headings associated with the record
      * (may be empty).
      *
+     * @param bool $extended Whether to return a keyed array with the following
+     * keys:
+     * - heading: the actual subject heading chunks
+     * - type: heading type
+     * - source: source vocabulary
+     *
      * @return array
      */
-    public function getAllSubjectHeadings()
+    public function getAllSubjectHeadings($extended = false)
     {
         $base = isset($this->fields['subjects'])
             ? $this->fields['subjects'] : [];
-        $callback = function ($str) {
-            return array_map('trim', explode(' -- ', $str));
+        $callback = function ($str) use ($extended) {
+            $s = array_map('trim', explode(' -- ', $str));
+            return $extended
+                ? ['heading' => $s, 'type' => '', 'source' => '']
+                : $s;
         };
         return array_map($callback, $base);
     }
diff --git a/module/VuFind/src/VuFind/RecordDriver/SolrDefault.php b/module/VuFind/src/VuFind/RecordDriver/SolrDefault.php
index 85ceedb4e016bd1497956d7dcaa1c08085c7822c..5d8d0c9411e82acb512a3da3bebdb0beed6721b1 100644
--- a/module/VuFind/src/VuFind/RecordDriver/SolrDefault.php
+++ b/module/VuFind/src/VuFind/RecordDriver/SolrDefault.php
@@ -199,9 +199,15 @@ class SolrDefault extends AbstractBase
      * returned as an array of chunks, increasing from least specific to most
      * specific.
      *
+     * @param bool $extended Whether to return a keyed array with the following
+     * keys:
+     * - heading: the actual subject heading chunks
+     * - type: heading type
+     * - source: source vocabulary
+     *
      * @return array
      */
-    public function getAllSubjectHeadings()
+    public function getAllSubjectHeadings($extended = false)
     {
         $headings = [];
         foreach (['topic', 'geographic', 'genre', 'era'] as $field) {
@@ -213,8 +219,10 @@ class SolrDefault extends AbstractBase
         // The Solr index doesn't currently store subject headings in a broken-down
         // format, so we'll just send each value as a single chunk.  Other record
         // drivers (i.e. MARC) can offer this data in a more granular format.
-        $callback = function ($i) {
-            return [$i];
+        $callback = function ($i) use ($extended) {
+            return $extended
+                ? ['heading' => [$i], 'type' => '', 'source' => '']
+                : [$i];
         };
         return array_map($callback, array_unique($headings));
     }
@@ -242,6 +250,51 @@ class SolrDefault extends AbstractBase
         return null;
     }
 
+    /**
+     * Get Author Information with Associated Data Fields
+     *
+     * @param string $index      The author index [primary, corporate, or secondary]
+     * used to construct a method name for retrieving author data (e.g.
+     * getPrimaryAuthors).
+     * @param array  $dataFields An array of fields to used to construct method
+     * names for retrieving author-related data (e.g., if you pass 'role' the
+     * data method will be similar to getPrimaryAuthorsRoles). This value will also
+     * be used as a key associated with each author in the resulting data array.
+     *
+     * @return array
+     */
+    public function getAuthorDataFields($index, $dataFields = [])
+    {
+        $data = $dataFieldValues = [];
+
+        // Collect author data
+        $authorMethod = sprintf('get%sAuthors', ucfirst($index));
+        $authors = $this->tryMethod($authorMethod, [], []);
+
+        // Collect attribute data
+        foreach ($dataFields as $field) {
+            $fieldMethod = $authorMethod . ucfirst($field) . 's';
+            $dataFieldValues[$field] = $this->tryMethod($fieldMethod, [], []);
+        }
+
+        // Match up author and attribute data (this assumes that the attribute
+        // arrays have the same indices as the author array; i.e. $author[$i]
+        // has $dataFieldValues[$attribute][$i].
+        foreach ($authors as $i => $author) {
+            if (!isset($data[$author])) {
+                $data[$author] = [];
+            }
+
+            foreach ($dataFieldValues as $field => $dataFieldValue) {
+                if (!empty($dataFieldValue[$i])) {
+                    $data[$author][$field][] = $dataFieldValue[$i];
+                }
+            }
+        }
+
+        return $data;
+    }
+
     /**
      * Get award notes for the record.
      *
@@ -420,29 +473,23 @@ class SolrDefault extends AbstractBase
      * Deduplicate author information into associative array with main/corporate/
      * secondary keys.
      *
+     * @param array $dataFields An array of extra data fields to retrieve (see
+     * getAuthorDataFields)
+     *
      * @return array
      */
-    public function getDeduplicatedAuthors()
-    {
-        $authors = [
-            'main' => $this->getAuthorRolesArray(
-                $this->getPrimaryAuthors(),
-                $this->getPrimaryAuthorsRoles()
-            ),
-            'corporate' => $this->getAuthorRolesArray(
-                $this->getCorporateAuthors(),
-                $this->getCorporateAuthorsRoles()
-            ),
-            'secondary' => $this->getAuthorRolesArray(
-                $this->getSecondaryAuthors(),
-                $this->getSecondaryAuthorsRoles()
-            )
-        ];
+    public function getDeduplicatedAuthors($dataFields = ['role'])
+    {
+        $authors = [];
+        foreach (['primary', 'secondary', 'corporate'] as $type) {
+            $authors[$type] = $this->getAuthorDataFields($type, $dataFields);
+        }
 
         // deduplicate
         $dedup = function (&$array1, &$array2) {
             if (!empty($array1) && !empty($array2)) {
-                foreach ($array1 as $author => $roles) {
+                $keys = array_keys($array1);
+                foreach ($keys as $author) {
                     if (isset($array2[$author])) {
                         $array1[$author] = array_merge(
                             $array1[$author],
@@ -454,52 +501,27 @@ class SolrDefault extends AbstractBase
             }
         };
 
-        $dedup($authors['main'], $authors['corporate']);
+        $dedup($authors['primary'], $authors['corporate']);
         $dedup($authors['secondary'], $authors['corporate']);
-        $dedup($authors['main'], $authors['secondary']);
+        $dedup($authors['primary'], $authors['secondary']);
 
-        $dedup_roles = function (&$array) {
-            foreach ($array as $author => $roles) {
-                if (is_array($roles)) {
-                    $array[$author] = array_unique($roles);
+        $dedup_data = function (&$array) {
+            foreach ($array as $author => $data) {
+                foreach ($data as $field => $values) {
+                    if (is_array($values)) {
+                        $array[$author][$field] = array_unique($values);
+                    }
                 }
             }
         };
 
-        $dedup_roles($authors['main']);
-        $dedup_roles($authors['secondary']);
-        $dedup_roles($authors['corporate']);
+        $dedup_data($authors['primary']);
+        $dedup_data($authors['secondary']);
+        $dedup_data($authors['corporate']);
 
         return $authors;
     }
 
-    /**
-     * Helper function to restructure author arrays including relators
-     *
-     * @param array $authors Array of authors
-     * @param array $roles   Array with relators of authors
-     *
-     * @return array
-     */
-    protected function getAuthorRolesArray($authors = [], $roles = [])
-    {
-        $authorRolesArray = [];
-
-        if (!empty($authors)) {
-            foreach ($authors as $index => $author) {
-                if (!isset($authorRolesArray[$author])) {
-                    $authorRolesArray[$author] = [];
-                }
-                if (isset($roles[$index]) && !empty($roles[$index])
-                ) {
-                    $authorRolesArray[$author][] = $roles[$index];
-                }
-            }
-        }
-
-        return $authorRolesArray;
-    }
-
     /**
      * Get the edition of the current record.
      *
@@ -630,7 +652,7 @@ class SolrDefault extends AbstractBase
                 && is_array($this->highlightDetails)
             ) {
                 foreach ($this->highlightDetails as $key => $value) {
-                    if (!in_array($key, $this->forbiddenSnippetFields)) {
+                    if ($value && !in_array($key, $this->forbiddenSnippetFields)) {
                         return [
                             'snippet' => $value[0],
                             'caption' => $this->getSnippetCaption($key)
@@ -1176,7 +1198,7 @@ class SolrDefault extends AbstractBase
     public function getRealTimeHoldings()
     {
         // Not supported by the Solr index -- implement in child classes.
-        return [];
+        return ['holdings' => []];
     }
 
     /**
@@ -1327,7 +1349,9 @@ class SolrDefault extends AbstractBase
             'author'     => mb_substr($this->getPrimaryAuthor(), 0, 300, 'utf-8'),
             'callnumber' => $this->getCallNumber(),
             'size'       => $size,
-            'title'      => mb_substr($this->getTitle(), 0, 300, 'utf-8')
+            'title'      => mb_substr($this->getTitle(), 0, 300, 'utf-8'),
+            'recordid'   => $this->getUniqueID(),
+            'source'   => $this->getSourceIdentifier(),
         ];
         if ($isbn = $this->getCleanISBN()) {
             $arr['isbn'] = $isbn;
@@ -1796,17 +1820,6 @@ class SolrDefault extends AbstractBase
             ? $this->fields['title_sort'] : parent::getSortTitle();
     }
 
-    /**
-     * Get longitude/latitude values (or empty array if not available).
-     *
-     * @return array
-     */
-    public function getLongLat()
-    {
-        return isset($this->fields['long_lat'])
-            ? $this->fields['long_lat'] : [];
-    }
-
     /**
      * Get schema.org type mapping, an array of sub-types of
      * http://schema.org/CreativeWork, defaulting to CreativeWork
@@ -1900,7 +1913,10 @@ class SolrDefault extends AbstractBase
         $query = new \VuFindSearch\Query\Query(
             'hierarchy_parent_id:"' . $safeId . '"'
         );
-        return $this->searchService->search('Solr', $query, 0, 0)->getTotal();
+        // Disable highlighting for efficiency; not needed here:
+        $params = new \VuFindSearch\ParamBag(['hl' => ['false']]);
+        return $this->searchService->search('Solr', $query, 0, 0, $params)
+            ->getTotal();
     }
 
     /**
@@ -1922,8 +1938,8 @@ class SolrDefault extends AbstractBase
      */
     public function getGeoLocation()
     {
-        return isset($this->fields['location_geo'])
-            ? $this->fields['location_geo'] : [];
+        return isset($this->fields['long_lat'])
+            ? $this->fields['long_lat'] : [];
     }
 
     /**
diff --git a/module/VuFind/src/VuFind/RecordDriver/SolrMarc.php b/module/VuFind/src/VuFind/RecordDriver/SolrMarc.php
index 9e788f26e8012c7ea77c5c6961ef77e8d58b990f..1e9d69951794405c1a67d3fccb93d57ce12419b4 100644
--- a/module/VuFind/src/VuFind/RecordDriver/SolrMarc.php
+++ b/module/VuFind/src/VuFind/RecordDriver/SolrMarc.php
@@ -44,6 +44,8 @@ use VuFind\Exception\ILS as ILSException,
  */
 class SolrMarc extends SolrDefault
 {
+    use IlsAwareTrait;
+
     /**
      * MARC record. Access only via getMarcRecord() as this is initialized lazily.
      *
@@ -52,25 +54,40 @@ class SolrMarc extends SolrDefault
     protected $lazyMarcRecord = null;
 
     /**
-     * ILS connection
-     *
-     * @var \VuFind\ILS\Connection
-     */
-    protected $ils = null;
-
-    /**
-     * Hold logic
+     * Fields that may contain subject headings, and their descriptions
      *
-     * @var \VuFind\ILS\Logic\Holds
+     * @var array
      */
-    protected $holdLogic;
+    protected $subjectFields = [
+        '600' => 'personal name',
+        '610' => 'corporate name',
+        '611' => 'meeting name',
+        '630' => 'uniform title',
+        '648' => 'chronological',
+        '650' => 'topic',
+        '651' => 'geographic',
+        '653' => '',
+        '655' => 'genre/form',
+        '656' => 'occupation'
+    ];
 
     /**
-     * Title hold logic
+     * Mappings from subject source indicators (2nd indicator of subject fields in
+     * MARC 21) to the their codes.
      *
-     * @var \VuFind\ILS\Logic\TitleHolds
+     * @var  array
+     * @link https://www.loc.gov/marc/bibliographic/bd6xx.html     Subject field docs
+     * @link https://www.loc.gov/standards/sourcelist/subject.html Code list
      */
-    protected $titleHoldLogic;
+    protected $subjectSources = [
+        '0' => 'lcsh',
+        '1' => 'lcshac',
+        '2' => 'mesh',
+        '3' => 'nal',
+        '4' => 'unknown',
+        '5' => 'cash',
+        '6' => 'rvm'
+    ];
 
     /**
      * Get access restriction notes for the record.
@@ -87,20 +104,21 @@ class SolrMarc extends SolrDefault
      * returned as an array of chunks, increasing from least specific to most
      * specific.
      *
+     * @param bool $extended Whether to return a keyed array with the following
+     * keys:
+     * - heading: the actual subject heading chunks
+     * - type: heading type
+     * - source: source vocabulary
+     *
      * @return array
      */
-    public function getAllSubjectHeadings()
+    public function getAllSubjectHeadings($extended = false)
     {
-        // These are the fields that may contain subject headings:
-        $fields = [
-            '600', '610', '611', '630', '648', '650', '651', '653', '655', '656'
-        ];
-
         // This is all the collected data:
         $retval = [];
 
         // Try each MARC field one at a time:
-        foreach ($fields as $field) {
+        foreach ($this->subjectFields as $field => $fieldType) {
             // Do we have any results for the current field?  If not, try the next.
             $results = $this->getMarcRecord()->getFields($field);
             if (!$results) {
@@ -124,7 +142,25 @@ class SolrMarc extends SolrDefault
                     }
                     // If we found at least one chunk, add a heading to our result:
                     if (!empty($current)) {
-                        $retval[] = $current;
+                        if ($extended) {
+                            $sourceIndicator = $result->getIndicator(2);
+                            $source = '';
+                            if (isset($this->subjectSources[$sourceIndicator])) {
+                                $source = $this->subjectSources[$sourceIndicator];
+                            } else {
+                                $source = $result->getSubfield('2');
+                                if ($source) {
+                                    $source = $source->getData();
+                                }
+                            }
+                            $retval[] = [
+                                'heading' => $current,
+                                'type' => $fieldType,
+                                'source' => $source ?: ''
+                            ];
+                        } else {
+                            $retval[] = $current;
+                        }
                     }
                 }
             }
@@ -226,6 +262,19 @@ class SolrMarc extends SolrDefault
         return $matches;
     }
 
+    /**
+     * Return full record as filtered XML for public APIs.
+     *
+     * @return string
+     */
+    public function getFilteredXML()
+    {
+        $record = clone($this->getMarcRecord());
+        // The default implementation does not filter out any fields
+        // $record->deleteFields('9', true);
+        return $record->toXML();
+    }
+
     /**
      * Get notes on finding aids related to the record.
      *
@@ -986,97 +1035,6 @@ class SolrMarc extends SolrDefault
         return parent::getXML($format, $baseUrl, $recordLink);
     }
 
-    /**
-     * Attach an ILS connection and related logic to the driver
-     *
-     * @param \VuFind\ILS\Connection       $ils            ILS connection
-     * @param \VuFind\ILS\Logic\Holds      $holdLogic      Hold logic handler
-     * @param \VuFind\ILS\Logic\TitleHolds $titleHoldLogic Title hold logic handler
-     *
-     * @return void
-     */
-    public function attachILS(\VuFind\ILS\Connection $ils,
-        \VuFind\ILS\Logic\Holds $holdLogic,
-        \VuFind\ILS\Logic\TitleHolds $titleHoldLogic
-    ) {
-        $this->ils = $ils;
-        $this->holdLogic = $holdLogic;
-        $this->titleHoldLogic = $titleHoldLogic;
-    }
-
-    /**
-     * Do we have an attached ILS connection?
-     *
-     * @return bool
-     */
-    protected function hasILS()
-    {
-        return null !== $this->ils;
-    }
-
-    /**
-     * Get an array of information about record holdings, obtained in real-time
-     * from the ILS.
-     *
-     * @return array
-     */
-    public function getRealTimeHoldings()
-    {
-        return $this->hasILS() ? $this->holdLogic->getHoldings(
-            $this->getUniqueID(), $this->getConsortialIDs()
-        ) : [];
-    }
-
-    /**
-     * Get an array of information about record history, obtained in real-time
-     * from the ILS.
-     *
-     * @return array
-     */
-    public function getRealTimeHistory()
-    {
-        // Get Acquisitions Data
-        if (!$this->hasILS()) {
-            return [];
-        }
-        try {
-            return $this->ils->getPurchaseHistory($this->getUniqueID());
-        } catch (ILSException $e) {
-            return [];
-        }
-    }
-
-    /**
-     * Get a link for placing a title level hold.
-     *
-     * @return mixed A url if a hold is possible, boolean false if not
-     */
-    public function getRealTimeTitleHold()
-    {
-        if ($this->hasILS()) {
-            $biblioLevel = strtolower($this->getBibliographicLevel());
-            if ("monograph" == $biblioLevel || strstr($biblioLevel, "part")) {
-                if ($this->ils->getTitleHoldsMode() != "disabled") {
-                    return $this->titleHoldLogic->getHold($this->getUniqueID());
-                }
-            }
-        }
-
-        return false;
-    }
-
-    /**
-     * Returns true if the record supports real-time AJAX status lookups.
-     *
-     * @return bool
-     */
-    public function supportsAjaxStatus()
-    {
-        // as AJAX status lookups are done via the ILS AJAX status lookup support is
-        // only given if the ILS is available for this record
-        return $this->hasILS();
-    }
-
     /**
      * Get access to the raw File_MARC object.
      *
diff --git a/module/VuFind/src/VuFind/RecordDriver/Summon.php b/module/VuFind/src/VuFind/RecordDriver/Summon.php
index e229322991fa06c132ce99e8cc9ecacf4004e6b8..79b49428cca6cf7a8f2c0f29bf04044f6a222c84 100644
--- a/module/VuFind/src/VuFind/RecordDriver/Summon.php
+++ b/module/VuFind/src/VuFind/RecordDriver/Summon.php
@@ -38,6 +38,18 @@ namespace VuFind\RecordDriver;
  */
 class Summon extends SolrDefault
 {
+    /**
+     * Fields that may contain subject headings, and their descriptions
+     *
+     * @var array
+     */
+    protected $subjectFields = [
+        'SubjectTerms' => 'topic',
+        'TemporalSubjectTerms' => 'chronological',
+        'GeographicLocations' => 'geographic',
+        'Keywords' => 'keyword',
+    ];
+
     /**
      * Date converter
      *
@@ -50,32 +62,31 @@ class Summon extends SolrDefault
      * returned as an array of chunks, increasing from least specific to most
      * specific.
      *
+     * @param bool $extended Whether to return a keyed array with the following
+     * keys:
+     * - heading: the actual subject heading chunks
+     * - type: heading type
+     * - source: source vocabulary
+     *
      * @return array
      */
-    public function getAllSubjectHeadings()
+    public function getAllSubjectHeadings($extended = false)
     {
         $retval = [];
-        $topic = isset($this->fields['SubjectTerms']) ?
-            $this->fields['SubjectTerms'] : [];
-        $temporal = isset($this->fields['TemporalSubjectTerms']) ?
-            $this->fields['TemporalSubjectTerms'] : [];
-        $geo = isset($this->fields['GeographicLocations']) ?
-            $this->fields['GeographicLocations'] : [];
-        $key = isset($this->fields['Keywords']) ?
-            $this->fields['Keywords'] : [];
 
-        $retval = [];
-        foreach ($topic as $t) {
-            $retval[] = [trim($t)];
-        }
-        foreach ($temporal as $t) {
-            $retval[] = [trim($t)];
-        }
-        foreach ($geo as $g) {
-            $retval[] = [trim($g)];
-        }
-        foreach ($key as $k) {
-            $retval[] = [trim($k)];
+        foreach ($this->subjectFields as $field => $fieldType) {
+            if (!isset($this->fields[$field])) {
+                continue;
+            }
+            foreach ($this->fields[$field] as $topic) {
+                $topic = trim($topic);
+                $retval[] = $extended
+                    ? [
+                        'heading' => [$topic],
+                        'type' => $fieldType,
+                        'source' => ''
+                    ] : [$topic];
+            }
         }
         return $retval;
     }
diff --git a/module/VuFind/src/VuFind/RecordTab/Factory.php b/module/VuFind/src/VuFind/RecordTab/Factory.php
index f37187e7cc78f947df08acd900dae1939cb0310d..b2be0188d60282f04f3c5056e7593cce63a21ceb 100644
--- a/module/VuFind/src/VuFind/RecordTab/Factory.php
+++ b/module/VuFind/src/VuFind/RecordTab/Factory.php
@@ -180,9 +180,7 @@ class Factory
         $mapType = isset($config->Content->recordMap)
             ? $config->Content->recordMap : null;
         $options = [];
-        $optionFields = [
-            'displayCoords', 'mapLabels', 'googleMapApiKey'
-        ];
+        $optionFields = ['displayCoords', 'mapLabels'];
         foreach ($optionFields as $field) {
             if (isset($config->Content->$field)) {
                 $options[$field] = $config->Content->$field;
diff --git a/module/VuFind/src/VuFind/RecordTab/Map.php b/module/VuFind/src/VuFind/RecordTab/Map.php
index 58193373d31ceb86a6b7b23e5481fd143bba652a..db8b69a3452444207e4f6065b506d097237a20c8 100644
--- a/module/VuFind/src/VuFind/RecordTab/Map.php
+++ b/module/VuFind/src/VuFind/RecordTab/Map.php
@@ -61,30 +61,16 @@ class Map extends AbstractBase
      */
     protected $mapLabels = null;
 
-    /**
-     * Google Maps API key.
-     *
-     * @var string
-     */
-    protected $googleMapApiKey = null;
-
     /**
      * Constructor
      *
-     * @param string $mapType Map provider (valid options: 'google' or 'openlayers';
+     * @param string $mapType Map provider (valid options: 'openlayers';
      * null to disable this feature)
      * @param array  $options Additional settings
      */
     public function __construct($mapType = null, $options = [])
     {
         switch (trim(strtolower($mapType))) {
-        case 'google':
-            // Confirm API key, then fall through to 'openlayers' case for
-            // other standard behavior:
-            if (empty($options['googleMapApiKey'])) {
-                throw new \Exception('Google API key must be set in config.ini');
-            }
-            $this->googleMapApiKey = $options['googleMapApiKey'];
         case 'openlayers':
             $this->mapType = trim(strtolower($mapType));
             $legalOptions = ['displayCoords', 'mapLabels'];
@@ -128,16 +114,6 @@ class Map extends AbstractBase
         return $this->mapType;
     }
 
-    /**
-     * Get the Google Maps API key.
-     *
-     * @return string
-     */
-    public function getGoogleMapApiKey()
-    {
-        return $this->googleMapApiKey;
-    }
-
     /**
      * Is this tab active?
      *
@@ -148,41 +124,10 @@ class Map extends AbstractBase
         if ($this->mapType == 'openlayers') {
             $geocoords = $this->getRecordDriver()->tryMethod('getGeoLocation');
             return !empty($geocoords);
-        } else if ($this->mapType == 'google') {
-            $longLat = $this->getRecordDriver()->tryMethod('getLongLat');
-            return !empty($longLat);
         }
         return false;
     }
 
-    /**
-     * Get the JSON needed to display the record on a Google map.
-     *
-     * @return string
-     */
-    public function getGoogleMapMarker()
-    {
-        $longLat = $this->getRecordDriver()->tryMethod('getLongLat');
-        if (empty($longLat)) {
-            return json_encode([]);
-        }
-        $markers = [];
-        $mapDisplayLabels = $this->getMapLabels();
-        foreach ($longLat as $key => $value) {
-            $coordval = explode(',', $value);
-            $label = isset($mapDisplayLabels[$key])
-                ? $mapDisplayLabels[$key] : '';
-            $markers[] = [
-                [
-                    'title' => $label,
-                    'lon' => $coordval[0],
-                    'lat' => $coordval[1]
-                ]
-            ];
-        }
-        return json_encode($markers);
-    }
-
     /**
      * Get the bbox-geo coordinates.
      *
@@ -195,8 +140,8 @@ class Map extends AbstractBase
             return [];
         }
         $coordarray = [];
-        /* Extract coordinates from location_geo field */
-        foreach ($geoCoords as $key => $value) {
+        /* Extract coordinates from long_lat field */
+        foreach ($geoCoords as $value) {
             $match = [];
             if (preg_match('/ENVELOPE\((.*),(.*),(.*),(.*)\)/', $value, $match)) {
                 $lonW = (float)$match[1];
@@ -309,7 +254,7 @@ class Map extends AbstractBase
             $mapDisplayLabels = $this->getMapLabels();
         }
         // Pass coordinates, display coordinates, and labels
-        foreach ($geoCoords as $key => $value) {
+        foreach (array_keys($geoCoords) as $key) {
             $mapCoords = '';
             $mapLabel = '';
             if ($this->displayCoords) {
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/Statistics/Driver/PluginManagerTest.php b/module/VuFind/src/VuFind/Related/Channels.php
similarity index 53%
rename from module/VuFind/tests/unit-tests/src/VuFindTest/Statistics/Driver/PluginManagerTest.php
rename to module/VuFind/src/VuFind/Related/Channels.php
index d7637770909c9cdef42193a2ec86b83d6ec64181..16e4661c0746482eaef4c30893d6b1bd3d7adfbe 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/Statistics/Driver/PluginManagerTest.php
+++ b/module/VuFind/src/VuFind/Related/Channels.php
@@ -1,10 +1,10 @@
 <?php
 /**
- * Statistics Driver Plugin Manager Test Class
+ * Related Records: Link to Channels
  *
  * PHP version 5
  *
- * Copyright (C) Villanova University 2010.
+ * Copyright (C) Villanova University 2017.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2,
@@ -20,47 +20,51 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
  * @category VuFind
- * @package  Tests
+ * @package  Related_Records
  * @author   Demian Katz <demian.katz@villanova.edu>
  * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
- * @link     https://vufind.org/wiki/development:testing:unit_tests Wiki
+ * @link     https://vufind.org/wiki/development:plugins:related_records_modules Wiki
  */
-namespace VuFindTest\Statistics\Driver;
-use VuFind\Statistics\Driver\PluginManager;
+namespace VuFind\Related;
 
 /**
- * Statistics Driver Plugin Manager Test Class
+ * Related Records: Link to Channels
  *
  * @category VuFind
- * @package  Tests
+ * @package  Related_Records
  * @author   Demian Katz <demian.katz@villanova.edu>
  * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
- * @link     https://vufind.org/wiki/development:testing:unit_tests Wiki
+ * @link     https://vufind.org/wiki/development:plugins:related_records_modules Wiki
  */
-class PluginManagerTest extends \VuFindTest\Unit\TestCase
+class Channels implements RelatedInterface
 {
     /**
-     * Test results.
+     * Record driver
+     *
+     * @var \VuFind\RecordDriver\AbstractBase
+     */
+    protected $driver;
+
+    /**
+     * Establishes base settings for making recommendations.
+     *
+     * @param string                            $settings Settings from config.ini
+     * @param \VuFind\RecordDriver\AbstractBase $driver   Record driver object
      *
      * @return void
      */
-    public function testShareByDefault()
+    public function init($settings, $driver)
     {
-        $pm = new PluginManager(null);
-        $this->assertFalse($pm->shareByDefault());
+        $this->driver = $driver;
     }
 
     /**
-     * Test expected interface.
-     *
-     * @return void
+     * Get the current record driver.
      *
-     * @expectedException        Zend\ServiceManager\Exception\RuntimeException
-     * @expectedExceptionMessage Plugin ArrayObject does not belong to VuFind\Statistics\Driver\AbstractBase
+     * @return array
      */
-    public function testExpectedInterface()
+    public function getDriver()
     {
-        $pm = new PluginManager(null);
-        $pm->validatePlugin(new \ArrayObject());
+        return $this->driver;
     }
 }
diff --git a/module/VuFind/src/VuFind/Related/PluginManager.php b/module/VuFind/src/VuFind/Related/PluginManager.php
index f57d380fabdb2593e6c1bac70a15cb627c2eab83..03554270f98d0d02acc97ebc580c82a8c6ea3034 100644
--- a/module/VuFind/src/VuFind/Related/PluginManager.php
+++ b/module/VuFind/src/VuFind/Related/PluginManager.php
@@ -26,7 +26,6 @@
  * @link     https://vufind.org/wiki/development:plugins:related_records_modules Wiki
  */
 namespace VuFind\Related;
-use Zend\ServiceManager\ConfigInterface;
 
 /**
  * Related record plugin manager
@@ -42,16 +41,20 @@ class PluginManager extends \VuFind\ServiceManager\AbstractPluginManager
     /**
      * Constructor
      *
-     * @param ConfigInterface $configuration Configuration settings (optional)
+     * Make sure plugins are properly initialized.
+     *
+     * @param mixed $configOrContainerInstance Configuration or container instance
+     * @param array $v3config                  If $configOrContainerInstance is a
+     * container, this value will be passed to the parent constructor.
      */
-    public function __construct(ConfigInterface $configuration = null)
-    {
-        // These plugins are not meant to be shared -- the same module may be used
-        // multiple times with different configurations, so we need to build a new
-        // copy each time the plugin is retrieved.
+    public function __construct($configOrContainerInstance = null,
+        array $v3config = []
+    ) {
+        // These objects are not meant to be shared -- every time we retrieve one,
+        // we are building a brand new object.
         $this->setShareByDefault(false);
 
-        parent::__construct($configuration);
+        parent::__construct($configOrContainerInstance, $v3config);
     }
 
     /**
diff --git a/module/VuFind/src/VuFind/Resolver/Driver/AbstractBase.php b/module/VuFind/src/VuFind/Resolver/Driver/AbstractBase.php
new file mode 100644
index 0000000000000000000000000000000000000000..2d9f1d5df71f55078a5fef80a2e8ad7e8a5c1b27
--- /dev/null
+++ b/module/VuFind/src/VuFind/Resolver/Driver/AbstractBase.php
@@ -0,0 +1,87 @@
+<?php
+/**
+ * AbstractBase for Resolver Driver
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2015.
+ *
+ * last update: 2011-04-13
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * @category VuFind
+ * @package  Resolver_Drivers
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development:plugins:link_resolver_drivers Wiki
+ */
+namespace VuFind\Resolver\Driver;
+
+/**
+ * AbstractBase for Resolver Driver
+ *
+ * @category VuFind
+ * @package  Resolver_Drivers
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development:plugins:link_resolver_drivers Wiki
+ */
+abstract class AbstractBase implements DriverInterface
+{
+    /**
+     * Base URL for link resolver
+     *
+     * @var string
+     */
+    protected $baseUrl;
+
+    /**
+     * Constructor
+     *
+     * @param string $baseUrl Base URL for link resolver
+     */
+    public function __construct($baseUrl)
+    {
+        $this->baseUrl = $baseUrl;
+    }
+
+    /**
+     * Get Resolver Url
+     *
+     * Transform the OpenURL as needed to get a working link to the resolver.
+     *
+     * @param string $openURL openURL (url-encoded)
+     *
+     * @return string Returns resolver specific url
+     */
+    public function getResolverUrl($openURL)
+    {
+        return $this->baseUrl . '?' . $openURL;
+    }
+
+    /**
+     * This controls whether a "More options" link will be shown below the fetched
+     * resolver links eventually linking to the resolver page previously being
+     * parsed.
+     * This is especially useful for resolver such as the EZB resolver returning
+     * XML which would not be of any immediate use for the user.
+     *
+     * @return bool
+     */
+    public function supportsMoreOptionsLink()
+    {
+        return true;
+    }
+}
diff --git a/module/VuFind/src/VuFind/Resolver/Driver/Demo.php b/module/VuFind/src/VuFind/Resolver/Driver/Demo.php
index 43ce20ba4289a8803ebe6d80dedf574ba9f5b3e4..d864b7cf74d6c04996bb841914603bbe21afaaa1 100644
--- a/module/VuFind/src/VuFind/Resolver/Driver/Demo.php
+++ b/module/VuFind/src/VuFind/Resolver/Driver/Demo.php
@@ -39,8 +39,18 @@ use DOMDocument, DOMXpath;
  * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
  * @link     https://vufind.org/wiki/development:plugins:link_resolver_drivers Wiki
  */
-class Demo implements DriverInterface
+class Demo extends AbstractBase
 {
+    /**
+     * Constructor
+     *
+     * @param string $baseUrl Base URL for link resolver
+     */
+    public function __construct($baseUrl = 'http://localhost')
+    {
+        parent::__construct($baseUrl);
+    }
+
     /**
      * Fetch Links
      *
diff --git a/module/VuFind/src/VuFind/Resolver/Driver/DriverInterface.php b/module/VuFind/src/VuFind/Resolver/Driver/DriverInterface.php
index 7f243ec690dd72f2613330a38e9fe99ecf09e8f8..f0ec93d8310579b36ebf8ad3689df73944ad9e8c 100644
--- a/module/VuFind/src/VuFind/Resolver/Driver/DriverInterface.php
+++ b/module/VuFind/src/VuFind/Resolver/Driver/DriverInterface.php
@@ -66,4 +66,27 @@ interface DriverInterface
      * @return array         Array of values
      */
     public function parseLinks($xmlstr);
+
+    /**
+     * Get Resolver Url
+     *
+     * Transform the OpenURL as needed to get a working link to the resolver.
+     *
+     * @param string $openURL openURL (url-encoded)
+     *
+     * @return string Returns resolver specific url
+     */
+    public function getResolverUrl($openURL);
+
+    /**
+     * This controls whether a "More options" link will be shown below the fetched
+     * resolver links eventually linking to the resolver page previously being
+     * parsed.
+     * This is especially useful for resolver such as the EZB resolver returning
+     * XML which would not be of any immediate use for the user.
+     *
+     * @return bool
+     */
+    public function supportsMoreOptionsLink();
+
 }
diff --git a/module/VuFind/src/VuFind/Resolver/Driver/Ezb.php b/module/VuFind/src/VuFind/Resolver/Driver/Ezb.php
index ad375be428e1113af9ec42cda196c132ad84e786..c507608d975286dcd13e429f86b8eae365fcdef3 100644
--- a/module/VuFind/src/VuFind/Resolver/Driver/Ezb.php
+++ b/module/VuFind/src/VuFind/Resolver/Driver/Ezb.php
@@ -5,6 +5,9 @@
  * EZB is a free service -- the API endpoint is available at
  * http://services.dnb.de/fize-service/gvr/full.xml
  *
+ * API documentation is available at
+ * http://www.zeitschriftendatenbank.de/services/schnittstellen/journals-online-print
+ *
  * PHP version 5
  *
  * Copyright (C) Markus Fischer, info@flyingfischer.ch
@@ -27,6 +30,7 @@
  * @category VuFind
  * @package  Resolver_Drivers
  * @author   Markus Fischer <info@flyingfischer.ch>
+ * @author   André Lahmann <lahmann@ub.uni-leipzig.de>
  * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
  * @link     https://vufind.org/wiki/development:plugins:link_resolver_drivers Wiki
  */
@@ -39,18 +43,12 @@ use DOMDocument, DOMXpath;
  * @category VuFind
  * @package  Resolver_Drivers
  * @author   Markus Fischer <info@flyingfischer.ch>
+ * @author   André Lahmann <lahmann@ub.uni-leipzig.de>
  * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
  * @link     https://vufind.org/wiki/development:plugins:link_resolver_drivers Wiki
  */
-class Ezb implements DriverInterface
+class Ezb extends AbstractBase
 {
-    /**
-     * Base URL for link resolver
-     *
-     * @var string
-     */
-    protected $baseUrl;
-
     /**
      * HTTP client
      *
@@ -66,7 +64,7 @@ class Ezb implements DriverInterface
      */
     public function __construct($baseUrl, \Zend\Http\Client $httpClient)
     {
-        $this->baseUrl = $baseUrl;
+        parent::__construct($baseUrl);
         $this->httpClient = $httpClient;
     }
 
@@ -81,32 +79,10 @@ class Ezb implements DriverInterface
      */
     public function fetchLinks($openURL)
     {
-        // Unfortunately the EZB-API only allows OpenURL V0.1 and
-        // breaks when sending a non expected parameter (like an ISBN).
-        // So we do have to 'downgrade' the OpenURL-String from V1.0 to V0.1
-        // and exclude all parameters that are not compliant with the EZB.
-
-        // Parse OpenURL into associative array:
-        $tmp = explode('&', $openURL);
-        $parsed = [];
-
-        foreach ($tmp as $current) {
-            $tmp2 = explode('=', $current, 2);
-            $parsed[$tmp2[0]] = $tmp2[1];
-        }
-
-        // Downgrade 1.0 to 0.1
-        if ($parsed['ctx_ver'] == 'Z39.88-2004') {
-            $openURL = $this->downgradeOpenUrl($parsed);
-        }
-
-        // make the request IP-based to allow automatic
-        // indication on institution level
-        $openURL .= '&pid=client_ip%3D' . $_SERVER['REMOTE_ADDR'];
+        // Get the actual resolver url for the given openUrl
+        $url = $this->getResolverUrl($openURL);
 
         // Make the call to the EZB and load results
-        $url = $this->baseUrl . '?' . $openURL;
-
         $feed = $this->httpClient->setUri($url)->send()->getBody();
         return $feed;
     }
@@ -146,6 +122,60 @@ class Ezb implements DriverInterface
         return $records;
     }
 
+    /**
+     * Get Resolver Url
+     *
+     * Transform the OpenURL as needed to get a working link to the resolver.
+     *
+     * @param string $openURL openURL (url-encoded)
+     *
+     * @return string Link
+     */
+    public function getResolverUrl($openURL)
+    {
+        // Unfortunately the EZB-API only allows OpenURL V0.1 and
+        // breaks when sending a non expected parameter (like an ISBN).
+        // So we do have to 'downgrade' the OpenURL-String from V1.0 to V0.1
+        // and exclude all parameters that are not compliant with the EZB.
+
+        // Parse OpenURL into associative array:
+        $tmp = explode('&', $openURL);
+        $parsed = [];
+
+        foreach ($tmp as $current) {
+            $tmp2 = explode('=', $current, 2);
+            $parsed[$tmp2[0]] = $tmp2[1];
+        }
+
+        // Downgrade 1.0 to 0.1
+        if ($parsed['ctx_ver'] == 'Z39.88-2004') {
+            $openURL = $this->downgradeOpenUrl($parsed);
+        }
+
+        // make the request IP-based to allow automatic
+        // indication on institution level
+        $openURL .= '&pid=client_ip%3D' . $_SERVER['REMOTE_ADDR'];
+
+        // Make the call to the EZB and load results
+        $url = $this->baseUrl . '?' . $openURL;
+
+        return $url;
+    }
+
+    /**
+     * Allows for resolver driver specific enabling/disabling of the more options
+     * link which will link directly to the resolver URL. This should return false if
+     * the resolver returns data in XML or any other human unfriendly response.
+     *
+     * @return bool
+     */
+    public function supportsMoreOptionsLink()
+    {
+        // the EZB link resolver returns unstyled XML which is not helpful for the
+        // user
+        return false;
+    }
+
     /**
      * Downgrade an OpenURL from v1.0 to v0.1 for compatibility with EZB.
      *
@@ -208,25 +238,73 @@ class Ezb implements DriverInterface
             "/OpenURLResponseXML/Full/ElectronicData/ResultList/Result[@state=" .
             $state . "]"
         );
+
+        /*
+         * possible state values:
+         * -1 ISSN nicht eindeutig
+         *  0 Standort-unabhängig frei zugänglich
+         *  1 Standort-unabhängig teilweise zugänglich (Unschärfe bedingt durch
+         *    unspezifische Anfrage oder Moving-Wall)
+         *  2 Lizenziert
+         *  3 Für gegebene Bibliothek teilweise lizenziert (Unschärfe bedingt durch
+         *    unspezifische Anfrage oder Moving-Wall)
+         *  4 nicht lizenziert
+         *  5 Zeitschrift gefunden
+         *    Angaben über Erscheinungsjahr, Datum ... liegen außerhalb des
+         *    hinterlegten bibliothekarischen Zeitraums
+         * 10 Unbekannt (ISSN unbekannt, Bibliothek unbekannt)
+         */
+        $state_access_mapping = [
+            '-1' => 'error',
+            '0'  => 'open',
+            '1'  => 'limited',
+            '2'  => 'open',
+            '3'  => 'limited',
+            '4'  => 'denied',
+            '5'  => 'denied',
+            '10' => 'unknown'
+        ];
+
         $i = 0;
         foreach ($results as $result) {
             $record = [];
             $titleXP = "/OpenURLResponseXML/Full/ElectronicData/ResultList/" .
-                "Result[@state={$state}]/Title";
-            $record['title'] = strip_tags(
-                $xpath->query($titleXP, $result)->item($i)->nodeValue
-            );
-            $record['coverage'] = $coverage;
+                "Result[@state={$state}][" . ($i + 1) . "]/Title";
+            $title = $xpath->query($titleXP, $result)->item(0);
+            if (isset($title)) {
+                $record['title'] = strip_tags($title->nodeValue);
+            }
+
+            $additionalXP = "/OpenURLResponseXML/Full/ElectronicData/ResultList/" .
+                "Result[@state={$state}][" . ($i + 1) . "]/Additionals/Additional";
+            $additionalType = ['nali', 'intervall', 'moving_wall'];
+            $additionals = [];
+            foreach ($additionalType as $type) {
+                $additional = $xpath
+                    ->query($additionalXP . "[@type='" . $type . "']", $result)
+                    ->item(0);
+                if (isset($additional->nodeValue)) {
+                    $additionals[$type] = strip_tags($additional->nodeValue);
+                }
+            }
+            $record['coverage']
+                = !empty($additionals) ? implode("; ", $additionals) : $coverage;
+
+            $record['access'] = $state_access_mapping[$state];
+
             $urlXP = "/OpenURLResponseXML/Full/ElectronicData/ResultList/" .
-                "Result[@state={$state}]/AccessURL";
-            $record['href'] = $xpath->query($urlXP, $result)->item($i)->nodeValue;
+                "Result[@state={$state}][" . ($i + 1) . "]/AccessURL";
+            $url = $xpath->query($urlXP, $result)->item(0);
+            if (isset($url->nodeValue)) {
+                $record['href'] = $url->nodeValue;
+            }
             // Service type needs to be hard-coded for calling code to properly
             // categorize links. The commented code below picks a more appropriate
             // value but won't work for now -- retained for future reference.
             //$service_typeXP = "/OpenURLResponseXML/Full/ElectronicData/ResultList/"
-            //    . "Result[@state={$state}]/AccessLevel";
+            //    . "Result[@state={$state}][".($i+1)."]/AccessLevel";
             //$record['service_type']
-            //    = $xpath->query($service_typeXP, $result)->item($i)->nodeValue;
+            //    = $xpath->query($service_typeXP, $result)->item(0)->nodeValue;
             $record['service_type'] = 'getFullTxt';
             array_push($records, $record);
             $i++;
@@ -249,12 +327,51 @@ class Ezb implements DriverInterface
         $results = $xpath->query(
             "/OpenURLResponseXML/Full/PrintData/ResultList/Result[@state={$state}]"
         );
+
+        /*
+         * possible state values:
+         * -1 ISSN nicht eindeutig
+         *  2 Vorhanden
+         *  3 Teilweise vorhanden (Unschärfe bedingt durch unspezifische Anfrage bei
+         *    nicht vollständig vorhandener Zeitschrift)
+         *  4 Nicht vorhanden
+         * 10 Unbekannt (ZDB-ID unbekannt, ISSN unbekannt, Bibliothek unbekannt)
+         */
+        $state_access_mapping = [
+            '-1' => 'error',
+            '2'  => 'open',
+            '3'  => 'limited',
+            '4'  => 'denied',
+            '10' => 'unknown'
+        ];
+
         $i = 0;
         foreach ($results as $result) {
             $record = [];
             $record['title'] = $coverage;
+
+            $resultXP = "/OpenURLResponseXML/Full/PrintData/ResultList/" .
+                "Result[@state={$state}][" . ($i + 1) . "]";
+            $resultElements = [
+                'Title', 'Location', 'Signature', 'Period', 'Holding_comment'
+            ];
+            $elements = [];
+            foreach ($resultElements as $element) {
+                $elem = $xpath->query($resultXP . "/" . $element, $result)->item(0);
+                if (isset($elem->nodeValue)) {
+                    $elements[$element] = strip_tags($elem->nodeValue);
+                }
+            }
+            $record['coverage']
+                = !empty($elements) ? implode("; ", $elements) : $coverage;
+
+            $record['access'] = $state_access_mapping[$state];
+
             $urlXP = "/OpenURLResponseXML/Full/PrintData/References/Reference/URL";
-            $record['href'] = $xpath->query($urlXP, $result)->item($i)->nodeValue;
+            $url = $xpath->query($urlXP, $result)->item($i);
+            if (isset($url->nodeValue)) {
+                $record['href'] = $url->nodeValue;
+            }
             // Service type needs to be hard-coded for calling code to properly
             // categorize links. The commented code below picks a more appropriate
             // value but won't work for now -- retained for future reference.
diff --git a/module/VuFind/src/VuFind/Resolver/Driver/Redi.php b/module/VuFind/src/VuFind/Resolver/Driver/Redi.php
index 7d90616ac5e27bf0f5ab476c0ee343ea4278ff8c..163fdeef2dfe3bc83e9f4fe8ec661a2624ac0b6b 100644
--- a/module/VuFind/src/VuFind/Resolver/Driver/Redi.php
+++ b/module/VuFind/src/VuFind/Resolver/Driver/Redi.php
@@ -40,7 +40,7 @@ use DOMDocument, Zend\Dom\DOMXPath;
  * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
  * @link     https://vufind.org/wiki/development:plugins:link_resolver_drivers Wiki
  */
-class Redi implements DriverInterface
+class Redi extends AbstractBase
 {
     /**
      * HTTP client
@@ -49,13 +49,6 @@ class Redi implements DriverInterface
      */
     protected $httpClient;
 
-    /**
-     * Base URL for link resolver
-     *
-     * @var string
-     */
-    protected $baseUrl;
-
     /**
      * Parsed resolver links
      *
@@ -71,7 +64,7 @@ class Redi implements DriverInterface
      */
     public function __construct($baseUrl, \Zend\Http\Client $httpClient)
     {
-        $this->baseUrl = $baseUrl;
+        parent::__construct($baseUrl);
         $this->httpClient = $httpClient;
     }
 
diff --git a/module/VuFind/src/VuFind/Resolver/Driver/Sfx.php b/module/VuFind/src/VuFind/Resolver/Driver/Sfx.php
index d2063132907bc821060ce7a0793b2b532369ab14..ccd6a7ec3c6b38204d293ac1e6792936851d0075 100644
--- a/module/VuFind/src/VuFind/Resolver/Driver/Sfx.php
+++ b/module/VuFind/src/VuFind/Resolver/Driver/Sfx.php
@@ -39,15 +39,8 @@ namespace VuFind\Resolver\Driver;
  * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
  * @link     https://vufind.org/wiki/development:plugins:link_resolver_drivers Wiki
  */
-class Sfx implements DriverInterface
+class Sfx extends AbstractBase
 {
-    /**
-     * Base URL for link resolver
-     *
-     * @var string
-     */
-    protected $baseUrl;
-
     /**
      * HTTP client
      *
@@ -63,7 +56,7 @@ class Sfx implements DriverInterface
      */
     public function __construct($baseUrl, \Zend\Http\Client $httpClient)
     {
-        $this->baseUrl = $baseUrl;
+        parent::__construct($baseUrl);
         $this->httpClient = $httpClient;
     }
 
diff --git a/module/VuFind/src/VuFind/Resolver/Driver/Threesixtylink.php b/module/VuFind/src/VuFind/Resolver/Driver/Threesixtylink.php
index 791dd6ba5e8ae91cec61734a43e3bed8f83d4665..0c72b3444f070d909f92c9d09870f8c395f17d0b 100644
--- a/module/VuFind/src/VuFind/Resolver/Driver/Threesixtylink.php
+++ b/module/VuFind/src/VuFind/Resolver/Driver/Threesixtylink.php
@@ -39,15 +39,8 @@ use DOMDocument, DOMXpath;
  * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
  * @link     https://vufind.org/wiki/development:plugins:link_resolver_drivers Wiki
  */
-class Threesixtylink implements DriverInterface
+class Threesixtylink extends AbstractBase
 {
-    /**
-     * Base URL for link resolver
-     *
-     * @var string
-     */
-    protected $baseUrl;
-
     /**
      * HTTP client
      *
@@ -63,7 +56,7 @@ class Threesixtylink implements DriverInterface
      */
     public function __construct($baseUrl, \Zend\Http\Client $httpClient)
     {
-        $this->baseUrl = $baseUrl;
+        parent::__construct($baseUrl);
         $this->httpClient = $httpClient;
     }
 
diff --git a/module/VuFind/src/VuFind/Role/DynamicRoleProviderFactory.php b/module/VuFind/src/VuFind/Role/DynamicRoleProviderFactory.php
index 7f03083eac55ce3917d6aaf3e7b95f098c15578d..9fdc312f2001716c009a1ad07f866a5b65861555 100644
--- a/module/VuFind/src/VuFind/Role/DynamicRoleProviderFactory.php
+++ b/module/VuFind/src/VuFind/Role/DynamicRoleProviderFactory.php
@@ -70,9 +70,9 @@ class DynamicRoleProviderFactory implements FactoryInterface
         ServiceLocatorInterface $serviceLocator, array $rbacConfig
     ) {
         $pm = new PermissionProvider\PluginManager(
-            new Config($rbacConfig['vufind_permission_provider_manager'])
+            $serviceLocator->getServiceLocator(),
+            $rbacConfig['vufind_permission_provider_manager']
         );
-        $pm->setServiceLocator($serviceLocator->getServiceLocator());
         return $pm;
     }
 
diff --git a/module/VuFind/src/VuFind/Role/PermissionProvider/User.php b/module/VuFind/src/VuFind/Role/PermissionProvider/User.php
index 2e8fa94246b537d103e1bb37f83d16cb825f03f2..d73c634affc7e286706ad7024463bcfec2708a25 100644
--- a/module/VuFind/src/VuFind/Role/PermissionProvider/User.php
+++ b/module/VuFind/src/VuFind/Role/PermissionProvider/User.php
@@ -77,7 +77,6 @@ class User implements PermissionProviderInterface,
         }
 
         // which user attribute has to match which pattern to get permissions?
-        $criteria = [];
         foreach ((array)$options as $option) {
             $parts = explode(' ', $option, 2);
             if (count($parts) < 2) {
diff --git a/module/VuFind/src/VuFind/Route/RouteGenerator.php b/module/VuFind/src/VuFind/Route/RouteGenerator.php
index 9d857a378af85ac4e5ca96014b0b3f5a2e5e82a2..8e1b229786b85842f8b45f9e395de7dd47492872 100644
--- a/module/VuFind/src/VuFind/Route/RouteGenerator.php
+++ b/module/VuFind/src/VuFind/Route/RouteGenerator.php
@@ -59,10 +59,8 @@ class RouteGenerator
         if (null === $nonTabRecordActions) {
             $this->nonTabRecordActions = [
                 'AddComment', 'DeleteComment', 'AddTag', 'DeleteTag', 'Save',
-                'Email', 'SMS', 'Cite', 'Export', 'RDF', 'Hold', 'BlockedHold',
-                'Home', 'StorageRetrievalRequest', 'AjaxTab',
-                'BlockedStorageRetrievalRequest', 'ILLRequest', 'BlockedILLRequest',
-                'PDF',
+                'Email', 'SMS', 'Cite', 'Export', 'RDF', 'Hold', 'Home',
+                'StorageRetrievalRequest', 'AjaxTab', 'ILLRequest', 'PDF',
             ];
         } else {
             $this->nonTabRecordActions = $nonTabRecordActions;
diff --git a/module/VuFind/src/VuFind/Search/BackendManager.php b/module/VuFind/src/VuFind/Search/BackendManager.php
index ba350513ca1e0e360423d859e70b6810cdb61dcb..177976165141f7f4f22d38176870cf309d12774a 100644
--- a/module/VuFind/src/VuFind/Search/BackendManager.php
+++ b/module/VuFind/src/VuFind/Search/BackendManager.php
@@ -30,7 +30,6 @@ namespace VuFind\Search;
 
 use Zend\ServiceManager\ServiceLocatorInterface;
 
-use Zend\EventManager\SharedListenerAggregateInterface;
 use Zend\EventManager\SharedEventManagerInterface;
 use Zend\EventManager\EventInterface;
 
@@ -48,7 +47,7 @@ use UnexpectedValueException;
  * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
  * @link     https://vufind.org Main Site
  */
-class BackendManager implements SharedListenerAggregateInterface
+class BackendManager
 {
     /**
      * Backend registry.
@@ -159,11 +158,8 @@ class BackendManager implements SharedListenerAggregateInterface
     public function attachShared(SharedEventManagerInterface $events)
     {
         if (!$this->listeners->offsetExists($events)) {
-            $listener = $events->attach(
-                'VuFind\Search',
-                'resolve',
-                [$this, 'onResolve']
-            );
+            $listener = [$this, 'onResolve'];
+            $events->attach('VuFind\Search', 'resolve', $listener);
             $this->listeners->attach($events, $listener);
         }
     }
@@ -179,7 +175,7 @@ class BackendManager implements SharedListenerAggregateInterface
     {
         if ($this->listeners->offsetExists($events)) {
             $listener = $this->listeners->offsetGet($events);
-            $events->detach('VuFind\Search', $listener);
+            $events->detach($listener, 'VuFind\Search');
             $this->listeners->detach($events);
         }
     }
diff --git a/module/VuFind/src/VuFind/Search/Base/Options.php b/module/VuFind/src/VuFind/Search/Base/Options.php
index 468106e7f0da218d510c29d6befe9a0d30652e49..3c31b3454275225136be8738ad87d9b215fbf075 100644
--- a/module/VuFind/src/VuFind/Search/Base/Options.php
+++ b/module/VuFind/src/VuFind/Search/Base/Options.php
@@ -893,22 +893,6 @@ abstract class Options implements TranslatorAwareInterface
         return $class[2];
     }
 
-    /**
-     * Sleep magic method -- the translator can't be serialized, so we need to
-     * exclude it from serialization.  Since we can't obtain a new one in the
-     * __wakeup() method, it needs to be re-injected from outside.
-     *
-     * @return array
-     */
-    public function __sleep()
-    {
-        $vars = get_object_vars($this);
-        unset($vars['configLoader']);
-        unset($vars['translator']);
-        $vars = array_keys($vars);
-        return $vars;
-    }
-
     /**
      * Should we include first/last options in result scroller navigation?
      *
diff --git a/module/VuFind/src/VuFind/Search/Base/Params.php b/module/VuFind/src/VuFind/Search/Base/Params.php
index 35b5e6954f9c1cfccfab1fd817c4a1ade77655c5..b2bf8fbd7a3b74c696cd54b3b11f3009e313351c 100644
--- a/module/VuFind/src/VuFind/Search/Base/Params.php
+++ b/module/VuFind/src/VuFind/Search/Base/Params.php
@@ -26,8 +26,6 @@
  * @link     https://vufind.org Main Page
  */
 namespace VuFind\Search\Base;
-use Zend\ServiceManager\ServiceLocatorAwareInterface,
-    Zend\ServiceManager\ServiceLocatorInterface;
 use VuFindSearch\Backend\Solr\LuceneSyntaxHelper, VuFindSearch\Query\Query,
     VuFindSearch\Query\QueryGroup;
 use VuFind\Search\QueryAdapter, VuFind\Solr\Utils as SolrUtils;
@@ -43,12 +41,8 @@ use VuFind\Search\QueryAdapter, VuFind\Solr\Utils as SolrUtils;
  * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
  * @link     https://vufind.org Main Page
  */
-class Params implements ServiceLocatorAwareInterface
+class Params
 {
-    use \Zend\ServiceManager\ServiceLocatorAwareTrait {
-        setServiceLocator as setServiceLocatorThroughTrait;
-    }
-
     /**
      * Internal representation of user query.
      *
@@ -126,6 +120,13 @@ class Params implements ServiceLocatorAwareInterface
      */
     protected $facetConfig = [];
 
+    /**
+     * Extra facet labels
+     *
+     * @var array
+     */
+    protected $extraFacetLabels = [];
+
     /**
      * Checkbox facet configuration
      *
@@ -173,18 +174,25 @@ class Params implements ServiceLocatorAwareInterface
      */
     protected $facetAliases = [];
 
+    /**
+     * Config loader
+     *
+     * @var \VuFind\Config\PluginManager
+     */
+    protected $configLoader;
+
     /**
      * Constructor
      *
      * @param \VuFind\Search\Base\Options  $options      Options to use
      * @param \VuFind\Config\PluginManager $configLoader Config loader
-     *
-     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function __construct($options, \VuFind\Config\PluginManager $configLoader)
     {
         $this->setOptions($options);
 
+        $this->configLoader = $configLoader;
+
         // Make sure we have some sort of query object:
         $this->query = new Query();
     }
@@ -928,12 +936,16 @@ class Params implements ServiceLocatorAwareInterface
     public function getFacetLabel($field, $value = null)
     {
         if (!isset($this->facetConfig[$field])
+            && !isset($this->extraFacetLabels[$field])
             && isset($this->facetAliases[$field])
         ) {
             $field = $this->facetAliases[$field];
         }
-        return isset($this->facetConfig[$field])
-            ? $this->facetConfig[$field] : 'unrecognized_facet_label';
+        if (isset($this->facetConfig[$field])) {
+            return $this->facetConfig[$field];
+        }
+        return isset($this->extraFacetLabels[$field])
+            ? $this->extraFacetLabels[$field] : 'unrecognized_facet_label';
     }
 
     /**
@@ -1471,7 +1483,7 @@ class Params implements ServiceLocatorAwareInterface
         if (!$this->hasHiddenFilter($newFilter)) {
             // Extract field and value from filter string:
             list($field, $value) = $this->parseFilter($newFilter);
-            if (!empty($field) && !empty($value)) {
+            if (!empty($field) && '' !== $value) {
                 $this->hiddenFilters[$field][] = $value;
             }
         }
@@ -1642,50 +1654,6 @@ class Params implements ServiceLocatorAwareInterface
         return $this->selectedShards;
     }
 
-    /**
-     * Sleep magic method -- the service locator can't be serialized, so we need to
-     * exclude it from serialization.  Since we can't obtain a new locator in the
-     * __wakeup() method, it needs to be re-injected from outside.
-     *
-     * @return array
-     */
-    public function __sleep()
-    {
-        $vars = get_object_vars($this);
-        unset($vars['serviceLocator']);
-        $vars = array_keys($vars);
-        return $vars;
-    }
-
-    /**
-     * Set the service locator.
-     *
-     * @param ServiceLocatorInterface $serviceLocator Locator to register
-     *
-     * @return Params
-     */
-    public function setServiceLocator(ServiceLocatorInterface $serviceLocator)
-    {
-        // If this isn't the top-level manager, get its parent:
-        if ($serviceLocator instanceof ServiceLocatorAwareInterface) {
-            $serviceLocator = $serviceLocator->getServiceLocator();
-        }
-        return $this->setServiceLocatorThroughTrait($serviceLocator);
-    }
-
-    /**
-     * Get a database table object.
-     *
-     * @param string $table Name of table to retrieve
-     *
-     * @return \VuFind\Db\Table\Gateway
-     */
-    public function getTable($table)
-    {
-        return $this->getServiceLocator()->get('VuFind\DbTablePluginManager')
-            ->get($table);
-    }
-
     /**
      * Translate a string (or string-castable object)
      *
@@ -1749,7 +1717,7 @@ class Params implements ServiceLocatorAwareInterface
      */
     protected function initFacetList($facetList, $facetSettings, $cfgFile = 'facets')
     {
-        $config = $this->getServiceLocator()->get('VuFind\Config')->get($cfgFile);
+        $config = $this->configLoader->get($cfgFile);
         if (!isset($config->$facetList)) {
             return false;
         }
@@ -1789,7 +1757,7 @@ class Params implements ServiceLocatorAwareInterface
     protected function initCheckboxFacets($facetList = 'CheckboxFacets',
         $cfgFile = 'facets'
     ) {
-        $config = $this->getServiceLocator()->get('VuFind\Config')->get($cfgFile);
+        $config = $this->configLoader->get($cfgFile);
         if (empty($config->$facetList)) {
             return false;
         }
diff --git a/module/VuFind/src/VuFind/Search/Base/Results.php b/module/VuFind/src/VuFind/Search/Base/Results.php
index a2b917e5586f11c103378edddb552800a7b80549..1bd9c895a5684e8a7565cd16f4ce552d5a9315ea 100644
--- a/module/VuFind/src/VuFind/Search/Base/Results.php
+++ b/module/VuFind/src/VuFind/Search/Base/Results.php
@@ -26,10 +26,10 @@
  * @link     https://vufind.org Main Page
  */
 namespace VuFind\Search\Base;
-use VuFind\Search\UrlQueryHelper, Zend\Paginator\Paginator,
-    Zend\ServiceManager\ServiceLocatorAwareInterface,
-    Zend\ServiceManager\ServiceLocatorInterface;
+use VuFind\Record\Loader;
+use VuFind\Search\Factory\UrlQueryHelperFactory;
 use VuFindSearch\Service as SearchService;
+use Zend\Paginator\Paginator;
 
 /**
  * Abstract results search model.
@@ -42,12 +42,8 @@ use VuFindSearch\Service as SearchService;
  * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
  * @link     https://vufind.org Main Page
  */
-abstract class Results implements ServiceLocatorAwareInterface
+abstract class Results
 {
-    use \Zend\ServiceManager\ServiceLocatorAwareTrait {
-        setServiceLocator as setServiceLocatorThroughTrait;
-    }
-
     /**
      * Search parameters
      *
@@ -140,15 +136,27 @@ abstract class Results implements ServiceLocatorAwareInterface
      */
     protected $searchService;
 
+    /**
+     * Record loader
+     *
+     * @var Loader
+     */
+    protected $recordLoader;
+
     /**
      * Constructor
      *
-     * @param \VuFind\Search\Base\Params $params Object representing user search
-     * parameters.
+     * @param \VuFind\Search\Base\Params $params        Object representing user
+     * search parameters.
+     * @param SearchService              $searchService Search service
+     * @param Loader                     $recordLoader  Record loader
      */
-    public function __construct(Params $params)
-    {
+    public function __construct(Params $params, SearchService $searchService,
+        Loader $recordLoader
+    ) {
         $this->setParams($params);
+        $this->searchService = $searchService;
+        $this->recordLoader = $recordLoader;
     }
 
     /**
@@ -196,16 +204,29 @@ abstract class Results implements ServiceLocatorAwareInterface
         return $this->getParams()->getOptions();
     }
 
+    /**
+     * Options for UrlQueryHelper
+     *
+     * @return array
+     */
+    protected function getUrlQueryHelperOptions()
+    {
+        return [];
+    }
+
     /**
      * Get the URL helper for this object.
      *
-     * @return UrlHelper
+     * @return \VuFind\Search\UrlQueryHelper
      */
     public function getUrlQuery()
     {
         // Set up URL helper:
         if (!isset($this->helpers['urlQuery'])) {
-            $this->helpers['urlQuery'] = new UrlQueryHelper($this->getParams());
+            $factory = new UrlQueryHelperFactory();
+            $this->helpers['urlQuery'] = $factory->fromParams(
+                $this->getParams(), $this->getUrlQueryHelperOptions()
+            );
         }
         return $this->helpers['urlQuery'];
     }
@@ -527,60 +548,6 @@ abstract class Results implements ServiceLocatorAwareInterface
         $this->recommend = $recommend;
     }
 
-    /**
-     * Set the service locator.
-     *
-     * @param ServiceLocatorInterface $serviceLocator Locator to register
-     *
-     * @return Results
-     */
-    public function setServiceLocator(ServiceLocatorInterface $serviceLocator)
-    {
-        // If this isn't the top-level manager, get its parent:
-        if ($serviceLocator instanceof ServiceLocatorAwareInterface) {
-            $serviceLocator = $serviceLocator->getServiceLocator();
-        }
-        return $this->setServiceLocatorThroughTrait($serviceLocator);
-    }
-
-    /**
-     * Restore the service locator (a cascading version of setServiceLocator()).
-     *
-     * @param ServiceLocatorInterface $serviceLocator Locator to register
-     *
-     * @return Results
-     */
-    public function restoreServiceLocator(ServiceLocatorInterface $serviceLocator)
-    {
-        $this->setServiceLocator($serviceLocator);
-        $params = $this->getParams();
-        if (method_exists($params, 'setServiceLocator')) {
-            $params->setServiceLocator($serviceLocator);
-        }
-        // Restore translator:
-        $this->getOptions()
-            ->setTranslator($serviceLocator->get('VuFind\Translator'));
-        $this->getOptions()
-            ->setConfigLoader($serviceLocator->get('VuFind\Config'));
-        return $this;
-    }
-
-    /**
-     * Sleep magic method -- the service locator can't be serialized, so we need to
-     * exclude it from serialization.  Since we can't obtain a new locator in the
-     * __wakeup() method, it needs to be re-injected from outside.
-     *
-     * @return array
-     */
-    public function __sleep()
-    {
-        $vars = get_object_vars($this);
-        unset($vars['serviceLocator']);
-        unset($vars['searchService']);
-        $vars = array_keys($vars);
-        return $vars;
-    }
-
     /**
      * Return search service.
      *
@@ -591,25 +558,9 @@ abstract class Results implements ServiceLocatorAwareInterface
      */
     protected function getSearchService()
     {
-        if (!$this->searchService) {
-            $this->searchService = $this->getServiceLocator()->get('VuFind\Search');
-        }
         return $this->searchService;
     }
 
-    /**
-     * Get a database table object.
-     *
-     * @param string $table Name of table to retrieve
-     *
-     * @return \VuFind\Db\Table\Gateway
-     */
-    public function getTable($table)
-    {
-        return $this->getServiceLocator()->get('VuFind\DbTablePluginManager')
-            ->get($table);
-    }
-
     /**
      * Translate a string if a translator is available (proxies method in Options).
      *
diff --git a/module/VuFind/src/VuFind/Search/EDS/Params.php b/module/VuFind/src/VuFind/Search/EDS/Params.php
index 0c9935df69f662bc519dd01cdaa3a4fb26705d74..6af017e261382f633ba395f73067b417e1dc09d0 100644
--- a/module/VuFind/src/VuFind/Search/EDS/Params.php
+++ b/module/VuFind/src/VuFind/Search/EDS/Params.php
@@ -124,33 +124,6 @@ class Params extends \VuFind\Search\Base\Params
         return $backendParams;
     }
 
-    /**
-     * Set up facets based on VuFind settings.
-     *
-     * @return array
-     */
-    protected function getBackendFacetParameters()
-    {
-        $config = $this->getServiceLocator()->get('VuFind\Config')->get('EDS');
-        $defaultFacetLimit = isset($config->Facet_Settings->facet_limit)
-            ? $config->Facet_Settings->facet_limit : 30;
-
-        $finalFacets = [];
-        foreach ($this->getFullFacetSettings() as $facet) {
-            // See if parameters are included as part of the facet name;
-            // if not, override them with defaults.
-            $parts = explode(',', $facet);
-            $facetName = $parts[0];
-            $defaultMode = ($this->getFacetOperator($facet) == 'OR') ? 'or' : 'and';
-            $facetMode = isset($parts[1]) ? $parts[1] : $defaultMode;
-            $facetPage = isset($parts[2]) ? $parts[2] : 1;
-            $facetLimit = isset($parts[3]) ? $parts[3] : $defaultFacetLimit;
-            $facetParams = "{$facetMode},{$facetPage},{$facetLimit}";
-            $finalFacets[] = "{$facetName},{$facetParams}";
-        }
-        return $finalFacets;
-    }
-
     /**
      * Set up filters based on VuFind settings.
      *
diff --git a/module/VuFind/src/VuFind/Search/Factory/AbstractSolrBackendFactory.php b/module/VuFind/src/VuFind/Search/Factory/AbstractSolrBackendFactory.php
index e0987fc71eb2dd63baea854232c53d647256628b..6ec45e1e9b8c1f843934d3699250b2c3d78c23c3 100644
--- a/module/VuFind/src/VuFind/Search/Factory/AbstractSolrBackendFactory.php
+++ b/module/VuFind/src/VuFind/Search/Factory/AbstractSolrBackendFactory.php
@@ -320,7 +320,7 @@ abstract class AbstractSolrBackendFactory implements FactoryInterface
                 'defaults' => ['fl' => '*,score'],
                 'appends'  => ['fq' => []],
             ],
-            'term' => [
+            'terms' => [
                 'functions' => ['terms'],
             ],
         ];
diff --git a/module/VuFind/src/VuFind/Search/Factory/PrimoBackendFactory.php b/module/VuFind/src/VuFind/Search/Factory/PrimoBackendFactory.php
index 67d9e280136275e1832f15447d34b81c8e2f0001..b423e134f5959380a8ea0df2b0dee4f22ae93984 100644
--- a/module/VuFind/src/VuFind/Search/Factory/PrimoBackendFactory.php
+++ b/module/VuFind/src/VuFind/Search/Factory/PrimoBackendFactory.php
@@ -91,7 +91,7 @@ class PrimoBackendFactory implements FactoryInterface
         $connector = $this->createConnector();
         $backend   = $this->createBackend($connector);
 
-        $this->createListeners($backend);
+        $this->createListeners();
 
         return $backend;
     }
@@ -114,11 +114,9 @@ class PrimoBackendFactory implements FactoryInterface
     /**
      * Create listeners.
      *
-     * @param Backend $backend Backend
-     *
      * @return void
      */
-    protected function createListeners(Backend $backend)
+    protected function createListeners()
     {
         $events = $this->serviceLocator->get('SharedEventManager');
 
diff --git a/module/VuFind/src/VuFind/Search/Factory/SolrStatsBackendFactory.php b/module/VuFind/src/VuFind/Search/Factory/SolrStatsBackendFactory.php
deleted file mode 100644
index 439744f2d69ba35039885baea0a322d4ed369a74..0000000000000000000000000000000000000000
--- a/module/VuFind/src/VuFind/Search/Factory/SolrStatsBackendFactory.php
+++ /dev/null
@@ -1,68 +0,0 @@
-<?php
-
-/**
- * Factory for the default SOLR backend.
- *
- * PHP version 5
- *
- * Copyright (C) Villanova University 2013.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- *
- * @category VuFind
- * @package  Search
- * @author   David Maus <maus@hab.de>
- * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
- * @link     https://vufind.org Main Site
- */
-namespace VuFind\Search\Factory;
-
-use VuFindSearch\Backend\Solr\Backend;
-
-/**
- * Factory for the default SOLR backend.
- *
- * @category VuFind
- * @package  Search
- * @author   David Maus <maus@hab.de>
- * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
- * @link     https://vufind.org Main Site
- */
-class SolrStatsBackendFactory extends AbstractSolrBackendFactory
-{
-    /**
-     * Constructor
-     */
-    public function __construct()
-    {
-        parent::__construct();
-        $this->solrCore = 'stats';
-        $this->searchConfig = 'searches';
-        $this->searchYaml = 'searchspecs.yaml';
-        $this->facetConfig = 'facets';
-    }
-
-    /**
-     * Get the Solr URL.
-     *
-     * @return string
-     */
-    protected function getSolrUrl()
-    {
-        $config = $this->config->get('config');
-        $base = isset($config->Statistics->solr)
-            ? $config->Statistics->solr : $config->Index->url;
-        return $base . '/' . $this->getSolrCore();
-    }
-}
diff --git a/module/VuFind/src/VuFind/Search/Factory/UrlQueryHelperFactory.php b/module/VuFind/src/VuFind/Search/Factory/UrlQueryHelperFactory.php
new file mode 100644
index 0000000000000000000000000000000000000000..a602fcd54081e54c631dce1d01b4a06b07b1144e
--- /dev/null
+++ b/module/VuFind/src/VuFind/Search/Factory/UrlQueryHelperFactory.php
@@ -0,0 +1,166 @@
+<?php
+/**
+ * Factory to build UrlQueryHelper.
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2016.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * @category VuFind
+ * @package  Search
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org Main Site
+ */
+namespace VuFind\Search\Factory;
+use VuFind\Search\UrlQueryHelper;
+use VuFind\Search\Base\Params;
+
+/**
+ * Factory to build UrlQueryHelper.
+ *
+ * @category VuFind
+ * @package  Search
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org Main Site
+ */
+class UrlQueryHelperFactory
+{
+    /**
+     * Extract default settings from the search parameters.
+     *
+     * @param Params $params VuFind search parameters
+     *
+     * @return array
+     */
+    protected function getDefaults(Params $params)
+    {
+        $options = $params->getOptions();
+        return [
+            'handler' => $options->getDefaultHandler(),
+            'limit' => $options->getDefaultLimit(),
+            'selectedShards' => $options->getDefaultSelectedShards(),
+            'sort' => $params->getDefaultSort(),
+            'view' => $options->getDefaultView(),
+        ];
+    }
+
+    /**
+     * Load default settings into the user-provided configuration.
+     *
+     * @param Params $params VuFind search parameters
+     * @param array  $config Config options
+     *
+     * @return array
+     */
+    protected function addDefaultsToConfig(Params $params, array $config)
+    {
+        // Load defaults unless they have been overridden in existing config
+        // array.
+        foreach ($this->getDefaults($params) as $key => $value) {
+            if (!isset($config['defaults'][$key])) {
+                $config['defaults'][$key] = $value;
+            }
+        }
+
+        // Load useful callbacks if they have not been specifically overridden
+        if (!isset($config['parseFilterCallback'])) {
+            $config['parseFilterCallback'] = [$params, 'parseFilter'];
+        }
+        if (!isset($config['getAliasesForFacetFieldCallback'])) {
+            $config['getAliasesForFacetFieldCallback']
+                = [$params, 'getAliasesForFacetField'];
+        }
+        return $config;
+    }
+
+    /**
+     * Extract URL query parameters from VuFind search parameters.
+     *
+     * @param Params $params VuFind search parameters
+     * @param array  $config Config options
+     *
+     * @return array
+     */
+    protected function getUrlParams(Params $params, array $config)
+    {
+        $urlParams = [];
+        $sort = $params->getSort();
+        if (null !== $sort && $sort != $config['defaults']['sort']) {
+            $urlParams['sort'] = $sort;
+        }
+        $limit = $params->getLimit();
+        if (null !== $limit && $limit != $config['defaults']['limit']) {
+            $urlParams['limit'] = $limit;
+        }
+        $view = $params->getView();
+        if (null !== $view && $view != $config['defaults']['view']) {
+            $urlParams['view'] = $view;
+        }
+        if ($params->getPage() != 1) {
+            $urlParams['page'] = $params->getPage();
+        }
+        $filters = $params->getFilters();
+        if (!empty($filters)) {
+            $urlParams['filter'] = [];
+            foreach ($filters as $field => $values) {
+                foreach ($values as $current) {
+                    $urlParams['filter'][] = $field . ':"' . $current . '"';
+                }
+            }
+        }
+        $hiddenFilters = $params->getHiddenFilters();
+        if (!empty($hiddenFilters)) {
+            foreach ($hiddenFilters as $field => $values) {
+                foreach ($values as $current) {
+                    $urlParams['hiddenFilters'][] = $field . ':"' . $current . '"';
+                }
+            }
+        }
+        $shards = $params->getSelectedShards();
+        if (!empty($shards)) {
+            sort($shards);
+            $defaultShards = $config['defaults']['selectedShards'];
+            sort($defaultShards);
+            if (implode(':::', $shards) != implode(':::', $defaultShards)) {
+                $urlParams['shard'] = $shards;
+            }
+        }
+        if ($params->hasDefaultsApplied()) {
+            $urlParams['dfApplied'] = 1;
+        }
+        return $urlParams;
+    }
+
+    /**
+     * Construct the UrlQueryHelper
+     *
+     * @param Params $params VuFind search parameters
+     * @param array  $config Config options
+     *
+     * @return UrlQueryHelper
+     */
+    public function fromParams(Params $params, array $config = [])
+    {
+        $finalConfig = $this->addDefaultsToConfig($params, $config);
+        return new UrlQueryHelper(
+            $this->getUrlParams($params, $finalConfig),
+            $params->getQuery(),
+            $finalConfig
+        );
+    }
+}
diff --git a/module/VuFind/src/VuFind/Search/Favorites/Params.php b/module/VuFind/src/VuFind/Search/Favorites/Params.php
index ccde0805c561f1c83bcec64c151ae951590caecf..ccbc456e07d4d16258e2767031458cdf36e1ef12 100644
--- a/module/VuFind/src/VuFind/Search/Favorites/Params.php
+++ b/module/VuFind/src/VuFind/Search/Favorites/Params.php
@@ -38,17 +38,6 @@ namespace VuFind\Search\Favorites;
  */
 class Params extends \VuFind\Search\Base\Params
 {
-    /**
-     * Constructor
-     *
-     * @param \VuFind\Search\Base\Options  $options      Options to use
-     * @param \VuFind\Config\PluginManager $configLoader Config loader
-     */
-    public function __construct($options, \VuFind\Config\PluginManager $configLoader)
-    {
-        parent::__construct($options, $configLoader);
-    }
-
     /**
      * Add filters to the object based on values found in the request object.
      *
diff --git a/module/VuFind/src/VuFind/Search/Favorites/Results.php b/module/VuFind/src/VuFind/Search/Favorites/Results.php
index 24c942b4a8a4184d3a3bd80e4463267409b75ac3..b27520589bd5d190aee8253a1e88b9718984ed6f 100644
--- a/module/VuFind/src/VuFind/Search/Favorites/Results.php
+++ b/module/VuFind/src/VuFind/Search/Favorites/Results.php
@@ -26,11 +26,15 @@
  * @link     https://vufind.org Main Site
  */
 namespace VuFind\Search\Favorites;
-use VuFind\Exception\ListPermission as ListPermissionException,
-    VuFind\Search\Base\Results as BaseResults,
-    VuFind\Record\Cache,
-    ZfcRbac\Service\AuthorizationServiceAwareInterface,
-    ZfcRbac\Service\AuthorizationServiceAwareTrait;
+use VuFind\Db\Table\Resource as ResourceTable;
+use VuFind\Db\Table\UserList as ListTable;
+use VuFind\Exception\ListPermission as ListPermissionException;
+use VuFind\Search\Base\Results as BaseResults;
+use VuFind\Record\Cache;
+use VuFind\Record\Loader;
+use VuFindSearch\Service as SearchService;
+use ZfcRbac\Service\AuthorizationServiceAwareInterface;
+use ZfcRbac\Service\AuthorizationServiceAwareTrait;
 
 /**
  * Search Favorites Results
@@ -60,6 +64,39 @@ class Results extends BaseResults
      */
     protected $list = false;
 
+    /**
+     * Resource table
+     *
+     * @var ResourceTable
+     */
+    protected $resourceTable;
+
+    /**
+     * UserList table
+     *
+     * @var ListTable
+     */
+    protected $listTable;
+
+    /**
+     * Constructor
+     *
+     * @param \VuFind\Search\Base\Params $params        Object representing user
+     * search parameters.
+     * @param SearchService              $searchService Search service
+     * @param Loader                     $recordLoader  Record loader
+     * @param ResourceTable              $resourceTable Resource table
+     * @param ListTable                  $listTable     UserList table
+     */
+    public function __construct(\VuFind\Search\Base\Params $params,
+        SearchService $searchService, Loader $recordLoader,
+        ResourceTable $resourceTable, ListTable $listTable
+    ) {
+        parent::__construct($params, $searchService, $recordLoader);
+        $this->resourceTable = $resourceTable;
+        $this->listTable = $listTable;
+    }
+
     /**
      * Returns the stored list of facets for the last search
      *
@@ -146,10 +183,9 @@ class Results extends BaseResults
         }
 
         // How many results were there?
-        $resource = $this->getTable('Resource');
         $userId = is_null($list) ? $this->user->id : $list->user_id;
         $listId = is_null($list) ? null : $list->id;
-        $rawResults = $resource->getFavorites(
+        $rawResults = $this->resourceTable->getFavorites(
             $userId, $listId, $this->getTagFilters(), $this->getParams()->getSort()
         );
         $this->resultTotal = count($rawResults);
@@ -157,7 +193,7 @@ class Results extends BaseResults
         // Apply offset and limit if necessary!
         $limit = $this->getParams()->getLimit();
         if ($this->resultTotal > $limit) {
-            $rawResults = $resource->getFavorites(
+            $rawResults = $this->resourceTable->getFavorites(
                 $userId, $listId, $this->getTagFilters(),
                 $this->getParams()->getSort(), $this->getStartRecord() - 1, $limit
             );
@@ -174,9 +210,8 @@ class Results extends BaseResults
             ];
         }
 
-        $recordLoader = $this->getServiceLocator()->get('VuFind\RecordLoader');
-        $recordLoader->setCacheContext(Cache::CONTEXT_FAVORITE);
-        $this->results = $recordLoader->loadBatch($recordsToRequest);
+        $this->recordLoader->setCacheContext(Cache::CONTEXT_FAVORITE);
+        $this->results = $this->recordLoader->loadBatch($recordsToRequest, true);
     }
 
     /**
@@ -204,12 +239,8 @@ class Results extends BaseResults
             // if one is found:
             $filters = $this->getParams()->getFilters();
             $listId = isset($filters['lists'][0]) ? $filters['lists'][0] : null;
-            if (null === $listId) {
-                $this->list = null;
-            } else {
-                $table = $this->getTable('UserList');
-                $this->list = $table->getExisting($listId);
-            }
+            $this->list = (null === $listId)
+                ? null : $this->listTable->getExisting($listId);
         }
         return $this->list;
     }
diff --git a/module/VuFind/src/VuFind/Search/MixedList/Results.php b/module/VuFind/src/VuFind/Search/MixedList/Results.php
index 582ed29f810464408b49bd953d2ab7a2fd1e37e7..f77dddbcb95baf405833cb4c194822398a9500f0 100644
--- a/module/VuFind/src/VuFind/Search/MixedList/Results.php
+++ b/module/VuFind/src/VuFind/Search/MixedList/Results.php
@@ -62,8 +62,7 @@ class Results extends BaseResults
     protected function performSearch()
     {
         $recordsToRequest = $this->getParams()->getRecordsToRequest();
-        $this->results = $this->getServiceLocator()->get('VuFind\RecordLoader')
-            ->loadBatch($recordsToRequest);
+        $this->results = $this->recordLoader->loadBatch($recordsToRequest);
         $this->resultTotal = count($this->results);
     }
 }
diff --git a/module/VuFind/src/VuFind/Statistics/Driver/Factory.php b/module/VuFind/src/VuFind/Search/Params/Factory.php
similarity index 61%
rename from module/VuFind/src/VuFind/Statistics/Driver/Factory.php
rename to module/VuFind/src/VuFind/Search/Params/Factory.php
index ff8c7b31a044cbec2e60b7e92bc4bdc6a2b81abd..db5f46a72a99ac44d1af33aa75d68a7ae1a6bd76 100644
--- a/module/VuFind/src/VuFind/Statistics/Driver/Factory.php
+++ b/module/VuFind/src/VuFind/Search/Params/Factory.php
@@ -1,10 +1,10 @@
 <?php
 /**
- * Statistics Driver Factory Class
+ * Search Params Object Factory Class
  *
  * PHP version 5
  *
- * Copyright (C) Villanova University 2014.
+ * Copyright (C) Villanova University 2017.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2,
@@ -20,19 +20,19 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
  * @category VuFind
- * @package  Statistics
+ * @package  Search
  * @author   Demian Katz <demian.katz@villanova.edu>
  * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
  * @link     https://vufind.org/wiki/development:plugins:hierarchy_components Wiki
  */
-namespace VuFind\Statistics\Driver;
+namespace VuFind\Search\Params;
 use Zend\ServiceManager\ServiceManager;
 
 /**
- * Statistics Driver Factory Class
+ * Search Params Object Factory Class
  *
  * @category VuFind
- * @package  Statistics
+ * @package  Search
  * @author   Demian Katz <demian.katz@villanova.edu>
  * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
  * @link     https://vufind.org/wiki/development:plugins:hierarchy_components Wiki
@@ -42,33 +42,16 @@ use Zend\ServiceManager\ServiceManager;
 class Factory
 {
     /**
-     * Factory for File driver.
+     * Factory for Solr params object.
      *
      * @param ServiceManager $sm Service manager.
      *
-     * @return File
-     */
-    public static function getFile(ServiceManager $sm)
-    {
-        $config = $sm->getServiceLocator()->get('VuFind\Config')->get('config');
-        $folder = isset($config->Statistics->file)
-            ? $config->Statistics->file : sys_get_temp_dir();
-        return new File($folder);
-    }
-
-    /**
-     * Factory for Solr driver.
-     *
-     * @param ServiceManager $sm Service manager.
-     *
-     * @return Solr
+     * @return \VuFind\Search\Solr\Params
      */
     public static function getSolr(ServiceManager $sm)
     {
-        return new Solr(
-            $sm->getServiceLocator()->get('VuFind\Solr\Writer'),
-            $sm->getServiceLocator()->get('VuFind\Search\BackendManager')
-                ->get('SolrStats')
-        );
+        $factory = new PluginFactory();
+        $helper = $sm->getServiceLocator()->get('VuFind\HierarchicalFacetHelper');
+        return $factory->createServiceWithName($sm, 'solr', 'Solr', [$helper]);
     }
 }
diff --git a/module/VuFind/src/VuFind/Search/Params/PluginFactory.php b/module/VuFind/src/VuFind/Search/Params/PluginFactory.php
index 4caff16388b33735d515016a420079559afbed7d..9e4c4c3a02e7181d78e1999398e956003cbb7be8 100644
--- a/module/VuFind/src/VuFind/Search/Params/PluginFactory.php
+++ b/module/VuFind/src/VuFind/Search/Params/PluginFactory.php
@@ -54,19 +54,19 @@ class PluginFactory extends \VuFind\ServiceManager\AbstractPluginFactory
      * @param ServiceLocatorInterface $serviceLocator Service locator
      * @param string                  $name           Name of service
      * @param string                  $requestedName  Unfiltered name of service
+     * @param array                   $extraParams    Extra constructor parameters
+     * (to follow the Options object and config loader)
      *
      * @return object
      */
     public function createServiceWithName(ServiceLocatorInterface $serviceLocator,
-        $name, $requestedName
+        $name, $requestedName, array $extraParams = []
     ) {
         $options = $serviceLocator->getServiceLocator()
             ->get('VuFind\SearchOptionsPluginManager')->get($requestedName);
         $class = $this->getClassName($name, $requestedName);
+        $configLoader = $serviceLocator->getServiceLocator()->get('VuFind\Config');
         // Clone the options instance in case caller modifies it:
-        return new $class(
-            clone($options),
-            $serviceLocator->getServiceLocator()->get('VuFind\Config')
-        );
+        return new $class(clone($options), $configLoader, ...$extraParams);
     }
 }
diff --git a/module/VuFind/src/VuFind/Search/Params/PluginManager.php b/module/VuFind/src/VuFind/Search/Params/PluginManager.php
index fcace47adef1020e96ce5f29dd037cd34b926dd9..60664942f3f7c74b61c56d040f7d58786e66d228 100644
--- a/module/VuFind/src/VuFind/Search/Params/PluginManager.php
+++ b/module/VuFind/src/VuFind/Search/Params/PluginManager.php
@@ -26,7 +26,6 @@
  * @link     https://vufind.org/wiki/development:plugins:record_drivers Wiki
  */
 namespace VuFind\Search\Params;
-use Zend\ServiceManager\ConfigInterface;
 
 /**
  * Search params plugin manager
@@ -42,15 +41,20 @@ class PluginManager extends \VuFind\ServiceManager\AbstractPluginManager
     /**
      * Constructor
      *
-     * @param ConfigInterface $configuration Configuration settings (optional)
+     * Make sure plugins are properly initialized.
+     *
+     * @param mixed $configOrContainerInstance Configuration or container instance
+     * @param array $v3config                  If $configOrContainerInstance is a
+     * container, this value will be passed to the parent constructor.
      */
-    public function __construct(ConfigInterface $configuration = null)
-    {
+    public function __construct($configOrContainerInstance = null,
+        array $v3config = []
+    ) {
         // These objects are not meant to be shared -- every time we retrieve one,
         // we are building a brand new object.
         $this->setShareByDefault(false);
 
-        parent::__construct($configuration);
+        parent::__construct($configOrContainerInstance, $v3config);
     }
 
     /**
diff --git a/module/VuFind/src/VuFind/Search/QueryAdapter.php b/module/VuFind/src/VuFind/Search/QueryAdapter.php
index 034ed22a5a642aead018b6204ff8f8f013a2bef5..689750136fece992c3f506d3e14bc0264114f86e 100644
--- a/module/VuFind/src/VuFind/Search/QueryAdapter.php
+++ b/module/VuFind/src/VuFind/Search/QueryAdapter.php
@@ -170,29 +170,31 @@ abstract class QueryAdapter
      */
     public static function fromRequest(Parameters $request, $defaultHandler)
     {
-        $groupCount = 0;
         $groups = [];
-
-        // Loop through each search group
-        while (!is_null($lookfor = $request->get("lookfor{$groupCount}"))) {
+        // Loop through all parameters and look for 'lookforX'
+        foreach ($request as $key => $value) {
+            if (!preg_match('/^lookfor(\d+)$/', $key, $matches)) {
+                continue;
+            }
+            $groupId = $matches[1];
             $group = [];
             $lastBool = null;
 
             // Loop through each term inside the group
-            for ($i = 0; $i < count($lookfor); $i++) {
+            for ($i = 0; $i < count($value); $i++) {
                 // Ignore advanced search fields with no lookup
-                if ($lookfor[$i] != '') {
+                if ($value[$i] != '') {
                     // Use default fields if not set
-                    $typeArr = $request->get('type' . $groupCount);
+                    $typeArr = $request->get("type$groupId");
                     $handler = !empty($typeArr[$i]) ? $typeArr[$i] : $defaultHandler;
 
-                    $opArr = $request->get('op' . $groupCount);
+                    $opArr = $request->get("op$groupId");
                     $operator = !empty($opArr[$i]) ? $opArr[$i] : null;
 
                     // Add term to this group
-                    $boolArr = $request->get('bool' . $groupCount);
+                    $boolArr = $request->get("bool$groupId");
                     $lastBool = isset($boolArr[0]) ? $boolArr[0] : 'AND';
-                    $group[] = new Query($lookfor[$i], $handler, $operator);
+                    $group[] = new Query($value[$i], $handler, $operator);
                 }
             }
 
@@ -201,9 +203,6 @@ abstract class QueryAdapter
                 // Add the completed group to the list
                 $groups[] = new QueryGroup($lastBool, $group);
             }
-
-            // Increment
-            $groupCount++;
         }
 
         return (count($groups) > 0)
diff --git a/module/VuFind/src/VuFind/Search/Results/Factory.php b/module/VuFind/src/VuFind/Search/Results/Factory.php
index ff723c194597747cd4062dbd80c362b76fac1c17..03f4d1f300ca93787639e085ed91fd9eae352d45 100644
--- a/module/VuFind/src/VuFind/Search/Results/Factory.php
+++ b/module/VuFind/src/VuFind/Search/Results/Factory.php
@@ -46,12 +46,16 @@ class Factory
      *
      * @param ServiceManager $sm Service manager.
      *
-     * @return Favorites
+     * @return \VuFind\Search\Favorites\Results
      */
     public static function getFavorites(ServiceManager $sm)
     {
         $factory = new PluginFactory();
-        $obj = $factory->createServiceWithName($sm, 'favorites', 'Favorites');
+        $tm = $sm->getServiceLocator()->get('VuFind\DbTablePluginManager');
+        $obj = $factory->createServiceWithName(
+            $sm, 'favorites', 'Favorites',
+            [$tm->get('Resource'), $tm->get('UserList')]
+        );
         $init = new \ZfcRbac\Initializer\AuthorizationServiceInitializer();
         $init->initialize($obj, $sm);
         return $obj;
@@ -62,7 +66,7 @@ class Factory
      *
      * @param ServiceManager $sm Service manager.
      *
-     * @return Solr
+     * @return \VuFind\Search\Solr\Results
      */
     public static function getSolr(ServiceManager $sm)
     {
@@ -77,4 +81,20 @@ class Factory
         );
         return $solr;
     }
+
+    /**
+     * Factory for Tags results object.
+     *
+     * @param ServiceManager $sm Service manager.
+     *
+     * @return \VuFind\Search\Tags\Results
+     */
+    public static function getTags(ServiceManager $sm)
+    {
+        $factory = new PluginFactory();
+        $tm = $sm->getServiceLocator()->get('VuFind\DbTablePluginManager');
+        return $factory->createServiceWithName(
+            $sm, 'tags', 'Tags', [$tm->get('Tags')]
+        );
+    }
 }
diff --git a/module/VuFind/src/VuFind/Search/Results/PluginFactory.php b/module/VuFind/src/VuFind/Search/Results/PluginFactory.php
index 14f53b00a9f69ce8df27dfe909d401c5f305c1be..1f0e2482c65d4c82e85eee65c37451a1f8a03dd6 100644
--- a/module/VuFind/src/VuFind/Search/Results/PluginFactory.php
+++ b/module/VuFind/src/VuFind/Search/Results/PluginFactory.php
@@ -54,15 +54,21 @@ class PluginFactory extends \VuFind\ServiceManager\AbstractPluginFactory
      * @param ServiceLocatorInterface $serviceLocator Service locator
      * @param string                  $name           Name of service
      * @param string                  $requestedName  Unfiltered name of service
+     * @param array                   $extraParams    Extra constructor parameters
+     * (to follow the Params, Search and RecordLoader objects)
      *
      * @return object
      */
     public function createServiceWithName(ServiceLocatorInterface $serviceLocator,
-        $name, $requestedName
+        $name, $requestedName, array $extraParams = []
     ) {
         $params = $serviceLocator->getServiceLocator()
             ->get('VuFind\SearchParamsPluginManager')->get($requestedName);
+        $searchService = $serviceLocator->getServiceLocator()
+            ->get('VuFind\Search');
+        $recordLoader = $serviceLocator->getServiceLocator()
+            ->get('VuFind\RecordLoader');
         $class = $this->getClassName($name, $requestedName);
-        return new $class($params);
+        return new $class($params, $searchService, $recordLoader, ...$extraParams);
     }
 }
diff --git a/module/VuFind/src/VuFind/Search/Results/PluginManager.php b/module/VuFind/src/VuFind/Search/Results/PluginManager.php
index 2341fef78c47eb37141cc036716dadddfdedca0d..076f6ef5ec5527bfdcb634445c59cb2ce104db1a 100644
--- a/module/VuFind/src/VuFind/Search/Results/PluginManager.php
+++ b/module/VuFind/src/VuFind/Search/Results/PluginManager.php
@@ -26,7 +26,6 @@
  * @link     https://vufind.org/wiki/development:plugins:record_drivers Wiki
  */
 namespace VuFind\Search\Results;
-use Zend\ServiceManager\ConfigInterface;
 
 /**
  * Search results plugin manager
@@ -42,15 +41,20 @@ class PluginManager extends \VuFind\ServiceManager\AbstractPluginManager
     /**
      * Constructor
      *
-     * @param ConfigInterface $configuration Configuration settings (optional)
+     * Make sure plugins are properly initialized.
+     *
+     * @param mixed $configOrContainerInstance Configuration or container instance
+     * @param array $v3config                  If $configOrContainerInstance is a
+     * container, this value will be passed to the parent constructor.
      */
-    public function __construct(ConfigInterface $configuration = null)
-    {
+    public function __construct($configOrContainerInstance = null,
+        array $v3config = []
+    ) {
         // These objects are not meant to be shared -- every time we retrieve one,
         // we are building a brand new object.
         $this->setShareByDefault(false);
 
-        parent::__construct($configuration);
+        parent::__construct($configOrContainerInstance, $v3config);
     }
 
     /**
diff --git a/module/VuFind/src/VuFind/Search/SearchRunner.php b/module/VuFind/src/VuFind/Search/SearchRunner.php
index eec7df35e9549f7ebf436fcf426446bbd1d64a8f..b5044ff498116c081f705e592947eab8fd935552 100644
--- a/module/VuFind/src/VuFind/Search/SearchRunner.php
+++ b/module/VuFind/src/VuFind/Search/SearchRunner.php
@@ -75,10 +75,15 @@ class SearchRunner
      * Constructor
      *
      * @param ResultsManager $resultsManager Results manager
+     * @param EventManager   $events         Event manager (optional)
      */
-    public function __construct(ResultsManager $resultsManager)
-    {
+    public function __construct(ResultsManager $resultsManager,
+        EventManager $events = null
+    ) {
         $this->resultsManager = $resultsManager;
+        if (null !== $events) {
+            $this->setEventManager($events);
+        }
     }
 
     /**
diff --git a/module/VuFind/src/VuFind/Search/SearchTabsHelper.php b/module/VuFind/src/VuFind/Search/SearchTabsHelper.php
index 6a4fb95d6c86709b6de3d9ece37323b2a4ee61a2..95b37c6972bc3a94d853bcb2c46111f9b2f571af 100644
--- a/module/VuFind/src/VuFind/Search/SearchTabsHelper.php
+++ b/module/VuFind/src/VuFind/Search/SearchTabsHelper.php
@@ -171,7 +171,7 @@ class SearchTabsHelper extends \Zend\View\Helper\AbstractHelper
         }
 
         $firstTab = null;
-        foreach ($this->tabConfig as $key => $label) {
+        foreach (array_keys($this->tabConfig) as $key) {
             $class = $this->extractClassName($key);
             if ($class == $searchClassId) {
                 if (null === $firstTab) {
diff --git a/module/VuFind/src/VuFind/Search/Solr/DeduplicationListener.php b/module/VuFind/src/VuFind/Search/Solr/DeduplicationListener.php
index a2a34cc42b9bb0d440c6744be2ed7d2f1f11428d..e0512d76f38551989b68f2df6bc146bf27876725 100644
--- a/module/VuFind/src/VuFind/Search/Solr/DeduplicationListener.php
+++ b/module/VuFind/src/VuFind/Search/Solr/DeduplicationListener.php
@@ -346,11 +346,7 @@ class DeduplicationListener
     {
         $result = [];
         foreach ($params->get('fq') as $fq) {
-            if (preg_match_all(
-                '/\bbuilding:"([^"]+)"/',
-                $fq,
-                $matches
-            )) {
+            if (preg_match_all('/\bbuilding:"([^"]+)"/', $fq, $matches)) {
                 $values = $matches[1];
                 foreach ($values as $value) {
                     if (preg_match('/^\d+\/([^\/]+?)\//', $value, $matches)) {
@@ -364,8 +360,7 @@ class DeduplicationListener
         }
 
         array_unshift($result, '');
-        $result = array_flip($result);
-        return $result;
+        return array_flip($result);
     }
 
 }
diff --git a/module/VuFind/src/VuFind/Search/Solr/HierarchicalFacetHelper.php b/module/VuFind/src/VuFind/Search/Solr/HierarchicalFacetHelper.php
index 7f555923a3ed680c6f91a1e85a3542b3356f6ff9..980e7cf9cead13905a6b88a6ab04c509e94b219a 100644
--- a/module/VuFind/src/VuFind/Search/Solr/HierarchicalFacetHelper.php
+++ b/module/VuFind/src/VuFind/Search/Solr/HierarchicalFacetHelper.php
@@ -28,6 +28,7 @@
 namespace VuFind\Search\Solr;
 
 use VuFind\I18n\TranslatableString;
+use VuFind\Search\UrlQueryHelper;
 
 /**
  * Functions for manipulating facets
@@ -85,6 +86,7 @@ class HierarchicalFacetHelper
      * @param string    $facet     Facet name
      * @param array     $facetList Facet list
      * @param UrlHelper $urlHelper Query URL helper for building facet URLs
+     * @param bool      $escape    Whether to escape URLs
      *
      * @return array Facet hierarchy
      *
@@ -92,15 +94,14 @@ class HierarchicalFacetHelper
      * converting-a-flat-array-with-parent-ids-to-a-nested-tree/
      * Based on this example
      */
-    public function buildFacetArray($facet, $facetList, $urlHelper = false)
-    {
-        // getParamArray() is expensive, so call it just once and pass it on
-        $paramArray = $urlHelper !== false ? $urlHelper->getParamArray() : null;
+    public function buildFacetArray($facet, $facetList, $urlHelper = false,
+        $escape = true
+    ) {
         // Create a keyed (for conversion to hierarchical) array of facet data
         $keyedList = [];
         foreach ($facetList as $item) {
             $keyedList[$item['value']] = $this->createFacetItem(
-                $facet, $item, $urlHelper, $paramArray
+                $facet, $item, $urlHelper, $escape
             );
         }
 
@@ -175,16 +176,14 @@ class HierarchicalFacetHelper
     /**
      * Create an item for the hierarchical facet array
      *
-     * @param string         $facet      Facet name
-     * @param array          $item       Facet item received from Solr
-     * @param UrlQueryHelper $urlHelper  UrlQueryHelper for creating facet
-     * url's
-     * @param array          $paramArray URL parameters
-     * active children
+     * @param string         $facet     Facet name
+     * @param array          $item      Facet item received from Solr
+     * @param UrlQueryHelper $urlHelper UrlQueryHelper for creating facet URLs
+     * @param bool           $escape    Whether to escape URLs
      *
      * @return array Facet item
      */
-    protected function createFacetItem($facet, $item, $urlHelper, $paramArray)
+    protected function createFacetItem($facet, $item, $urlHelper, $escape = true)
     {
         $href = '';
         $exclude = '';
@@ -192,16 +191,15 @@ class HierarchicalFacetHelper
         if ($urlHelper !== false) {
             if ($item['isApplied']) {
                 $href = $urlHelper->removeFacet(
-                    $facet, $item['value'], true, $item['operator'], $paramArray
-                );
+                    $facet, $item['value'], $item['operator']
+                )->getParams($escape);
             } else {
                 $href = $urlHelper->addFacet(
-                    $facet, $item['value'], $item['operator'], $paramArray
-                );
+                    $facet, $item['value'], $item['operator']
+                )->getParams($escape);
             }
-            $exclude = $urlHelper->addFacet(
-                $facet, $item['value'], 'NOT', $paramArray
-            );
+            $exclude = $urlHelper->addFacet($facet, $item['value'], 'NOT')
+                ->getParams($escape);
         }
 
         $displayText = $item['displayText'];
diff --git a/module/VuFind/src/VuFind/Search/Solr/HierarchicalFacetListener.php b/module/VuFind/src/VuFind/Search/Solr/HierarchicalFacetListener.php
index 0f974ae07bccb2c3a4851526d4055ae4cdf5e197..6f4f6edcb5e6a1afd7828fdebc2131a2d5249084 100644
--- a/module/VuFind/src/VuFind/Search/Solr/HierarchicalFacetListener.php
+++ b/module/VuFind/src/VuFind/Search/Solr/HierarchicalFacetListener.php
@@ -151,7 +151,9 @@ class HierarchicalFacetListener
             return $event;
         }
         $context = $event->getParam('context');
-        if ($context == 'search' || $context == 'retrieve') {
+        if ($context == 'search' || $context == 'retrieve'
+            || $context == 'retrieveBatch'
+        ) {
             $this->processHierarchicalFacets($event);
         }
         return $event;
diff --git a/module/VuFind/src/VuFind/Search/Solr/Params.php b/module/VuFind/src/VuFind/Search/Solr/Params.php
index 9689a2d893bd900369351fcbacfd608bccfff1ee..9aa8e56d2e51c523cbc43816727fd49c0c88470a 100644
--- a/module/VuFind/src/VuFind/Search/Solr/Params.php
+++ b/module/VuFind/src/VuFind/Search/Solr/Params.php
@@ -88,15 +88,26 @@ class Params extends \VuFind\Search\Base\Params
      */
     protected $pivotFacets = null;
 
+    /**
+     * Hierarchical Facet Helper
+     *
+     * @var HierarchicalFacetHelper
+     */
+    protected $facetHelper;
+
     /**
      * Constructor
      *
      * @param \VuFind\Search\Base\Options  $options      Options to use
      * @param \VuFind\Config\PluginManager $configLoader Config loader
+     * @param HierarchicalFacetHelper      $facetHelper  Hierarchical facet helper
      */
-    public function __construct($options, \VuFind\Config\PluginManager $configLoader)
-    {
+    public function __construct($options, \VuFind\Config\PluginManager $configLoader,
+        HierarchicalFacetHelper $facetHelper = null
+    ) {
         parent::__construct($options, $configLoader);
+        $this->facetHelper = $facetHelper;
+
         // Use basic facet limit by default, if set:
         $config = $configLoader->get($options->getFacetsIni());
         if (isset($config->Results_Settings->facet_limit)
@@ -107,6 +118,9 @@ class Params extends \VuFind\Search\Base\Params
         if (isset($config->LegacyFields)) {
             $this->facetAliases = $config->LegacyFields->toArray();
         }
+        if (isset($config->ExtraFacetLabels)) {
+            $this->extraFacetLabels = $config->ExtraFacetLabels->toArray();
+        }
         if (isset($config->Results_Settings->facet_limit_by_field)) {
             foreach ($config->Results_Settings->facet_limit_by_field as $k => $v) {
                 $this->facetLimitByField[$k] = $v;
@@ -296,7 +310,7 @@ class Params extends \VuFind\Search\Base\Params
      */
     protected function initFacetList($facetList, $facetSettings, $cfgFile = 'facets')
     {
-        $config = $this->getServiceLocator()->get('VuFind\Config')->get('facets');
+        $config = $this->configLoader->get('facets');
         if (isset($config->$facetSettings->facet_limit)
             && is_numeric($config->$facetSettings->facet_limit)
         ) {
@@ -423,7 +437,7 @@ class Params extends \VuFind\Search\Base\Params
      */
     public function getQueryIDLimit()
     {
-        $config = $this->getServiceLocator()->get('VuFind\Config')->get('config');
+        $config = $this->configLoader->get('config');
         return isset($config->Index->maxBooleanClauses)
             ? $config->Index->maxBooleanClauses : 1024;
     }
@@ -586,11 +600,6 @@ class Params extends \VuFind\Search\Base\Params
         $hierarchicalFacets = $this->getOptions()->getHierarchicalFacets();
         $hierarchicalFacetSeparators
             = $this->getOptions()->getHierarchicalFacetSeparators();
-        $facetHelper = null;
-        if (!empty($hierarchicalFacets)) {
-            $facetHelper = $this->getServiceLocator()
-                ->get('VuFind\HierarchicalFacetHelper');
-        }
         // Convert range queries to a language-non-specific format:
         $caseInsensitiveRegex = '/^\(\[(.*) TO (.*)\] OR \[(.*) TO (.*)\]\)$/';
         if (preg_match('/^\[(.*) TO (.*)\]$/', $value, $matches)) {
@@ -604,12 +613,12 @@ class Params extends \VuFind\Search\Base\Params
             ) {
                 $filter['displayText'] = $matches[1] . '-' . $matches[2];
             }
-        } else if (in_array($field, $hierarchicalFacets)) {
+        } else if ($this->facetHelper && in_array($field, $hierarchicalFacets)) {
             // Display hierarchical facet levels nicely
             $separator = isset($hierarchicalFacetSeparators[$field])
                 ? $hierarchicalFacetSeparators[$field]
                 : '/';
-            $filter['displayText'] = $facetHelper->formatDisplayText(
+            $filter['displayText'] = $this->facetHelper->formatDisplayText(
                 $filter['displayText'], true, $separator
             );
             if ($translate) {
diff --git a/module/VuFind/src/VuFind/Search/SolrAuth/Results.php b/module/VuFind/src/VuFind/Search/SolrAuth/Results.php
index 9b81dd415428eadc1d1e85e3eca6d39455735677..aa8ffc769b6d6651147c42bd6bf5b5f15a544044 100644
--- a/module/VuFind/src/VuFind/Search/SolrAuth/Results.php
+++ b/module/VuFind/src/VuFind/Search/SolrAuth/Results.php
@@ -26,6 +26,8 @@
  * @link     https://vufind.org Main Page
  */
 namespace VuFind\Search\SolrAuth;
+use VuFind\Record\Loader;
+use VuFindSearch\Service as SearchService;
 
 /**
  * Solr Authority Search Parameters
@@ -41,12 +43,15 @@ class Results extends \VuFind\Search\Solr\Results
     /**
      * Constructor
      *
-     * @param \VuFind\Search\Base\Params $params Object representing user search
-     * parameters.
+     * @param \VuFind\Search\Base\Params $params        Object representing user
+     * search parameters.
+     * @param SearchService              $searchService Search service
+     * @param Loader                     $recordLoader  Record loader
      */
-    public function __construct(\VuFind\Search\Base\Params $params)
-    {
-        parent::__construct($params);
+    public function __construct(\VuFind\Search\Base\Params $params,
+        SearchService $searchService, Loader $recordLoader
+    ) {
+        parent::__construct($params, $searchService, $recordLoader);
         $this->backendId = 'SolrAuth';
     }
 }
diff --git a/module/VuFind/src/VuFind/Search/SolrAuthor/Results.php b/module/VuFind/src/VuFind/Search/SolrAuthor/Results.php
index c75436b2e064ffde421be5b57cb76bdc55069d90..4d896f9a8fc3089e216472ebeab56a3377e0d666 100644
--- a/module/VuFind/src/VuFind/Search/SolrAuthor/Results.php
+++ b/module/VuFind/src/VuFind/Search/SolrAuthor/Results.php
@@ -27,6 +27,8 @@
  */
 namespace VuFind\Search\SolrAuthor;
 use VuFind\Search\Solr\Results as SolrResults;
+use VuFind\Record\Loader;
+use VuFindSearch\Service as SearchService;
 
 /**
  * Author Search Options
@@ -42,16 +44,25 @@ class Results extends SolrResults
     /**
      * Constructor
      *
-     * @param \VuFind\Search\Base\Params $params Object representing user search
-     * parameters.
+     * @param \VuFind\Search\Base\Params $params        Object representing user
+     * search parameters.
+     * @param SearchService              $searchService Search service
+     * @param Loader                     $recordLoader  Record loader
      */
-    public function __construct($params)
-    {
-        // Call parent constructor:
-        parent::__construct($params);
+    public function __construct(\VuFind\Search\Base\Params $params,
+        SearchService $searchService, Loader $recordLoader
+    ) {
+        parent::__construct($params, $searchService, $recordLoader);
+    }
 
-        // Set up URL helper to use appropriate search parameter:
-        $this->getUrlQuery()->setBasicSearchParam('author');
+    /**
+     * Options for UrlQueryHelper
+     *
+     * @return array
+     */
+    protected function getUrlQueryHelperOptions()
+    {
+        return ['basicSearchParam' => 'author'];
     }
 
     /**
diff --git a/module/VuFind/src/VuFind/Search/SolrReserves/Results.php b/module/VuFind/src/VuFind/Search/SolrReserves/Results.php
index c611199ccafba7b283456d0a212896d3067f42b0..eb1ce36626a0515e26e799a9bc621dfc149f4738 100644
--- a/module/VuFind/src/VuFind/Search/SolrReserves/Results.php
+++ b/module/VuFind/src/VuFind/Search/SolrReserves/Results.php
@@ -27,6 +27,8 @@
  * @link     https://vufind.org Main Page
  */
 namespace VuFind\Search\SolrReserves;
+use VuFind\Record\Loader;
+use VuFindSearch\Service as SearchService;
 
 /**
  * Solr Reserves Search Parameters
@@ -43,12 +45,15 @@ class Results extends \VuFind\Search\Solr\Results
     /**
      * Constructor
      *
-     * @param \VuFind\Search\Base\Params $params Object representing user search
-     * parameters.
+     * @param \VuFind\Search\Base\Params $params        Object representing user
+     * search parameters.
+     * @param SearchService              $searchService Search service
+     * @param Loader                     $recordLoader  Record loader
      */
-    public function __construct(\VuFind\Search\Base\Params $params)
-    {
-        parent::__construct($params);
+    public function __construct(\VuFind\Search\Base\Params $params,
+        SearchService $searchService, Loader $recordLoader
+    ) {
+        parent::__construct($params, $searchService, $recordLoader);
         $this->backendId = 'SolrReserves';
     }
 }
diff --git a/module/VuFind/src/VuFind/Search/SolrWeb/Results.php b/module/VuFind/src/VuFind/Search/SolrWeb/Results.php
index 7c1c30d1da2018146f8856ae8c6ff270b399f96b..c3644b63f69115f38fe3daf8769171fc40211ffb 100644
--- a/module/VuFind/src/VuFind/Search/SolrWeb/Results.php
+++ b/module/VuFind/src/VuFind/Search/SolrWeb/Results.php
@@ -26,6 +26,8 @@
  * @link     https://vufind.org Main Page
  */
 namespace VuFind\Search\SolrWeb;
+use VuFind\Record\Loader;
+use VuFindSearch\Service as SearchService;
 
 /**
  * Solr Web Search Parameters
@@ -41,12 +43,15 @@ class Results extends \VuFind\Search\Solr\Results
     /**
      * Constructor
      *
-     * @param \VuFind\Search\Base\Params $params Object representing user search
-     * parameters.
+     * @param \VuFind\Search\Base\Params $params        Object representing user
+     * search parameters.
+     * @param SearchService              $searchService Search service
+     * @param Loader                     $recordLoader  Record loader
      */
-    public function __construct(\VuFind\Search\Base\Params $params)
-    {
-        parent::__construct($params);
+    public function __construct(\VuFind\Search\Base\Params $params,
+        SearchService $searchService, Loader $recordLoader
+    ) {
+        parent::__construct($params, $searchService, $recordLoader);
         $this->backendId = 'SolrWeb';
     }
 }
diff --git a/module/VuFind/src/VuFind/Search/Summon/Params.php b/module/VuFind/src/VuFind/Search/Summon/Params.php
index 9adcbbc847bf17b8de1d805dd7baa80f39b77a26..dd4ec33a6f79df864c513b7bafe3c414f296267f 100644
--- a/module/VuFind/src/VuFind/Search/Summon/Params.php
+++ b/module/VuFind/src/VuFind/Search/Summon/Params.php
@@ -188,7 +188,7 @@ class Params extends \VuFind\Search\Base\Params
         $backendParams->set('didYouMean', $options->spellcheckEnabled());
 
         // Get the language setting:
-        $lang = $this->getServiceLocator()->get('VuFind\Translator')->getLocale();
+        $lang = $this->getOptions()->getTranslator()->getLocale();
         $backendParams->set('language', substr($lang, 0, 2));
 
         if ($options->highlightEnabled()) {
@@ -212,7 +212,7 @@ class Params extends \VuFind\Search\Base\Params
      */
     protected function getBackendFacetParameters()
     {
-        $config = $this->getServiceLocator()->get('VuFind\Config')->get('Summon');
+        $config = $this->configLoader->get('Summon');
         $defaultFacetLimit = isset($config->Facet_Settings->facet_limit)
             ? $config->Facet_Settings->facet_limit : 30;
         $fieldSpecificLimits = isset($config->Facet_Settings->facet_limit_by_field)
@@ -266,6 +266,13 @@ class Params extends \VuFind\Search\Base\Params
                         $params->set(
                             'expand', strtolower(trim($safeValue)) == 'true'
                         );
+                    } else if ($filt['field'] == 'openAccessFilter') {
+                        // Special case -- "open access filter" is a separate
+                        // parameter from other facets.
+                        $params->set(
+                            'openAccessFilter',
+                            strtolower(trim($safeValue)) == 'true'
+                        );
                     } else if ($filt['field'] == 'excludeNewspapers') {
                         // Special case -- support a checkbox for excluding
                         // newspapers:
diff --git a/module/VuFind/src/VuFind/Search/Summon/Results.php b/module/VuFind/src/VuFind/Search/Summon/Results.php
index 827b720b9a494a8e30eecb774268e0fd1b469486..2fdaecd7ca20c787ba125294162b2f9381b5b732 100644
--- a/module/VuFind/src/VuFind/Search/Summon/Results.php
+++ b/module/VuFind/src/VuFind/Search/Summon/Results.php
@@ -125,6 +125,11 @@ class Results extends \VuFind\Search\Base\Results
      */
     public function getFacetList($filter = null)
     {
+        // Make sure we have processed the search before proceeding:
+        if (null === $this->responseFacets) {
+            $this->performAndProcessSearch();
+        }
+
         // If there is no filter, we'll use all facets as the filter:
         $filter = is_null($filter)
             ? $this->getParams()->getFacetConfig()
@@ -350,8 +355,17 @@ class Results extends \VuFind\Search\Base\Results
             $limit = 50;
         }
         $params->resetFacetConfig();
+        if (null !== $facetSort && 'count' !== $facetSort) {
+            throw new \Exception("$facetSort facet sort not supported by Summon.");
+        }
         foreach ($facetfields as $facet) {
-            $params->addFacet($facet . ',or,' . $page . ',' . $limit);
+            $mode = $params->getFacetOperator($facet) === 'OR' ? 'or' : 'and';
+            $params->addFacet("$facet,$mode,$page,$limit");
+
+            // Clear existing filters for the selected field if necessary:
+            if ($removeFilter) {
+                $params->removeAllFilters($facet);
+            }
         }
         $params = $params->getBackendParameters();
         $collection = $this->getSearchService()->search(
diff --git a/module/VuFind/src/VuFind/Search/Tags/Results.php b/module/VuFind/src/VuFind/Search/Tags/Results.php
index 5cb79bf923174b1a5c8724f575c3a4be1c20f726..d511e718a18021e25977a8da1e7116e3a79538c5 100644
--- a/module/VuFind/src/VuFind/Search/Tags/Results.php
+++ b/module/VuFind/src/VuFind/Search/Tags/Results.php
@@ -26,7 +26,10 @@
  * @link     https://vufind.org Main Site
  */
 namespace VuFind\Search\Tags;
+use VuFind\Db\Table\Tags as TagsTable;
+use VuFind\Record\Loader;
 use VuFind\Search\Base\Results as BaseResults;
+use VuFindSearch\Service as SearchService;
 
 /**
  * Search Tags Results
@@ -39,6 +42,29 @@ use VuFind\Search\Base\Results as BaseResults;
  */
 class Results extends BaseResults
 {
+    /**
+     * Tags table
+     *
+     * @var TagsTable
+     */
+    protected $tagsTable;
+
+    /**
+     * Constructor
+     *
+     * @param \VuFind\Search\Base\Params $params        Object representing user
+     * search parameters.
+     * @param SearchService              $searchService Search service
+     * @param Loader                     $recordLoader  Record loader
+     * @param TagsTable                  $tagsTable     Resource table
+     */
+    public function __construct(\VuFind\Search\Base\Params $params,
+        SearchService $searchService, Loader $recordLoader, TagsTable $tagsTable
+    ) {
+        parent::__construct($params, $searchService, $recordLoader);
+        $this->tagsTable = $tagsTable;
+    }
+
     /**
      * Process a fuzzy tag query.
      *
@@ -62,11 +88,10 @@ class Results extends BaseResults
      */
     protected function performTagSearch($fuzzy)
     {
-        $table = $this->getTable('Tags');
         $query = $fuzzy
             ? $this->formatFuzzyQuery($this->getParams()->getDisplayQuery())
             : $this->getParams()->getDisplayQuery();
-        $rawResults = $table->resourceSearch(
+        $rawResults = $this->tagsTable->resourceSearch(
             $query, null, $this->getParams()->getSort(), 0, null, $fuzzy
         );
 
@@ -76,7 +101,7 @@ class Results extends BaseResults
         // Apply offset and limit if necessary!
         $limit = $this->getParams()->getLimit();
         if ($this->resultTotal > $limit) {
-            $rawResults = $table->resourceSearch(
+            $rawResults = $this->tagsTable->resourceSearch(
                 $query, null, $this->getParams()->getSort(),
                 $this->getStartRecord() - 1, $limit, $fuzzy
             );
@@ -103,7 +128,7 @@ class Results extends BaseResults
         $callback = function ($row) {
             return ['id' => $row['record_id'], 'source' => $row['source']];
         };
-        $this->results = $this->getServiceLocator()->get('VuFind\RecordLoader')
+        $this->results = $this->recordLoader
             ->loadBatch(array_map($callback, $results));
     }
 
diff --git a/module/VuFind/src/VuFind/Search/UrlQueryHelper.php b/module/VuFind/src/VuFind/Search/UrlQueryHelper.php
index a112d5c97ae545eb153a1f4da8c68dcd80116339..03b5cf7d40e4f0d2d532334264eec508f859f50c 100644
--- a/module/VuFind/src/VuFind/Search/UrlQueryHelper.php
+++ b/module/VuFind/src/VuFind/Search/UrlQueryHelper.php
@@ -26,6 +26,9 @@
  * @link     https://vufind.org Main Site
  */
 namespace VuFind\Search;
+use VuFind\Search\Base\Options;
+use VuFindSearch\Query\AbstractQuery;
+use VuFindSearch\Query\Query;
 use VuFindSearch\Query\QueryGroup;
 
 /**
@@ -40,61 +43,134 @@ use VuFindSearch\Query\QueryGroup;
 class UrlQueryHelper
 {
     /**
-     * Options object
+     * Configuration for this helper.
      *
-     * @var \VuFind\Search\Base\Options
+     * @var array
      */
-    protected $options;
+    protected $config;
 
     /**
-     * Params object
+     * URL query parameters
      *
-     * @var \VuFind\Search\Base\Params
+     * @var array
      */
-    protected $params;
+    protected $urlParams = [];
 
     /**
-     * URL search param
+     * Current query object
      *
-     * @var string
+     * @var AbstractQuery
      */
-    protected $basicSearchParam = 'lookfor';
+    protected $queryObject;
 
     /**
-     * Base parameters for every search
+     * Constructor
      *
-     * @var array
+     * @param array         $urlParams             Array of URL query parameters.
+     * @param AbstractQuery $query                 Query object to use to update
+     * URL query.
+     * @param array         $options               Configuration options for the
+     * object.
+     * @param bool          $regenerateQueryParams Should we add parameters based
+     * on the contents of $query to $urlParams (true) or are they already there
+     * (false)?
      */
-    protected $defaultParams = [];
+    public function __construct(array $urlParams, AbstractQuery $query,
+        array $options = [], $regenerateQueryParams = true
+    ) {
+        $this->config = $options;
+        $this->urlParams = $urlParams;
+        $this->queryObject = $query;
+        if ($regenerateQueryParams) {
+            $this->regenerateSearchQueryParams();
+        }
+    }
 
     /**
-     * Should we suppress the standard query parameter?
+     * Get the name of the basic search param.
      *
-     * @var bool
+     * @return string
      */
-    protected $suppressQuery = false;
+    protected function getBasicSearchParam()
+    {
+        return isset($this->config['basicSearchParam'])
+            ? $this->config['basicSearchParam'] : 'lookfor';
+    }
 
     /**
-     * Constructor
+     * Reset search-related parameters in the internal array.
      *
-     * @param \VuFind\Search\Base\Params $params VuFind search results object.
+     * @return void
      */
-    public function __construct(\VuFind\Search\Base\Params $params)
+    protected function clearSearchQueryParams()
     {
-        $this->params = $params;
-        $this->options = $params->getOptions();
+        unset($this->urlParams[$this->getBasicSearchParam()]);
+        unset($this->urlParams['join']);
+        unset($this->urlParams['type']);
+        $searchParams = ['bool', 'lookfor', 'type', 'op'];
+        foreach (array_keys($this->urlParams) as $key) {
+            if (preg_match('/(' . implode('|', $searchParams) . ')[0-9]+/', $key)) {
+                unset($this->urlParams[$key]);
+            }
+        }
     }
 
     /**
-     * Set the name of the parameter used for basic search terms.
-     *
-     * @param string $param Parameter name to set.
+     * Adjust the internal query array based on the query object.
      *
      * @return void
      */
-    public function setBasicSearchParam($param)
+    protected function regenerateSearchQueryParams()
+    {
+        $this->clearSearchQueryParams();
+        if ($this->isQuerySuppressed()) {
+            return;
+        }
+        if ($this->queryObject instanceof QueryGroup) {
+            $this->urlParams['join'] = $this->queryObject->getOperator();
+            foreach ($this->queryObject->getQueries() as $i => $current) {
+                if ($current instanceof QueryGroup) {
+                    $operator = $current->isNegated()
+                        ? 'NOT' : $current->getOperator();
+                    $this->urlParams['bool' . $i] = [$operator];
+                    foreach ($current->getQueries() as $inner) {
+                        if (!isset($this->urlParams['lookfor' . $i])) {
+                            $this->urlParams['lookfor' . $i] = [];
+                        }
+                        if (!isset($this->urlParams['type' . $i])) {
+                            $this->urlParams['type' . $i] = [];
+                        }
+                        $this->urlParams['lookfor' . $i][] = $inner->getString();
+                        $this->urlParams['type' . $i][] = $inner->getHandler();
+                        if (null !== ($op = $inner->getOperator())) {
+                            $this->urlParams['op' . $i][] = $op;
+                        }
+                    }
+                }
+            }
+        } else if ($this->queryObject instanceof Query) {
+            $search = $this->queryObject->getString();
+            if (!empty($search)) {
+                $this->urlParams[$this->getBasicSearchParam()] = $search;
+            }
+            $type = $this->queryObject->getHandler();
+            if (!empty($type)) {
+                $this->urlParams['type'] = $type;
+            }
+        }
+    }
+
+    /**
+     * Look up a default value in the internal configuration array.
+     *
+     * @param string $key Name of default to load
+     *
+     * @return mixed
+     */
+    protected function getDefault($key)
     {
-        $this->basicSearchParam = $param;
+        return isset($this->config['defaults'][$key])
+            ? $this->config['defaults'][$key] : null;
     }
 
     /**
@@ -103,11 +179,12 @@ class UrlQueryHelper
      * @param string $name  Name of parameter
      * @param string $value Value of parameter
      *
-     * @return void
+     * @return UrlQueryHelper
      */
     public function setDefaultParameter($name, $value)
     {
-        $this->defaultParams[$name] = $value;
+        $this->urlParams[$name] = $value;
+        return $this;
     }
 
     /**
@@ -115,11 +192,13 @@ class UrlQueryHelper
      *
      * @param bool $suppress Should we suppress queries?
      *
-     * @return void
+     * @return UrlQueryHelper
      */
     public function setSuppressQuery($suppress)
     {
-        $this->suppressQuery = $suppress;
+        $this->config['suppressQuery'] = $suppress;
+        $this->regenerateSearchQueryParams();
+        return $this;
     }
 
     /**
@@ -129,7 +208,8 @@ class UrlQueryHelper
      */
     public function isQuerySuppressed()
     {
-        return $this->suppressQuery;
+        return isset($this->config['suppressQuery'])
+            ? (bool)$this->config['suppressQuery'] : false;
     }
 
     /**
@@ -139,102 +219,18 @@ class UrlQueryHelper
      */
     public function getParamArray()
     {
-        $params = $this->defaultParams;
-
-        // Build all the URL parameters based on search object settings:
-        if (!$this->suppressQuery) {
-            if ($this->params->getSearchType() == 'advanced') {
-                $query = $this->params->getQuery();
-                if ($query instanceof QueryGroup) {
-                    $params['join'] = $query->getOperator();
-                    foreach ($query->getQueries() as $i => $current) {
-                        if ($current instanceof QueryGroup) {
-                            $operator = $current->isNegated()
-                                ? 'NOT' : $current->getOperator();
-                            $params['bool' . $i] = [$operator];
-                            foreach ($current->getQueries() as $inner) {
-                                if (!isset($params['lookfor' . $i])) {
-                                    $params['lookfor' . $i] = [];
-                                }
-                                if (!isset($params['type' . $i])) {
-                                    $params['type' . $i] = [];
-                                }
-                                $params['lookfor' . $i][] = $inner->getString();
-                                $params['type' . $i][] = $inner->getHandler();
-                                if (null !== ($op = $inner->getOperator())) {
-                                    $params['op' . $i][] = $op;
-                                }
-                            }
-                        } else {
-                            throw new \Exception('Unexpected Query object.');
-                        }
-                    }
-                } else {
-                    throw new \Exception('Unexpected Query object.');
-                }
-            } else {
-                $search = $this->params->getDisplayQuery();
-                if (!empty($search)) {
-                    $params[$this->basicSearchParam] = $search;
-                }
-                $type = $this->params->getSearchHandler();
-                if (!empty($type)) {
-                    $params['type'] = $type;
-                }
-            }
-        }
-        $sort = $this->params->getSort();
-        if (!is_null($sort)
-            && $sort != $this->params->getDefaultSort()
-        ) {
-            $params['sort'] = $sort;
-        }
-        $limit = $this->params->getLimit();
-        if (!is_null($limit)
-            && $limit != $this->options->getDefaultLimit()
-        ) {
-            $params['limit'] = $limit;
-        }
-        $view = $this->params->getView();
-        if (!is_null($view)
-            && $view != $this->options->getDefaultView()
-        ) {
-            $params['view'] = $view;
-        }
-        if ($this->params->getPage() != 1) {
-            $params['page'] = $this->params->getPage();
-        }
-        $filters = $this->params->getFilters();
-        if (!empty($filters)) {
-            $params['filter'] = [];
-            foreach ($filters as $field => $values) {
-                foreach ($values as $current) {
-                    $params['filter'][] = $field . ':"' . $current . '"';
-                }
-            }
-        }
-        $hiddenFilters = $this->params->getHiddenFilters();
-        if (!empty($hiddenFilters)) {
-            foreach ($hiddenFilters as $field => $values) {
-                foreach ($values as $current) {
-                    $params['hiddenFilters'][] = $field . ':"' . $current . '"';
-                }
-            }
-        }
-        $shards = $this->params->getSelectedShards();
-        if (!empty($shards)) {
-            sort($shards);
-            $defaultShards = $this->options->getDefaultSelectedShards();
-            sort($defaultShards);
-            if (implode(':::', $shards) != implode(':::', $defaultShards)) {
-                $params['shard'] = $shards;
-            }
-        }
-        if ($this->params->hasDefaultsApplied()) {
-            $params['dfApplied'] = 1;
-        }
+        return $this->urlParams;
+    }
 
-        return $params;
+    /**
+     * Magic method: behavior when this object is treated as a string.
+     *
+     * @return string
+     */
+    public function __toString()
+    {
+        $escape = isset($this->config['escape']) ? $this->config['escape'] : true;
+        return $this->getParams($escape);
     }
 
     /**
@@ -243,46 +239,41 @@ class UrlQueryHelper
      * @param string $from Search term to find
      * @param string $to   Search term to insert
      *
-     * @return string
+     * @return UrlQueryHelper
      */
     public function replaceTerm($from, $to)
     {
-        $newParams = clone($this->params);
-        $newParams->getQuery()->replaceTerm($from, $to);
-        $helper = new static($newParams);
-        return $helper->getParams();
+        $query = clone($this->queryObject);
+        $query->replaceTerm($from, $to);
+        return new static($this->urlParams, $query, $this->config);
     }
 
     /**
      * Add a facet to the parameters.
      *
-     * @param string $field      Facet field
-     * @param string $value      Facet value
-     * @param string $operator   Facet type to add (AND, OR, NOT)
-     * @param array  $paramArray Optional array of parameters to use instead of
-     * getParamArray()
+     * @param string $field    Facet field
+     * @param string $value    Facet value
+     * @param string $operator Facet type to add (AND, OR, NOT)
      *
-     * @return string
+     * @return UrlQueryHelper
      */
-    public function addFacet($field, $value, $operator = 'AND', $paramArray = null)
+    public function addFacet($field, $value, $operator = 'AND')
     {
         // Facets are just a special case of filters:
         $prefix = ($operator == 'NOT') ? '-' : ($operator == 'OR' ? '~' : '');
-        return $this->addFilter($prefix . $field . ':"' . $value . '"', $paramArray);
+        return $this->addFilter($prefix . $field . ':"' . $value . '"');
     }
 
     /**
      * Add a filter to the parameters.
      *
-     * @param string $filter     Filter to add
-     * @param array  $paramArray Optional array of parameters to use instead of
-     * getParamArray()
+     * @param string $filter Filter to add
      *
-     * @return string
+     * @return UrlQueryHelper
      */
-    public function addFilter($filter, $paramArray = null)
+    public function addFilter($filter)
     {
-        $params = is_null($paramArray) ? $this->getParamArray() : $paramArray;
+        $params = $this->urlParams;
 
         // Add the filter:
         if (!isset($params['filter'])) {
@@ -293,7 +284,7 @@ class UrlQueryHelper
         // Clear page:
         unset($params['page']);
 
-        return '?' . $this->buildQueryString($params);
+        return new static($params, $this->queryObject, $this->config, false);
     }
 
     /**
@@ -303,11 +294,11 @@ class UrlQueryHelper
      */
     public function removeAllFilters()
     {
-        $params = $this->getParamArray();
+        $params = $this->urlParams;
         // Clear page:
         unset($params['filter']);
 
-        return '?' . $this->buildQueryString($params);
+        return new static($params, $this->queryObject, $this->config, false);
     }
 
     /**
@@ -319,25 +310,62 @@ class UrlQueryHelper
      */
     public function getParams($escape = true)
     {
-        return '?' . $this->buildQueryString($this->getParamArray(), $escape);
+        return '?' . $this->buildQueryString($this->urlParams, $escape);
+    }
+
+    /**
+     * Parse apart the field and value from a URL filter string.
+     *
+     * @param string $filter A filter string from url : "field:value"
+     *
+     * @return array         Array with elements 0 = field, 1 = value.
+     */
+    protected function parseFilter($filter)
+    {
+        // Simplistic explode/trim behavior if no callback is provided:
+        if (!isset($this->config['parseFilterCallback'])
+            || !is_callable($this->config['parseFilterCallback'])
+        ) {
+            $parts = explode(':', $filter, 2);
+            $parts[1] = trim($parts[1], '"');
+            return $parts;
+        }
+        return call_user_func($this->config['parseFilterCallback'], $filter);
+    }
+
+    /**
+     * Given a facet field, return an array containing all aliases of that
+     * field.
+     *
+     * @param string $field Field to look up
+     *
+     * @return array
+     */
+    protected function getAliasesForFacetField($field)
+    {
+        // If no callback is provided, aliases are unsupported:
+        if (!isset($this->config['getAliasesForFacetFieldCallback'])
+            || !is_callable($this->config['getAliasesForFacetFieldCallback'])
+        ) {
+            return [$field];
+        }
+        return call_user_func(
+            $this->config['getAliasesForFacetFieldCallback'], $field
+        );
     }
 
     /**
      * Remove a facet from the parameters.
      *
-     * @param string $field      Facet field
-     * @param string $value      Facet value
-     * @param bool   $escape     Should we escape the string for use in the view?
-     * @param string $operator   Facet type to add (AND, OR, NOT)
-     * @param array  $paramArray Optional array of parameters to use instead of
-     * getParamArray()
+     * @param string $field    Facet field
+     * @param string $value    Facet value
+     * @param string $operator Facet type to add (AND, OR, NOT)
      *
      * @return string
      */
-    public function removeFacet($field, $value, $escape = true, $operator = 'AND',
-        $paramArray = null
-    ) {
-        $params = is_null($paramArray) ? $this->getParamArray() : $paramArray;
+    public function removeFacet($field, $value, $operator = 'AND')
+    {
+        $params = $this->urlParams;
 
         // Account for operators:
         if ($operator == 'NOT') {
@@ -346,14 +374,14 @@ class UrlQueryHelper
             $field = '~' . $field;
         }
 
-        $fieldAliases = $this->params->getAliasesForFacetField($field);
+        $fieldAliases = $this->getAliasesForFacetField($field);
 
         // Remove the filter:
         $newFilter = [];
         if (isset($params['filter']) && is_array($params['filter'])) {
             foreach ($params['filter'] as $current) {
                 list($currentField, $currentValue)
-                    = $this->params->parseFilter($current);
+                    = $this->parseFilter($current);
                 if (!in_array($currentField, $fieldAliases)
                     || $currentValue != $value
                 ) {
@@ -370,50 +398,47 @@ class UrlQueryHelper
         // Clear page:
         unset($params['page']);
 
-        return '?' . $this->buildQueryString($params, $escape);
+        return new static($params, $this->queryObject, $this->config, false);
     }
 
     /**
      * Remove a filter from the parameters.
      *
      * @param string $filter Filter to add
-     * @param bool   $escape Should we escape the string for use in the view?
      *
      * @return string
      */
-    public function removeFilter($filter, $escape = true)
+    public function removeFilter($filter)
     {
         // Treat this as a special case of removeFacet:
-        list($field, $value) = $this->params->parseFilter($filter);
-        return $this->removeFacet($field, $value, $escape);
+        list($field, $value) = $this->parseFilter($filter);
+        return $this->removeFacet($field, $value);
     }
 
     /**
      * Return HTTP parameters to render a different page of results.
      *
-     * @param string $p      New page parameter (null for NO page parameter)
-     * @param bool   $escape Should we escape the string for use in the view?
+     * @param string $p New page parameter (null for NO page parameter)
      *
      * @return string
      */
-    public function setPage($p, $escape = true)
+    public function setPage($p)
     {
-        return $this->updateQueryString('page', $p, 1, $escape);
+        return $this->updateQueryString('page', $p, 1);
     }
 
     /**
      * Return HTTP parameters to render the current page with a different sort
      * parameter.
      *
-     * @param string $s      New sort parameter (null for NO sort parameter)
-     * @param bool   $escape Should we escape the string for use in the view?
+     * @param string $s New sort parameter (null for NO sort parameter)
      *
      * @return string
      */
-    public function setSort($s, $escape = true)
+    public function setSort($s)
     {
         return $this->updateQueryString(
-            'sort', $s, $this->params->getDefaultSort(), $escape, true
+            'sort', $s, $this->getDefault('sort'), true
         );
     }
 
@@ -422,16 +447,17 @@ class UrlQueryHelper
      * handler.
      *
      * @param string $handler new Handler.
-     * @param bool   $escape  Should we escape the string for use in the view?
      *
      * @return string
      */
-    public function setHandler($handler, $escape = true)
+    public function setHandler($handler)
     {
-        return $this->updateQueryString(
-            'type', $handler, $this->options->getDefaultHandler(),
-            $escape
-        );
+        $query = clone($this->queryObject);
+        // We can only set the handler on basic queries:
+        if ($query instanceof Query) {
+            $query->setHandler($handler);
+        }
+        return new static($this->urlParams, $query, $this->config);
     }
 
     /**
@@ -441,32 +467,30 @@ class UrlQueryHelper
      * Note: This is called setViewParam rather than setView to avoid confusion
      * with the \Zend\View\Helper\AbstractHelper interface.
      *
-     * @param string $v      New sort parameter (null for NO view parameter)
-     * @param bool   $escape Should we escape the string for use in the view?
+     * @param string $v New sort parameter (null for NO view parameter)
      *
      * @return string
      */
-    public function setViewParam($v, $escape = true)
+    public function setViewParam($v)
     {
         // Because of the way view settings are stored in the session, we always
         // want an explicit value here (hence null rather than default view in
         // third parameter below):
-        return $this->updateQueryString('view', $v, null, $escape);
+        return $this->updateQueryString('view', $v, null);
     }
 
     /**
      * Return HTTP parameters to render the current page with a different limit
      * parameter.
      *
-     * @param string $l      New limit parameter (null for NO limit parameter)
-     * @param bool   $escape Should we escape the string for use in the view?
+     * @param string $l New limit parameter (null for NO limit parameter)
      *
      * @return string
      */
-    public function setLimit($l, $escape = true)
+    public function setLimit($l)
     {
         return $this->updateQueryString(
-            'limit', $l, $this->options->getDefaultLimit(), $escape, true
+            'limit', $l, $this->getDefault('limit'), true
         );
     }
 
@@ -475,30 +499,13 @@ class UrlQueryHelper
      * of search terms.
      *
      * @param string $lookfor New search terms
-     * @param bool   $escape  Should we escape the string for use in the view?
      *
      * @return string
      */
-    public function setSearchTerms($lookfor, $escape = true)
+    public function setSearchTerms($lookfor)
     {
-        // If we're currently dealing with an advanced query, turn it off so
-        // that it can be overridden:
-        if ($this->params->getSearchType() == 'advanced') {
-            $savedSuppressQuery = $this->suppressQuery;
-            $this->suppressQuery = true;
-        }
-
-        // Generate the URL:
-        $new = $this->updateQueryString(
-            $this->basicSearchParam, $lookfor, null, $escape, true
-        );
-
-        // Restore settings to their previous state:
-        if (isset($savedSuppressQuery)) {
-            $this->suppressQuery = $savedSuppressQuery;
-        }
-
-        return $new;
+        $query = new Query($lookfor);
+        return new static($this->urlParams, $query, $this->config);
     }
 
     /**
@@ -512,7 +519,7 @@ class UrlQueryHelper
     public function asHiddenFields($filter = [])
     {
         $retVal = '';
-        foreach ($this->getParamArray() as $paramName => $paramValue) {
+        foreach ($this->urlParams as $paramName => $paramValue) {
             if (is_array($paramValue)) {
                 foreach ($paramValue as $paramValue2) {
                     if (!$this->filtered($paramName, $paramValue2, $filter)) {
@@ -554,16 +561,15 @@ class UrlQueryHelper
      * @param string $value     Value to use (null to skip field entirely)
      * @param string $default   Default value (skip field if $value matches; null
      *                          for no default).
-     * @param bool   $escape    Should we escape the string for use in the view?
      * @param bool   $clearPage Should we clear the page number, if any?
      *
      * @return string
      */
     protected function updateQueryString($field, $value, $default = null,
-        $escape = true, $clearPage = false
+        $clearPage = false
     ) {
-        $params = $this->getParamArray();
-        if (is_null($value) || $value == $default) {
+        $params = $this->urlParams;
+        if (null === $value || $value == $default) {
             unset($params[$field]);
         } else {
             $params[$field] = $value;
@@ -571,7 +577,7 @@ class UrlQueryHelper
         if ($clearPage && isset($params['page'])) {
             unset($params['page']);
         }
-        return '?' . $this->buildQueryString($params, $escape);
+        return new static($params, $this->queryObject, $this->config, false);
     }
 
     /**
diff --git a/module/VuFind/src/VuFind/Service/Factory.php b/module/VuFind/src/VuFind/Service/Factory.php
index 6593137e45e7fc47d4a1d3e4d9f0f81c8d5bbb23..1a0ef93fbcb9a26aea4d4d8156a9a7af21c1b12a 100644
--- a/module/VuFind/src/VuFind/Service/Factory.php
+++ b/module/VuFind/src/VuFind/Service/Factory.php
@@ -109,12 +109,26 @@ class Factory
             ? (bool)$config->Site->showBookBag : false;
         $size = isset($config->Site->bookBagMaxSize)
             ? $config->Site->bookBagMaxSize : 100;
+        $activeInSearch = isset($config->Site->bookbagTogglesInSearch)
+            ? $config->Site->bookbagTogglesInSearch : true;
         return new \VuFind\Cart(
             $sm->get('VuFind\RecordLoader'), $sm->get('VuFind\CookieManager'),
-            $size, $active
+            $size, $active, $activeInSearch
         );
     }
 
+    /**
+     * Construct the Channel Provider Plugin Manager.
+     *
+     * @param ServiceManager $sm Service manager.
+     *
+     * @return \VuFind\ChannelProvider\PluginManager
+     */
+    public static function getChannelProviderPluginManager(ServiceManager $sm)
+    {
+        return static::getGenericPluginManager($sm, 'ChannelProvider');
+    }
+
     /**
      * Construct the config manager.
      *
@@ -126,7 +140,7 @@ class Factory
     {
         $config = $sm->get('Config');
         return new \VuFind\Config\PluginManager(
-            new \Zend\ServiceManager\Config($config['vufind']['config_reader'])
+            $sm, $config['vufind']['config_reader']
         );
     }
 
@@ -215,7 +229,12 @@ class Factory
         $domain = isset($config->Cookies->domain)
             ? $config->Cookies->domain
             : null;
-        return new \VuFind\Cookie\CookieManager($_COOKIE, $path, $domain, $secure);
+        $session_name = isset($config->Cookies->session_name)
+            ? $config->Cookies->session_name
+            : null;
+        return new \VuFind\Cookie\CookieManager(
+            $_COOKIE, $path, $domain, $secure, $session_name
+        );
     }
 
     /**
@@ -272,6 +291,18 @@ class Factory
         );
     }
 
+    /**
+     * Construct the Db\Row Plugin Manager.
+     *
+     * @param ServiceManager $sm Service manager.
+     *
+     * @return \VuFind\Db\Row\PluginManager
+     */
+    public static function getDbRowPluginManager(ServiceManager $sm)
+    {
+        return static::getGenericPluginManager($sm, 'Db\Row');
+    }
+
     /**
      * Construct the Db\Table Plugin Manager.
      *
@@ -313,9 +344,7 @@ class Factory
         $configKey = strtolower(str_replace('\\', '_', $ns));
         $config = $sm->get('Config');
         return new $className(
-            new \Zend\ServiceManager\Config(
-                $config['vufind']['plugin_managers'][$configKey]
-            )
+            $sm, $config['vufind']['plugin_managers'][$configKey]
         );
     }
 
@@ -481,21 +510,6 @@ class Factory
         );
     }
 
-    /**
-     * Construct the logger.
-     *
-     * @param ServiceManager $sm Service manager.
-     *
-     * @return \VuFind\Log\Logger
-     */
-    public static function getLogger(ServiceManager $sm)
-    {
-        $logger = new \VuFind\Log\Logger();
-        $logger->setServiceLocator($sm);
-        $logger->setConfig($sm->get('VuFind\Config')->get('config'));
-        return $logger;
-    }
-
     /**
      * Construct the ProxyManager configuration.
      *
@@ -535,17 +549,16 @@ class Factory
             : (isset($config->Captcha->privateKey)
                 ? $config->Captcha->privateKey
                 : '');
-        $recaptcha = new \VuFind\Service\ReCaptcha(
-            $siteKey, $secretKey, ['ssl' => true]
-        );
+        $httpClient = $sm->get('VuFind\Http')->createClient();
+        $translator = $sm->get('VuFind\Translator');
+        $options = ['lang' => $translator->getLocale()];
         if (isset($config->Captcha->theme)) {
-            $recaptcha->setOption('theme', $config->Captcha->theme);
+            $options['theme'] = $config->Captcha->theme;
         }
-        $translator = $sm->get('VuFind\Translator');
-        $recaptcha->setOption('lang', $translator->getLocale());
+        $recaptcha = new \VuFind\Service\ReCaptcha(
+            $siteKey, $secretKey, ['ssl' => true], $options, null, $httpClient
+        );
 
-        $httpClient = $sm->get('VuFind\Http')->createClient();
-        $recaptcha->setHttpClient($httpClient);
         return $recaptcha;
     }
 
@@ -620,22 +633,6 @@ class Factory
         );
     }
 
-    /**
-     * Construct the record stats helper.
-     *
-     * @param ServiceManager $sm Service manager.
-     *
-     * @return \VuFind\Statistics\Record
-     */
-    public static function getRecordStats(ServiceManager $sm)
-    {
-        return new \VuFind\Statistics\Record(
-            $sm->get('VuFind\Config')->get('config'),
-            $sm->get('VuFind\StatisticsDriverPluginManager'),
-            $sm->get('VuFind\SessionManager')->getId()
-        );
-    }
-
     /**
      * Construct the RecordTab Plugin Manager.
      *
@@ -687,7 +684,7 @@ class Factory
         );
         $registry = $sm->createScopedServiceManager();
         $smConfig->configureServiceManager($registry);
-        $manager  = new \VuFind\Search\BackendManager($registry);
+        $manager = new \VuFind\Search\BackendManager($registry);
 
         return $manager;
     }
@@ -752,37 +749,36 @@ class Factory
     public static function getSearchRunner(ServiceManager $sm)
     {
         return new \VuFind\Search\SearchRunner(
-            $sm->get('VuFind\SearchResultsPluginManager')
+            $sm->get('VuFind\SearchResultsPluginManager'),
+            new \Zend\EventManager\EventManager($sm->get('SharedEventManager'))
         );
     }
 
     /**
-     * Construct the search specs reader.
+     * Construct the search service.
      *
      * @param ServiceManager $sm Service manager.
      *
-     * @return \VuFind\Config\SearchSpecsReader
+     * @return \VuFindSearch\Service
      */
-    public static function getSearchSpecsReader(ServiceManager $sm)
+    public static function getSearchService(ServiceManager $sm)
     {
-        return new \VuFind\Config\SearchSpecsReader(
-            $sm->get('VuFind\CacheManager')
+        return new \VuFindSearch\Service(
+            new \Zend\EventManager\EventManager($sm->get('SharedEventManager'))
         );
     }
 
     /**
-     * Construct the search stats helper.
+     * Construct the search specs reader.
      *
      * @param ServiceManager $sm Service manager.
      *
-     * @return \VuFind\Statistics\Search
+     * @return \VuFind\Config\SearchSpecsReader
      */
-    public static function getSearchStats(ServiceManager $sm)
+    public static function getSearchSpecsReader(ServiceManager $sm)
     {
-        return new \VuFind\Statistics\Search(
-            $sm->get('VuFind\Config')->get('config'),
-            $sm->get('VuFind\StatisticsDriverPluginManager'),
-            $sm->get('VuFind\SessionManager')->getId()
+        return new \VuFind\Config\SearchSpecsReader(
+            $sm->get('VuFind\CacheManager')
         );
     }
 
@@ -834,18 +830,6 @@ class Factory
         );
     }
 
-    /**
-     * Construct the Statistics\Driver Plugin Manager.
-     *
-     * @param ServiceManager $sm Service manager.
-     *
-     * @return \VuFind\Statistics\Driver\PluginManager
-     */
-    public static function getStatisticsDriverPluginManager(ServiceManager $sm)
-    {
-        return static::getGenericPluginManager($sm, 'Statistics\Driver');
-    }
-
     /**
      * Construct the tag helper.
      *
@@ -932,4 +916,18 @@ class Factory
             $client, true, $ip
         );
     }
+
+    /**
+     * Construct the YAML reader.
+     *
+     * @param ServiceManager $sm Service manager.
+     *
+     * @return \VuFind\Config\YamlReader
+     */
+    public static function getYamlReader(ServiceManager $sm)
+    {
+        return new \VuFind\Config\YamlReader(
+            $sm->get('VuFind\CacheManager')
+        );
+    }
 }
diff --git a/module/VuFind/src/VuFind/Service/ReCaptcha.php b/module/VuFind/src/VuFind/Service/ReCaptcha.php
index 2a8ff0925846f56f3428cceebad3facdde8868d0..fc2a3c2ae81c5028cd25702838e97ab0d84af4b2 100644
--- a/module/VuFind/src/VuFind/Service/ReCaptcha.php
+++ b/module/VuFind/src/VuFind/Service/ReCaptcha.php
@@ -20,7 +20,7 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
  * @category VuFind
- * @package  View_Helpers
+ * @package  Service
  * @author   Chris Hallberg <crhallberg@gmail.com>
  * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
  * @link     https://vufind.org/wiki/development Wiki
@@ -36,7 +36,7 @@ namespace VuFind\Service;
  * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
  * @link     https://vufind.org/wiki/development Wiki
  */
-class ReCaptcha extends \LosReCaptcha\Service\ReCaptcha
+class ReCaptcha extends \ZendService\ReCaptcha\ReCaptcha
 {
     /**
      * Get the HTML code for the captcha
@@ -66,7 +66,7 @@ class ReCaptcha extends \LosReCaptcha\Service\ReCaptcha
         $divregex = '/<div[^>]*id=[\'"]recaptcha_widget[\'"][^>]*>/';
 
         $scriptRegex = '|<script[^>]*></script>|';
-        $scriptReplacement = '<script>/*form magic*/</script>';
+        $scriptReplacement = ''; // remove
 
         return preg_replace(
             [$divregex, $scriptRegex],
diff --git a/module/VuFind/src/VuFind/ServiceManager/AbstractPluginManager.php b/module/VuFind/src/VuFind/ServiceManager/AbstractPluginManager.php
index 94dc060fa382857b6214c46d36dd7e918771a31d..6e83f1039bcf023d98c3773e43d256c847429094 100644
--- a/module/VuFind/src/VuFind/ServiceManager/AbstractPluginManager.php
+++ b/module/VuFind/src/VuFind/ServiceManager/AbstractPluginManager.php
@@ -46,13 +46,16 @@ abstract class AbstractPluginManager extends Base
     /**
      * Constructor
      *
-     * Make sure table gateways are properly initialized.
+     * Make sure plugins are properly initialized.
      *
-     * @param ConfigInterface $configuration Configuration settings (optional)
+     * @param mixed $configOrContainerInstance Configuration or container instance
+     * @param array $v3config                  If $configOrContainerInstance is a
+     * container, this value will be passed to the parent constructor.
      */
-    public function __construct(ConfigInterface $configuration = null)
-    {
-        parent::__construct($configuration);
+    public function __construct($configOrContainerInstance = null,
+        array $v3config = []
+    ) {
+        parent::__construct($configOrContainerInstance, $v3config);
         $this->addInitializer(
             ['VuFind\ServiceManager\Initializer', 'initPlugin'], false
         );
diff --git a/module/VuFind/src/VuFind/Session/AbstractBase.php b/module/VuFind/src/VuFind/Session/AbstractBase.php
index 0adaa6914c316d11248313499220ef5ef4c7433c..748a7491287911c701302297e953b6f075ccfd16 100644
--- a/module/VuFind/src/VuFind/Session/AbstractBase.php
+++ b/module/VuFind/src/VuFind/Session/AbstractBase.php
@@ -143,8 +143,10 @@ abstract class AbstractBase implements SaveHandlerInterface,
      */
     public function destroy($sess_id)
     {
-        $table = $this->getTable('Search');
-        $table->destroySession($sess_id);
+        $searchTable = $this->getTable('Search');
+        $searchTable->destroySession($sess_id);
+        $sessionTable = $this->getTable('ExternalSession');
+        $sessionTable->destroySession($sess_id);
         return true;
     }
 
diff --git a/module/VuFind/src/VuFind/Session/Database.php b/module/VuFind/src/VuFind/Session/Database.php
index 7320f68ffc829e031020b6acf8771f827f88d117..752f7a251201833d6931d27617c9f1a115ad3a4b 100644
--- a/module/VuFind/src/VuFind/Session/Database.php
+++ b/module/VuFind/src/VuFind/Session/Database.php
@@ -55,7 +55,7 @@ class Database extends AbstractBase
                 ->readSession($sess_id, $this->lifetime);
         } catch (SessionExpiredException $e) {
             $this->destroy($sess_id);
-            return;
+            return '';
         }
     }
 
diff --git a/module/VuFind/src/VuFind/Session/ManagerFactory.php b/module/VuFind/src/VuFind/Session/ManagerFactory.php
index 4210d729bd32c02c2e7b46f29c256cec98f865a2..db2c4de87114998e67075ec46b1ddef8ab4f5a43 100644
--- a/module/VuFind/src/VuFind/Session/ManagerFactory.php
+++ b/module/VuFind/src/VuFind/Session/ManagerFactory.php
@@ -56,10 +56,17 @@ class ManagerFactory implements \Zend\ServiceManager\FactoryInterface
             'cookie_path' => $cookieManager->getPath(),
             'cookie_secure' => $cookieManager->isSecure()
         ];
+
         $domain = $cookieManager->getDomain();
         if (!empty($domain)) {
             $options['cookie_domain'] = $domain;
         }
+
+        $name = $cookieManager->getSessionName();
+        if (!empty($name)) {
+            $options['name'] = $name;
+        }
+
         return $options;
     }
 
diff --git a/module/VuFind/src/VuFind/Statistics/AbstractBase.php b/module/VuFind/src/VuFind/Statistics/AbstractBase.php
deleted file mode 100644
index 4ca00530e4e6fd6805a9a303587091d760d7f465..0000000000000000000000000000000000000000
--- a/module/VuFind/src/VuFind/Statistics/AbstractBase.php
+++ /dev/null
@@ -1,250 +0,0 @@
-<?php
-/**
- * VuFind Stastics Controller
- *
- * PHP version 5
- *
- * Copyright (C) Villanova University 2010.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- *
- * @category VuFind
- * @package  Statistics
- * @author   Chris Hallberg <challber@villanova.edu>
- * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
- * @link     https://vufind.org Main Page
- */
-namespace VuFind\Statistics;
-use VuFind\Statistics\Driver\PluginManager, Zend\Config\Config;
-
-/**
- * VuFind Search Controller
- *
- * @category VuFind
- * @package  Statistics
- * @author   Chris Hallberg <challber@villanova.edu>
- * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
- * @link     https://vufind.org Main Page
- */
-abstract class AbstractBase
-{
-    /**
-     * Array of statistics drivers (null if not yet initialized)
-     *
-     * @var array
-     */
-    protected $drivers = null;
-
-    /**
-     * An identifier of the source of the current set of statistics
-     *
-     * @var string
-     */
-    protected $source;
-
-    /**
-     * Session ID
-     *
-     * @var string
-     */
-    protected $sessId;
-
-    /**
-     * Statistics driver plugin manager
-     *
-     * @var PluginManager
-     */
-    protected $pluginManager;
-
-    /**
-     * VuFind configuration
-     *
-     * @var Config
-     */
-    protected $config;
-
-    /**
-     * Constructor
-     *
-     * @param Config        $config VuFind configuration
-     * @param PluginManager $pm     Statistics driver plugin manager
-     * @param string        $sessId Session ID
-     */
-    public function __construct(Config $config, PluginManager $pm, $sessId)
-    {
-        $this->config = $config;
-        // Source pulled from class name
-        $source = explode('\\', get_class($this));
-        $this->source = end($source);
-        $this->pluginManager = $pm;
-        $this->sessId = $sessId;
-    }
-    
-    /**
-     * Get the stat drivers.
-     *
-     * @return array
-     */
-    protected function getDrivers()
-    {
-        if (null === $this->drivers) {
-            $this->drivers = $this->getDriversForSource($this->source);
-        }
-        return $this->drivers;
-    }
-
-    /**
-     * Create an array of statistics drivers that log a particular type of data.
-     *
-     * @param string $source Name of data type, or null to only obtain objects which
-     * log ALL data types.
-     * @param bool   $getAll If set to true, this parameter causes the method to
-     * ignore $source and return every driver object.  This should only be used
-     * when reading data, never when writing.
-     *
-     * @return array
-     */
-    public function getDriversForSource($source, $getAll = false)
-    {
-        $drivers = [];
-
-        // For each mode
-        if (isset($this->config->Statistics->mode)) {
-            foreach ($this->config->Statistics->mode as $config) {
-                $setting = explode(':', $config);
-
-                // If the config setting has a limiter, we may need to skip this
-                // record, so we should do some checks (unless we're set to accept
-                // any match through the $getAll parameter).
-                if (count($setting) > 1 && !$getAll) {
-                    // If we only want global drivers, we don't want anything with
-                    // limits.
-                    if (null === $source) {
-                        continue;
-                    }
-
-                    // If we got this far, we know that $source is not null; let's
-                    // see if the requested source is supported.
-                    $legalOptions = array_map('trim', explode(',', $setting[1]));
-                    if (!in_array($source, $legalOptions)) {
-                        continue;
-                    }
-                }
-
-                // If we got this far, we want the current option!  Build the driver:
-                $newDriver = $this->pluginManager->get($setting[0]);
-
-                // Set the name of the data source;  we use the special value
-                // "global" to represent global writer requests (the special null
-                // case):
-                $newDriver->setSource(null === $source ? 'global' : $source);
-                $drivers[] = $newDriver;
-            }
-        }
-
-        return $drivers;
-    }
-
-    /**
-     * Chooses the appropriate saving actions and formats based on config
-     *
-     * @param array                        $data    Associative array of data
-     * @param Zend_Controller_Request_Http $request Request data from the controller
-     *
-     * @return void
-     */
-    protected function save($data, $request)
-    {
-        $drivers = $this->getDrivers();
-        if (!empty($drivers)) {
-            $userData = $this->getUserData($request);
-            foreach ($drivers as $writer) {
-                $writer->write($data, $userData);
-            }
-        }
-    }
-
-    /**
-     * Returns a count and most used list
-     *
-     * @param int  $listLength How long the top list is
-     * @param bool $bySource   Sort data by source?
-     *
-     * @return mixed
-     */
-    abstract public function getStatsSummary($listLength, $bySource);
-
-    /**
-     * Returns the common information available without data
-     *
-     * @param Zend_Controller_Request_Http $request Request data from the controller
-     *
-     * @return array commonData
-     */
-    protected function getUserData($request)
-    {
-        $server = $request->getServer();
-        $agent = $server->get('HTTP_USER_AGENT');
-        $parts = explode(' ', $this->getBrowser($agent));
-        $browser = $parts[0];
-        $version = isset($parts[1]) ? $parts[1] : '';
-        return [
-            'id'               => uniqid('', true),
-            'datestamp'        => substr(date('c', strtotime('now')), 0, -6) . 'Z',
-            'browser'          => $browser,
-            'browserVersion'   => $version,
-            'ipaddress'        => $server->get('REMOTE_ADDR'),
-            'referrer'         => ($server->get('HTTP_REFERER') == null)
-                ? 'Manual'
-                : $server->get('HTTP_REFERER'),
-            'url'              => $server->get('REQUEST_URI'),
-            'session'          => $this->sessId
-        ];
-    }
-
-    /**
-     * Parse the browser name and version from the agent string
-     *
-     * @param string $agent Browser user agent string
-     *
-     * @return string browser name and version
-     */
-    public function getBrowser($agent)
-    {
-        // Try to use browscap.ini if available:
-        $browser = @get_browser($agent, true);
-        if (isset($browser['parent'])) {
-            return $browser['parent'];
-        }
-
-        // If browscap.ini didn't work, do our best:
-        if (strpos($agent, "Opera") > -1) {
-            $split = explode(' ', $agent);
-            return str_replace('/', ' ', $split[0]);
-        }
-        if (strpos($agent, "Chrome") > -1) {
-            $split = explode(' ', $agent);
-            return str_replace('/', ' ', $split[count($split) - 2]);
-        }
-        if (strpos($agent, "Firefox") > -1 || strpos($agent, "Safari") > -1) {
-            $split = explode(' ', $agent);
-            return str_replace('/', ' ', end($split));
-        }
-        if (strpos($agent, "compatible;") > -1) {
-            $data = explode("compatible;", $agent);
-            $split = preg_split('/[;\)]/', $data[1]);
-            return str_replace('/', ' ', trim($split[0]));
-        }
-    }
-}
diff --git a/module/VuFind/src/VuFind/Statistics/Driver/AbstractBase.php b/module/VuFind/src/VuFind/Statistics/Driver/AbstractBase.php
deleted file mode 100644
index 63228f80d56770eaad4e20ae4be5681725778810..0000000000000000000000000000000000000000
--- a/module/VuFind/src/VuFind/Statistics/Driver/AbstractBase.php
+++ /dev/null
@@ -1,111 +0,0 @@
-<?php
-/**
- * Abstract Base for Statistics Drivers
- *
- * PHP version 5
- *
- * Copyright (C) Villanova University 2010.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- *
- * @category VuFind
- * @package  Statistics
- * @author   Chris Hallberg <challber@villanova.edu>
- * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
- * @link     https://vufind.org Main Site
- */
-namespace VuFind\Statistics\Driver;
-
-/**
- * Base driver for statistics
- *
- * @category VuFind
- * @package  Statistics
- * @author   Chris Hallberg <challber@villanova.edu>
- * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
- * @link     https://vufind.org Main Site
- */
-abstract class AbstractBase
-{
-    /**
-     * Statistics source
-     *
-     * @var string
-     */
-    protected $source = null;
-
-    /**
-     * Get the source that is using the statistics.
-     *
-     * @return string
-     */
-    public function getSource()
-    {
-        return $this->source;
-    }
-
-    /**
-     * Set the source that is using the statistics.
-     *
-     * @param string $source Name of source.
-     *
-     * @return void
-     */
-    public function setSource($source)
-    {
-        $this->source = $source;
-    }
-
-    /**
-     * Write a message to the log.
-     *
-     * @param array $data     Data specific to what we're saving
-     * @param array $userData Browser, IP, urls, etc
-     *
-     * @return void
-     */
-    abstract public function write($data, $userData);
-
-    /**
-     * Get all the instances of a field.
-     *
-     * @param string $field What field of data are we researching?
-     * @param array  $value Extra options for search. Value => match this value
-     *
-     * @return array
-     *
-     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
-     */
-    public function getFullList($field, $value = [])
-    {
-        // Assume no statistics
-        return [];
-    }
-
-    /**
-     * Returns browser usage statistics
-     *
-     * @param bool $version Include the version numbers in the list
-     * @param int  $limit   How many items to return
-     *
-     * @return array
-     *
-     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
-     */
-    public function getBrowserStats($version, $limit)
-    {
-        // Assume no statistics
-        return [];
-    }
-}
diff --git a/module/VuFind/src/VuFind/Statistics/Driver/Db.php b/module/VuFind/src/VuFind/Statistics/Driver/Db.php
deleted file mode 100644
index e8715af68b09c41bd49ceffa8fef36351c372a84..0000000000000000000000000000000000000000
--- a/module/VuFind/src/VuFind/Statistics/Driver/Db.php
+++ /dev/null
@@ -1,91 +0,0 @@
-<?php
-/**
- * Database Statistics Driver
- *
- * PHP version 5
- *
- * Copyright (C) Villanova University 2010.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- *
- * @category VuFind
- * @package  Statistics
- * @author   Chris Hallberg <challber@villanova.edu>
- * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
- * @link     https://vufind.org Main Site
- */
-namespace VuFind\Statistics\Driver;
-
-/**
- * Writer to put statistics into the DB
- *
- * @category VuFind
- * @package  Statistics
- * @author   Chris Hallberg <challber@villanova.edu>
- * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
- * @link     https://vufind.org Main Site
- */
-class Db extends AbstractBase implements \VuFind\Db\Table\DbTableAwareInterface
-{
-    use \VuFind\Db\Table\DbTableAwareTrait;
-
-    /**
-     * Write a message to the log.
-     *
-     * @param array $data     Data specific to what we're saving
-     * @param array $userData Browser, IP, urls, etc
-     *
-     * @return void
-     */
-    public function write($data, $userData)
-    {
-        // Unset the coded-in datestamp, since the database will auto-generate
-        // it internally with greater accuracy.
-        unset($userData['datestamp']);
-
-        // Make sure the browser version is a legal length.
-        $userData['browserVersion'] = substr($userData['browserVersion'], 0, 8);
-
-        $this->getDbTable('UserStatsFields')->save($data, $userData);
-    }
-
-    /**
-     * Get all the instances of a field.
-     *
-     * @param string $field What field of data are we researching?
-     * @param array  $value Extra options for search. Value => match this value
-     *
-     * @return array
-     */
-    public function getFullList($field, $value = [])
-    {
-        // Use the model
-        return $this->getDbTable('UserStatsFields')->getFields($field, $value)
-            ->toArray();
-    }
-
-    /**
-     * Returns browser usage statistics
-     *
-     * @param bool $version Include the version numbers in the list
-     * @param int  $limit   How many items to return
-     *
-     * @return array
-     */
-    public function getBrowserStats($version, $limit)
-    {
-        $userStats = $this->getDbTable('UserStats');
-        return $userStats->getBrowserStats($version, $limit);
-    }
-}
diff --git a/module/VuFind/src/VuFind/Statistics/Driver/File.php b/module/VuFind/src/VuFind/Statistics/Driver/File.php
deleted file mode 100644
index 62707954a70cce1f88608e91f52d253ebeea413a..0000000000000000000000000000000000000000
--- a/module/VuFind/src/VuFind/Statistics/Driver/File.php
+++ /dev/null
@@ -1,126 +0,0 @@
-<?php
-/**
- * File Statistics Driver
- *
- * PHP version 5
- *
- * Copyright (C) Villanova University 2010.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- *
- * @category VuFind
- * @package  Statistics
- * @author   Chris Hallberg <challber@villanova.edu>
- * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
- * @link     https://vufind.org Main Site
- */
-namespace VuFind\Statistics\Driver;
-
-/**
- * Writer to put statistics into an XML File
- *
- * @category VuFind
- * @package  Statistics
- * @author   Chris Hallberg <challber@villanova.edu>
- * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
- * @link     https://vufind.org Main Site
- */
-class File extends AbstractBase
-{
-    /**
-     * Folder where stats will be written.
-     *
-     * @var string
-     */
-    protected $folder;
-
-    /**
-     * Constructor
-     *
-     * @param string $folder Folder where stats will be written.
-     */
-    public function __construct($folder)
-    {
-        $this->folder = $folder;
-    }
-
-    /**
-     * Get the name of the folder for storing statistics.
-     *
-     * @return string
-     */
-    protected function getFolder()
-    {
-        return $this->folder;
-    }
-
-    /**
-     * Write a message to the log.
-     *
-     * @param array $data     Data specific to what we're saving
-     * @param array $userData Browser, IP, urls, etc
-     *
-     * @throws \Exception
-     * @return void
-     */
-    public function write($data, $userData)
-    {
-        $xml = $this->getSaveXML(array_merge($data, $userData), 1);
-        $filename = rtrim($this->getFolder(), '/');
-        if (!file_exists($filename)) {
-            mkdir($filename);
-        }
-        $file = strtolower($this->getSource());
-        $index = (strrpos($file, '.')) ? -1 : strlen($file);
-        $filename .= '/' . substr($file, 0, $index) . '.xml';
-        if (file_exists($filename)) {
-            $file = file_get_contents($filename);
-            // remove <xml .. >
-            $xml .= "\n" . substr($file, 39, strlen($file));
-        } else {
-            $xml .= "\n</xml>";
-        }
-        $file = fopen($filename, 'w');
-        if (!$file) {
-            throw new \Exception('Cannot write to log file.');
-        }
-        fwrite($file, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" . $xml);
-        fclose($file);
-    }
-
-    /**
-     * Convert data array to XML
-     *
-     * @param array $data Associative array of data
-     * @param int   $tab  How far the string should be indented with tabs
-     *
-     * @return string
-     */
-    protected function getSaveXML($data, $tab = 0)
-    {
-        $xml = str_repeat("\t", $tab) . "<doc>\n";
-        $tab++;
-        foreach ($data as $tag => $value) {
-            $xml .= str_repeat("\t", $tab);
-            $insert = (strtolower(gettype($value)) == 'boolean')
-                ? ($value)
-                    ? 'true'
-                    : 'false'
-                : $value;
-            $xml .= '<field name="' . $tag . '">' . $insert . "</field>\n";
-        }
-        $tab--;
-        return $xml . str_repeat("\t", $tab) . "</doc>";
-    }
-}
diff --git a/module/VuFind/src/VuFind/Statistics/Driver/Solr.php b/module/VuFind/src/VuFind/Statistics/Driver/Solr.php
deleted file mode 100644
index 87da4d8aadcb54dea3d391e8cc62a21df551a311..0000000000000000000000000000000000000000
--- a/module/VuFind/src/VuFind/Statistics/Driver/Solr.php
+++ /dev/null
@@ -1,182 +0,0 @@
-<?php
-/**
- * Solr Statistics Driver
- *
- * PHP version 5
- *
- * Copyright (C) Villanova University 2010.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- *
- * @category VuFind
- * @package  Statistics
- * @author   Chris Hallberg <challber@villanova.edu>
- * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
- * @link     https://vufind.org Main Site
- */
-namespace VuFind\Statistics\Driver;
-use VuFind\Solr\Writer;
-use VuFindSearch\Backend\Solr\Backend;
-use VuFindSearch\Query\Query;
-use VuFindSearch\ParamBag;
-
-/**
- * Writer to put statistics to the Solr index
- *
- * @category VuFind
- * @package  Statistics
- * @author   Chris Hallberg <challber@villanova.edu>
- * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
- * @link     https://vufind.org Main Site
- */
-class Solr extends AbstractBase
-{
-    /**
-     * Solr writer
-     *
-     * @var Writer
-     */
-    protected $solrWriter;
-
-    /**
-     * Solr backend
-     *
-     * @var Backend
-     */
-    protected $solrBackend;
-
-    /**
-     * Constructor
-     *
-     * @param Writer  $writer  Solr writer
-     * @param Backend $backend Solr backend
-     */
-    public function __construct(Writer $writer, Backend $backend)
-    {
-        $this->solrWriter = $writer;
-        $this->solrBackend = $backend;
-    }
-
-    /**
-     * Write a message to the log.     *
-     *
-     * @param array $data     Data specific to what we're saving
-     * @param array $userData Browser, IP, urls, etc
-     *
-     * @return void
-     */
-    public function write($data, $userData)
-    {
-        if (isset($data['phrase']) && $data['phrase'] == '') {
-            $data['phrase'] = '*:*';
-        }
-        $update = new \VuFindSearch\Backend\Solr\Document\UpdateDocument();
-        $update->addRecord(
-            new \VuFindSearch\Backend\Solr\Record\SerializableRecord(
-                array_merge($data, $userData)
-            )
-        );
-        $this->solrWriter->save('SolrStats', $update);
-    }
-
-    /**
-     * Get the total count of a field.
-     *
-     * @param string $field What field of data are we researching?
-     * @param array  $value Extra options for search. Value => match this value
-     *
-     * @return array
-     */
-    public function getFullList($field, $value = ['value' => '[* TO *]'])
-    {
-        $query = new Query($field . ':' . $value['value']);
-        $params = new ParamBag();
-        $params->add('fl', $field);
-        $start = 0;
-        $limit = 1000;
-        $data = [];
-        do {
-            $response = $this->solrBackend->search($query, $start, $limit, $params);
-            $records = $response->getRecords();
-            foreach ($records as $doc) {
-                $data[] = [$field => $doc->$field];
-            }
-            $start += $limit;
-        } while (count($records) > 0);
-        return $data;
-    }
-
-    /**
-     * Returns browser usage statistics
-     *
-     * @param bool $version    Include the version numbers in the list
-     * @param int  $listLength How many items to return
-     *
-     * @return array
-     */
-    public function getBrowserStats($version, $listLength = 5)
-    {
-        $query = new Query('*:*');
-        $params = new ParamBag();
-        $params->add('fl', 'browser,browserVersion');
-        $params->add('group', 'true');
-        $params->add('group.field', 'session');
-        $start = 0;
-        $limit = 1000;
-        $hashes = [];
-        do {
-            $response = $this->solrBackend->search($query, $start, $limit, $params);
-            $groups = $response->getGroups();
-            foreach ($groups['session']['groups'] as $group) {
-                if ($version) {
-                    // Version specific
-                    $browser = $group['doclist']['docs'][0]['browser']
-                        . ' ' . $group['doclist']['docs'][0]['browserVersion'];
-                    if (isset($hashes[$browser])) {
-                        $hashes[$browser] ++;
-                    } elseif (count($hashes) < $limit) {
-                        $hashes[$browser] = 1;
-                    }
-                } else {
-                    // Browser name
-                    if (isset($hashes[$group['doclist']['docs'][0]['browser']])) {
-                        $hashes[$group['doclist']['docs'][0]['browser']] ++;
-                    } elseif (count($hashes) < $limit) {
-                        $hashes[$group['doclist']['docs'][0]['browser']] = 1;
-                    }
-                }
-            }
-            $start += $limit;
-        } while (count($groups['session']['groups']) > 0);
-        $solrBrowsers = [];
-        foreach ($hashes as $browser => $count) {
-            $newBrowser = [
-                'browserName' => $browser,
-                'count' => $count
-            ];
-            // Insert sort (limit to listLength)
-            for ($i = 0;$i < $listLength - 1 && $i < count($solrBrowsers);$i++) {
-                if ($count > $solrBrowsers[$i]['count']) {
-                    // Insert in order
-                    array_splice($solrBrowsers, $i, 0, [$newBrowser]);
-                    continue 2; // Skip the append after this loop
-                }
-            }
-            if (count($solrBrowsers) < $listLength) {
-                $solrBrowsers[] = $newBrowser;
-            }
-        }
-        return $solrBrowsers;
-    }
-}
diff --git a/module/VuFind/src/VuFind/Statistics/Record.php b/module/VuFind/src/VuFind/Statistics/Record.php
deleted file mode 100644
index 8446a030739c29b2ff7ed34327f9b638239556dd..0000000000000000000000000000000000000000
--- a/module/VuFind/src/VuFind/Statistics/Record.php
+++ /dev/null
@@ -1,124 +0,0 @@
-<?php
-/**
- * VuFind Statistics Class for Record Views
- *
- * PHP version 5
- *
- * Copyright (C) Villanova University 2009.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- *
- * @category VuFind
- * @package  Statistics
- * @author   Chris Hallberg <challber@villanova.edu>
- * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
- * @link     https://vufind.org/wiki/development Wiki
- */
-namespace VuFind\Statistics;
-
-/**
- * VuFind Statistics Class for Record Views
- *
- * @category VuFind
- * @package  Statistics
- * @author   Chris Hallberg <challber@villanova.edu>
- * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
- * @link     https://vufind.org/wiki/development Wiki
- */
-class Record extends AbstractBase
-{
-    /**
-     * Saves the record view to wherever the config [Statistics] says so
-     *
-     * @param \VuFind\Search\Base\Results  $data    Results from Search controller
-     * @param Zend_Controller_Request_Http $request Request data
-     *
-     * @return void
-     */
-    public function log($data, $request)
-    {
-        $this->save(
-            [
-                'recordId'     => $data->getUniqueId(),
-                'recordSource' => $data->getSourceIdentifier()
-            ],
-            $request
-        );
-    }
-
-    /**
-     * Returns a set of basic statistics including total records
-     * and most commonly viewed records.
-     *
-     * @param int  $listLength How long the top list is
-     * @param bool $bySource   Sort record views by source?
-     *
-     * @return array
-     */
-    public function getStatsSummary($listLength = 5, $bySource = false)
-    {
-        foreach ($this->getDrivers() as $driver) {
-            $summary = $driver->getFullList('recordId');
-            if (!empty($summary)) {
-                $sources = $driver->getFullList('recordSource');
-                $hashes = [];
-                // Generate hashes (faster than grouping by looping)
-                for ($i = 0;$i < count($summary);$i++) {
-                    $source = $sources[$i]['recordSource'];
-                    $id = $summary[$i]['recordId'];
-                    $hashes[$source][$id]
-                        = isset($hashes[$source][$id])
-                        ? $hashes[$source][$id] + 1
-                        : 1;
-                }
-                $top = [];
-                // For each source
-                foreach ($hashes as $source => $records) {
-                    // Using a reference to consolidate code dramatically
-                    $reference = & $top;
-                    if ($bySource) {
-                        $top[$source] = [];
-                        $reference = & $top[$source];
-                    }
-                    // For each record
-                    foreach ($records as $id => $count) {
-                        $newRecord = [
-                            'value'  => $id,
-                            'count'  => $count,
-                            'source' => $source
-                        ];
-                        // Insert sort (limit to listLength)
-                        $refCount = count($reference);
-                        for ($i = 0; $i < $listLength - 1 && $i < $refCount; $i++) {
-                            if ($count > $reference[$i]['count']) {
-                                // Insert in order
-                                array_splice($reference, $i, 0, [$newRecord]);
-                                continue 2; // Skip the append after this loop
-                            }
-                        }
-                        if (count($reference) < $listLength) {
-                            $reference[] = $newRecord;
-                        }
-                    }
-                    $reference = array_slice($reference, 0, $listLength);
-                }
-                return [
-                    'top'   => $top,
-                    'total' => count($summary)
-                ];
-            }
-        }
-        return [];
-    }
-}
diff --git a/module/VuFind/src/VuFind/Statistics/Search.php b/module/VuFind/src/VuFind/Statistics/Search.php
deleted file mode 100644
index 7e1d9c89e689f3cfaba1e220d71b69829894ce63..0000000000000000000000000000000000000000
--- a/module/VuFind/src/VuFind/Statistics/Search.php
+++ /dev/null
@@ -1,141 +0,0 @@
-<?php
-/**
- * VuFind Statistics Class for Searches
- *
- * PHP version 5
- *
- * Copyright (C) Villanova University 2009.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- *
- * @category VuFind
- * @package  Statistics
- * @author   Chris Hallberg <challber@villanova.edu>
- * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
- * @link     https://vufind.org/wiki/development Wiki
- */
-namespace VuFind\Statistics;
-
-/**
- * VuFind Statistics Class for Searches
- *
- * @category VuFind
- * @package  Statistics
- * @author   Chris Hallberg <challber@villanova.edu>
- * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
- * @link     https://vufind.org/wiki/development Wiki
- */
-class Search extends AbstractBase
-{
-    /**
-     * Saves the search to wherever the config [Statistics] says so
-     *
-     * @param \VuFind\Search\Base\Results  $data    Results from Search controller
-     * @param Zend_Controller_Request_Http $request Request data from the controller
-     *
-     * @return void
-     */
-    public function log($data, $request)
-    {
-        $stat = [
-            'phrase'       => $data->getParams()->getDisplayQuery(),
-            'searchSource' => $data->getParams()->getSearchClassId(),
-            'type'         => $data->getParams()->getSearchHandler(),
-            'resultCount'  => $data->getResultTotal(),
-            'noresults'    => $data->getResultTotal() == 0
-        ];
-        $this->save($stat, $request);
-    }
-
-    /**
-     * Returns a set of basic statistics including total searches,
-     * number of empty searches and most popular search terms.
-     *
-     * @param int  $listLength Number of top searches to return
-     * @param bool $bySource   Separate searches by search source?
-     *
-     * @return array
-     */
-    public function getStatsSummary($listLength = 5, $bySource = false)
-    {
-        foreach ($this->getDrivers() as $driver) {
-            $summary = $driver->getFullList('phrase');
-            if (!empty($summary)) {
-                $sources = $driver->getFullList('searchSource');
-                $hashes = [];
-                // Generate hashes (faster than grouping by looping)
-                for ($i = 0;$i < count($summary);$i++) {
-                    if (!isset($sources[$i]['searchSource'])) {
-                        $sources[$i]['searchSource'] = 'Search';
-                    } else {
-                        // Escape multivalue index
-                        $sources[$i]['searchSource']
-                            = implode(', ', (Array)$sources[$i]['searchSource']);
-                    }
-                    // Escape multivalue index
-                    $summary[$i]['phrase']
-                        = implode(', ', (Array)$summary[$i]['phrase']);
-                    // Store everything in a string array for fast sorting later
-                    $source = $sources[$i]['searchSource'];
-                    $hashes[$source][$summary[$i]['phrase']]
-                        = isset($hashes[$source][$summary[$i]['phrase']])
-                        ? $hashes[$source][$summary[$i]['phrase']] + 1
-                        : 1;
-                }
-                $top = [];
-                // For each source
-                foreach ($hashes as $source => $records) {
-                    // Using a reference to consolidate code dramatically
-                    $reference = & $top;
-                    if ($bySource) {
-                        $top[$source] = [];
-                        $reference = & $top[$source];
-                    }
-                    // For each record
-                    foreach ($records as $phrase => $count) {
-                        $value = ($phrase == '' || $phrase == '*:*')
-                            ? '(empty)'
-                            : $phrase;
-                        $newRecord = [
-                            'value'  => $value,
-                            'count'  => $count,
-                            'source' => $source
-                        ];
-                        // Insert sort (limit to listLength)
-                        $refCount = count($reference);
-                        for ($i = 0; $i < $listLength - 1 && $i < $refCount; $i++) {
-                            if ($count > $reference[$i]['count']) {
-                                // Insert in order
-                                array_splice($reference, $i, 0, [$newRecord]);
-                                continue 2; // Skip the append after this loop
-                            }
-                        }
-                        if (count($reference) < $listLength) {
-                            $reference[] = $newRecord;
-                        }
-                    }
-                    $reference = array_slice($reference, 0, $listLength);
-                }
-                return [
-                    'top'   => $top,
-                    'total' => count($summary),
-                    'empty' => count(
-                        $driver->getFullList('noresults', ['value' => 'true'])
-                    )
-                ];
-            }
-        }
-        return [];
-    }
-}
diff --git a/module/VuFind/src/VuFind/View/Helper/AbstractLayoutClass.php b/module/VuFind/src/VuFind/View/Helper/AbstractLayoutClass.php
index af9b84e6c0bccbbb87a589a585c255a81516922e..33a1115d55eb6e4638b2c95f751c8ca5f8d67897 100644
--- a/module/VuFind/src/VuFind/View/Helper/AbstractLayoutClass.php
+++ b/module/VuFind/src/VuFind/View/Helper/AbstractLayoutClass.php
@@ -43,7 +43,7 @@ abstract class AbstractLayoutClass extends \Zend\View\Helper\AbstractHelper
      *
      * @var bool
      */
-    protected $left;
+    protected $sidebarOnLeft;
 
     /**
      * Is the sidebar offcanvas?
@@ -60,7 +60,7 @@ abstract class AbstractLayoutClass extends \Zend\View\Helper\AbstractHelper
      */
     public function __construct($left = false, $offcanvas = false)
     {
-        $this->left = $left;
+        $this->sidebarOnLeft = $left;
         $this->offcanvas = $offcanvas;
     }
 
diff --git a/module/VuFind/src/VuFind/View/Helper/AbstractSearch.php b/module/VuFind/src/VuFind/View/Helper/AbstractSearch.php
index 77df6b724e707f2234ca5cb35f119f3f7330637c..04a70abd3cb78ef8e68768c44a1c1a7c5f28453d 100644
--- a/module/VuFind/src/VuFind/View/Helper/AbstractSearch.php
+++ b/module/VuFind/src/VuFind/View/Helper/AbstractSearch.php
@@ -84,11 +84,11 @@ abstract class AbstractSearch extends AbstractHelper
                 }
                 $html .= '<a href="'
                     . $results->getUrlQuery()
-                        ->replaceTerm($term, $data['new_term'])
+                        ->replaceTerm($term, $data['new_term'])->getParams()
                     . '">' . $view->escapeHtml($word) . '</a>';
                 if (isset($data['expand_term']) && !empty($data['expand_term'])) {
                     $url = $results->getUrlQuery()
-                        ->replaceTerm($term, $data['expand_term']);
+                        ->replaceTerm($term, $data['expand_term'])->getParams();
                     $html .= $this->renderExpandLink($url, $view);
                 }
             }
diff --git a/module/VuFind/src/VuFind/View/Helper/Bootstrap3/Factory.php b/module/VuFind/src/VuFind/View/Helper/Bootstrap3/Factory.php
index fb2ad863b1e190711a6679eb2da4d99b937e61ce..3743de4a0914ffdf200fc1c64c8436cc42c98caf 100644
--- a/module/VuFind/src/VuFind/View/Helper/Bootstrap3/Factory.php
+++ b/module/VuFind/src/VuFind/View/Helper/Bootstrap3/Factory.php
@@ -65,7 +65,7 @@ class Factory
     public static function getLayoutClass(ServiceManager $sm)
     {
         $config = $sm->getServiceLocator()->get('VuFind\Config')->get('config');
-        $left = !isset($config->Site->sidebarOnLeft)
+        $sidebarOnLeft = !isset($config->Site->sidebarOnLeft)
             ? false : $config->Site->sidebarOnLeft;
         $mirror = !isset($config->Site->mirrorSidebarInRTL)
             ? true : $config->Site->mirrorSidebarInRTL;
@@ -75,10 +75,10 @@ class Factory
         // pull it back out here to avoid duplicate effort, then use it to apply
         // the mirror setting appropriately.
         $layout = $sm->getServiceLocator()->get('viewmanager')->getViewModel();
-        if ($layout->rtl && !$mirror) {
-            $left = !$left;
+        if ($layout->rtl && $mirror) {
+            $sidebarOnLeft = !$sidebarOnLeft;
         }
-        return new LayoutClass($left, $offcanvas);
+        return new LayoutClass($sidebarOnLeft, $offcanvas);
     }
 
     /**
diff --git a/module/VuFind/src/VuFind/View/Helper/Bootstrap3/LayoutClass.php b/module/VuFind/src/VuFind/View/Helper/Bootstrap3/LayoutClass.php
index 92cc9f527caf1134a644e40067e530d2c414eb44..9592853267b21a038a6ffe004e0fa1396bfe4027 100644
--- a/module/VuFind/src/VuFind/View/Helper/Bootstrap3/LayoutClass.php
+++ b/module/VuFind/src/VuFind/View/Helper/Bootstrap3/LayoutClass.php
@@ -53,18 +53,18 @@ class LayoutClass extends \VuFind\View\Helper\AbstractLayoutClass
     {
         switch ($class) {
         case 'mainbody':
-            return $this->left
-                ? 'col-sm-9 col-sm-push-3'
-                : 'col-sm-9';
+            return $this->sidebarOnLeft
+                ? 'mainbody right'
+                : 'mainbody left';
         case 'sidebar':
-            return $this->left
-                ? 'sidebar col-sm-3 col-sm-pull-9 hidden-print'
-                : 'sidebar col-sm-3 hidden-print';
+            return $this->sidebarOnLeft
+                ? 'sidebar left hidden-print'
+                : 'sidebar right hidden-print';
         case 'offcanvas-row':
             if (!$this->offcanvas) {
                 return "";
             }
-            return $this->left
+            return $this->sidebarOnLeft
                 ? 'offcanvas offcanvas-left flip'
                 : 'offcanvas offcanvas-right flip';
         }
diff --git a/module/VuFind/src/VuFind/View/Helper/Bootstrap3/Recaptcha.php b/module/VuFind/src/VuFind/View/Helper/Bootstrap3/Recaptcha.php
index 4a33ee68efea0f3996d17a6787214df079562e51..0bc879aacb956d0a3cbb48c36da91106a0b0c99c 100644
--- a/module/VuFind/src/VuFind/View/Helper/Bootstrap3/Recaptcha.php
+++ b/module/VuFind/src/VuFind/View/Helper/Bootstrap3/Recaptcha.php
@@ -46,9 +46,8 @@ class Recaptcha extends \VuFind\View\Helper\Root\Recaptcha
      */
     public function __construct($rc, $config)
     {
-        $this->prefixHtml = '<div class="form-group">' .
-            '<div class="col-sm-9 col-sm-offset-3">';
-        $this->suffixHtml = '</div></div>';
+        $this->prefixHtml = '<div class="form-group">';
+        $this->suffixHtml = '</div>';
         parent::__construct($rc, $config);
     }
 }
diff --git a/module/VuFind/src/VuFind/View/Helper/Root/AlphaBrowse.php b/module/VuFind/src/VuFind/View/Helper/Root/AlphaBrowse.php
index d0f83d6453a0957dabee6537e554060edf1df826..abe8d1ad492d31ef536b5320bf284fa9d4f89da2 100644
--- a/module/VuFind/src/VuFind/View/Helper/Root/AlphaBrowse.php
+++ b/module/VuFind/src/VuFind/View/Helper/Root/AlphaBrowse.php
@@ -90,7 +90,7 @@ class AlphaBrowse extends \Zend\View\Helper\AbstractHelper
     /**
      * Escape a string for inclusion in a Solr query.
      *
-     * @param type $str String to escape
+     * @param string $str String to escape
      *
      * @return string
      */
diff --git a/module/VuFind/src/VuFind/View/Helper/Root/Factory.php b/module/VuFind/src/VuFind/View/Helper/Root/Factory.php
index 340d1b8154ffc28ba3e5121b5a6f8e13b59bdc5b..75f036f557c2d2e740047bdbf72ed6e6133da0d5 100644
--- a/module/VuFind/src/VuFind/View/Helper/Root/Factory.php
+++ b/module/VuFind/src/VuFind/View/Helper/Root/Factory.php
@@ -245,13 +245,17 @@ class Factory
     {
         $config = $sm->getServiceLocator()->get('VuFind\Config')->get('config');
         $url = isset($config->Piwik->url) ? $config->Piwik->url : false;
-        $siteId = isset($config->Piwik->site_id) ? $config->Piwik->site_id : 1;
+        $options = [
+            'siteId' => isset($config->Piwik->site_id) ? $config->Piwik->site_id : 1,
+            'searchPrefix' => isset($config->Piwik->searchPrefix)
+                ? $config->Piwik->searchPrefix : null
+        ];
         $customVars = isset($config->Piwik->custom_variables)
             ? $config->Piwik->custom_variables
             : false;
         $request = $sm->getServiceLocator()->get('Request');
         $router = $sm->getServiceLocator()->get('Router');
-        return new Piwik($url, $siteId, $customVars, $router, $request);
+        return new Piwik($url, $options, $customVars, $router, $request);
     }
 
     /**
@@ -339,9 +343,12 @@ class Factory
             ),
             true
         );
+        $resolverPluginManager = $sm->getServiceLocator()
+            ->get('VuFind\ResolverDriverPluginManager');
         return new OpenUrl(
             $sm->get('context'),
             $openUrlRules,
+            $resolverPluginManager,
             isset($config->OpenURL) ? $config->OpenURL : null
         );
     }
@@ -444,9 +451,12 @@ class Factory
     public static function getSearchBox(ServiceManager $sm)
     {
         $config = $sm->getServiceLocator()->get('VuFind\Config');
+        $mainConfig = $config->get('config');
         return new SearchBox(
             $sm->getServiceLocator()->get('VuFind\SearchOptionsPluginManager'),
-            $config->get('searchbox')->toArray()
+            $config->get('searchbox')->toArray(),
+            isset($mainConfig->SearchPlaceholder)
+                ? $mainConfig->SearchPlaceholder->toArray() : []
         );
     }
 
diff --git a/module/VuFind/src/VuFind/View/Helper/Root/Flashmessages.php b/module/VuFind/src/VuFind/View/Helper/Root/Flashmessages.php
index ac7ec7a7366253cbd8a5e80deb71f21e339c77a5..26703238acc071d6f25f4b4cf12ddf74279bfbe4 100644
--- a/module/VuFind/src/VuFind/View/Helper/Root/Flashmessages.php
+++ b/module/VuFind/src/VuFind/View/Helper/Root/Flashmessages.php
@@ -82,7 +82,14 @@ class Flashmessages extends AbstractHelper
                 $this->fm->getMessages($ns), $this->fm->getCurrentMessages($ns)
             );
             foreach (array_unique($messages, SORT_REGULAR) as $msg) {
-                $html .= '<div class="' . $this->getClassForNamespace($ns) . '">';
+                $html .= '<div class="' . $this->getClassForNamespace($ns) . '"';
+                if (isset($msg['dataset'])) {
+                    foreach ($msg['dataset'] as $attr => $value) {
+                        $html .= ' data-' . $attr . '="'
+                            . htmlspecialchars($value) . '"';
+                    }
+                }
+                $html .= '>';
                 // Advanced form:
                 if (is_array($msg)) {
                     // Use a different translate helper depending on whether
diff --git a/module/VuFind/src/VuFind/View/Helper/Root/GeoCoords.php b/module/VuFind/src/VuFind/View/Helper/Root/GeoCoords.php
index ed372fab0bcaca39dff9dfc4920a7ff119f881da..b5ae5296247fcb2fa69eea67f5d3bece4ff33e0b 100644
--- a/module/VuFind/src/VuFind/View/Helper/Root/GeoCoords.php
+++ b/module/VuFind/src/VuFind/View/Helper/Root/GeoCoords.php
@@ -58,7 +58,7 @@ class GeoCoords extends \Zend\View\Helper\AbstractHelper
      *
      * @var string
      */
-    protected $geoField = 'location_geo';
+    protected $geoField = 'long_lat';
 
     /**
      * Constructor
diff --git a/module/VuFind/src/VuFind/View/Helper/Root/OpenUrl.php b/module/VuFind/src/VuFind/View/Helper/Root/OpenUrl.php
index 6f1393deedc64b576f2b0ef3a79b4c96da4e0e96..55eaedeed62a03745ede6364f6287b2b51cdfc06 100644
--- a/module/VuFind/src/VuFind/View/Helper/Root/OpenUrl.php
+++ b/module/VuFind/src/VuFind/View/Helper/Root/OpenUrl.php
@@ -26,6 +26,7 @@
  * @link     https://vufind.org/wiki/development Wiki
  */
 namespace VuFind\View\Helper\Root;
+use VuFind\Resolver\Driver\PluginManager;
 
 /**
  * OpenUrl view helper
@@ -59,6 +60,13 @@ class OpenUrl extends \Zend\View\Helper\AbstractHelper
      */
     protected $openUrlRules;
 
+    /**
+     * Resolver plugin manager
+     *
+     * @var PluginManager
+     */
+    protected $resolverPluginManager;
+
     /**
      * Current RecordDriver
      *
@@ -76,15 +84,17 @@ class OpenUrl extends \Zend\View\Helper\AbstractHelper
     /**
      * Constructor
      *
-     * @param \VuFind\View\Helper\Root\Context $context      Context helper
-     * @param array                            $openUrlRules VuFind OpenURL rules
-     * @param \Zend\Config\Config              $config       VuFind OpenURL config
+     * @param \VuFind\View\Helper\Root\Context $context       Context helper
+     * @param array                            $openUrlRules  VuFind OpenURL rules
+     * @param PluginManager                    $pluginManager Resolver plugin manager
+     * @param \Zend\Config\Config              $config        VuFind OpenURL config
      */
     public function __construct(\VuFind\View\Helper\Root\Context $context,
-        $openUrlRules, $config = null
+        $openUrlRules, PluginManager $pluginManager, $config = null
     ) {
         $this->context = $context;
         $this->openUrlRules = $openUrlRules;
+        $this->resolverPluginManager = $pluginManager;
         $this->config = $config;
     }
 
@@ -192,9 +202,23 @@ class OpenUrl extends \Zend\View\Helper\AbstractHelper
             );
         }
 
+        // instantiate the resolver plugin to get a proper resolver link
+        $resolver = isset($this->config->resolver)
+            ? $this->config->resolver : 'other';
+        $openurl = $this->recordDriver->getOpenUrl();
+        if ($this->resolverPluginManager->has($resolver)) {
+            $resolverObj = new \VuFind\Resolver\Connection(
+                $this->resolverPluginManager->get($resolver)
+            );
+            $resolverUrl = $resolverObj->getResolverUrl($openurl);
+        } else {
+            $resolverUrl = empty($base) ? '' : $base . '?' . $openurl;
+        }
+
         // Build parameters needed to display the control:
         $params = [
-            'openUrl' => $this->recordDriver->getOpenUrl(),
+            'resolverUrl' => $resolverUrl,
+            'openUrl' => $openurl,
             'openUrlBase' => empty($base) ? false : $base,
             'openUrlWindow' => empty($this->config->window_settings)
                 ? false : $this->config->window_settings,
@@ -291,6 +315,11 @@ class OpenUrl extends \Zend\View\Helper\AbstractHelper
      */
     protected function checkIfRulesApply()
     {
+        // special case if no rules are defined at all assume that any record is
+        // valid for openUrls
+        if (!isset($this->openUrlRules) || count($this->openUrlRules) < 1) {
+            return true;
+        }
         foreach ($this->openUrlRules as $rules) {
             if (!$this->checkExcludedRecordsRules($rules)
                 && $this->checkSupportedRecordsRules($rules)
diff --git a/module/VuFind/src/VuFind/View/Helper/Root/Piwik.php b/module/VuFind/src/VuFind/View/Helper/Root/Piwik.php
index 45266fe9fc22ae727bdec7ed06782940c323cff7..c69324b309de3b510f64cf8a564609c9ce85ceb7 100644
--- a/module/VuFind/src/VuFind/View/Helper/Root/Piwik.php
+++ b/module/VuFind/src/VuFind/View/Helper/Root/Piwik.php
@@ -52,6 +52,13 @@ class Piwik extends \Zend\View\Helper\AbstractHelper
      */
     protected $siteId;
 
+    /**
+     * Search prefix (see config.ini for details)
+     *
+     * @var string
+     */
+    protected $searchPrefix;
+
     /**
      * Whether to track use custom variables to track additional information
      *
@@ -100,19 +107,26 @@ class Piwik extends \Zend\View\Helper\AbstractHelper
      *
      * @param string|bool                      $url        Piwik address
      * (false if disabled)
-     * @param int                              $siteId     Piwik site ID
+     * @param int|array                        $options    Options array (or,
+     * if a single value, the Piwik site ID -- for backward compatibility)
      * @param bool                             $customVars Whether to track
      * additional information in custom variables
      * @param Zend\Mvc\Router\Http\RouteMatch  $router     Request
      * @param Zend\Http\PhpEnvironment\Request $request    Request
      */
-    public function __construct($url, $siteId, $customVars, $router, $request)
+    public function __construct($url, $options, $customVars, $router, $request)
     {
         $this->url = $url;
         if ($url && substr($url, -1) != '/') {
             $this->url .= '/';
         }
-        $this->siteId = $siteId;
+        if (is_array($options)) {
+            $this->siteId = $options['siteId'];
+            $this->searchPrefix = isset($options['searchPrefix'])
+                ? $options['searchPrefix'] : '';
+        } else {
+            $this->siteId = $options;
+        }
         $this->customVars = $customVars;
         $this->router = $router;
         $this->request = $request;
@@ -244,10 +258,13 @@ class Piwik extends \Zend\View\Helper\AbstractHelper
     protected function getSearchResults()
     {
         $viewModel = $this->getView()->plugin('view_model');
+        if ('layout/lightbox' === $viewModel->getCurrent()->getTemplate()) {
+            return null;
+        }
         $children = $viewModel->getCurrent()->getChildren();
         if (isset($children[0])) {
             $template = $children[0]->getTemplate();
-            if (!strstr($template, '/home')) {
+            if (!strstr($template, '/home') && !strstr($template, 'facet-list')) {
                 $results = $children[0]->getVariable('results');
                 if (is_a($results, 'VuFind\Search\Base\Results')) {
                     return $results;
@@ -508,7 +525,7 @@ EOT;
         // Use trackSiteSearch *instead* of trackPageView in searches
         return <<<EOT
     VuFindPiwikTracker.trackSiteSearch(
-        '$backendId|$searchTerms', '$searchType', $resultCount
+        '{$this->searchPrefix}$backendId|$searchTerms', '$searchType', $resultCount
     );
 
 EOT;
@@ -543,7 +560,7 @@ EOT;
         // Use trackSiteSearch *instead* of trackPageView in searches
         return <<<EOT
     VuFindPiwikTracker.trackSiteSearch(
-        'Combined|$searchTerms', '$searchType', $resultCount
+        '{$this->searchPrefix}Combined|$searchTerms', '$searchType', $resultCount
     );
 
 EOT;
diff --git a/module/VuFind/src/VuFind/View/Helper/Root/ProxyUrl.php b/module/VuFind/src/VuFind/View/Helper/Root/ProxyUrl.php
index cb87741da46caa9aeae01e173df921dac4d71110..21bdbeb3c01758226b46ccd788bec9f687c4e83d 100644
--- a/module/VuFind/src/VuFind/View/Helper/Root/ProxyUrl.php
+++ b/module/VuFind/src/VuFind/View/Helper/Root/ProxyUrl.php
@@ -64,9 +64,10 @@ class ProxyUrl extends \Zend\View\Helper\AbstractHelper
      */
     public function __invoke($url)
     {
-        if (isset($this->config->EZproxy->host)) {
-            $url = $this->config->EZproxy->host . '/login?qurl=' . urlencode($url);
-        }
-        return $url;
+        $usePrefix = !isset($this->config->EZproxy->prefixLinks)
+            || $this->config->EZproxy->prefixLinks;
+        return ($usePrefix && isset($this->config->EZproxy->host))
+            ? $this->config->EZproxy->host . '/login?qurl=' . urlencode($url)
+            : $url;
     }
 }
diff --git a/module/VuFind/src/VuFind/View/Helper/Root/Record.php b/module/VuFind/src/VuFind/View/Helper/Root/Record.php
index 1054069909e0afc83b627f1cbad27fb5472f5673..c9bf3514ca17720961ac0fcb1f8b75ad1e2d22b8 100644
--- a/module/VuFind/src/VuFind/View/Helper/Root/Record.php
+++ b/module/VuFind/src/VuFind/View/Helper/Root/Record.php
@@ -100,7 +100,7 @@ class Record extends AbstractHelper
      *
      * @return string
      */
-    protected function renderTemplate($name, $context = null)
+    public function renderTemplate($name, $context = null)
     {
         // Set default context if none provided:
         if (is_null($context)) {
@@ -410,16 +410,20 @@ class Record extends AbstractHelper
      * Render an HTML checkbox control for the current record.
      *
      * @param string $idPrefix Prefix for checkbox HTML ids
+     * @param string $formAttr ID of form for [form] attribute
      *
      * @return string
      */
-    public function getCheckbox($idPrefix = '')
+    public function getCheckbox($idPrefix = '', $formAttr = false)
     {
         static $checkboxCount = 0;
         $id = $this->driver->getSourceIdentifier() . '|'
             . $this->driver->getUniqueId();
         $context
             = ['id' => $id, 'count' => $checkboxCount++, 'prefix' => $idPrefix];
+        if ($formAttr) {
+            $context['formAttr'] = $formAttr;
+        }
         return $this->contextHelper->renderInContext(
             'record/checkbox.phtml', $context
         );
diff --git a/module/VuFind/src/VuFind/View/Helper/Root/RecordDataFormatter.php b/module/VuFind/src/VuFind/View/Helper/Root/RecordDataFormatter.php
new file mode 100644
index 0000000000000000000000000000000000000000..cf5e262c106ea2d6a1ca1a2b8da2da17b42d65d1
--- /dev/null
+++ b/module/VuFind/src/VuFind/View/Helper/Root/RecordDataFormatter.php
@@ -0,0 +1,297 @@
+<?php
+/**
+ * Record driver data formatting view helper
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2016.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * @category VuFind
+ * @package  View_Helpers
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development:architecture:record_data_formatter
+ * Wiki
+ */
+namespace VuFind\View\Helper\Root;
+use VuFind\RecordDriver\AbstractBase as RecordDriver;
+use Zend\View\Helper\AbstractHelper;
+
+/**
+ * Record driver data formatting view helper
+ *
+ * @category VuFind
+ * @package  View_Helpers
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development:architecture:record_data_formatter
+ * Wiki
+ */
+class RecordDataFormatter extends AbstractHelper
+{
+    /**
+     * Default settings.
+     *
+     * @var array
+     */
+    protected $defaults = [];
+
+    /**
+     * Sort callback for field specification.
+     *
+     * @param array $a First value to compare
+     * @param array $b Second value to compare
+     *
+     * @return int
+     */
+    public function specSortCallback($a, $b)
+    {
+        $posA = isset($a['pos']) ? $a['pos'] : 0;
+        $posB = isset($b['pos']) ? $b['pos'] : 0;
+        if ($posA === $posB) {
+            return 0;
+        }
+        return $posA < $posB ? -1 : 1;
+    }
+
+    /**
+     * Create formatted key/value data based on a record driver and field spec.
+     *
+     * @param RecordDriver $driver Record driver object.
+     * @param array        $spec   Formatting specification
+     *
+     * @return array
+     */
+    public function getData(RecordDriver $driver, array $spec)
+    {
+        $result = [];
+
+        // Sort the spec into order by position:
+        uasort($spec, [$this, 'specSortCallback']);
+
+        // Apply the spec:
+        foreach ($spec as $field => $current) {
+            // Extract the relevant data from the driver.
+            $data = $this->extractData($driver, $current);
+            $allowZero = isset($current['allowZero']) ? $current['allowZero'] : true;
+            if (!empty($data) || ($allowZero && ($data === 0 || $data === '0'))) {
+                // Determine the rendering method to use with the second element
+                // of the current spec.
+                $renderMethod = empty($current['renderType'])
+                    ? 'renderSimple' : 'render' . $current['renderType'];
+
+                // Add the rendered data to the return value if it is non-empty:
+                if (is_callable([$this, $renderMethod])) {
+                    $text = $this->$renderMethod($driver, $data, $current);
+                    if (!$text && (!$allowZero || ($text !== 0 && $text !== '0'))) {
+                        continue;
+                    }
+                    // Allow dynamic label override:
+                    if (isset($current['labelFunction'])
+                        && is_callable($current['labelFunction'])
+                    ) {
+                        $field = call_user_func($current['labelFunction'], $data);
+                    }
+                    $context = isset($current['context']) ? $current['context'] : [];
+                    $result[$field] = [
+                        'value' => $text,
+                        'context' => $context
+                    ];
+                }
+            }
+        }
+        return $result;
+    }
+
+    /**
+     * Get default configuration.
+     *
+     * @param string $key Key for configuration to look up.
+     *
+     * @return array
+     */
+    public function getDefaults($key)
+    {
+        // No value stored? Return empty array:
+        if (!isset($this->defaults[$key])) {
+            return [];
+        }
+        // Callback stored? Resolve to array on demand:
+        if (is_callable($this->defaults[$key])) {
+            $this->defaults[$key] = $this->defaults[$key]();
+            if (!is_array($this->defaults[$key])) {
+                throw new \Exception('Callback for ' . $key . ' must return array');
+            }
+        }
+        // Send back array:
+        return $this->defaults[$key];
+    }
+
+    /**
+     * Set default configuration.
+     *
+     * @param string         $key    Key for configuration to set.
+     * @param array|Callable $values Defaults to store (either an array, or a
+     * Callable returning an array).
+     *
+     * @return void
+     */
+    public function setDefaults($key, $values)
+    {
+        if (!is_array($values) && !is_callable($values)) {
+            throw new \Exception('$values must be array or Callable');
+        }
+        $this->defaults[$key] = $values;
+    }
+
+    /**
+     * Extract data (usually from the record driver).
+     *
+     * @param RecordDriver $driver  Record driver
+     * @param array        $options Incoming options
+     *
+     * @return mixed
+     */
+    protected function extractData(RecordDriver $driver, array $options)
+    {
+        // Static cache for persisting data.
+        static $cache = [];
+
+        // If $method is a bool, return it as-is; this allows us to force the
+        // rendering (or non-rendering) of particular data independent of the
+        // record driver.
+        $method = isset($options['dataMethod']) ? $options['dataMethod'] : false;
+        if ($method === true || $method === false) {
+            return $method;
+        }
+
+        $useCache = isset($options['cacheData']) && $options['cacheData'];
+
+        if ($useCache) {
+            $cacheKey = $driver->getUniqueID() . '|'
+                . $driver->getSourceIdentifier() . '|' . $method;
+            if (isset($cache[$cacheKey])) {
+                return $cache[$cacheKey];
+            }
+        }
+
+        // Default action: try to extract data from the record driver:
+        $data = $driver->tryMethod($method);
+
+        if ($useCache) {
+            $cache[$cacheKey] = $data;
+        }
+
+        return $data;
+    }
+
+    /**
+     * Render using the record view helper.
+     *
+     * @param RecordDriver $driver  Reoord driver object.
+     * @param mixed        $data    Data to render
+     * @param array        $options Rendering options.
+     *
+     * @return string
+     */
+    protected function renderRecordHelper(RecordDriver $driver, $data,
+        array $options
+    ) {
+        $method = isset($options['helperMethod']) ? $options['helperMethod'] : null;
+        $plugin = $this->getView()->plugin('record');
+        if (empty($method) || !is_callable([$plugin, $method])) {
+            throw new \Exception('Cannot call "' . $method . '" on helper.');
+        }
+        return $plugin($driver)->$method($data);
+    }
+
+    /**
+     * Render a record driver template.
+     *
+     * @param RecordDriver $driver  Reoord driver object.
+     * @param mixed        $data    Data to render
+     * @param array        $options Rendering options.
+     *
+     * @return string
+     */
+    protected function renderRecordDriverTemplate(RecordDriver $driver, $data,
+        array $options
+    ) {
+        if (!isset($options['template'])) {
+            throw new \Exception('Template option missing.');
+        }
+        $helper = $this->getView()->plugin('record');
+        $context = isset($options['context']) ? $options['context'] : [];
+        $context['driver'] = $driver;
+        $context['data'] = $data;
+        return trim(
+            $helper($driver)->renderTemplate($options['template'], $context)
+        );
+    }
+
+    /**
+     * Get a link associated with a value, or else return false if link does
+     * not apply.
+     *
+     * @param string $value   Value associated with link.
+     * @param array  $options Rendering options.
+     *
+     * @return string|bool
+     */
+    protected function getLink($value, $options)
+    {
+        if (isset($options['recordLink']) && $options['recordLink']) {
+            $helper = $this->getView()->plugin('record');
+            return $helper->getLink($options['recordLink'], $value);
+        }
+        return false;
+    }
+
+    /**
+     * Simple rendering method.
+     *
+     * @param RecordDriver $driver  Reoord driver object.
+     * @param mixed        $data    Data to render
+     * @param array        $options Rendering options.
+     *
+     * @return string
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+     */
+    protected function renderSimple(RecordDriver $driver, $data, array $options)
+    {
+        $view = $this->getView();
+        $escaper = (isset($options['translate']) && $options['translate'])
+            ? $view->plugin('transEsc') : $view->plugin('escapeHtml');
+        $separator = isset($options['separator'])
+            ? $options['separator'] : '<br />';
+        $retVal = '';
+        $array = (array)$data;
+        $remaining = count($data);
+        foreach ($array as $line) {
+            $remaining--;
+            $text = $escaper($line);
+            $retVal .= ($link = $this->getLink($line, $options))
+                ? '<a href="' . $link . '">' . $text . '</a>' : $text;
+            if ($remaining > 0) {
+                $retVal .= $separator;
+            }
+        }
+        return (isset($options['prefix']) ? $options['prefix'] : '')
+            . $retVal
+            . (isset($options['suffix']) ? $options['suffix'] : '');
+    }
+}
diff --git a/module/VuFind/src/VuFind/View/Helper/Root/RecordDataFormatter/SpecBuilder.php b/module/VuFind/src/VuFind/View/Helper/Root/RecordDataFormatter/SpecBuilder.php
new file mode 100644
index 0000000000000000000000000000000000000000..dd8a4f91cb292d1d3ff10ecda696a768ea40c2c7
--- /dev/null
+++ b/module/VuFind/src/VuFind/View/Helper/Root/RecordDataFormatter/SpecBuilder.php
@@ -0,0 +1,136 @@
+<?php
+/**
+ * Specification builder for record driver data formatting view helper
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2016.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * @category VuFind
+ * @package  View_Helpers
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development Wiki
+ */
+namespace VuFind\View\Helper\Root\RecordDataFormatter;
+
+/**
+ * Specification builder for record driver data formatting view helper
+ *
+ * @category VuFind
+ * @package  View_Helpers
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development Wiki
+ */
+class SpecBuilder
+{
+    /**
+     * Spec
+     *
+     * @var array
+     */
+    protected $spec = [];
+
+    /**
+     * Highest position value so far.
+     *
+     * @var int
+     */
+    protected $maxPos = 0;
+
+    /**
+     * Constructor
+     *
+     * @param array $spec Existing specification lines (optional)
+     */
+    public function __construct($spec = [])
+    {
+        $this->spec = $spec;
+        foreach ($spec as $current) {
+            if (isset($current['pos']) && $current['pos'] > $this->maxPos) {
+                $this->maxPos = $current['pos'];
+            }
+        }
+    }
+    /**
+     * Set a generic spec line.
+     *
+     * @param string $key        Label to associate with this spec line
+     * @param string $dataMethod Method of data retrieval for rendering element
+     * @param string $renderType Type of rendering to use to generate output
+     * @param array  $options    Additional options
+     *
+     * @return array
+     */
+    public function setLine($key, $dataMethod, $renderType = null, $options = [])
+    {
+        $options['dataMethod'] = $dataMethod;
+        $options['renderType'] = $renderType;
+        if (!isset($options['pos'])) {
+            $this->maxPos += 100;
+            $options['pos'] = $this->maxPos;
+        }
+        $this->spec[$key] = $options;
+    }
+
+    /**
+     * Construct a record driver template spec line.
+     *
+     * @param string $key        Label to associate with this spec line
+     * @param string $dataMethod Method of data retrieval for rendering element
+     * @param string $template   Record driver template to render with data
+     * @param array  $options    Additional options
+     *
+     * @return array
+     */
+    public function setTemplateLine($key, $dataMethod, $template, $options = [])
+    {
+        $options['template'] = $template;
+        return $this->setLine($key, $dataMethod, 'RecordDriverTemplate', $options);
+    }
+
+    /**
+     * Reorder the specs to match the provided array of keys.
+     *
+     * @param array $orderedKeys Keys in the desired order
+     * @param int   $defaultPos  Position to use for elements not included in
+     * $orderedKeys (null to put unrecognized items at end of list).
+     *
+     * @return void
+     */
+    public function reorderKeys($orderedKeys, $defaultPos = null)
+    {
+        $lookup = array_flip($orderedKeys);
+        if (null === $defaultPos) {
+            $defaultPos = (max($lookup) + 2) * 100;
+        }
+        foreach (array_keys($this->spec) as $key) {
+            $this->spec[$key]['pos'] = isset($lookup[$key])
+                ? ($lookup[$key] + 1) * 100 : $defaultPos;
+        }
+    }
+
+    /**
+     * Get the spec.
+     *
+     * @return array
+     */
+    public function getArray()
+    {
+        return $this->spec;
+    }
+}
diff --git a/module/VuFind/src/VuFind/View/Helper/Root/RecordDataFormatterFactory.php b/module/VuFind/src/VuFind/View/Helper/Root/RecordDataFormatterFactory.php
new file mode 100644
index 0000000000000000000000000000000000000000..f2da01a84343bf6d659ec0422716d9b71d142832
--- /dev/null
+++ b/module/VuFind/src/VuFind/View/Helper/Root/RecordDataFormatterFactory.php
@@ -0,0 +1,300 @@
+<?php
+/**
+ * Factory for record driver data formatting view helper
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2016.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * @category VuFind
+ * @package  View_Helpers
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development:architecture:record_data_formatter
+ * Wiki
+ */
+namespace VuFind\View\Helper\Root;
+
+/**
+ * Factory for record driver data formatting view helper
+ *
+ * @category VuFind
+ * @package  View_Helpers
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development:architecture:record_data_formatter
+ * Wiki
+ */
+class RecordDataFormatterFactory
+{
+    /**
+     * Create the helper.
+     *
+     * @return RecordDataFormatter
+     */
+    public function __invoke()
+    {
+        $helper = new RecordDataFormatter();
+        $helper->setDefaults(
+            'collection-info', [$this, 'getDefaultCollectionInfoSpecs']
+        );
+        $helper->setDefaults(
+            'collection-record', [$this, 'getDefaultCollectionRecordSpecs']
+        );
+        $helper->setDefaults('core', [$this, 'getDefaultCoreSpecs']);
+        $helper->setDefaults('description', [$this, 'getDefaultDescriptionSpecs']);
+        return $helper;
+    }
+
+    /**
+     * Get default specifications for displaying data in collection-info metadata.
+     *
+     * @return array
+     */
+    public function getDefaultCollectionInfoSpecs()
+    {
+        $spec = new RecordDataFormatter\SpecBuilder();
+        $spec->setTemplateLine(
+            'Main Authors', 'getDeduplicatedAuthors', 'data-authors.phtml',
+            [
+                'useCache' => true,
+                'labelFunction' => function ($data) {
+                    return count($data['main']) > 1
+                        ? 'Main Authors' : 'Main Author';
+                },
+                'context' => ['type' => 'main', 'schemaLabel' => 'author'],
+            ]
+        );
+        $spec->setTemplateLine(
+            'Corporate Authors', 'getDeduplicatedAuthors', 'data-authors.phtml',
+            [
+                'useCache' => true,
+                'labelFunction' => function ($data) {
+                    return count($data['corporate']) > 1
+                        ? 'Corporate Authors' : 'Corporate Author';
+                },
+                'context' => ['type' => 'corporate', 'schemaLabel' => 'creator'],
+            ]
+        );
+        $spec->setTemplateLine(
+            'Other Authors', 'getDeduplicatedAuthors', 'data-authors.phtml',
+            [
+                'useCache' => true,
+                'context' => [
+                    'type' => 'secondary', 'schemaLabel' => 'contributor'
+                ],
+            ]
+        );
+        $spec->setLine('Summary', 'getSummary');
+        $spec->setLine(
+            'Format', 'getFormats', 'RecordHelper',
+            ['helperMethod' => 'getFormatList']
+        );
+        $spec->setLine('Language', 'getLanguages');
+        $spec->setTemplateLine(
+            'Published', 'getPublicationDetails', 'data-publicationDetails.phtml'
+        );
+        $spec->setLine(
+            'Edition', 'getEdition', null,
+            ['prefix' => '<span property="bookEdition">', 'suffix' => '</span>']
+        );
+        $spec->setTemplateLine('Series', 'getSeries', 'data-series.phtml');
+        $spec->setTemplateLine(
+            'Subjects', 'getAllSubjectHeadings', 'data-allSubjectHeadings.phtml'
+        );
+        $spec->setTemplateLine('Online Access', true, 'data-onlineAccess.phtml');
+        $spec->setTemplateLine(
+            'Related Items', 'getAllRecordLinks', 'data-allRecordLinks.phtml'
+        );
+        $spec->setLine('Notes', 'getGeneralNotes');
+        $spec->setLine('Production Credits', 'getProductionCredits');
+        $spec->setLine('ISBN', 'getISBNs');
+        $spec->setLine('ISSN', 'getISSNs');
+        return $spec->getArray();
+    }
+
+    /**
+     * Get default specifications for displaying data in collection-record metadata.
+     *
+     * @return array
+     */
+    public function getDefaultCollectionRecordSpecs()
+    {
+        $spec = new RecordDataFormatter\SpecBuilder();
+        $spec->setLine('Summary', 'getSummary');
+        $spec->setTemplateLine(
+            'Main Authors', 'getDeduplicatedAuthors', 'data-authors.phtml',
+            [
+                'useCache' => true,
+                'labelFunction' => function ($data) {
+                    return count($data['main']) > 1
+                        ? 'Main Authors' : 'Main Author';
+                },
+                'context' => ['type' => 'main', 'schemaLabel' => 'author'],
+            ]
+        );
+        $spec->setTemplateLine(
+            'Corporate Authors', 'getDeduplicatedAuthors', 'data-authors.phtml',
+            [
+                'useCache' => true,
+                'labelFunction' => function ($data) {
+                    return count($data['corporate']) > 1
+                        ? 'Corporate Authors' : 'Corporate Author';
+                },
+                'context' => ['type' => 'corporate', 'schemaLabel' => 'creator'],
+            ]
+        );
+        $spec->setTemplateLine(
+            'Other Authors', 'getDeduplicatedAuthors', 'data-authors.phtml',
+            [
+                'useCache' => true,
+                'context' => [
+                    'type' => 'secondary', 'schemaLabel' => 'contributor'
+                ],
+            ]
+        );
+        $spec->setLine('Language', 'getLanguages');
+        $spec->setLine(
+            'Format', 'getFormats', 'RecordHelper',
+            ['helperMethod' => 'getFormatList']
+        );
+        $spec->setLine('Access', 'getAccessRestrictions');
+        $spec->setLine('Related Items', 'getRelationshipNotes');
+        return $spec->getArray();
+    }
+
+    /**
+     * Get default specifications for displaying data in core metadata.
+     *
+     * @return array
+     */
+    public function getDefaultCoreSpecs()
+    {
+        $spec = new RecordDataFormatter\SpecBuilder();
+        $spec->setTemplateLine(
+            'Published in', 'getContainerTitle', 'data-containerTitle.phtml'
+        );
+        $spec->setLine(
+            'New Title', 'getNewerTitles', null, ['recordLink' => 'title']
+        );
+        $spec->setLine(
+            'Previous Title', 'getPreviousTitles', null, ['recordLink' => 'title']
+        );
+        $spec->setTemplateLine(
+            'Main Authors', 'getDeduplicatedAuthors', 'data-authors.phtml',
+            [
+                'useCache' => true,
+                'labelFunction' => function ($data) {
+                    return count($data['primary']) > 1
+                        ? 'Main Authors' : 'Main Author';
+                },
+                'context' => [
+                    'type' => 'primary',
+                    'schemaLabel' => 'author',
+                    'requiredDataFields' => [
+                        ['name' => 'role', 'prefix' => 'CreatorRoles::']
+                    ]
+                ]
+            ]
+        );
+        $spec->setTemplateLine(
+            'Corporate Authors', 'getDeduplicatedAuthors', 'data-authors.phtml',
+            [
+                'useCache' => true,
+                'labelFunction' => function ($data) {
+                    return count($data['corporate']) > 1
+                        ? 'Corporate Authors' : 'Corporate Author';
+                },
+                'context' => [
+                    'type' => 'corporate',
+                    'schemaLabel' => 'creator',
+                    'requiredDataFields' => [
+                        ['name' => 'role', 'prefix' => 'CreatorRoles::']
+                    ]
+                ]
+            ]
+        );
+        $spec->setTemplateLine(
+            'Other Authors', 'getDeduplicatedAuthors', 'data-authors.phtml',
+            [
+                'useCache' => true,
+                'context' => [
+                    'type' => 'secondary',
+                    'schemaLabel' => 'contributor',
+                    'requiredDataFields' => [
+                        ['name' => 'role', 'prefix' => 'CreatorRoles::']
+                    ]
+                ],
+            ]
+        );
+        $spec->setLine(
+            'Format', 'getFormats', 'RecordHelper',
+            ['helperMethod' => 'getFormatList']
+        );
+        $spec->setLine('Language', 'getLanguages');
+        $spec->setTemplateLine(
+            'Published', 'getPublicationDetails', 'data-publicationDetails.phtml'
+        );
+        $spec->setLine(
+            'Edition', 'getEdition', null,
+            ['prefix' => '<span property="bookEdition">', 'suffix' => '</span>']
+        );
+        $spec->setTemplateLine('Series', 'getSeries', 'data-series.phtml');
+        $spec->setTemplateLine(
+            'Subjects', 'getAllSubjectHeadings', 'data-allSubjectHeadings.phtml'
+        );
+        $spec->setTemplateLine(
+            'child_records', 'getChildRecordCount', 'data-childRecords.phtml',
+            ['allowZero' => false]
+        );
+        $spec->setTemplateLine('Online Access', true, 'data-onlineAccess.phtml');
+        $spec->setTemplateLine(
+            'Related Items', 'getAllRecordLinks', 'data-allRecordLinks.phtml'
+        );
+        $spec->setTemplateLine('Tags', true, 'data-tags.phtml');
+        return $spec->getArray();
+    }
+
+    /**
+     * Get default specifications for displaying data in the description tab.
+     *
+     * @return array
+     */
+    public function getDefaultDescriptionSpecs()
+    {
+        $spec = new RecordDataFormatter\SpecBuilder();
+        $spec->setLine('Summary', 'getSummary');
+        $spec->setLine('Published', 'getDateSpan');
+        $spec->setLine('Item Description', 'getGeneralNotes');
+        $spec->setLine('Physical Description', 'getPhysicalDescriptions');
+        $spec->setLine('Publication Frequency', 'getPublicationFrequency');
+        $spec->setLine('Playing Time', 'getPlayingTimes');
+        $spec->setLine('Format', 'getSystemDetails');
+        $spec->setLine('Audience', 'getTargetAudienceNotes');
+        $spec->setLine('Awards', 'getAwards');
+        $spec->setLine('Production Credits', 'getProductionCredits');
+        $spec->setLine('Bibliography', 'getBibliographyNotes');
+        $spec->setLine('ISBN', 'getISBNs');
+        $spec->setLine('ISSN', 'getISSNs');
+        $spec->setLine('DOI', 'getCleanDOI');
+        $spec->setLine('Related Items', 'getRelationshipNotes');
+        $spec->setLine('Access', 'getAccessRestrictions');
+        $spec->setLine('Finding Aid', 'getFindingAids');
+        $spec->setLine('Publication_Place', 'getHierarchicalPlaceNames');
+        $spec->setTemplateLine('Author Notes', true, 'data-authorNotes.phtml');
+        return $spec->getArray();
+    }
+}
diff --git a/module/VuFind/src/VuFind/View/Helper/Root/RecordLink.php b/module/VuFind/src/VuFind/View/Helper/Root/RecordLink.php
index be65d2c35cf4d91e471a1aed8d93dc7bb0fa624e..f052b2efc781b18918b3cb4cde18b65f3f89d244 100644
--- a/module/VuFind/src/VuFind/View/Helper/Root/RecordLink.php
+++ b/module/VuFind/src/VuFind/View/Helper/Root/RecordLink.php
@@ -119,7 +119,7 @@ class RecordLink extends \Zend\View\Helper\AbstractHelper
         // Build the URL:
         $urlHelper = $this->getView()->plugin('url');
         $details = $this->router->getActionRouteDetails($driver, $action);
-        return $urlHelper($details['route'], $details['params']);
+        return $urlHelper($details['route'], $details['params'] ?: []);
     }
 
     /**
diff --git a/module/VuFind/src/VuFind/View/Helper/Root/ResultFeed.php b/module/VuFind/src/VuFind/View/Helper/Root/ResultFeed.php
index eecc7864725e423cc0f1f7987faad8470b085e9f..30a21166fbefe49aff1609a08e909444c958cdf7 100644
--- a/module/VuFind/src/VuFind/View/Helper/Root/ResultFeed.php
+++ b/module/VuFind/src/VuFind/View/Helper/Root/ResultFeed.php
@@ -26,11 +26,11 @@
  * @link     https://vufind.org/wiki/development Wiki
  */
 namespace VuFind\View\Helper\Root;
-use DateTime,
-    VuFind\I18n\Translator\TranslatorAwareInterface,
-    Zend\Feed\Writer\Writer as FeedWriter,
-    Zend\Feed\Writer\Feed,
-    Zend\View\Helper\AbstractHelper;
+use DateTime;
+use VuFind\I18n\Translator\TranslatorAwareInterface;
+use Zend\Feed\Writer\Writer as FeedWriter;
+use Zend\Feed\Writer\Feed;
+use Zend\View\Helper\AbstractHelper;
 
 /**
  * "Results as feed" view helper
@@ -65,13 +65,13 @@ class ResultFeed extends AbstractHelper implements TranslatorAwareInterface
     }
 
     /**
-     * Set up Dublin Core extension.
+     * Set up custom extensions.
      *
      * @return void
      */
-    protected function registerExtension()
+    protected function registerExtensions()
     {
-        $manager = FeedWriter::getExtensionManager();
+        $manager = new \Zend\Feed\Writer\ExtensionPluginManager();
         $manager->setInvokableClass(
             'dublincorerendererentry',
             'VuFind\Feed\Writer\Extension\DublinCore\Renderer\Entry'
@@ -86,6 +86,7 @@ class ResultFeed extends AbstractHelper implements TranslatorAwareInterface
         $manager->setInvokableClass(
             'opensearchfeed', 'VuFind\Feed\Writer\Extension\OpenSearch\Feed'
         );
+        FeedWriter::setExtensionManager($manager);
         FeedWriter::registerExtension('OpenSearch');
     }
 
@@ -101,7 +102,7 @@ class ResultFeed extends AbstractHelper implements TranslatorAwareInterface
      */
     public function __invoke($results, $currentPath = null)
     {
-        $this->registerExtension();
+        $this->registerExtensions();
 
         // Determine base URL if not already provided:
         if (is_null($currentPath)) {
@@ -121,30 +122,37 @@ class ResultFeed extends AbstractHelper implements TranslatorAwareInterface
             );
         }
         $feed->setLink(
-            $baseUrl . $results->getUrlQuery()->setViewParam(null, false)
+            $baseUrl . $results->getUrlQuery()->setViewParam(null)->getParams(false)
         );
         $feed->setFeedLink(
             $baseUrl . $results->getUrlQuery()->getParams(false),
             $results->getParams()->getView()
         );
         $feed->setDescription(
-            $this->translate('Showing') . ' ' . $results->getStartRecord() . '-'
-            . $results->getEndRecord() . ' ' . $this->translate('of') . ' '
-            . $results->getResultTotal()
+            strip_tags(
+                $this->translate(
+                    'showing_results_of_html',
+                    [
+                        '%%start%%' => $results->getStartRecord(),
+                        '%%end%%' => $results->getEndRecord(),
+                        '%%total%%' => $results->getResultTotal()
+                    ]
+                )
+            )
         );
 
         $params = $results->getParams();
 
         // add atom links for easier paging
         $feed->addOpensearchLink(
-            $baseUrl . $results->getUrlQuery()->setPage(1, false),
+            $baseUrl . $results->getUrlQuery()->setPage(1)->getParams(false),
             'first',
             $params->getView()
         );
         if ($params->getPage() > 1) {
             $feed->addOpensearchLink(
                 $baseUrl . $results->getUrlQuery()
-                    ->setPage($params->getPage() - 1, false),
+                    ->setPage($params->getPage() - 1)->getParams(false),
                 'previous',
                 $params->getView()
             );
@@ -153,13 +161,13 @@ class ResultFeed extends AbstractHelper implements TranslatorAwareInterface
         if ($params->getPage() < $lastPage) {
             $feed->addOpensearchLink(
                 $baseUrl . $results->getUrlQuery()
-                    ->setPage($params->getPage() + 1, false),
+                    ->setPage($params->getPage() + 1)->getParams(false),
                 'next',
                 $params->getView()
             );
         }
         $feed->addOpensearchLink(
-            $baseUrl . $results->getUrlQuery()->setPage($lastPage, false),
+            $baseUrl . $results->getUrlQuery()->setPage($lastPage)->getParams(false),
             'last',
             $params->getView()
         );
diff --git a/module/VuFind/src/VuFind/View/Helper/Root/SearchBox.php b/module/VuFind/src/VuFind/View/Helper/Root/SearchBox.php
index a4fb93bc11c2c4841cd5b88ef2355c3defbe4fce..ad912bf51d49846d5de9150a164d7d26c2ac9f21 100644
--- a/module/VuFind/src/VuFind/View/Helper/Root/SearchBox.php
+++ b/module/VuFind/src/VuFind/View/Helper/Root/SearchBox.php
@@ -46,6 +46,13 @@ class SearchBox extends \Zend\View\Helper\AbstractHelper
      */
     protected $config;
 
+    /**
+     * Placeholders from config.ini
+     *
+     * @var array
+     */
+    protected $placeholders;
+
     /**
      * Search options plugin manager
      *
@@ -65,11 +72,14 @@ class SearchBox extends \Zend\View\Helper\AbstractHelper
      *
      * @param OptionsManager $optionsManager Search options plugin manager
      * @param array          $config         Configuration for search box
+     * @param array          $placeholders   Array of placeholders keyed by backend
      */
-    public function __construct(OptionsManager $optionsManager, $config = [])
-    {
+    public function __construct(OptionsManager $optionsManager, $config = [],
+        $placeholders = []
+    ) {
         $this->optionsManager = $optionsManager;
         $this->config = $config;
+        $this->placeholders = $placeholders;
     }
 
     /**
@@ -155,6 +165,26 @@ class SearchBox extends \Zend\View\Helper\AbstractHelper
         return $final;
     }
 
+    /**
+     * Get placeholder text from config using the activeSearchClass as key
+     *
+     * @param string $activeSearchClass Active search class ID
+     *
+     * @return string
+     */
+    public function getPlaceholderText($activeSearchClass)
+    {
+        // Searchbox place
+        if (!empty($this->placeholders)) {
+            return isset($this->placeholders[$activeSearchClass])
+                ? $this->placeholders[$activeSearchClass]
+                : (isset($this->placeholders['default'])
+                    ? $this->placeholders['default']
+                    : null);
+        }
+        return null;
+    }
+
     /**
      * Get an array of information on search handlers for use in generating a
      * drop-down or hidden field. Returns an array of arrays with 'value', 'label',
diff --git a/module/VuFind/src/VuFind/View/Helper/Root/SearchTabs.php b/module/VuFind/src/VuFind/View/Helper/Root/SearchTabs.php
index 04735d9feeaf5486632843fe48557bb604da8d27..af6f87fcb52a6d4475ba8123708ad7e1ead50a9d 100644
--- a/module/VuFind/src/VuFind/View/Helper/Root/SearchTabs.php
+++ b/module/VuFind/src/VuFind/View/Helper/Root/SearchTabs.php
@@ -110,8 +110,7 @@ class SearchTabs extends \Zend\View\Helper\AbstractHelper
     public function getTabConfig($activeSearchClass, $query, $handler,
         $type = 'basic', $hiddenFilters = []
     ) {
-        $retVal = [];
-        $matchFound = false;
+        $retVal = ['tabs' => []];
         $allFilters = $this->helper->getTabFilterConfig();
         foreach ($this->helper->getTabConfig() as $key => $label) {
             $class = $this->helper->extractClassName($key);
@@ -119,8 +118,8 @@ class SearchTabs extends \Zend\View\Helper\AbstractHelper
             if ($class == $activeSearchClass
                 && $this->helper->filtersMatch($class, $hiddenFilters, $filters)
             ) {
-                $matchFound = true;
-                $retVal[] = $this->createSelectedTab($key, $class, $label);
+                $retVal['selected'] = $this->createSelectedTab($key, $class, $label);
+                $retVal['tabs'][] = $retVal['selected'];
             } else if ($type == 'basic') {
                 if (!isset($activeOptions)) {
                     $activeOptions
@@ -129,17 +128,21 @@ class SearchTabs extends \Zend\View\Helper\AbstractHelper
                 $newUrl = $this->remapBasicSearch(
                     $activeOptions, $class, $query, $handler, $filters
                 );
-                $retVal[] = $this->createBasicTab($key, $class, $label, $newUrl);
+                $retVal['tabs'][]
+                    = $this->createBasicTab($key, $class, $label, $newUrl);
             } else if ($type == 'advanced') {
-                $retVal[] = $this->createAdvancedTab($key, $class, $label, $filters);
+                $retVal['tabs'][]
+                    = $this->createAdvancedTab($key, $class, $label, $filters);
             } else {
-                $retVal[] = $this->createHomeTab($key, $class, $label, $filters);
+                $retVal['tabs'][]
+                    = $this->createHomeTab($key, $class, $label, $filters);
             }
         }
-        if (!$matchFound && !empty($retVal)) {
+        if (!isset($retVal['selected']) && !empty($retVal['tabs'])) {
             // Make the first tab for the given search class selected
-            foreach ($retVal as &$tab) {
+            foreach ($retVal['tabs'] as &$tab) {
                 if ($tab['class'] == $activeSearchClass) {
+                    $retVal['selected'] = $tab;
                     $tab['selected'] = true;
                     break;
                 }
@@ -158,11 +161,12 @@ class SearchTabs extends \Zend\View\Helper\AbstractHelper
      */
     public function getTabConfigForParams($params)
     {
-        return $this->getTabConfig(
+        $tabConfig = $this->getTabConfig(
             $params->getSearchClassId(), $params->getDisplayQuery(),
             $params->getSearchHandler(), $params->getSearchType(),
             $params->getHiddenFilters()
         );
+        return $tabConfig['tabs'];
     }
 
     /**
diff --git a/module/VuFind/src/VuFind/View/Helper/Root/SortFacetList.php b/module/VuFind/src/VuFind/View/Helper/Root/SortFacetList.php
index cf17f6b55e78b5485dac4295e91cf6f61a279c30..3bfcf4a1783dfdc94142602d9f0aa7ed7e89d157 100644
--- a/module/VuFind/src/VuFind/View/Helper/Root/SortFacetList.php
+++ b/module/VuFind/src/VuFind/View/Helper/Root/SortFacetList.php
@@ -59,8 +59,8 @@ class SortFacetList extends AbstractHelper
         $results->getParams()->setLimit($results->getOptions()->getDefaultLimit());
         $urlHelper = $this->getView()->plugin('url');
         foreach ($list as $value) {
-            $url = $urlHelper($searchRoute)
-                . $results->getUrlQuery()->addFacet($field, $value['value']);
+            $url = $urlHelper($searchRoute) . $results->getUrlQuery()
+                ->addFacet($field, $value['value'])->getParams();
             $facets[$url] = $value['displayText'];
         }
         natcasesort($facets);
diff --git a/module/VuFind/src/VuFind/XSLT/Importer.php b/module/VuFind/src/VuFind/XSLT/Importer.php
index 4219a26686a8d02cb17d35cdaa7c561ef6ffecbd..5707cf52ef0d7621b0358079eaf89969e33c283b 100644
--- a/module/VuFind/src/VuFind/XSLT/Importer.php
+++ b/module/VuFind/src/VuFind/XSLT/Importer.php
@@ -26,11 +26,12 @@
  * @link     https://vufind.org/wiki/ Wiki
  */
 namespace VuFind\XSLT;
-use DOMDocument, VuFind\Config\Locator as ConfigLocator,
-    XSLTProcessor, Zend\Console\Console,
-    VuFindSearch\Backend\Solr\Document\RawXMLDocument,
-    Zend\ServiceManager\ServiceLocatorAwareInterface,
-    Zend\ServiceManager\ServiceLocatorInterface;
+use DOMDocument;
+use VuFind\Config\Locator as ConfigLocator;
+use VuFindSearch\Backend\Solr\Document\RawXMLDocument;
+use XSLTProcessor;
+use Zend\Console\Console;
+use Zend\ServiceManager\ServiceLocatorInterface;
 
 /**
  * VuFind XSLT importer
@@ -41,9 +42,24 @@ use DOMDocument, VuFind\Config\Locator as ConfigLocator,
  * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
  * @link     https://vufind.org/wiki/ Wiki
  */
-class Importer implements ServiceLocatorAwareInterface
+class Importer
 {
-    use \Zend\ServiceManager\ServiceLocatorAwareTrait;
+    /**
+     * Service locator
+     *
+     * @var ServiceLocatorInterface
+     */
+    protected $serviceLocator;
+
+    /**
+     * Constructor
+     *
+     * @param ServiceLocatorInterface $sm Service manager
+     */
+    public function __construct(ServiceLocatorInterface $sm)
+    {
+        $this->serviceLocator = $sm;
+    }
 
     /**
      * Save an XML file to the Solr index using the specified configuration.
@@ -64,7 +80,7 @@ class Importer implements ServiceLocatorAwareInterface
 
         // Save the results (or just display them, if in test mode):
         if (!$testMode) {
-            $solr = $this->getServiceLocator()->get('VuFind\Solr\Writer');
+            $solr = $this->serviceLocator->get('VuFind\Solr\Writer');
             $solr->save($index, new RawXMLDocument($xml));
         } else {
             Console::write($xml . "\n");
@@ -171,7 +187,7 @@ class Importer implements ServiceLocatorAwareInterface
                 }
                 $methods = get_class_methods($class);
                 if (method_exists($class, 'setServiceLocator')) {
-                    $class::setServiceLocator($this->getServiceLocator());
+                    $class::setServiceLocator($this->serviceLocator);
                 }
                 foreach ($methods as $method) {
                     $xsl->registerPHPFunctions($class . '::' . $method);
diff --git a/module/VuFind/src/VuFindTest/Search/TestHarness/Results.php b/module/VuFind/src/VuFindTest/Search/TestHarness/Results.php
index 374690efd25096bd2a0298f7a726970f68afd266..99f4224e5b8bf9cc697f5febee247517f32db19c 100644
--- a/module/VuFind/src/VuFindTest/Search/TestHarness/Results.php
+++ b/module/VuFind/src/VuFindTest/Search/TestHarness/Results.php
@@ -26,6 +26,8 @@
  * @link     https://vufind.org Main Page
  */
 namespace VuFindTest\Search\TestHarness;
+use VuFind\Record\Loader;
+use VuFindSearch\Service as SearchService;
 use VuFindTest\RecordDriver\TestHarness as RecordDriver;
 
 /**
@@ -55,18 +57,32 @@ class Results extends \VuFind\Search\Base\Results
      */
     protected $driverCache = [];
 
+    /**
+     * Fake facet response
+     *
+     * @var array
+     */
+    protected $facets;
+
     /**
      * Constructor
      *
-     * @param \VuFind\Search\Base\Params $params Object representing user search
-     * parameters.
-     * @param int                        $total  Total result set size to simulate
+     * @param \VuFind\Search\Base\Params $params        Object representing user
+     * search parameters.
+     * @param SearchService              $searchService Search service
+     * @param Loader                     $recordLoader  Record loader
+     * @param int                        $total         Total result set size to
+     * simulate
+     * @param array                      $facets        Facet response (optional)
      */
-    public function __construct(Params $params, $total = 100)
-    {
-        parent::__construct($params);
+    public function __construct(\VuFind\Search\Base\Params $params,
+        SearchService $searchService, Loader $recordLoader,
+        $total = 100, $facets = []
+    ) {
+        parent::__construct($params, $searchService, $recordLoader);
         $this->fakeExpectedTotal = $total;
         $this->searchId = 'fake';   // fill a fake value here so we don't hit the DB
+        $this->facets = $facets;
     }
 
     /**
@@ -79,8 +95,7 @@ class Results extends \VuFind\Search\Base\Results
      */
     public function getFacetList($filter = null)
     {
-        // not supported
-        return [];
+        return $this->facets;
     }
 
     /**
diff --git a/module/VuFind/src/VuFindTest/Unit/DbTestCase.php b/module/VuFind/src/VuFindTest/Unit/DbTestCase.php
index 5d0608d40982b2bbd9cdf5431230d2c8247e7670..9a17aabd8959e3c795a11e5527c93f491f8d1b18 100644
--- a/module/VuFind/src/VuFindTest/Unit/DbTestCase.php
+++ b/module/VuFind/src/VuFindTest/Unit/DbTestCase.php
@@ -27,6 +27,7 @@
  * @link     https://vufind.org/wiki/development:testing:unit_tests Wiki
  */
 namespace VuFindTest\Unit;
+use Zend\ServiceManager\ServiceManager;
 
 /**
  * Abstract base class for PHPUnit database test cases.
@@ -39,6 +40,84 @@ namespace VuFindTest\Unit;
  */
 abstract class DbTestCase extends TestCase
 {
+    /**
+     * Add table manager to service manager.
+     *
+     * @param ServiceManager $sm Service manager
+     *
+     * @return void
+     */
+    protected function addTableManager(ServiceManager $sm)
+    {
+        $factory = new \VuFind\Db\Table\PluginManager(
+            new \Zend\ServiceManager\Config(
+                [
+                    'abstract_factories' =>
+                        ['VuFind\Db\Table\PluginFactory'],
+                    'factories' => [
+                        'changetracker' =>
+                            'VuFind\Db\Table\Factory::getChangeTracker',
+                        'comments' => 'VuFind\Db\Table\Factory::getComments',
+                        'externalsession' =>
+                            'VuFind\Db\Table\Factory::getExternalSession',
+                        'oairesumption' =>
+                            'VuFind\Db\Table\Factory::getOaiResumption',
+                        'record' => 'VuFind\Db\Table\Factory::getRecord',
+                        'resource' => 'VuFind\Db\Table\Factory::getResource',
+                        'resourcetags' =>
+                            'VuFind\Db\Table\Factory::getResourceTags',
+                        'search' => 'VuFind\Db\Table\Factory::getSearch',
+                        'session' => 'VuFind\Db\Table\Factory::getSession',
+                        'tags' => 'VuFind\Db\Table\Factory::getTags',
+                        'user' => 'VuFind\Db\Table\Factory::getUser',
+                        'usercard' => 'VuFind\Db\Table\Factory::getUserCard',
+                        'userlist' => 'VuFind\Db\Table\Factory::getUserList',
+                        'userresource' =>
+                            'VuFind\Db\Table\Factory::getUserResource',
+                    ],
+                ]
+            )
+        );
+        $factory->setServiceLocator($sm);
+        $sm->setService('VuFind\DbTablePluginManager', $factory);
+    }
+
+    /**
+     * Add row manager to service manager.
+     *
+     * @param ServiceManager $sm Service manager
+     *
+     * @return void
+     */
+    protected function addRowManager(ServiceManager $sm)
+    {
+        $factory = new \VuFind\Db\Row\PluginManager(
+            new \Zend\ServiceManager\Config(
+                [
+                    'factories' => [
+                        'changetracker' => 'VuFind\Db\Row\Factory::getChangeTracker',
+                        'comments' => 'VuFind\Db\Row\Factory::getComments',
+                        'externalsession' =>
+                            'VuFind\Db\Row\Factory::getExternalSession',
+                        'oairesumption' => 'VuFind\Db\Row\Factory::getOaiResumption',
+                        'record' => 'VuFind\Db\Row\Factory::getRecord',
+                        'resource' => 'VuFind\Db\Row\Factory::getResource',
+                        'resourcetags' => 'VuFind\Db\Row\Factory::getResourceTags',
+                        'search' => 'VuFind\Db\Row\Factory::getSearch',
+                        'session' => 'VuFind\Db\Row\Factory::getSession',
+                        'tags' => 'VuFind\Db\Row\Factory::getTags',
+                        'user' => 'VuFind\Db\Row\Factory::getUser',
+                        'usercard' => 'VuFind\Db\Row\Factory::getUserCard',
+                        'userlist' => 'VuFind\Db\Row\Factory::getUserList',
+                        'userresource' => 'VuFind\Db\Row\Factory::getUserResource',
+                    ],
+                ]
+            )
+        );
+        $factory->setServiceLocator($sm);
+        $sm->setService('VuFind\DbRowPluginManager', $factory);
+    }
+
     /**
      * Get a service manager.
      *
@@ -55,24 +134,11 @@ abstract class DbTestCase extends TestCase
                 $sm->get('VuFind\Config')->get('config')
             );
             $sm->setService('VuFind\DbAdapter', $dbFactory->getAdapter());
-            $factory = new \VuFind\Db\Table\PluginManager(
-                new \Zend\ServiceManager\Config(
-                    [
-                        'abstract_factories' =>
-                            ['VuFind\Db\Table\PluginFactory'],
-                        'factories' => [
-                            'resource' => 'VuFind\Db\Table\Factory::getResource',
-                            'user' => 'VuFind\Db\Table\Factory::getUser',
-                            'userlist' => 'VuFind\Db\Table\Factory::getUserList',
-                        ]
-                    ]
-                )
-            );
-            $factory->setServiceLocator($sm);
-            $sm->setService('VuFind\DbTablePluginManager', $factory);
+            $this->addTableManager($sm);
+            $this->addRowManager($sm);
             $sm->setService(
                 'VuFind\SessionManager',
-                $this->getMock('Zend\Session\SessionManager')
+                $this->createMock('Zend\Session\SessionManager')
             );
 
             // Override the configuration so PostgreSQL tests can work:
@@ -82,16 +148,18 @@ abstract class DbTestCase extends TestCase
                 [
                     'vufind' => [
                         'pgsql_seq_mapping'  => [
-                            'comments'       => ['id', 'comments_id_seq'],
-                            'oai_resumption' => ['id', 'oai_resumption_id_seq'],
-                            'resource'       => ['id', 'resource_id_seq'],
-                            'resource_tags'  => ['id', 'resource_tags_id_seq'],
-                            'search'         => ['id', 'search_id_seq'],
-                            'session'        => ['id', 'session_id_seq'],
-                            'tags'           => ['id', 'tags_id_seq'],
-                            'user'           => ['id', 'user_id_seq'],
-                            'user_list'      => ['id', 'user_list_id_seq'],
-                            'user_resource'  => ['id', 'user_resource_id_seq']
+                            'comments'         => ['id', 'comments_id_seq'],
+                            'external_session' => ['id', 'external_session_id_seq'],
+                            'oai_resumption'   => ['id', 'oai_resumption_id_seq'],
+                            'record'           => ['id', 'record_id_seq'],
+                            'resource'         => ['id', 'resource_id_seq'],
+                            'resource_tags'    => ['id', 'resource_tags_id_seq'],
+                            'search'           => ['id', 'search_id_seq'],
+                            'session'          => ['id', 'session_id_seq'],
+                            'tags'             => ['id', 'tags_id_seq'],
+                            'user'             => ['id', 'user_id_seq'],
+                            'user_list'        => ['id', 'user_list_id_seq'],
+                            'user_resource'    => ['id', 'user_resource_id_seq'],
                         ]
                     ]
                 ]
diff --git a/module/VuFind/src/VuFindTest/Unit/TestCase.php b/module/VuFind/src/VuFindTest/Unit/TestCase.php
index dff552c20875a24c4d8847e2965d531cb01f1268..5309f1d70cb7fc429362aecbfbb0a3ead8e9be74 100644
--- a/module/VuFind/src/VuFindTest/Unit/TestCase.php
+++ b/module/VuFind/src/VuFindTest/Unit/TestCase.php
@@ -192,7 +192,7 @@ abstract class TestCase extends \PHPUnit_Framework_TestCase
                 'VuFind\SearchSpecsReader', new \VuFind\Config\SearchSpecsReader()
             );
             $this->serviceManager->setService(
-                'VuFind\Logger', $this->getMock('VuFind\Log\Logger')
+                'VuFind\Logger', $this->createMock('VuFind\Log\Logger')
             );
             $this->serviceManager->setService(
                 'VuFind\Http', new \VuFindHttp\HttpService()
diff --git a/module/VuFind/tests/fixtures/configs/googlewarnings/config.ini b/module/VuFind/tests/fixtures/configs/googlewarnings/config.ini
index f459455e30d578673ab00b7268ab31982fd9252e..62b4d120b4fac63e1b12ebde2e29b07c360df699 100644
--- a/module/VuFind/tests/fixtures/configs/googlewarnings/config.ini
+++ b/module/VuFind/tests/fixtures/configs/googlewarnings/config.ini
@@ -2,4 +2,8 @@
 apiKey = 'fake'
 
 [GoogleSearch]
-fake = fake
\ No newline at end of file
+fake = fake
+
+[Content]
+recordMap = google
+googleMapApiKey = abcd
\ No newline at end of file
diff --git a/module/VuFind/tests/fixtures/recommend/europeana b/module/VuFind/tests/fixtures/recommend/europeana
new file mode 100644
index 0000000000000000000000000000000000000000..0baf6d6cc80cf14ca9455ffcb538bf5818dcd173
--- /dev/null
+++ b/module/VuFind/tests/fixtures/recommend/europeana
@@ -0,0 +1,14 @@
+HTTP/1.1 200 OK
+Content-Type: application/rss+xml
+Date: Wed, 05 Apr 2017 13:55:18 GMT
+Server: Apache-Coyote/1.1
+X-Vcap-Request-Id: 63351bb2-903e-446f-6aad-1ced4f862592
+transfer-encoding: chunked
+Connection: Close
+
+f2f
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?><rss xmlns:georss="http://www.georss.org/georss" xmlns:fieldtrip="http://www.fieldtripper.com/fieldtrip_rss" xmlns:europeana="http://www.europeana.eu" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:enrichment="http://www.europeana.eu/schemas/ese/enrichment/" version="2.0"><channel><title>Europeana Open Search</title><link>http://www.europeana.eu</link><description>Europeana Open Search results</description><opensearch:totalResults>38810</opensearch:totalResults><opensearch:startIndex>1</opensearch:startIndex><opensearch:itemsPerPage>12</opensearch:itemsPerPage><atom:link href="" rel="search" type="application/rss+xml"/><opensearch:Query role="request" searchTerms="test" startPage="1"/><image><title>Europeana Open Search</title><link>http://www.europeana.eu</link><url>http://www.europeana.eu/portal/sp/img/europeana-logo-en.png</url></image><item><guid>http://www.europeana.eu/portal/record/92099/BibliographicResource_2000068736886.html</guid><title>Guiard des Moulins , Petite Bible historiale de Charles V. [Paris, BnF, MSS Français 5707]</title><link>http://www.europeana.eu/portal/record/92099/BibliographicResource_2000068736886.html</link><description>Maître du Livre du sacre. Enlumineur de l'oeuvre reproduite; The European Library</description></item><item><guid>http://www.europeana.eu/portal/record/92099/BibliographicResource_2000060239235.html</guid><title>Guiard des Moulins , Bible Historiale de Jean de Berry. [Paris, BnF, MSS Français 20090]</title><link>http://www.europeana.eu/portal/record/92099/BibliographicResource_2000060239235.html</link><description>The European Library</description></item><item><guid>http://www.europeana.eu/portal/record/92099/BibliographicResource_1000157170726.html</guid><title>Saint Augustin , De civitate Dei (Livres XI-XXII) , traduit en français par Raoul de Presle. [Paris, BnF, MSS Français 173]</title><link>http://www.europeana.eu/portal/record/92099/BibliographicResource_1000157170726.html</link><description>Raoul de Presle. Traducteur; The European Library</description></item><item><guid>http://www.europeana.eu/portal/record/92099/BibliographicResource_1000157170711.html</guid><title>Saint Augustin , La cité de Dieu [De Civitate Dei] , (Livres XI-XXII), traduit en français par Raoul de Presles. [Paris, BnF, MSS Français 174]</title><link>http://www.europeana.eu/portal/record/92099/BibliographicResource_1000157170711.html</link><description>Augustinus (saint ; 0354-0430). Auteur du texte; The European Library</description></item><item><guid>http://www.europeana.eu/portal/record/92099/BibliographicResource_1000157170710.html</guid><title>Saint Augustin , De Civitate Dei , traduit en français par Raoul de Presles (Livre I-X). [Paris, BnF, MSS Français 22912]</title><link>http://www.europeana.eu/portal/record/92099/BibliographicResource_1000157170710.html</link><description>Augustinus (saint ; 0354-0430). Auteur du texte; The European Library</description></item><item><guid>http://www.europeana.eu/portal/record/92099/BibliographicResource_1000157170694.html</guid><title>Péan Gastineau , Vie de saint Martin de Tours (en vers). [Paris, BnF, MSS Français 1043]</title><link>http://www.europeana.eu/portal/record/92099/BibliographicResource_1000157170694.html</link><description>Péan Gatineau (11..-1227?). Auteur du texte; The European Library</description></item><item><guid>http://www.europeana.eu/portal/record/92099/BibliographicResource_1000157170677.html</guid><title>Guillaume Durand, évêque de Mende , Rational des divins offices , traduit en français par Jean Golein. [Paris, BnF, MSS Français 437]</title><link>http://www.europeana.eu/portal/record/92099/BibliographicResource
+854
+_1000157170677.html</link><description>Jean Golein. Traducteur; 1374; The European Library</description></item><item><guid>http://www.europeana.eu/portal/record/92099/BibliographicResource_1000157170645.html</guid><title>Guillaume Durand , Rational des divins offices [ Rationale divinorum officiorum ] , traduction française par Jean Golein. [Paris, BnF, MSS Français 176]</title><link>http://www.europeana.eu/portal/record/92099/BibliographicResource_1000157170645.html</link><description>Durand, Guillaume (évêque de Mende). Auteur du texte; The European Library</description></item><item><guid>http://www.europeana.eu/portal/record/92097/BibliographicResource_1000126675952.html</guid><title>Natural polymorphisms and transmitted drug resistance in Estonian HIV-1 CRF06_cpx and its recombinant viruses</title><link>http://www.europeana.eu/portal/record/92097/BibliographicResource_1000126675952.html</link><description>Avi, Radko; The European Library</description></item><item><guid>http://www.europeana.eu/portal/record/92097/BibliographicResource_1000126675484.html</guid><title>Tests for assessing the child’s school readiness and general development. Trial of the tests on the samples of pre-school children and first-grade students in Estonia</title><link>http://www.europeana.eu/portal/record/92097/BibliographicResource_1000126675484.html</link><description>Häidkind, Pille; The European Library</description></item><item><guid>http://www.europeana.eu/portal/record/92097/BibliographicResource_1000126675470.html</guid><title>Simultaneous adsorption of Cd2+, Ni2+, and Pb2+ on peat</title><link>http://www.europeana.eu/portal/record/92097/BibliographicResource_1000126675470.html</link><description>Sõukand, Ülis; The European Library</description></item><item><guid>http://www.europeana.eu/portal/record/92097/BibliographicResource_1000126675469.html</guid><title>Haaslava valla infoleht 2009. aasta valimiste ajal</title><link>http://www.europeana.eu/portal/record/92097/BibliographicResource_1000126675469.html</link><description>Vaagen, Ilona; 2011; The European Library</description></item></channel></rss>
+0
+
diff --git a/module/VuFind/tests/fixtures/resolver/response/ezb.xml b/module/VuFind/tests/fixtures/resolver/response/ezb.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9604c86044f64365713006b92f343f0966797eeb
--- /dev/null
+++ b/module/VuFind/tests/fixtures/resolver/response/ezb.xml
@@ -0,0 +1,110 @@
+HTTP/1.1 200 OK
+Date: Thu, 21 Apr 2016 13:25:49 GMT
+Server: Apache
+Content-Length: 5592
+Vary: Accept-Encoding
+Content-Type: text/xml;charset=UTF-8
+
+
+<OpenURLResponseXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0.0" xsi:noNamespaceSchemaLocation="http://ezb.uni-regensburg.de/ezeit/vascoda/vifa/vifaxml/response_vr_v1_0_1.xsd">
+    <Full>
+        <ElectronicData>
+            <Library>Universitätsbibliothek Leipzig</Library>
+            <References>
+                <Reference>
+                    <URL>http://www.bibliothek.uni-regensburg.de/ezeit/?1482826</URL>
+                    <Label>EZB-Opac</Label>
+                </Reference>
+                <Reference>
+                    <URL>http://www.bibliothek.uni-regensburg.de/ezeit/?2010839</URL>
+                    <Label>EZB-Opac</Label>
+                </Reference>
+                <Reference>
+                    <URL>http://www.bibliothek.uni-regensburg.de/ezeit/search.phtml?bibid=UBL&amp;lang=de&amp;jq_type1=KT&amp;jq_term1=Noûs : a Quarterly Journal of Philosophy (1997-)</URL>
+                    <Label>EZB-Suche</Label>
+                </Reference>
+            </References>
+            <ResultList>
+                <Result state="3">
+                    <Title>Noûs : a Quarterly Journal of Philosophy (1997-)</Title>
+                    <JournalURL>http://onlinelibrary.wiley.com/journal/10.1111/(ISSN)1468-0068</JournalURL>
+                    <AccessURL>http://onlinelibrary.wiley.com/journal/10.1111/(ISSN)1468-0068</AccessURL>
+                    <AccessLevel>homepage</AccessLevel>
+                    <Additionals>
+                        <Additional type="intervall">ab Vol. 31, Iss. 1 (1997)</Additional>
+                    </Additionals>
+                    <ReadmeURL lang="de">https://www.ub.uni-leipzig.de/index.php?id=163#Wiley Core 2015</ReadmeURL>
+                    <ReadmeURL lang="en">http://www.ub.uni-leipzig.de/kata_db/Readme.htm#Wiley Core 2015</ReadmeURL>
+                </Result>
+                <Result state="3">
+                    <Title>Noûs (ältere Jahrgänge via JSTOR)</Title>
+                    <JournalURL>http://www.jstor.org/action/showPublication?journalCode=nous</JournalURL>
+                    <AccessURL>http://www.jstor.org/action/showPublication?journalCode=nous</AccessURL>
+                    <AccessLevel>homepage</AccessLevel>
+                    <Additionals>
+                        <Additional type="intervall">ab Vol. 1, Iss. 1 (1967)</Additional>
+                        <Additional type="moving_wall">für die Ausgaben der aktuellen 11 Jahrgänge nicht verfügbar</Additional>
+                    </Additionals>
+                    <ReadmeURL lang="de">https://www.ub.uni-leipzig.de/index.php?id=163#jstor_arts1</ReadmeURL>
+                    <ReadmeURL lang="en">http://www.ub.uni-leipzig.de/kata_db/Readme.htm#jstor_arts1</ReadmeURL>
+                </Result>
+                <Result state="3">
+                    <Title>Nous (via EBSCO Host)</Title>
+                    <JournalURL>http://search.ebscohost.com/direct.asp?db=aph&amp;jid=D97&amp;scope=site</JournalURL>
+                    <AccessURL>http://search.ebscohost.com/direct.asp?db=aph&amp;jid=D97&amp;scope=site</AccessURL>
+                    <AccessLevel>homepage</AccessLevel>
+                    <Additionals>
+                        <Additional type="moving_wall">für die Ausgaben der vergangenen 12 Monate nicht verfügbar</Additional>
+                    </Additionals>
+                    <ReadmeURL lang="de">https://www.ub.uni-leipzig.de/index.php?id=163#ebsco_aph</ReadmeURL>
+                    <ReadmeURL lang="en">http://www.ub.uni-leipzig.de/kata_db/Readme.htm#ebsco_aph</ReadmeURL>
+                </Result>
+                <Result state="3">
+                    <Title>Nous (via EBSCO Host)</Title>
+                    <JournalURL>http://search.ebscohost.com/direct.asp?db=lfh&amp;jid=D97&amp;scope=site</JournalURL>
+                    <AccessURL>http://search.ebscohost.com/direct.asp?db=lfh&amp;jid=D97&amp;scope=site</AccessURL>
+                    <AccessLevel>homepage</AccessLevel>
+                    <Additionals>
+                        <Additional type="moving_wall">für die Ausgaben der vergangenen 12 Monate nicht verfügbar</Additional>
+                    </Additionals>
+                    <ReadmeURL lang="de">https://www.ub.uni-leipzig.de/index.php?id=163#ebsco_lfh</ReadmeURL>
+                    <ReadmeURL lang="en">http://www.ub.uni-leipzig.de/kata_db/Readme.htm#ebsco_lfh</ReadmeURL>
+                </Result>
+                <Result state="3">
+                    <Title>Philosophical Perspectives (aktuelle Jahrgänge)</Title>
+                    <JournalURL>http://onlinelibrary.wiley.com/journal/10.1111/%28ISSN%291520-8583</JournalURL>
+                    <AccessURL>http://onlinelibrary.wiley.com/journal/10.1111/%28ISSN%291520-8583</AccessURL>
+                    <AccessLevel>homepage</AccessLevel>
+                    <Additionals>
+                        <Additional type="intervall">ab Vol. 17 (2003)</Additional>
+                    </Additionals>
+                    <ReadmeURL lang="de">https://www.ub.uni-leipzig.de/index.php?id=163#Wiley Core 2015</ReadmeURL>
+                    <ReadmeURL lang="en">http://www.ub.uni-leipzig.de/kata_db/Readme.htm#Wiley Core 2015</ReadmeURL>
+                </Result>
+            </ResultList>
+        </ElectronicData>
+        <PrintData>
+            <Library>Universitätsbibliothek Leipzig</Library>
+            <References>
+                <Reference>
+                    <URL>http://dispatch.opac.dnb.de/CHARSET=ISO-8859-1/DB=1.1/CMD?ACT=SRCHA&amp;IKT=8509&amp;SRT=LST_ty&amp;TRM=IDN+011960027+or+IDN+01545794X&amp;HLIB=009030085#009030085</URL>
+                    <Label>ZDB-OPAC</Label>
+                </Reference>
+            </References>
+            <ResultList>
+                <Result state="2">
+                    <Title>Philosophical perspectives</Title>
+                    <Location>Leipzig UB</Location>
+                    <Holding_comment>Nachweis als Serie</Holding_comment>
+                </Result>
+                <Result state="2">
+                    <Title>Noûs</Title>
+                    <Location>Leipzig UB // HB/FH/ Standortsignatur: 96-7-558</Location>
+                    <Signature>CA 5470 Magazin: 96-7-558</Signature>
+                    <Period>1.1967 - 27.1993; 30.1996 - 43.2009</Period>
+                    <Holding_comment>Letzten 15 Jg. Freihand</Holding_comment>
+                </Result>
+            </ResultList>
+        </PrintData>
+    </Full>
+</OpenURLResponseXML>
\ No newline at end of file
diff --git a/module/VuFind/tests/integration-tests/src/VuFindTest/Auth/ILSTest.php b/module/VuFind/tests/integration-tests/src/VuFindTest/Auth/ILSTest.php
index 5e4d8957072808656d9d5b2ec0d471f61035b8fb..4e5282a65a6a22892b0726f36d1fb32fa0245a3c 100644
--- a/module/VuFind/tests/integration-tests/src/VuFindTest/Auth/ILSTest.php
+++ b/module/VuFind/tests/integration-tests/src/VuFindTest/Auth/ILSTest.php
@@ -76,10 +76,10 @@ class ILSTest extends \VuFindTest\Unit\DbTestCase
         if (!$this->continuousIntegrationRunning()) {
             return $this->markTestSkipped('Continuous integration not running.');
         }
-        $this->driver = $this->getMock('VuFind\ILS\Driver\Sample');
+        $this->driver = $this->createMock('VuFind\ILS\Driver\Sample');
         $driverManager = new \VuFind\ILS\Driver\PluginManager();
         $driverManager->setService('Sample', $this->driver);
-        $mockConfigReader = $this->getMock('VuFind\Config\PluginManager');
+        $mockConfigReader = $this->createMock('VuFind\Config\PluginManager');
         $mockConfigReader->expects($this->any())->method('get')
             ->will($this->returnValue(new \Zend\Config\Config([])));
         $this->auth = new \VuFind\Auth\ILS(
diff --git a/module/VuFind/tests/integration-tests/src/VuFindTest/Auth/ShibbolethTest.php b/module/VuFind/tests/integration-tests/src/VuFindTest/Auth/ShibbolethTest.php
index 345128d9e06343a6190dab81ff0ca367f5941cd1..2562efd8b585dbaee6e3381b19ba256bc81df2ab 100644
--- a/module/VuFind/tests/integration-tests/src/VuFindTest/Auth/ShibbolethTest.php
+++ b/module/VuFind/tests/integration-tests/src/VuFindTest/Auth/ShibbolethTest.php
@@ -76,7 +76,10 @@ class ShibbolethTest extends \VuFindTest\Unit\DbTestCase
         if (null === $config) {
             $config = $this->getAuthConfig();
         }
-        $obj = clone($this->getAuthManager()->get('Shibboleth'));
+        $obj = new Shibboleth($this->createMock('Zend\Session\ManagerInterface'));
+        \VuFind\ServiceManager\Initializer::initInstance(
+            $obj, $this->getServiceManager()
+        );
         $obj->setConfig($config);
         return $obj;
     }
diff --git a/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/AdvancedSearchTest.php b/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/AdvancedSearchTest.php
index d1ba6ad504600a4853c7d90a1049c3c695f8ed1e..0c372fd778201c3c7c7609087c3f122257ed5e69 100644
--- a/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/AdvancedSearchTest.php
+++ b/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/AdvancedSearchTest.php
@@ -26,6 +26,7 @@
  * @link     https://vufind.org Main Page
  */
 namespace VuFindTest\Mink;
+use Behat\Mink\Element\Element;
 
 /**
  * Mink test class to test advanced search.
@@ -67,17 +68,32 @@ class AdvancedSearchTest extends \VuFindTest\Unit\MinkTestCase
     }
 
     /**
-     * Test that the home page is available.
+     * Find the "edit advanced search link" and click it.
+     *
+     * @param Element $page Page element
      *
      * @return void
      */
-    public function testBootstrapThree()
+    protected function editAdvancedSearch(Element $page)
     {
-        // Change the theme:
-        $this->changeConfigs(
-            ['config' => ['Site' => ['theme' => 'bootstrap3']]]
-        );
+        $links = $page->findAll('css', '.adv_search_links a');
+        foreach ($links as $link) {
+            if ($this->checkVisibility($link)
+                && $link->getHtml() == 'Edit this Advanced Search'
+            ) {
+                $link->click();
+                break;
+            }
+        }
+    }
 
+    /**
+     * Test that the advanced search form is operational.
+     *
+     * @return void
+     */
+    public function testAdvancedSearch()
+    {
         // Go to the advanced search page
         $session = $this->getMinkSession();
         $path = '/Search/Advanced';
@@ -94,12 +110,12 @@ class AdvancedSearchTest extends \VuFindTest\Unit\MinkTestCase
         $this->snooze();
         $this->findCss($page, '#search0_3');
         // No visible x next to lonely search term
-        $this->findCss($page, '#search1_0 .close.hidden');
+        $this->findCss($page, '#search1_0 .adv-term-remove.hidden');
         // Add a search term in another group
         $session->executeScript("addSearch(1)"); // add_search_link_1 click
         $this->findCss($page, '#search1_1');
         // Visible x next to lonely search term
-        $this->findCss($page, '#search1_0 .close:not(.hidden)');
+        $this->findCss($page, '#search1_0 .adv-term-remove:not(.hidden)');
 
         // Enter search for bride of the tomb
         $this->findCss($page, '#search_lookfor0_0')->setValue('bride');
@@ -108,32 +124,26 @@ class AdvancedSearchTest extends \VuFindTest\Unit\MinkTestCase
         $this->findCss($page, '#search_lookfor0_2')->setValue('garbage');
         $this->findCss($page, '#search_lookfor0_3')->setValue('1883');
         $this->findCss($page, '#search_type0_3')->selectOption('year');
+        $this->findCss($page, '#search_lookfor1_0')->setValue('miller');
 
         // Submit search form
         $this->findCss($page, '[type=submit]')->press();
 
         // Check for proper search
         $this->assertEquals(
-            '(All Fields:bride AND Title:tomb AND All Fields:garbage AND Year of Publication:1883)',
+            '(All Fields:bride AND Title:tomb AND All Fields:garbage AND Year of Publication:1883) AND (All Fields:miller)',
             $this->findCss($page, '.adv_search_terms strong')->getHtml()
         );
 
         // Test edit search
-        $links = $page->findAll('css', '.adv_search_links a');
-        foreach ($links as $link) {
-            if ($this->checkVisibility($link)
-                && $link->getHtml() == 'Edit this Advanced Search'
-            ) {
-                $link->click();
-                break;
-            }
-        }
+        $this->editAdvancedSearch($page);
         $this->assertEquals('bride', $this->findCss($page, '#search_lookfor0_0')->getValue());
         $this->assertEquals('tomb',  $this->findCss($page, '#search_lookfor0_1')->getValue());
         $this->assertEquals('Title', $this->findCss($page, '#search_type0_1')->getValue());
         $this->assertEquals('garbage',  $this->findCss($page, '#search_lookfor0_2')->getValue());
         $this->assertEquals('1883',  $this->findCss($page, '#search_lookfor0_3')->getValue());
         $this->assertEquals('year',  $this->findCss($page, '#search_type0_3')->getValue());
+        $this->assertEquals('miller',  $this->findCss($page, '#search_lookfor1_0')->getValue());
 
         // Term removal
         $session->executeScript("deleteSearch(0, 2)"); // search0_2 x click
@@ -141,5 +151,21 @@ class AdvancedSearchTest extends \VuFindTest\Unit\MinkTestCase
         // Terms collapsing up
         $this->assertEquals('1883', $this->findCss($page, '#search_lookfor0_2')->getValue());
         $this->assertEquals('year', $this->findCss($page, '#search_type0_2')->getValue());
+
+        // Group removal
+        $session->executeScript("deleteGroup(0)");
+
+        // Submit search form
+        $this->findCss($page, '[type=submit]')->press();
+
+        // Check for proper search (second group only)
+        $this->assertEquals(
+            '(All Fields:miller)',
+            $this->findCss($page, '.adv_search_terms strong')->getHtml()
+        );
+
+        // Test edit search (modified search is restored properly)
+        $this->editAdvancedSearch($page);
+        $this->assertEquals('miller',  $this->findCss($page, '#search_lookfor0_0')->getValue());
     }
 }
diff --git a/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/BasicTest.php b/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/BasicTest.php
index e009d10801d3425509b6f5ac72198e9c0562c9ac..51e126d7e81eac6b6b7fc3ab380f24e60d62da8b 100644
--- a/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/BasicTest.php
+++ b/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/BasicTest.php
@@ -62,7 +62,7 @@ class BasicTest extends \VuFindTest\Unit\MinkTestCase
         $session = $this->getMinkSession();
         $session->visit($this->getVuFindUrl() . '/Search/Home');
         $page = $session->getPage();
-        $this->findCss($page, '.searchForm [name="lookfor"]')
+        $this->findCss($page, '#searchForm_lookfor')
             ->setValue('id:testsample1');
         $this->findCss($page, '.btn.btn-primary')->click();
         $this->snooze();
diff --git a/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/BulkTest.php b/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/BulkTest.php
index 50c4236fe70a2a055b1be74d39ae63373f16badb..681c628859017b9c5893dba09bca283f047e1b9f 100644
--- a/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/BulkTest.php
+++ b/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/BulkTest.php
@@ -61,7 +61,10 @@ class BulkTest extends \VuFindTest\Unit\MinkTestCase
         $session = $this->getMinkSession();
         $path = '/Search/Results?lookfor=id%3A(testsample1+OR+testsample2)';
         $session->visit($this->getVuFindUrl() . $path);
-        return $session->getPage();
+        $page = $session->getPage();
+        // Hide autocomplete menu
+        $this->findCss($page, '#side-panel-format .title')->click();
+        return $page;
     }
 
     /**
@@ -192,6 +195,7 @@ class BulkTest extends \VuFindTest\Unit\MinkTestCase
 
         // Save the favorites.
         $this->findCss($page, '.modal-body input[name=submit]')->click();
+        $this->snooze();
         $result = $this->findCss($page, '.modal-body .alert-success');
         $this->assertEquals(
             'Your item(s) were saved successfully. Go to List.', $result->getText()
@@ -237,6 +241,7 @@ class BulkTest extends \VuFindTest\Unit\MinkTestCase
         // Do the export:
         $submit = $this->findCss($page, '.modal-body input[name=submit]');
         $submit->click();
+        $this->snooze();
         $result = $this->findCss($page, '.modal-body .alert .text-center .btn');
         $this->assertEquals('Download File', $result->getText());
     }
diff --git a/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/CallnumberBrowseTest.php b/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/CallnumberBrowseTest.php
index eb0e9309637673b33ea83a1dbc937c085495e82d..2b5b034b30dd66fd757e1f73a3b2ce244a739383 100644
--- a/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/CallnumberBrowseTest.php
+++ b/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/CallnumberBrowseTest.php
@@ -65,7 +65,7 @@ class CallnumberBrowseTest extends \VuFindTest\Unit\MinkTestCase
         $session = $this->getMinkSession();
         $session->visit($this->getVuFindUrl() . '/Search/Home');
         $page = $session->getPage();
-        $this->findCss($page, '.searchForm [name="lookfor"]')->setValue($query);
+        $this->findCss($page, '#searchForm_lookfor')->setValue($query);
         $this->findCss($page, '.btn.btn-primary')->click();
         $this->snooze();
         return $page;
diff --git a/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/CartTest.php b/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/CartTest.php
index eaade7d8a92f611b601b6f56100c9bb256b61ce0..399cb6c5536f77c0577ed35656b08dc7d00c325e 100644
--- a/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/CartTest.php
+++ b/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/CartTest.php
@@ -136,20 +136,39 @@ class CartTest extends \VuFindTest\Unit\MinkTestCase
     }
 
     /**
-     * Add the current page of results to the cart.
+     * Add the current page of results to the cart (using the select all bulk
+     * controls).
      *
-     * @param Element $page       Page element
-     * @param Element $updateCart Add to cart button
+     * @param Element $page        Page element
+     * @param Element $updateCart  Add to cart button
+     * @param string  $selectAllId ID of select all checkbox
      *
      * @return void
      */
-    protected function addCurrentPageToCart(Element $page, Element $updateCart)
+    protected function addCurrentPageToCart(Element $page, Element $updateCart,
+        $selectAllId = '#addFormCheckboxSelectAll'
+    )
     {
-        $selectAll = $page->find('css', '#addFormCheckboxSelectAll');
+        $selectAll = $page->find('css', $selectAllId);
         $selectAll->check();
         $updateCart->click();
     }
 
+    /**
+     * Add the current page of results to the cart (using the individual add
+     * buttons).
+     *
+     * @param Element $page        Page element
+     *
+     * @return void
+     */
+    protected function addCurrentPageToCartUsingButtons(Element $page)
+    {
+        foreach ($page->findAll('css', '.cart-add') as $button) {
+            $button->click();
+        }
+    }
+
     /**
      * Open the cart lightbox.
      *
@@ -169,21 +188,18 @@ class CartTest extends \VuFindTest\Unit\MinkTestCase
      * into the cart, then opening the lightbox so that additional actions may
      * be attempted.
      *
+     * @param array  $extraConfigs Extra config settings
+     * @param string $selectAllId  ID of select all checkbox
+     *
      * @return Element
      */
-    protected function setUpGenericCartTest($extraConfigs = [])
-    {
+    protected function setUpGenericCartTest($extraConfigs = []) {
         // Activate the cart:
         $extraConfigs['config']['Site'] = ['showBookBag' => true];
         $this->changeConfigs($extraConfigs);
 
         $page = $this->getSearchResultsPage();
-
-        // Click "add" without selecting anything.
-        $updateCart = $this->findCss($page, '#updateCart');
-
-        // Now actually select something:
-        $this->addCurrentPageToCart($page, $updateCart);
+        $this->addCurrentPageToCartUsingButtons($page);
         $this->assertEquals('2', $this->findCss($page, '#cartItems strong')->getText());
 
         // Open the cart and empty it:
@@ -263,7 +279,16 @@ class CartTest extends \VuFindTest\Unit\MinkTestCase
     public function testAddingNothing()
     {
         // Activate the cart:
-        $this->changeConfigs(['config' => ['Site' => ['showBookBag' => true]]]);
+        $this->changeConfigs(
+            [
+                'config' => [
+                    'Site' => [
+                        'showBookBag' => true,
+                        'bookbagTogglesInSearch' => false
+                    ]
+                ]
+            ]
+        );
 
         $page = $this->getSearchResultsPage();
 
@@ -281,7 +306,16 @@ class CartTest extends \VuFindTest\Unit\MinkTestCase
     public function testAddingDuplicates()
     {
          // Activate the cart:
-        $this->changeConfigs(['config' => ['Site' => ['showBookBag' => true]]]);
+        $this->changeConfigs(
+            [
+                'config' => [
+                    'Site' => [
+                        'showBookBag' => true,
+                        'bookbagTogglesInSearch' => false
+                    ]
+                ]
+            ]
+        );
 
         $page = $this->getSearchResultsPage();
 
@@ -302,7 +336,15 @@ class CartTest extends \VuFindTest\Unit\MinkTestCase
     {
          // Activate the cart:
         $this->changeConfigs(
-            ['config' => ['Site' => ['showBookBag' => true, 'bookBagMaxSize' => 1]]]
+            [
+                'config' => [
+                    'Site' => [
+                        'showBookBag' => true,
+                        'bookBagMaxSize' => 1,
+                        'bookbagTogglesInSearch' => false
+                    ]
+                ]
+            ]
         );
 
         $page = $this->getSearchResultsPage();
@@ -382,7 +424,9 @@ class CartTest extends \VuFindTest\Unit\MinkTestCase
 
         // First try deleting without selecting anything:
         $delete->click();
+        $this->snooze();
         $this->findCss($page, '#cart-confirm-delete')->click();
+        $this->snooze();
         $this->checkForNonSelectedMessage($page);
 
         // Now actually select the records to delete:
@@ -427,6 +471,33 @@ class CartTest extends \VuFindTest\Unit\MinkTestCase
         $this->assertEquals('0', $this->findCss($page, '#cartItems strong')->getText());
     }
 
+    /**
+     * Test that we can put items in the cart using the bottom checkbox/button.
+     *
+     * @return void
+     */
+    public function testFillCartUsingBottomControls()
+    {
+         // Activate the cart:
+        $this->changeConfigs(
+            [
+                'config' => [
+                    'Site' => [
+                        'showBookBag' => true,
+                        'bookbagTogglesInSearch' => false
+                    ]
+                ]
+            ]
+        );
+        $page = $this->getSearchResultsPage();
+        $this->addCurrentPageToCart(
+            $page,
+            $this->findCss($page, '#bottom_updateCart'),
+            '#bottom_addFormCheckboxSelectAll'
+        );
+        $this->assertEquals('2', $this->findCss($page, '#cartItems strong')->getText());
+    }
+
     /**
      * Test that we can put items in the cart and then remove them outside of
      * the lightbox.
@@ -469,6 +540,7 @@ class CartTest extends \VuFindTest\Unit\MinkTestCase
 
         // First try clicking without selecting anything:
         $button->click();
+        $this->snooze();
         $this->checkForNonSelectedMessage($page);
 
         // Now do it for real -- we should get a login prompt.
@@ -481,6 +553,7 @@ class CartTest extends \VuFindTest\Unit\MinkTestCase
         $this->findCss($page, '.modal-body .createAccountLink')->click();
         $this->fillInAccountForm($page);
         $this->findCss($page, '.modal-body .btn.btn-primary')->click();
+        $this->snooze();
 
         $this->findCss($page, '.modal #email_from')->setValue('asdf@asdf.com');
         $this->findCss($page, '.modal #email_message')->setValue('message');
@@ -507,6 +580,7 @@ class CartTest extends \VuFindTest\Unit\MinkTestCase
 
         // First try clicking without selecting anything:
         $button->click();
+        $this->snooze();
         $this->checkForNonSelectedMessage($page);
 
         // Now do it for real -- we should get a login prompt.
@@ -552,6 +626,7 @@ class CartTest extends \VuFindTest\Unit\MinkTestCase
 
         // First try clicking without selecting anything:
         $button->click();
+        $this->snooze();
         $this->checkForNonSelectedMessage($page);
 
         // Now do it for real -- we should get an export option list:
@@ -607,6 +682,9 @@ class CartTest extends \VuFindTest\Unit\MinkTestCase
         $submit = $this->findCss($page, '.modal-body input[name=submit]');
         $submit->click();
         $this->snooze();
+        $windows = $this->getMinkSession()->getWindowNames();
+        $this->assertEquals(2, count($windows));
+        $this->getMinkSession()->switchToWindow($windows[1]);
         $this->assertEquals(
             'https://www.google.com/', $this->getMinkSession()->getCurrentUrl()
         );
@@ -625,6 +703,7 @@ class CartTest extends \VuFindTest\Unit\MinkTestCase
 
         // First try clicking without selecting anything:
         $button->click();
+        $this->snooze();
         $this->checkForNonSelectedMessage($page);
 
         // Now do it for real -- we should get redirected.
@@ -638,6 +717,74 @@ class CartTest extends \VuFindTest\Unit\MinkTestCase
         );
     }
 
+    protected function assertVisible($combo, $elements, $name, $exp)
+    {
+        $message = $elements[$name]
+            ? $name . " should be hidden.\n" . print_r($combo, true)
+            : $name . " should be visible.\n" . print_r($combo, true);
+        $this->assertEquals($elements[$name], $exp, $message);
+    }
+
+    protected function runConfigCombo($page, $combo)
+    {
+        $this->changeConfigs(['config' => ['Site' => $combo]]);
+        $this->getMinkSession()->reload();
+        $this->snooze();
+        $elements = [
+            'headerBtn'  => $page->find('css', '#cartItems') !== null,
+            'bulkEmail'  => $page->find('css', '#ribbon-email') !== null,
+            'bulkUpdateCart' => $page->find('css', '#updateCart') !== null,
+            'resultCartBtns'   => $page->find('css', '.result .btn-bookbag-toggle') !== null,
+            'resultCheckbox'   => $page->find('css', '.result .checkbox-select-item') !== null,
+        ];
+        // Expected
+        $this->assertVisible($combo, $elements, 'headerBtn', $combo['showBookBag']);
+        $this->assertVisible($combo, $elements, 'bulkEmail', $combo['showBulkOptions'], $combo);
+        $this->assertVisible($combo, $elements, 'bulkUpdateCart', $combo['showBookBag'] && ($combo['showBulkOptions'] || !$combo['bookbagTogglesInSearch']));
+        $this->assertVisible($combo, $elements, 'resultCartBtns', $combo['showBookBag'] && $combo['bookbagTogglesInSearch']);
+        $this->assertVisible($combo, $elements, 'resultCheckbox', $elements['bulkEmail'] || $elements['bulkUpdateCart']);
+        return $elements;
+    }
+
+    public function testToolbarVisibilityConfigCombinations() {
+        $page = $this->getSearchResultsPage();
+        $elements = $this->runConfigCombo($page, [
+            'showBookBag' => true,
+            'showBulkOptions' => false,
+            'bookbagTogglesInSearch' => false,
+        ]);
+        $elements = $this->runConfigCombo($page, [
+            'showBookBag' => false,
+            'showBulkOptions' => false,
+            'bookbagTogglesInSearch' => true,
+        ]);
+        $elements = $this->runConfigCombo($page, [
+            'showBookBag' => false,
+            'showBulkOptions' => true,
+            'bookbagTogglesInSearch' => false,
+        ]);
+        $elements = $this->runConfigCombo($page, [
+            'showBookBag' => true,
+            'showBulkOptions' => false,
+            'bookbagTogglesInSearch' => true,
+        ]);
+        $elements = $this->runConfigCombo($page, [
+            'showBookBag' => true,
+            'showBulkOptions' => true,
+            'bookbagTogglesInSearch' => false,
+        ]);
+        $elements = $this->runConfigCombo($page, [
+            'showBookBag' => false,
+            'showBulkOptions' => true,
+            'bookbagTogglesInSearch' => true,
+        ]);
+        $elements = $this->runConfigCombo($page, [
+            'showBookBag' => true,
+            'showBulkOptions' => true,
+            'bookbagTogglesInSearch' => true,
+        ]);
+    }
+
     /**
      * Standard teardown method.
      *
diff --git a/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/ChannelsTest.php b/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/ChannelsTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..7e2c480d23c41251145f0f722b9285e4ede951aa
--- /dev/null
+++ b/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/ChannelsTest.php
@@ -0,0 +1,111 @@
+<?php
+/**
+ * Mink cart test class.
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2011.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * @category VuFind
+ * @package  Tests
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org Main Page
+ */
+namespace VuFindTest\Mink;
+use Behat\Mink\Element\Element;
+
+/**
+ * Mink cart test class.
+ *
+ * @category VuFind
+ * @package  Tests
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org Main Page
+ */
+class ChannelsTest extends \VuFindTest\Unit\MinkTestCase
+{
+    /**
+     * Get a reference to a standard search results page.
+     *
+     * @return Element
+     */
+    protected function getChannelsPage()
+    {
+        $session = $this->getMinkSession();
+        $path = '/Channels/Search?lookfor=building%3A%22weird_ids.mrc%22';
+        $session->visit($this->getVuFindUrl() . $path);
+        return $session->getPage();
+    }
+
+    /**
+     * Make sure the page works, channels exists, search
+     */
+    public function testBasic()
+    {
+        $page = $this->getChannelsPage();
+        // Channels are here
+        $this->findCss($page, 'div.channel');
+        // Check number of channels
+        $channels = $page->findAll('css', 'div.channel');
+        $this->assertEquals(6, count($channels));
+        // Make sure search input matches url
+        $this->assertEquals(
+            'building:"weird_ids.mrc"',
+            $this->findCss($page, '[action*="Channels/Search"] .form-control')->getValue()
+        );
+    }
+
+    /**
+     * Add channels button
+     */
+    public function testAddChannels()
+    {
+        $page = $this->getChannelsPage();
+        $channel = $this->findCss($page, 'div.channel');
+        // Initial counts
+        $this->assertEquals(6, count($page->findAll('css', 'div.channel')));
+        $this->assertEquals(8, count($channel->findAll('css', '.channel-add-menu .dropdown-menu li')));
+        // Click first add button
+        $this->findCss($channel, '.add-btn')->click();
+        $this->snooze();
+        // Post count
+        $this->assertEquals(8, count($page->findAll('css', 'div.channel')));
+        $this->assertEquals(6, count($channel->findAll('css', '.channel-add-menu .dropdown-menu li')));
+    }
+
+    /**
+     * Switch to search
+     */
+    public function testSwitchToSearch()
+    {
+        $page = $this->getChannelsPage();
+        $channel = $this->findCss($page, 'div.channel');
+        // Click link to go to search results
+        $this->findCss($channel, '.channel_search')->click();
+        // Make sure the search translated
+        $this->assertEquals(
+            'building:"weird_ids.mrc"',
+            $this->findCss($page, '#searchForm_lookfor')->getValue()
+        );
+        // Check facet
+        $this->assertEquals(
+            'Suggested Topics: Adult children of aging parents',
+            $this->findCss($page, '.active-filters .facet')->getText()
+        );
+    }
+}
diff --git a/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/CombinedSearchTest.php b/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/CombinedSearchTest.php
index f217ff5176c6c3b21424078b38c51b71a75528b1..88ae8326ad87e03d48b1ed330f2a44dfddd74a6c 100644
--- a/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/CombinedSearchTest.php
+++ b/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/CombinedSearchTest.php
@@ -104,7 +104,7 @@ class CombinedSearchTest extends \VuFindTest\Unit\MinkTestCase
         $session = $this->getMinkSession();
         $session->visit($this->getVuFindUrl() . '/Combined');
         $page = $session->getPage();
-        $this->findCss($page, '.searchForm [name="lookfor"]')
+        $this->findCss($page, '#searchForm_lookfor')
             ->setValue('id:"testsample1" OR id:"theplus+andtheminus-"');
         $this->findCss($page, '.btn.btn-primary')->click();
         $this->snooze();
@@ -127,7 +127,7 @@ class CombinedSearchTest extends \VuFindTest\Unit\MinkTestCase
         $session = $this->getMinkSession();
         $session->visit($this->getVuFindUrl() . '/Combined');
         $page = $session->getPage();
-        $this->findCss($page, '.searchForm [name="lookfor"]')
+        $this->findCss($page, '#searchForm_lookfor')
             ->setValue('id:"testsample1" OR id:"theplus+andtheminus-"');
         $this->findCss($page, '.btn.btn-primary')->click();
         $this->snooze();
@@ -149,7 +149,7 @@ class CombinedSearchTest extends \VuFindTest\Unit\MinkTestCase
         $session = $this->getMinkSession();
         $session->visit($this->getVuFindUrl() . '/Combined');
         $page = $session->getPage();
-        $this->findCss($page, '.searchForm [name="lookfor"]')
+        $this->findCss($page, '#searchForm_lookfor')
             ->setValue('id:"testsample1" OR id:"theplus+andtheminus-"');
         $this->findCss($page, '.btn.btn-primary')->click();
         $this->snooze();
diff --git a/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/FavoritesTest.php b/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/FavoritesTest.php
index a404209b31e32639816487579992a023e0ecc6df..817b9c454349174d7cdd706cc3679bce6ae401e4 100644
--- a/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/FavoritesTest.php
+++ b/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/FavoritesTest.php
@@ -74,7 +74,7 @@ class FavoritesTest extends \VuFindTest\Unit\MinkTestCase
         $session = $this->getMinkSession();
         $session->visit($this->getVuFindUrl() . '/Search/Home');
         $page = $session->getPage();
-        $this->findCss($page, '.searchForm [name="lookfor"]')->setValue('Dewey');
+        $this->findCss($page, '#searchForm_lookfor')->setValue('Dewey');
         $this->findCss($page, '.btn.btn-primary')->click();
         return $page;
     }
@@ -113,11 +113,6 @@ class FavoritesTest extends \VuFindTest\Unit\MinkTestCase
      */
     public function testAddRecordToFavoritesNewAccount()
     {
-        // Change the theme:
-        $this->changeConfigs(
-            ['config' => ['Site' => ['theme' => 'bootstrap3']]]
-        );
-
         $page = $this->gotoRecord();
 
         $this->findCss($page, '.save-record')->click();
@@ -170,11 +165,6 @@ class FavoritesTest extends \VuFindTest\Unit\MinkTestCase
      */
     public function testAddRecordToFavoritesLogin()
     {
-        // Change the theme:
-        $this->changeConfigs(
-            ['config' => ['Site' => ['theme' => 'bootstrap3']]]
-        );
-
         $page = $this->gotoRecord();
 
         $this->findCss($page, '.save-record')->click();
@@ -196,6 +186,7 @@ class FavoritesTest extends \VuFindTest\Unit\MinkTestCase
         $this->findCss($page, '#make-list')->click();
         $this->findCss($page, '#list_title')->setValue('Future List');
         $this->findCss($page, '.modal-body .btn.btn-primary')->click();
+        $this->snooze();
         $this->assertEquals(
             $this->findCss($page, '#save_list option[selected]')->getHtml(),
             'Future List'
@@ -221,11 +212,6 @@ class FavoritesTest extends \VuFindTest\Unit\MinkTestCase
      */
     public function testAddRecordToFavoritesLoggedIn()
     {
-        // Change the theme:
-        $this->changeConfigs(
-            ['config' => ['Site' => ['theme' => 'bootstrap3']]]
-        );
-
         $page = $this->gotoRecord();
         // Login
         $this->findCss($page, '#loginOptions a')->click();
@@ -250,11 +236,6 @@ class FavoritesTest extends \VuFindTest\Unit\MinkTestCase
      */
     public function testAddSearchItemToFavoritesNewAccount()
     {
-        // Change the theme:
-        $this->changeConfigs(
-            ['config' => ['Site' => ['theme' => 'bootstrap3']]]
-        );
-
         $page = $this->gotoSearch();
 
         $this->findCss($page, '.save-record')->click();
@@ -276,6 +257,7 @@ class FavoritesTest extends \VuFindTest\Unit\MinkTestCase
             $page, ['username' => 'username2', 'email' => 'username2@ignore.com']
         );
         $this->findCss($page, '.modal-body .btn.btn-primary')->click();
+        $this->snooze();
         $this->findCss($page, '#save_list');
         // Make list
         $this->findCss($page, '#make-list')->click();
@@ -317,14 +299,10 @@ class FavoritesTest extends \VuFindTest\Unit\MinkTestCase
      */
     public function testAddSearchItemToFavoritesLogin()
     {
-        // Change the theme:
-        $this->changeConfigs(
-            ['config' => ['Site' => ['theme' => 'bootstrap3']]]
-        );
-
         $page = $this->gotoSearch();
 
         $this->findCss($page, '.save-record')->click();
+        $this->snooze();
         // Login
         // - empty
         $this->submitLoginForm($page);
@@ -338,21 +316,26 @@ class FavoritesTest extends \VuFindTest\Unit\MinkTestCase
         // Make Two Lists
         // - One for the next test
         $this->findCss($page, '#make-list')->click();
+        $this->snooze();
         $this->findCss($page, '#list_title')->setValue('Future List');
         $this->findCss($page, '.modal-body .btn.btn-primary')->click();
+        $this->snooze();
         $this->assertEquals(
             $this->findCss($page, '#save_list option[selected]')->getHtml(),
             'Future List'
         );
         // - One for now
         $this->findCss($page, '#make-list')->click();
+        $this->snooze();
         $this->findCss($page, '#list_title')->setValue('Login Test List');
         $this->findCss($page, '.modal-body .btn.btn-primary')->click();
+        $this->snooze();
         $this->assertEquals(
             $this->findCss($page, '#save_list option[selected]')->getHtml(),
             'Login Test List'
         );
         $this->findCss($page, '.modal-body .btn.btn-primary')->click();
+        $this->snooze();
         $this->findCss($page, '.alert.alert-success');
     }
 
@@ -364,17 +347,14 @@ class FavoritesTest extends \VuFindTest\Unit\MinkTestCase
      */
     public function testAddSearchItemToFavoritesLoggedIn()
     {
-        // Change the theme:
-        $this->changeConfigs(
-            ['config' => ['Site' => ['theme' => 'bootstrap3']]]
-        );
-
         $page = $this->gotoSearch();
         // Login
         $this->findCss($page, '#loginOptions a')->click();
         $this->snooze();
         $this->fillInLoginForm($page, 'username2', 'test');
         $this->submitLoginForm($page);
+        // Count lists
+        $listCount = count($page->findAll('css', '.savedLists a'));
         // Save Record
         $this->findCss($page, '.save-record')->click();
         $this->snooze();
@@ -382,6 +362,11 @@ class FavoritesTest extends \VuFindTest\Unit\MinkTestCase
         $this->findCss($page, '.modal-body .btn.btn-primary')->click();
         $this->snooze();
         $this->findCss($page, '.alert.alert-success');
+        // Test save status update on modal close
+        $this->findCss($page, '.modal-body .btn.btn-default')->click();
+        $this->snooze();
+        $savedLists = $page->findAll('css', '.savedLists a');
+        $this->assertEquals($listCount + 1, count($savedLists));
     }
 
     /**
@@ -503,6 +488,7 @@ class FavoritesTest extends \VuFindTest\Unit\MinkTestCase
         // Do the export:
         $submit = $this->findCss($page, '.modal-body input[name=submit]');
         $submit->click();
+        $this->snooze();
         $result = $this->findCss($page, '.modal-body .alert .text-center .btn');
         $this->assertEquals('Download File', $result->getText());
     }
diff --git a/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/IlsActionsTest.php b/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/IlsActionsTest.php
index bbc92f31e0d19531da08beeb5c7541cb93777bc9..e130ac88c5ebef437364775ae66492178e6ef0f4 100644
--- a/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/IlsActionsTest.php
+++ b/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/IlsActionsTest.php
@@ -127,15 +127,14 @@ class IlsActionsTest extends \VuFindTest\Unit\MinkTestCase
                 'cancelHolds' => 0,
                 'cancelILLRequests' => 0,
                 'cancelStorageRetrievalRequests' => 0,
-                'checkILLRequestBlock' => 0,
                 'checkILLRequestIsValid' => 0,
                 'checkRenewBlock' => 0,
-                'checkRequestBlock' => 0,
                 'checkRequestIsValid' => 0,
-                'checkStorageRetrievalRequestBlock' => 0,
                 'checkStorageRetrievalRequestIsValid' => 0,
+                'getAccountBlocks' => 0,
                 'getDefaultRequestGroup' => 0,
                 'getHoldDefaultRequiredDate' => 0,
+                'getRequestBlocks' => 0,
                 'placeHold' => 0,
                 'placeILLRequest' => 0,
                 'placeStorageRetrievalRequest' => 0,
@@ -300,7 +299,7 @@ class IlsActionsTest extends \VuFindTest\Unit\MinkTestCase
         );
         $page = $this->gotoRecordById();
         $element = $this->findCss($page, '.alert.alert-info a');
-        $this->assertEquals('Login', $element->getText());
+        $this->assertEquals('Login for hold and recall information', $element->getText());
         $element->click();
         $this->snooze();
         $this->findCss($page, '.createAccountLink')->click();
@@ -369,7 +368,7 @@ class IlsActionsTest extends \VuFindTest\Unit\MinkTestCase
         // Log in the user on the record page:
         $page = $this->gotoRecordById();
         $element = $this->findCss($page, '.alert.alert-info a');
-        $this->assertEquals('Login', $element->getText());
+        $this->assertEquals('Login for hold and recall information', $element->getText());
         $element->click();
         $this->snooze();
         $this->fillInLoginForm($page, 'username1', 'test', false);
@@ -434,7 +433,7 @@ class IlsActionsTest extends \VuFindTest\Unit\MinkTestCase
         // Log in the user on the record page:
         $page = $this->gotoRecordById();
         $element = $this->findCss($page, '.alert.alert-info a');
-        $this->assertEquals('Login', $element->getText());
+        $this->assertEquals('Login for hold and recall information', $element->getText());
         $element->click();
         $this->snooze();
         $this->fillInLoginForm($page, 'username1', 'test', false);
@@ -470,7 +469,7 @@ class IlsActionsTest extends \VuFindTest\Unit\MinkTestCase
         // Log in the user on the record page:
         $page = $this->gotoRecordById();
         $element = $this->findCss($page, '.alert.alert-info a');
-        $this->assertEquals('Login', $element->getText());
+        $this->assertEquals('Login for hold and recall information', $element->getText());
         $element->click();
         $this->snooze();
         $this->fillInLoginForm($page, 'username1', 'test', false);
diff --git a/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/LinkResolverTest.php b/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/LinkResolverTest.php
index 7d565501f5b6e3169a613946327b31be28553899..148013219e9e97692a5273e67ac573ff19d435d1 100644
--- a/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/LinkResolverTest.php
+++ b/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/LinkResolverTest.php
@@ -154,7 +154,7 @@ class LinkResolverTest extends \VuFindTest\Unit\MinkTestCase
         $session = $this->getMinkSession();
         $session->visit($this->getVuFindUrl() . '/Search/Home');
         $page = $session->getPage();
-        $this->findCss($page, '.searchForm [name="lookfor"]')
+        $this->findCss($page, '#searchForm_lookfor')
             ->setValue('id:testsample1');
         $this->findCss($page, '.btn.btn-primary')->click();
 
@@ -182,7 +182,7 @@ class LinkResolverTest extends \VuFindTest\Unit\MinkTestCase
         $session = $this->getMinkSession();
         $session->visit($this->getVuFindUrl() . '/Search/Home');
         $page = $session->getPage();
-        $this->findCss($page, '.searchForm [name="lookfor"]')
+        $this->findCss($page, '#searchForm_lookfor')
             ->setValue('id:testsample1');
         $this->findCss($page, '.btn.btn-primary')->click();
 
diff --git a/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/ListViewsTest.php b/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/ListViewsTest.php
index 69fbd8a79ab22ecd9944a19419fe10f00d4c2b1c..d3aced1cff5ba9ac03396ef4525f7fa0ac822c14 100644
--- a/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/ListViewsTest.php
+++ b/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/ListViewsTest.php
@@ -74,7 +74,7 @@ class ListViewsTest extends \VuFindTest\Unit\MinkTestCase
         $session = $this->getMinkSession();
         $session->visit($this->getVuFindUrl() . '/Search/Home');
         $page = $session->getPage();
-        $this->findCss($page, '.searchForm [name="lookfor"]')
+        $this->findCss($page, '#searchForm_lookfor')
             ->setValue('id:testdeweybrowse');
         $this->findCss($page, '.btn.btn-primary')->click();
         $this->snooze();
@@ -192,7 +192,7 @@ class ListViewsTest extends \VuFindTest\Unit\MinkTestCase
         // Search for anything else
         $session->visit($this->getVuFindUrl() . '/Search/Home');
         $page = $session->getPage();
-        $this->findCss($page, '.searchForm [name="lookfor"]')
+        $this->findCss($page, '#searchForm_lookfor')
             ->setValue('anything else');
         $this->findCss($page, '.btn.btn-primary')->click();
         // Come back
diff --git a/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/RecordActionsTest.php b/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/RecordActionsTest.php
index 708d57f8bbcc6bce2fadfaf1d59c06f1d133f873..35a0ba129601c166c9fe6c68d9ea6abaf99cdba0 100644
--- a/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/RecordActionsTest.php
+++ b/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/RecordActionsTest.php
@@ -73,7 +73,7 @@ class RecordActionsTest extends \VuFindTest\Unit\MinkTestCase
         $session = $this->getMinkSession();
         $session->visit($this->getVuFindUrl() . '/Search/Home');
         $page = $session->getPage();
-        $this->findCss($page, '.searchForm [name="lookfor"]')->setValue('Dewey');
+        $this->findCss($page, '#searchForm_lookfor')->setValue('Dewey');
         $this->findCss($page, '.btn.btn-primary')->click();
         $this->findCss($page, '.result a.title')->click();
         return $page;
@@ -102,11 +102,6 @@ class RecordActionsTest extends \VuFindTest\Unit\MinkTestCase
      */
     public function testAddComment()
     {
-        // Change the theme:
-        $this->changeConfigs(
-            ['config' => ['Site' => ['theme' => 'bootstrap3']]]
-        );
-
         // Go to a record view
         $page = $this->gotoRecord();
         // Click add comment without logging in
@@ -132,15 +127,15 @@ class RecordActionsTest extends \VuFindTest\Unit\MinkTestCase
         );
         // "Add" empty comment
         $this->findCss($page, 'form.comment-form .btn-primary')->click();
-        $this->assertNull($page->find('css', '.comment.row'));
+        $this->assertNull($page->find('css', '.comment'));
         // Add comment
         $this->findCss($page, 'form.comment-form [name="comment"]')->setValue('one');
         $this->findCss($page, 'form.comment-form .btn-primary')->click();
-        $this->findCss($page, '.comment.row');
+        $this->findCss($page, '.comment');
         // Remove comment
-        $this->findCss($page, '.comment.row .delete')->click();
+        $this->findCss($page, '.comment .delete')->click();
         $this->snooze(); // wait for UI update
-        $this->assertNull($page->find('css', '.comment.row'));
+        $this->assertNull($page->find('css', '.comment'));
         // Logout
         $this->findCss($page, '.logoutOptions a.logout')->click();
     }
@@ -152,11 +147,6 @@ class RecordActionsTest extends \VuFindTest\Unit\MinkTestCase
      */
     public function testAddTag()
     {
-        // Change the theme:
-        $this->changeConfigs(
-            ['config' => ['Site' => ['theme' => 'bootstrap3']]]
-        );
-
         // Go to a record view
         $page = $this->gotoRecord();
         // Click to add tag
@@ -249,11 +239,10 @@ class RecordActionsTest extends \VuFindTest\Unit\MinkTestCase
      */
     public function testAddSensitiveTag()
     {
-        // Change the theme:
+        // Set up configs:
         $this->changeConfigs(
             [
                 'config' => [
-                    'Site' => ['theme' => 'bootstrap3'],
                     'Social' => ['case_sensitive_tags' => 'true']
                 ]
             ]
@@ -284,11 +273,10 @@ class RecordActionsTest extends \VuFindTest\Unit\MinkTestCase
      */
     public function testEmail()
     {
-        // Change the theme:
+        // Set up configs:
         $this->changeConfigs(
             [
                 'config' => [
-                    'Site' => ['theme' => 'bootstrap3'],
                     'Mail' => ['testOnly' => 1],
                 ]
             ]
@@ -357,11 +345,10 @@ class RecordActionsTest extends \VuFindTest\Unit\MinkTestCase
      */
     public function testSMS()
     {
-        // Change the theme:
+        // Set up configs:
         $this->changeConfigs(
             [
                 'config' => [
-                    'Site' => ['theme' => 'bootstrap3'],
                     'Mail' => ['testOnly' => 1],
                 ]
             ]
diff --git a/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/SearchActionsTest.php b/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/SearchActionsTest.php
index 9985a75807e38bbba0d3b5158045c019151382c5..cde2a41b136b1b3b099915eabb4fcbd5bee5b873 100644
--- a/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/SearchActionsTest.php
+++ b/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/SearchActionsTest.php
@@ -75,7 +75,7 @@ class SearchActionsTest extends \VuFindTest\Unit\MinkTestCase
         $session = $this->getMinkSession();
         $session->visit($this->getVuFindUrl() . '/Search/Home');
         $page = $session->getPage();
-        $this->findCss($page, '.searchForm [name="lookfor"]')->setValue($query);
+        $this->findCss($page, '#searchForm_lookfor')->setValue($query);
         $this->findCss($page, '.btn.btn-primary')->click();
         $this->snooze();
         return $page;
@@ -356,7 +356,7 @@ class SearchActionsTest extends \VuFindTest\Unit\MinkTestCase
         $genreMore = $this->findCss($page, '#more-narrowGroupHidden-genre_facet');
         $genreMore->click();
         $this->facetListProcedure($page, $limit, true);
-        $this->assertEquals(1, count($page->find('css', '.list-group.filters')));
+        $this->assertEquals(1, count($page->find('css', '.active-filters')));
     }
 
     /**
@@ -374,7 +374,7 @@ class SearchActionsTest extends \VuFindTest\Unit\MinkTestCase
         $this->findCss($page, '#j1_1.jstree-open .jstree-icon');
         $this->findCss($page, '#j1_2 a')->click();
         $this->snooze();
-        $filter = $this->findCss($page, '.filters .list-group-item.active');
+        $filter = $this->findCss($page, '.active-filters .facet');
         $this->assertEquals('hierarchy: 1/level1a/level2a/', $filter->getText());
         $this->findCss($page, '#j1_2 .fa-check');
     }
diff --git a/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/VisualizationTest.php b/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/VisualizationTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..2a725a1fa2d4f4a892129904d8b2b0f02fcb8a26
--- /dev/null
+++ b/module/VuFind/tests/integration-tests/src/VuFindTest/Mink/VisualizationTest.php
@@ -0,0 +1,70 @@
+<?php
+/**
+ * Mink test class for visualization view.
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2017.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * @category VuFind
+ * @package  Tests
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org Main Page
+ */
+namespace VuFindTest\Mink;
+
+/**
+ * Mink test class for visualization view.
+ *
+ * @category VuFind
+ * @package  Tests
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org Main Page
+ */
+class VisualizationTest extends \VuFindTest\Unit\MinkTestCase
+{
+    /**
+     * Test that combined results work in mixed AJAX/non-AJAX mode.
+     *
+     * @return void
+     */
+    public function testVisualization()
+    {
+        $this->changeConfigs(
+            [
+                'searches' => [
+                    'General' => [
+                        'default_top_recommend' => ['VisualFacets'],
+                    ],
+                    'Views' => ['list' => 'List', 'visual' => 'Visual'],
+                ]
+            ]
+        );
+        $session = $this->getMinkSession();
+        $session->visit(
+            $this->getVuFindUrl()
+            . '/Search/Results?filter[]=building%3A"journals.mrc"&view=visual'
+        );
+        $page = $session->getPage();
+        $this->snooze();
+        $text = $this->findCss($page, '#visualResults')->getText();
+        // Confirm that some content has been dynamically loaded into the
+        // visualization area:
+        $this->assertContains('A - General Works', $text);
+    }
+}
diff --git a/module/VuFind/tests/integration-tests/src/VuFindTest/View/Helper/Root/ResultFeedTest.php b/module/VuFind/tests/integration-tests/src/VuFindTest/View/Helper/Root/ResultFeedTest.php
index f8b754ead542a9c915e015a9a127f9ba0ccce492..5d581bdeca4c214e4741073c8aca4fdc670c0f46 100644
--- a/module/VuFind/tests/integration-tests/src/VuFindTest/View/Helper/Root/ResultFeedTest.php
+++ b/module/VuFind/tests/integration-tests/src/VuFindTest/View/Helper/Root/ResultFeedTest.php
@@ -59,22 +59,23 @@ class ResultFeedTest extends \VuFindTest\Unit\ViewHelperTestCase
      */
     protected function getPlugins()
     {
-        $currentPath = $this->getMock('VuFind\View\Helper\Root\CurrentPath');
+        $currentPath = $this->createMock('VuFind\View\Helper\Root\CurrentPath');
         $currentPath->expects($this->any())->method('__invoke')
             ->will($this->returnValue('/test/path'));
 
-        $recordLink = $this->getMock(
-            'VuFind\View\Helper\Root\RecordLink', [],
-            [new \VuFind\Record\Router(
-                $this->getServiceManager()->get('VuFind\RecordLoader'),
-                new \Zend\Config\Config([])
-            )
-            ]
-        );
+        $recordLink = $this->getMockBuilder('VuFind\View\Helper\Root\RecordLink')
+            ->setConstructorArgs(
+                [
+                    new \VuFind\Record\Router(
+                        $this->getServiceManager()->get('VuFind\RecordLoader'),
+                        new \Zend\Config\Config([])
+                    )
+                ]
+            )->getMock();
         $recordLink->expects($this->any())->method('getUrl')
             ->will($this->returnValue('test/url'));
 
-        $serverUrl = $this->getMock('Zend\View\Helper\ServerUrl');
+        $serverUrl = $this->createMock('Zend\View\Helper\ServerUrl');
         $serverUrl->expects($this->any())->method('__invoke')
             ->will($this->returnValue('http://server/url'));
 
@@ -85,6 +86,21 @@ class ResultFeedTest extends \VuFindTest\Unit\ViewHelperTestCase
         ];
     }
 
+    /**
+     * Mock out the translator.
+     *
+     * @return \Zend\I18n\Translator\TranslatorInterface
+     */
+    protected function getMockTranslator()
+    {
+        $mock = $this->getMockBuilder('Zend\I18n\Translator\TranslatorInterface')
+            ->getMock();
+        $mock->expects($this->at(1))->method('translate')
+            ->with($this->equalTo('showing_results_of_html'), $this->equalTo('default'))
+            ->will($this->returnValue('Showing <strong>%%start%% - %%end%%</strong> results of <strong>%%total%%</strong>'));
+        return $mock;
+    }
+
     /**
      * Test feed generation
      *
@@ -106,6 +122,7 @@ class ResultFeedTest extends \VuFindTest\Unit\ViewHelperTestCase
         $results->getParams()->initFromRequest($request);
 
         $helper = new ResultFeed();
+        $helper->setTranslator($this->getMockTranslator());
         $helper->setView($this->getPhpRenderer($this->getPlugins()));
         $feed = $helper->__invoke($results, '/test/path');
         $this->assertTrue(is_object($feed));
@@ -120,7 +137,7 @@ class ResultFeedTest extends \VuFindTest\Unit\ViewHelperTestCase
         // Now re-parse it and check for some expected values:
         $parsedFeed = \Zend\Feed\Reader\Reader::importString($rss);
         $this->assertEquals(
-            'Showing 1-2 of 2', $parsedFeed->getDescription()
+            'Showing 1 - 2 results of 2', $parsedFeed->getDescription()
         );
         $items = [];
         $i = 0;
diff --git a/module/VuFind/tests/phpunit.xml b/module/VuFind/tests/phpunit.xml
index 4bd62bcdb5cc1d5fcda988ae1e7ff9e5b84d7ba6..3df142c2ff2cda726a2e8ea6e32ada767bb5cd6e 100644
--- a/module/VuFind/tests/phpunit.xml
+++ b/module/VuFind/tests/phpunit.xml
@@ -12,9 +12,9 @@
     <whitelist addUncoveredFilesFromWhitelist="true">
       <directory suffix=".php">../src/VuFind</directory>
       <directory suffix=".php">../../VuFindAdmin/src</directory>
+      <directory suffix=".php">../../VuFindApi/src</directory>
       <directory suffix=".php">../../VuFindConsole/src</directory>
       <directory suffix=".php">../../VuFindDevTools/src</directory>
-      <directory suffix=".php">../../VuFindHttp/src</directory>
       <directory suffix=".php">../../VuFindSearch/src</directory>
       <directory suffix=".php">../../VuFindTheme/src</directory>
     </whitelist>
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/Auth/DatabaseUnitTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/Auth/DatabaseUnitTest.php
index 8f85a97d747d9f271f8d26164f3a087a1aae65c8..faaad67f294b3dfdc30648df9bff77df0ad1c545 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/Auth/DatabaseUnitTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/Auth/DatabaseUnitTest.php
@@ -232,8 +232,8 @@ class DatabaseUnitTest extends \VuFindTest\Unit\DbTestCase
     protected function getRequest($post = [])
     {
         $post = new Parameters($post);
-        $request
-            = $this->getMock('Zend\Http\PhpEnvironment\Request', ['getPost']);
+        $request = $this->getMockBuilder('Zend\Http\PhpEnvironment\Request')
+            ->setMethods(['getPost'])->getMock();
         $request->expects($this->any())->method('getPost')
             ->will($this->returnValue($post));
         return $request;
@@ -248,8 +248,8 @@ class DatabaseUnitTest extends \VuFindTest\Unit\DbTestCase
      */
     protected function getDatabase($table)
     {
-        $tableManager
-            = $this->getMock('VuFind\Db\Table\PluginManager', ['get']);
+        $tableManager = $this->getMockBuilder('VuFind\Db\Table\PluginManager')
+            ->setMethods(['get'])->getMock();
         $tableManager->expects($this->once())->method('get')
             ->with($this->equalTo('User'))
             ->will($this->returnValue($table));
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/Autocomplete/TagTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/Autocomplete/TagTest.php
index 17cd49b6f5ea05456879789038c5d4977944c408..0ba75894d6bab0eae4ea21cc370f3faed62a59a7 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/Autocomplete/TagTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/Autocomplete/TagTest.php
@@ -67,12 +67,13 @@ class TagTest extends \VuFindTest\Unit\DbTestCase
         ];
 
         // Fake services:
-        $tagTable = $this->getMock('VuFind\Db\Table\Tags', ['matchText']);
+        $tagTable = $this->getMockBuilder('VuFind\Db\Table\Tags')
+            ->disableOriginalConstructor()->setMethods(['matchText'])->getMock();
         $tagTable->expects($this->once())->method('matchText')
             ->with($this->equalTo('foo'))
             ->will($this->returnValue($tags));
-        $tableManager
-            = $this->getMock('VuFind\Db\Table\PluginManager', ['get']);
+        $tableManager = $this->getMockBuilder('VuFind\Db\Table\PluginManager')
+            ->setMethods(['get'])->getMock();
         $tableManager->expects($this->once())->method('get')
             ->with($this->equalTo('Tags'))
             ->will($this->returnValue($tagTable));
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/CartTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/CartTest.php
index 87473d3225077560621b9bab335f77c979ca9cdb..cbfc99e7775fbd1e4205062407b0e52355445868 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/CartTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/CartTest.php
@@ -53,13 +53,12 @@ class CartTest extends \PHPUnit_Framework_TestCase
      */
     public function setUp()
     {
-        $this->loader = $this->getMock(
-            'VuFind\Record\Loader', [],
-            [
-                $this->getMock('VuFindSearch\Service'),
-                $this->getMock('VuFind\RecordDriver\PluginManager')
-            ]
-        );
+        $this->loader = $this->getMockBuilder('VuFind\Record\Loader')
+            ->setMethods([])
+            ->setConstructorArgs([
+                $this->createMock('VuFindSearch\Service'),
+                $this->createMock('VuFind\RecordDriver\PluginManager')
+            ])->getMock();
     }
 
     /**
@@ -75,10 +74,10 @@ class CartTest extends \PHPUnit_Framework_TestCase
     protected function getMockCookieManager($cookies = [], $path = '/',
         $domain = null, $secure = false
     ) {
-        return $this->getMock(
-            'VuFind\Cookie\CookieManager', ['set'],
-            [$cookies, $path, $domain, $secure]
-        );
+        return $this->getMockBuilder('VuFind\Cookie\CookieManager')
+            ->setMethods(['set'])
+            ->setConstructorArgs([$cookies, $path, $domain, $secure])
+            ->getMock();
     }
 
     /**
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/Config/PluginFactoryTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/Config/PluginFactoryTest.php
index 1e1d4b742f16d0bab7df88084252edc8bc12a781..9d4c6b1650b62c1135757b13b66004371bef4d25 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/Config/PluginFactoryTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/Config/PluginFactoryTest.php
@@ -75,20 +75,36 @@ class PluginFactoryTest extends \VuFindTest\Unit\TestCase
             . "[Section2]\n"
             . "d=4\ne=5\nf=6\n"
             . "[Section3]\n"
-            . "g=7\nh=8\ni=9\n";
+            . "g=7\nh=8\ni=9\n"
+            . "[Section4]\n"
+            . "j[] = 1\nj[] = 2\nk[a] = 1\nk[b] = 2\n";
         $childPath = Locator::getLocalConfigPath('unit-test-child.ini', null, true);
         $child = "[Section1]\n"
             . "j=10\nk=11\nl=12\n"
             . "[Section2]\n"
             . "m=13\nn=14\no=15\n"
+            . "[Section4]\n"
+            . "j[] = 3\nk[c] = 3\n"
             . "[Parent_Config]\n"
             . "path=\"{$parentPath}\"\n"
             . "override_full_sections=Section1\n";
+        $child2Path = Locator::getLocalConfigPath('unit-test-child2.ini', null, true);
+        $child2 = "[Section1]\n"
+            . "j=10\nk=11\nl=12\n"
+            . "[Section2]\n"
+            . "m=13\nn=14\no=15\n"
+            . "[Section4]\n"
+            . "j[] = 3\nk[c] = 3\n"
+            . "[Parent_Config]\n"
+            . "path=\"{$parentPath}\"\n"
+            . "override_full_sections=Section1\n"
+            . "merge_array_settings=true\n";
 
         // Fail if we are unable to write files:
-        if (null === $parentPath || null === $childPath
+        if (null === $parentPath || null === $childPath || null === $child2Path
             || !file_put_contents($parentPath, $parent)
             || !file_put_contents($childPath, $child)
+            || !file_put_contents($child2Path, $child2)
         ) {
             self::$writeFailed = true;
             return;
@@ -118,7 +134,7 @@ class PluginFactoryTest extends \VuFindTest\Unit\TestCase
     protected function getConfig($name)
     {
         return $this->factory->createServiceWithName(
-            $this->getMock('Zend\ServiceManager\ServiceLocatorInterface'),
+            $this->createMock('Zend\ServiceManager\ServiceLocatorInterface'),
             $name, $name
         );
     }
@@ -175,6 +191,45 @@ class PluginFactoryTest extends \VuFindTest\Unit\TestCase
 
         // Make sure Section 3 was inherited; values from parent should exist.
         $this->assertEquals('7', $config->Section3->g);
+
+        // Make sure Section 4 arrays were overwritten.
+        $this->assertEquals([3], $config->Section4->j->toArray());
+        $this->assertEquals(['c' => 3], $config->Section4->k->toArray());
+    }
+
+    /**
+     * Test inheritance features with array merging turned on.
+     *
+     * @return void
+     */
+    public function testInheritanceWithArrayMerging()
+    {
+        if (self::$writeFailed) {
+            $this->markTestSkipped('Could not write test configurations.');
+        }
+
+        // Make sure load succeeds:
+        $config = $this->getConfig('unit-test-child2');
+        $this->assertTrue(is_object($config));
+
+        // Make sure Section 1 was overridden; values from parent should not be
+        // present.
+        $this->assertTrue(!isset($config->Section1->a));
+        $this->assertEquals('10', $config->Section1->j);
+
+        // Make sure Section 2 was merged; values from parent and child should
+        // both be present.
+        $this->assertEquals('4', $config->Section2->d);
+        $this->assertEquals('13', $config->Section2->m);
+
+        // Make sure Section 3 was inherited; values from parent should exist.
+        $this->assertEquals('7', $config->Section3->g);
+
+        // Make sure Section 4 arrays were overwritten.
+        $this->assertEquals([1, 2, 3], $config->Section4->j->toArray());
+        $this->assertEquals(
+            ['a' => 1, 'b' => 2, 'c' => 3], $config->Section4->k->toArray()
+        );
     }
 
     /**
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/Config/SearchSpecsReaderTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/Config/SearchSpecsReaderTest.php
index 52d8c0f294722b12b7c986f5f04618488bf2e542..43363b88f3f47438fb2ae84caf1a65a6954424f0 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/Config/SearchSpecsReaderTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/Config/SearchSpecsReaderTest.php
@@ -65,9 +65,9 @@ class SearchSpecsReaderTest extends \VuFindTest\Unit\TestCase
         $parentPath = Locator::getLocalConfigPath('top.yaml', null, true);
         $parent = "top: foo";
         $childPath = Locator::getLocalConfigPath('middle.yaml', null, true);
-        $child = "@parent_yaml: $parentPath\nmiddle: bar";
+        $child = "\"@parent_yaml\": $parentPath\nmiddle: bar";
         $grandchildPath = Locator::getLocalConfigPath('bottom.yaml', null, true);
-        $grandchild = "@parent_yaml: $childPath\nbottom: baz";
+        $grandchild = "\"@parent_yaml\": $childPath\nbottom: baz";
 
         // Fail if we are unable to write files:
         if (null === $parentPath || null === $childPath || null === $grandchildPath
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/Config/UpgradeTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/Config/UpgradeTest.php
index 27f77e9333c54630661bc819f77c9ab4aa24bf25..b8562fc06ca6bb10d806d672373b4d9fcb763aa7 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/Config/UpgradeTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/Config/UpgradeTest.php
@@ -89,16 +89,19 @@ class UpgradeTest extends \VuFindTest\Unit\TestCase
 
         // Prior to 2.4, we expect exactly one warning about using a deprecated
         // theme:
-        $expectedWarnings = [];
+        $expectedWarnings = [
+            'The Statistics module has been removed from Vufind. '
+            . 'For usage tracking, please configure Google Analytics or Piwik.'
+        ];
         if ((float)$version < 1.3) {
             $expectedWarnings[] = "WARNING: This version of VuFind does not support "
-                . "the default theme.  Your config.ini [Site] theme setting "
-                . "has been reset to the default: bootprint3.  You may need to "
+                . "the default theme. Your config.ini [Site] theme setting "
+                . "has been reset to the default: bootprint3. You may need to "
                 . "reimplement your custom theme.";
         } else if ((float)$version < 2.4) {
             $expectedWarnings[] = "WARNING: This version of VuFind does not support "
-                . "the blueprint theme.  Your config.ini [Site] theme setting "
-                . "has been reset to the default: bootprint3.  You may need to "
+                . "the blueprint theme. Your config.ini [Site] theme setting "
+                . "has been reset to the default: bootprint3. You may need to "
                 . "reimplement your custom theme.";
         }
         $this->assertEquals($expectedWarnings, $warnings);
@@ -403,6 +406,18 @@ class UpgradeTest extends \VuFindTest\Unit\TestCase
                 $warnings
             )
         );
+        $this->assertTrue(
+            in_array(
+                'Google Maps is no longer a supported Content/recordMap option;'
+                . ' please review your config.ini.',
+                $warnings
+            )
+        );
+        $results = $upgrader->getNewConfigs();
+        $this->assertFalse(isset($results['config.ini']['Content']['recordMap']));
+        $this->assertFalse(
+            isset($results['config.ini']['Content']['googleMapApiKey'])
+        );
     }
 
     /**
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/Content/Covers/AmazonTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/Content/Covers/AmazonTest.php
index a65e99dcd44db2e2ef7fa68fd1a9036234a1d255..73a52f41b72b71cc491c8d468cc1ca4cd36b6b2b 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/Content/Covers/AmazonTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/Content/Covers/AmazonTest.php
@@ -107,10 +107,10 @@ class AmazonTest extends \PHPUnit_Framework_TestCase
      */
     protected function getUrl($size, $isbn = '0739313126', $throw = false)
     {
-        $amazon = $this->getMock(
-            'VuFind\Content\Covers\Amazon', ['getAmazonService'],
-            ['fake', 'fakesecret']
-        );
+        $amazon = $this->getMockBuilder(__NAMESPACE__ . '\CoverAmazonMock')
+            ->setMethods(['getAmazonService'])
+            ->setConstructorArgs(['fake', 'fakesecret'])
+            ->getMock();
         $params = [];
         if (!empty($isbn)) {
             $behavior = $throw
@@ -134,10 +134,10 @@ class AmazonTest extends \PHPUnit_Framework_TestCase
      */
     protected function getFakeService($isbn, $expectedBehavior)
     {
-        $service = $this->getMock(
-            'ZendService\Amazon\Amazon', ['itemLookup'],
-            ['fakekey', 'US', 'fakesecret']
-        );
+        $service = $this->getMockBuilder(__NAMESPACE__ . '\ZendAmazonMock')
+            ->setMethods(['itemLookup'])
+            ->setConstructorArgs(['fakekey', 'US', 'fakesecret'])
+            ->getMock();
         if (!empty($isbn)) {
             $service->expects($this->once())
                 ->method('itemLookup')
@@ -158,3 +158,17 @@ class AmazonTest extends \PHPUnit_Framework_TestCase
         return unserialize(file_get_contents($file));
     }
 }
+
+class CoverAmazonMock extends \VuFind\Content\Covers\Amazon
+{
+    public function getAmazonService($key)
+    {
+    }
+}
+
+class ZendAmazonMock extends \ZendService\Amazon\Amazon
+{
+    public function itemLookup($asin, array $options = [])
+    {
+    }
+}
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/Controller/Plugin/FollowupTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/Controller/Plugin/FollowupTest.php
index d10b2f9a934e6d748d1721e1874b486bc1ddd1ed..8cf9d49bfc48a7ff1b65fbd60554af5c536def6e 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/Controller/Plugin/FollowupTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/Controller/Plugin/FollowupTest.php
@@ -100,7 +100,8 @@ class FollowupTest extends TestCase
      */
     protected function getMockController($url = 'http://localhost/default-url')
     {
-        $controller = $this->getMock('VuFind\Controller\AbstractBase');
+        $controller = $this->getMockBuilder('VuFind\Controller\AbstractBase')
+            ->disableOriginalConstructor()->getMock();
         $controller->expects($this->any())->method('getServerUrl')->will($this->returnValue($url));
         return $controller;
     }
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/Controller/Plugin/NewItemsTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/Controller/Plugin/NewItemsTest.php
index 13c46d81d4dd92edc9ae43c0531af7256d7895bb..b806f5dc1487732e7643fd4121d4d25b6dcf567f 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/Controller/Plugin/NewItemsTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/Controller/Plugin/NewItemsTest.php
@@ -50,7 +50,7 @@ class NewItemsTest extends TestCase
      */
     public function testGetBibIDsFromCatalog()
     {
-        $flash = $this->getMock('Zend\Mvc\Controller\Plugin\FlashMessenger');
+        $flash = $this->createMock('Zend\Mvc\Controller\Plugin\FlashMessenger');
         $config = new Config(['result_pages' => 10]);
         $newItems = new NewItems($config);
         $bibs = $newItems->getBibIDsFromCatalog(
@@ -66,7 +66,7 @@ class NewItemsTest extends TestCase
      */
     public function testGetBibIDsFromCatalogWithIDLimit()
     {
-        $flash = $this->getMock('Zend\Mvc\Controller\Plugin\FlashMessenger');
+        $flash = $this->createMock('Zend\Mvc\Controller\Plugin\FlashMessenger');
         $flash->expects($this->once())->method('addMessage')
             ->with($this->equalTo('too_many_new_items'), $this->equalTo('info'));
         $config = new Config(['result_pages' => 10]);
@@ -84,15 +84,16 @@ class NewItemsTest extends TestCase
      */
     public function testGetFundList()
     {
-        $catalog = $this->getMock(
-            'VuFind\ILS\Connection', ['checkCapability', 'getFunds'],
-            [], '', false
-        );
+        $catalog = $this->getMockBuilder(__NAMESPACE__ . '\MockILSConnection')
+            ->setMethods(['checkCapability', 'getFunds'])
+            ->disableOriginalConstructor()
+            ->getMock();
         $catalog->expects($this->once())->method('checkCapability')
             ->with($this->equalTo('getFunds'))->will($this->returnValue(true));
         $catalog->expects($this->once())->method('getFunds')
             ->will($this->returnValue(['a', 'b', 'c']));
-        $controller = $this->getMock('VuFind\Controller\SearchController');
+        $controller = $this->getMockBuilder('VuFind\Controller\SearchController')
+            ->disableOriginalConstructor()->getMock();
         $controller->expects($this->once())->method('getILS')
             ->will($this->returnValue($catalog));
         $newItems = new NewItems(new Config([]));
@@ -208,9 +209,10 @@ class NewItemsTest extends TestCase
      */
     protected function getMockCatalog()
     {
-        $catalog = $this->getMock(
-            'VuFind\ILS\Connection', ['getNewItems'], [], '', false
-        );
+        $catalog = $this->getMockBuilder(__NAMESPACE__ . '\MockILSConnection')
+            ->setMethods(['getNewItems'])
+            ->disableOriginalConstructor()
+            ->getMock();
         $catalog->expects($this->once())->method('getNewItems')
             ->with(
                 $this->equalTo(1), $this->equalTo(200),
@@ -233,8 +235,8 @@ class NewItemsTest extends TestCase
      */
     protected function getMockParams($idLimit = 1024)
     {
-        $params = $this
-            ->getMock('VuFind\Search\Solr\Params', [], [], '', false);
+        $params = $this->getMockBuilder('VuFind\Search\Solr\Params')
+            ->disableOriginalConstructor()->getMock();
         $params->expects($this->once())->method('getLimit')
             ->will($this->returnValue(20));
         $params->expects($this->once())->method('getQueryIDLimit')
@@ -242,3 +244,14 @@ class NewItemsTest extends TestCase
         return $params;
     }
 }
+
+class MockILSConnection extends \VuFind\ILS\Connection
+{
+    public function getFunds()
+    {
+    }
+
+    public function getNewItems()
+    {
+    }
+}
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/Controller/Plugin/ResultScrollerTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/Controller/Plugin/ResultScrollerTest.php
index 2a7c3953639e0737c271388efc31ef4d29c258e5..5b509546d30d6dfa5c84ef646993fb43b0a2dbdf 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/Controller/Plugin/ResultScrollerTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/Controller/Plugin/ResultScrollerTest.php
@@ -50,7 +50,9 @@ class ResultScrollerTest extends TestCase
      */
     public function testDisabled()
     {
-        $plugin = new ResultScroller(new Container('test'), false);
+        $mockManager = $this->getMockBuilder('VuFind\Search\Results\PluginManager')
+            ->disableOriginalConstructor()->getMock();
+        $plugin = new ResultScroller(new Container('test'), $mockManager, false);
         $results = $this->getMockResults();
         $this->assertFalse($plugin->init($results));
         $expected = [
@@ -336,7 +338,13 @@ class ResultScrollerTest extends TestCase
         if (null !== $sort) {
             $params->setSort($sort, true);
         }
-        $results = new \VuFindTest\Search\TestHarness\Results($params, $total);
+        $ss = $this->getMockBuilder('VuFindSearch\Service')
+            ->disableOriginalConstructor()->getMock();
+        $rl = $this->getMockBuilder('VuFind\Record\Loader')
+            ->disableOriginalConstructor()->getMock();
+        $results = new \VuFindTest\Search\TestHarness\Results(
+            $params, $ss, $rl, $total
+        );
         return $results;
     }
 
@@ -349,15 +357,50 @@ class ResultScrollerTest extends TestCase
      *
      * @return ResultScroller
      */
-    protected function getMockResultScroller($results = null,
-        $methods = ['restoreLastSearch', 'rememberSearch']
-    ) {
-        $mock = $this->getMock(
-            'VuFind\Controller\Plugin\ResultScroller', $methods, [new Container('test')]
-        );
-        if (in_array('restoreLastSearch', $methods) && null !== $results) {
-            $mock->expects($this->any())->method('restoreLastSearch')->will($this->returnValue($results));
-        }
-        return $mock;
+    protected function getMockResultScroller($results) {
+        $mockManager = $this->getMockBuilder('VuFind\Search\Results\PluginManager')
+            ->disableOriginalConstructor()->getMock();
+        return new ResultScrollerMock($mockManager, $results);
+    }
+}
+
+/**
+ * Mock class to stub search results
+ */
+class ResultScrollerMock extends \VuFind\Controller\Plugin\ResultScroller
+{
+    /**
+     * Search results to return
+     *
+     * @var \VuFind\Search\Base\Results
+     */
+    protected $testResults;
+
+    public function __construct($mockManager, $testResults)
+    {
+        parent::__construct(new Container('test'), $mockManager);
+        $this->testResults = $testResults;
+    }
+
+    /**
+     * Stubbed
+     *
+     * @return \VuFind\Search\Base\Results
+     */
+    protected function restoreLastSearch()
+    {
+        return $this->testResults;
+    }
+
+    /**
+     * Stubbed
+     *
+     * @param \VuFind\Search\Base\Results $search Search object to remember.
+     *
+     * @return void
+     */
+    protected function rememberSearch($search)
+    {
+        return null;
     }
 }
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/Cover/LoaderTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/Cover/LoaderTest.php
index 0eb780295573b42b33531bfbf1b962044a557a8b..2dbb5a0b7bdf11ba8cc25c50d3413236d3c60d5f 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/Cover/LoaderTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/Cover/LoaderTest.php
@@ -59,7 +59,8 @@ class LoaderTest extends \VuFindTest\Unit\TestCase
      */
     public function testUtterFailure()
     {
-        $theme = $this->getMock('VuFindTheme\ThemeInfo', [], ['foo', 'bar']);
+        $theme = $this->getMockBuilder('VuFindTheme\ThemeInfo')
+            ->setConstructorArgs(['foo', 'bar'])->getMock();
         $theme->expects($this->once())->method('findContainingTheme')->with($this->equalTo(['images/noCover2.gif']))->will($this->returnValue(false));
         $loader = $this->getLoader([], null, $theme);
         $loader->getImage();
@@ -135,13 +136,13 @@ class LoaderTest extends \VuFindTest\Unit\TestCase
      * @param \Zend\Http\Client                    $client  HTTP client (null to create TestAdapter)
      * @param array|bool                           $mock    Array of functions to mock, or false for real object
      *
-     * @return void
+     * @return Loader
      */
     protected function getLoader($config = [], $manager = null, $theme = null, $client = null, $mock = false)
     {
         $config = new Config($config);
         if (null === $manager) {
-            $manager = $this->getMock('VuFind\Content\Covers\PluginManager');
+            $manager = $this->createMock('VuFind\Content\Covers\PluginManager');
         }
         if (null === $theme) {
             $theme = new ThemeInfo($this->getThemeDir(), $this->testTheme);
@@ -152,7 +153,10 @@ class LoaderTest extends \VuFindTest\Unit\TestCase
             $client->setAdapter($adapter);
         }
         if ($mock) {
-            return $this->getMock('VuFind\Cover\Loader', $mock, [$config, $manager, $theme, $client]);
+            return $this->getMockBuilder(__NAMESPACE__ . '\MockLoader')
+                ->setMethods($mock)
+                ->setConstructorArgs([$config, $manager, $theme, $client])
+                ->getMock();
         }
         return new Loader($config, $manager, $theme, $client);
     }
@@ -167,3 +171,10 @@ class LoaderTest extends \VuFindTest\Unit\TestCase
         return realpath(__DIR__ . '/../../../../../../../themes');
     }
 }
+
+class MockLoader extends \VuFind\Cover\Loader
+{
+    public function debug($msg, array $context = [], $prependClass = true)
+    {
+    }
+}
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/ILS/Driver/DemoTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/ILS/Driver/DemoTest.php
index 46223719c980d7d74e058d1981f8d89ea033d89e..ffacb5242126412d7d930cce09180a6e853c2ac3 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/ILS/Driver/DemoTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/ILS/Driver/DemoTest.php
@@ -56,7 +56,7 @@ class DemoTest extends \VuFindTest\Unit\TestCase
         $session = $this->getMockBuilder('Zend\Session\Container')
             ->disableOriginalConstructor()->getMock();
         $this->driver = new Demo(
-            new \VuFind\Date\Converter(), $this->getMock('VuFindSearch\Service'),
+            new \VuFind\Date\Converter(), $this->createMock('VuFindSearch\Service'),
             function () use ($session) { return $session; }
         );
         $this->driver->init();
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/ILS/Driver/MultiBackendTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/ILS/Driver/MultiBackendTest.php
index a83d8828850ab18c0e82fd040237a100d04852ff..63faa7a4df0f649b39b4fc5df6d749698a6399dc 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/ILS/Driver/MultiBackendTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/ILS/Driver/MultiBackendTest.php
@@ -52,7 +52,8 @@ class MultiBackendTest extends \VuFindTest\Unit\TestCase
     {
         $this->setExpectedException('VuFind\Exception\ILS');
         $test = new MultiBackend(
-            new \VuFind\Config\PluginManager(), $this->getMockILSAuthenticator()
+            new \VuFind\Config\PluginManager(), $this->getMockILSAuthenticator(),
+            $this->getMockSM()
         );
         $test->init();
     }
@@ -80,13 +81,15 @@ class MultiBackendTest extends \VuFindTest\Unit\TestCase
         $writer = new \Zend\Log\Writer\Mock();
         $logger->addWriter($writer);
 
-        $mockPM = $this->getMock('\VuFind\Config\PluginManager');
+        $mockPM = $this->createMock('\VuFind\Config\PluginManager');
         $mockPM->expects($this->any())
             ->method('get')
             ->will(
                 $this->throwException(new \Zend\Config\Exception\RuntimeException())
             );
-        $driver = new MultiBackend($mockPM, $this->getMockILSAuthenticator());
+        $driver = new MultiBackend(
+            $mockPM, $this->getMockILSAuthenticator(), $this->getMockSM()
+        );
         $driver->setConfig(['Drivers' => []]);
         $driver->setLogger($logger);
         $driver->init();
@@ -158,7 +161,6 @@ class MultiBackendTest extends \VuFindTest\Unit\TestCase
      */
     public function testGetDriver()
     {
-        $driver = $this->getDriver();
         //Set up the mock driver to be retrieved
         $ILS = $this->getMockILS('Voyager', ['init', 'setConfig']);
         $ILS->expects($this->once())
@@ -168,8 +170,9 @@ class MultiBackendTest extends \VuFindTest\Unit\TestCase
             ->with(['config' => 'values']);
 
         //Set up the ServiceLocator so it returns our mock driver
-        $sm = $this->getMockSM($this->once(), 'Voyager', $ILS);
-        $driver->setServiceLocator($sm);
+        $driver = $this->getDriver(
+            $this->getMockSM($this->once(), 'Voyager', $ILS)
+        );
 
         //Add an entry for our test driver to the array of drivers
         $drivers = ['testing2' => 'Voyager'];
@@ -196,13 +199,15 @@ class MultiBackendTest extends \VuFindTest\Unit\TestCase
         $this->assertEquals($configData, $val);
 
         $config = new \Zend\Config\Config($configData);
-        $mockPM = $this->getMock('\VuFind\Config\PluginManager');
+        $mockPM = $this->createMock('\VuFind\Config\PluginManager');
         $mockPM->expects($this->any())
             ->method('get')
             ->will(
                 $this->throwException(new \Zend\Config\Exception\RuntimeException())
             );
-        $driver = new MultiBackend($mockPM, $this->getMockILSAuthenticator());
+        $driver = new MultiBackend(
+            $mockPM, $this->getMockILSAuthenticator(), $this->getMockSM()
+        );
         $driver->setConfig(['Drivers' => []]);
         $driver->init();
         $val = $this->callMethod($driver, 'getDriverConfig', ['bad']);
@@ -379,11 +384,6 @@ class MultiBackendTest extends \VuFindTest\Unit\TestCase
      */
     public function testGetHolding()
     {
-        $driver = $this->getDriver();
-        $drivers = ['d1' => 'Voyager'];
-        $this->setProperty($driver, 'drivers', $drivers);
-        $id = '123456';
-
         $ILS = $this->getMockILS('Voyager', ['init', 'getHolding']);
         $ILS->expects($this->exactly(2))
             ->method('getHolding')
@@ -405,7 +405,10 @@ class MultiBackendTest extends \VuFindTest\Unit\TestCase
             );
 
         $sm = $this->getMockSM($this->any(), 'Voyager', $ILS);
-        $driver->setServiceLocator($sm);
+        $driver = $this->getDriver($sm);
+        $drivers = ['d1' => 'Voyager'];
+        $this->setProperty($driver, 'drivers', $drivers);
+        $id = '123456';
 
         $expectedReturn = ['id' => 'd1.123456', 'status' => 'in'];
         $return = $driver->getHolding("d1.$id");
@@ -425,11 +428,6 @@ class MultiBackendTest extends \VuFindTest\Unit\TestCase
      */
     public function testGetPurchaseHistory()
     {
-        $driver = $this->getDriver();
-        $drivers = ['d1' => 'Voyager'];
-        $this->setProperty($driver, 'drivers', $drivers);
-        $id = 'd1.123456';
-
         $driverReturn = ['purchases' => '123456'];
         $ILS = $this->getMockILS('Voyager', ['init', 'getPurchaseHistory']);
         $ILS->expects($this->once())
@@ -438,7 +436,10 @@ class MultiBackendTest extends \VuFindTest\Unit\TestCase
             ->will($this->returnValue($driverReturn));
 
         $sm = $this->getMockSM($this->any(), 'Voyager', $ILS);
-        $driver->setServiceLocator($sm);
+        $driver = $this->getDriver($sm);
+        $drivers = ['d1' => 'Voyager'];
+        $this->setProperty($driver, 'drivers', $drivers);
+        $id = 'd1.123456';
 
         $return = $driver->getPurchaseHistory($id);
         $this->assertEquals($driverReturn, $return);
@@ -501,10 +502,6 @@ class MultiBackendTest extends \VuFindTest\Unit\TestCase
      */
     public function testGetStatus()
     {
-        $driver = $this->getDriver();
-        $drivers = ['d1' => 'Voyager'];
-        $this->setProperty($driver, 'drivers', $drivers);
-
         $ILS = $this->getMockILS('Voyager', ['init', 'getStatus']);
         $ILS->expects($this->exactly(2))
             ->method('getStatus')
@@ -531,7 +528,9 @@ class MultiBackendTest extends \VuFindTest\Unit\TestCase
             );
 
         $sm = $this->getMockSM($this->any(), 'Voyager', $ILS);
-        $driver->setServiceLocator($sm);
+        $driver = $this->getDriver($sm);
+        $drivers = ['d1' => 'Voyager'];
+        $this->setProperty($driver, 'drivers', $drivers);
 
         $return = $driver->getStatus('d1.123456');
         $this->assertEquals(['id' => 'd1.123456', 'status' => 'in'], $return);
@@ -550,10 +549,6 @@ class MultiBackendTest extends \VuFindTest\Unit\TestCase
      */
     public function testGetStatuses()
     {
-        $driver = $this->getDriver();
-        $drivers = ['d1' => 'Voyager'];
-        $this->setProperty($driver, 'drivers', $drivers);
-
         $ILS = $this->getMockILS('Voyager', ['init', 'getStatus']);
         $ILS->expects($this->exactly(4))
             ->method('getStatus')
@@ -584,7 +579,9 @@ class MultiBackendTest extends \VuFindTest\Unit\TestCase
             );
 
         $sm = $this->getMockSM($this->any(), 'Voyager', $ILS);
-        $driver->setServiceLocator($sm);
+        $driver = $this->getDriver($sm);
+        $drivers = ['d1' => 'Voyager'];
+        $this->setProperty($driver, 'drivers', $drivers);
 
         $ids = [
             'd1.123456', 'd1.098765', 'd1.654321', 'd1.567890'
@@ -623,11 +620,14 @@ class MultiBackendTest extends \VuFindTest\Unit\TestCase
      */
     public function testDefaultDriver()
     {
-        $driver = $this->getDriver();
         //Case: The parameters let it know what driver to use
             //Result: return the function results for that driver
         $patron = $this->getPatron('username', 'institution');
 
+        $ILS = $this->getMockILS('Voyager', ['getMyTransactions', 'init']);
+
+        $sm = $this->getMockSM($this->any(), 'Voyager', $ILS);
+        $driver = $this->getDriver($sm);
         $drivers = [
             'otherinst' => 'Unicorn',
             'institution' => 'Voyager'
@@ -637,16 +637,11 @@ class MultiBackendTest extends \VuFindTest\Unit\TestCase
         $patronPrefixless = $this->callMethod(
             $driver, 'stripIdPrefixes', [$patron, 'institution']
         );
-
-        $ILS = $this->getMockILS('Voyager', ['getMyTransactions', 'init']);
         $ILS->expects($this->atLeastOnce())
             ->method('getMyTransactions')
             ->with($patronPrefixless)
             ->will($this->returnValue(true));
 
-        $sm = $this->getMockSM($this->any(), 'Voyager', $ILS);
-        $driver->setServiceLocator($sm);
-
         $returnVal = $driver->getMyTransactions($patron);
         $this->assertTrue($returnVal);
 
@@ -664,7 +659,8 @@ class MultiBackendTest extends \VuFindTest\Unit\TestCase
             ->will($this->returnValue(true));
 
         $sm = $this->getMockSM($this->any(), 'Unicorn', $ILS);
-        $driver->setServiceLocator($sm);
+        $driver = $this->getDriver($sm);
+        $this->setProperty($driver, 'drivers', $drivers);
 
         $this->setProperty($driver, 'defaultDriver', 'otherinst');
         $returnVal = $driver->getMyTransactions($patron);
@@ -678,10 +674,6 @@ class MultiBackendTest extends \VuFindTest\Unit\TestCase
      */
     public function testGetNewItems()
     {
-        $driver = $this->getDriver();
-        $drivers = ['d1' => 'Voyager'];
-        $this->setProperty($driver, 'drivers', $drivers);
-
         $return = [
             'count' => 2,
             'results' => ['id' => '1', 'id' => '2']
@@ -694,7 +686,9 @@ class MultiBackendTest extends \VuFindTest\Unit\TestCase
             ->will($this->returnValue($return));
 
         $sm = $this->getMockSM($this->any(), 'Voyager', $ILS);
-        $driver->setServiceLocator($sm);
+        $driver = $this->getDriver($sm);
+        $drivers = ['d1' => 'Voyager'];
+        $this->setProperty($driver, 'drivers', $drivers);
 
         // getNewItems only works with a default driver, so the first calls fails
         $result = $driver->getNewItems(1, 10, 5, 0);
@@ -794,11 +788,6 @@ class MultiBackendTest extends \VuFindTest\Unit\TestCase
      */
     public function testFindReserves()
     {
-        $driver = $this->getDriver();
-        $drivers = ['d1' => 'Voyager'];
-        $this->setProperty($driver, 'drivers', $drivers);
-        $id = '123456';
-
         $reservesReturn = [
             [
                 'BIB_ID' => '12345',
@@ -821,7 +810,10 @@ class MultiBackendTest extends \VuFindTest\Unit\TestCase
             ->will($this->returnValue($reservesReturn));
 
         $sm = $this->getMockSM($this->any(), 'Voyager', $ILS);
-        $driver->setServiceLocator($sm);
+        $driver = $this->getDriver($sm);
+        $drivers = ['d1' => 'Voyager'];
+        $this->setProperty($driver, 'drivers', $drivers);
+        $id = '123456';
 
         // findReserves only works with a default driver, so the first calls fails
         $result = $driver->findReserves('course', 'inst', 'dept');
@@ -2161,7 +2153,6 @@ class MultiBackendTest extends \VuFindTest\Unit\TestCase
      */
     public function testSupportsMethod()
     {
-        $driver = $this->getDriver();
         //Set up the mock driver to be retrieved
         $ILS = $this->getMockILS('Voyager', ['setConfig', 'init']);
         $ILS->expects($this->once())
@@ -2172,7 +2163,7 @@ class MultiBackendTest extends \VuFindTest\Unit\TestCase
 
         //Set up the ServiceLocator so it returns our mock driver
         $sm = $this->getMockSM($this->once(), 'Voyager', $ILS);
-        $driver->setServiceLocator($sm);
+        $driver = $this->getDriver($sm);
 
         //Add an entry for our test driver to the array of drivers
         $drivers = ['testing3' => 'Voyager'];
@@ -2238,10 +2229,6 @@ class MultiBackendTest extends \VuFindTest\Unit\TestCase
     protected function initSimpleMethodTest(
         $times1, $times2, $function, $params, $return1, $return2
     ) {
-        $driver = $this->getDriver();
-        $drivers = ['d1' => 'Voyager', 'd2' => 'Demo', 'd3' => 'DummyILS'];
-        $this->setProperty($driver, 'drivers', $drivers);
-
         $voyager = $this->getMockILS('Voyager', ['init', $function]);
         call_user_func_array(
             [$voyager->expects($times1)->method($function), 'with'], $params
@@ -2254,9 +2241,8 @@ class MultiBackendTest extends \VuFindTest\Unit\TestCase
 
         $dummyILS = new DummyILS();
 
-        $sm = $this->getMockForAbstractClass(
-            'Zend\ServiceManager\ServiceLocatorInterface'
-        );
+        $sm = $this->getMockBuilder('VuFind\ILS\Driver\PluginManager')
+            ->disableOriginalConstructor()->getMock();
         $sm->expects($this->any())
             ->method('get')
             ->with($this->logicalOr('Voyager', 'Demo', 'DummyILS'))
@@ -2274,7 +2260,9 @@ class MultiBackendTest extends \VuFindTest\Unit\TestCase
                     }
                 )
             );
-        $driver->setServiceLocator($sm);
+        $driver = $this->getDriver($sm);
+        $drivers = ['d1' => 'Voyager', 'd2' => 'Demo', 'd3' => 'DummyILS'];
+        $this->setProperty($driver, 'drivers', $drivers);
 
         return $driver;
     }
@@ -2282,12 +2270,15 @@ class MultiBackendTest extends \VuFindTest\Unit\TestCase
     /**
      * Method to get a fresh MultiBackend Driver.
      *
+     * @param object $sm Service manager (null for default mock)
+     *
      * @return mixed A MultiBackend instance.
      */
-    protected function getDriver()
+    protected function getDriver($sm = null)
     {
         $driver = new MultiBackend(
-            $this->getPluginManager(), $this->getMockILSAuthenticator()
+            $this->getPluginManager(), $this->getMockILSAuthenticator(),
+            $sm === null ? $this->getMockSM() : $sm
         );
         $driver->setConfig(
             [
@@ -2339,7 +2330,7 @@ class MultiBackendTest extends \VuFindTest\Unit\TestCase
     {
         $configData = ['config' => 'values'];
         $config = new \Zend\Config\Config($configData);
-        $mockPM = $this->getMock('\VuFind\Config\PluginManager');
+        $mockPM = $this->createMock('\VuFind\Config\PluginManager');
         $mockPM->expects($this->any())
             ->method('get')
             ->will($this->returnValue($config));
@@ -2358,14 +2349,14 @@ class MultiBackendTest extends \VuFindTest\Unit\TestCase
     {
         $cat_username = $instance ? $instance . '.' . $username : $username;
         return [
-                    'id' => 1,
-                    'firstname' => 'JANE',
-                    'lastname' => 'DOE',
-                    'cat_username' => $cat_username,
-                    'cat_password' => 'password',
-                    'email' => '',
-                    'major' => '',
-                    'college' => ''
+            'id' => 1,
+            'firstname' => 'JANE',
+            'lastname' => 'DOE',
+            'cat_username' => $cat_username,
+            'cat_password' => 'password',
+            'email' => '',
+            'major' => '',
+            'college' => ''
         ];
     }
 
@@ -2380,12 +2371,11 @@ class MultiBackendTest extends \VuFindTest\Unit\TestCase
      *
      * @return object The Mock Service Manager created.
      */
-    protected function getMockSM($times, $driver, $return)
+    protected function getMockSM($times = null, $driver = 'Voyager', $return = null)
     {
-        $sm = $this->getMockForAbstractClass(
-            'Zend\ServiceManager\ServiceLocatorInterface'
-        );
-        $sm->expects($times)
+        $sm = $this->getMockBuilder('VuFind\ILS\Driver\PluginManager')
+            ->disableOriginalConstructor()->getMock();
+        $sm->expects($times === null ? $this->any() : $times)
             ->method('get')
             ->with($driver)
             ->will($this->returnValue($return));
@@ -2401,14 +2391,15 @@ class MultiBackendTest extends \VuFindTest\Unit\TestCase
     {
         $session = $this->getMockBuilder('Zend\Session\Container')
             ->disableOriginalConstructor()->getMock();
-        return $this->getMock(
-            "VuFind\ILS\Driver\Demo", $methods,
-            [
-                new \VuFind\Date\Converter(),
-                $this->getMock('VuFindSearch\Service'),
-                function () use ($session) { return $session; }
-            ]
-        );
+        return $this->getMockBuilder(__NAMESPACE__ . '\DemoMock')
+            ->setMethods($methods)
+            ->setConstructorArgs(
+                [
+                    new \VuFind\Date\Converter(),
+                    $this->createMock('VuFindSearch\Service'),
+                    function () use ($session) { return $session; }
+                ]
+            )->getMock();
     }
 
     /**
@@ -2426,21 +2417,27 @@ class MultiBackendTest extends \VuFindTest\Unit\TestCase
             if ($type == 'Demo') {
                 $mock = $this->getMockDemoDriver($methods);
             } else {
-                $mock = $this->getMock(
-                    "VuFind\ILS\Driver\\$type", $methods,
-                    [new \VuFind\Date\Converter()]
-                );
+                $mock = $this->getMockBuilder(__NAMESPACE__ . '\\' . $type . 'Mock')
+                    ->setMethods($methods)
+                    ->setConstructorArgs([new \VuFind\Date\Converter()])
+                    ->getMock();
             }
         } catch(\Exception $e) {
-            $mock = $this->getMock(
-                "VuFind\ILS\Driver\\$type", $methods
-            );
+            $mock = $this->getMockBuilder(__NAMESPACE__ . '\\' . $type . 'Mock')
+                ->setMethods($methods)->getMock();
         }
         if ($methods && in_array('init', $methods)) {
             $mock->expects($this->any())
                 ->method('init')
                 ->will($this->returnValue(null));
         }
+        if ($methods && in_array('supportsMethod', $methods)) {
+            $mock = $this
+                ->getMockBuilder(__NAMESPACE__ . '\\' . $type . 'NoSupportMock')
+                ->setMethods($methods)
+                ->setConstructorArgs([new \VuFind\Date\Converter()])
+                ->getMock();
+        }
         $mock->setConfig(['dummy_config' => true]);
         return $mock;
     }
@@ -2538,3 +2535,92 @@ class DummyILS extends \VuFind\ILS\Driver\AbstractBase
         return [];
     }
 }
+
+trait ILSMockTrait
+{
+    public function cancelHolds($cancelDetails)
+    {
+    }
+    public function cancelILLRequests($cancelDetails)
+    {
+    }
+    public function cancelStorageRetrievalRequests($cancelDetails)
+    {
+    }
+    public function checkRequestIsValid($id, $data, $patron)
+    {
+    }
+    public function checkILLRequestIsValid($id, $data, $patron)
+    {
+    }
+    public function checkStorageRetrievalRequestIsValid($id, $data, $patron)
+    {
+    }
+    public function getCancelHoldDetails($holdDetails)
+    {
+    }
+    public function getCancelILLRequestDetails($holdDetails)
+    {
+    }
+    public function getCancelStorageRetrievalRequestDetails($holdDetails)
+    {
+    }
+    public function getConfig($function, $params = null)
+    {
+    }
+    public function getDefaultPickUpLocation($patron = false, $holdDetails = null)
+    {
+    }
+    public function getDefaultRequestGroup($patron = false, $holdDetails = null)
+    {
+    }
+    public function getMyILLRequests($patron)
+    {
+    }
+    public function getILLPickUpLibraries($patron = false, $holdDetails = null)
+    {
+    }
+    public function getILLPickUpLocations($id, $pickupLib, $patron)
+    {
+    }
+    public function getPickUpLocations($patron = false, $holdDetails = null)
+    {
+    }
+    public function getRenewDetails($checkoutDetails)
+    {
+    }
+    public function getRequestGroups($bibId = null, $patron = null, $holdDetails = null)
+    {
+    }
+    public function placeHold($holdDetails)
+    {
+    }
+    public function placeILLRequest($holdDetails)
+    {
+    }
+    public function placeStorageRetrievalRequest($details)
+    {
+    }
+    public function renewMyItems($renewDetails)
+    {
+    }
+}
+class DemoMock extends \VuFind\ILS\Driver\Demo
+{
+    use ILSMockTrait;
+}
+class VoyagerMock extends \VuFind\ILS\Driver\Voyager
+{
+    use ILSMockTrait;
+}
+class VoyagerNoSupportMock extends \VuFind\ILS\Driver\Voyager
+{
+    use ILSMockTrait;
+    public function supportsMethod(...$args) {
+        return false;
+    }
+}
+class UnicornMock extends \VuFind\ILS\Driver\Unicorn
+{
+    use ILSMockTrait;
+}
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/ILS/Driver/NoILSTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/ILS/Driver/NoILSTest.php
index 584b47e7d05c579a464d0d7efe0c5b87e3c6eb7b..6f33ccbed56bc96dedce3ecd99f5cf66104b09e6 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/ILS/Driver/NoILSTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/ILS/Driver/NoILSTest.php
@@ -60,13 +60,13 @@ class NoILSTest extends \VuFindTest\Unit\TestCase
      */
     public function setUp()
     {
-        $this->loader = $this->getMock(
-            'VuFind\Record\Loader', [],
-            [
-                $this->getMock('VuFindSearch\Service'),
-                $this->getMock('VuFind\RecordDriver\PluginManager')
-            ]
-        );
+        $this->loader = $this->getMockBuilder('VuFind\Record\Loader')
+            ->setConstructorArgs(
+                [
+                    $this->createMock('VuFindSearch\Service'),
+                    $this->createMock('VuFind\RecordDriver\PluginManager')
+                ]
+            )->getMock();
         $this->driver = new NoILS($this->loader);
         $this->driver->init();
     }
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/ILS/Driver/PAIATest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/ILS/Driver/PAIATest.php
index 1af911b12ca7d3219767a0869cd3bef3d498b3bd..b622c449f39f97b6e82425212fef02080794bef7 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/ILS/Driver/PAIATest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/ILS/Driver/PAIATest.php
@@ -120,7 +120,7 @@ class PAIATest extends \VuFindTest\Unit\ILSDriverTestCase
                 'createdate' => '06-07-2016',
                 'duedate' => '',
                 'id' => '',
-                'title' => null,
+                'title' => 'Open source licensing : software freedom and intellectual property law ; [open source licensees are free to: use open source software for any purpose, make and distribute copies, create and distribute derivative works, access and use the source code, com / Rosen, Lawrence (c 2005)',
                 'feeid' => null,
                 'about' => 'Open source licensing : software freedom and intellectual property law ; [open source licensees are free to: use open source software for any purpose, make and distribute copies, create and distribute derivative works, access and use the source code, com / Rosen, Lawrence (c 2005)',
                 'item' => 'http://uri.gbv.de/document/opac-de-830:bar:830$28295402'
@@ -134,7 +134,7 @@ class PAIATest extends \VuFindTest\Unit\ILSDriverTestCase
                 'createdate' => '05-23-2016',
                 'duedate' => '',
                 'id' => '',
-                'title' => null,
+                'title' => 'Zend framework in action / Allen, Rob (2009)',
                 'feeid' => null,
                 'about' => 'Zend framework in action / Allen, Rob (2009)',
                 'item' => 'http://uri.gbv.de/document/opac-de-830:bar:830$28323471'
@@ -148,7 +148,7 @@ class PAIATest extends \VuFindTest\Unit\ILSDriverTestCase
                 'createdate' => '05-23-2016',
                 'duedate' => '',
                 'id' => '',
-                'title' => null,
+                'title' => 'Unsere historischen Gärten / Lutze, Margot (1986)',
                 'feeid' => null,
                 'about' => 'Unsere historischen Gärten / Lutze, Margot (1986)',
                 'item' => 'http://uri.gbv.de/document/opac-de-830:bar:830$24476416'
@@ -162,7 +162,7 @@ class PAIATest extends \VuFindTest\Unit\ILSDriverTestCase
                 'createdate' => '06-16-2016',
                 'duedate' => '',
                 'id' => '',
-                'title' => null,
+                'title' => 'Triumphe des Backsteins = Triumphs of brick / (1992)',
                 'feeid' => null,
                 'about' => 'Triumphe des Backsteins = Triumphs of brick / (1992)',
                 'item' => 'http://uri.gbv.de/document/opac-de-830:bar:830$33204941'
@@ -176,7 +176,7 @@ class PAIATest extends \VuFindTest\Unit\ILSDriverTestCase
                 'createdate' => '05-23-2016',
                 'duedate' => '',
                 'id' => '',
-                'title' => null,
+                'title' => 'Lehrbuch der Botanik / Strasburger, Eduard (2008)',
                 'feeid' => null,
                 'about' => 'Lehrbuch der Botanik / Strasburger, Eduard (2008)',
                 'item' => 'http://uri.gbv.de/document/opac-de-830:bar:830$26461872'
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/ILS/Driver/SymphonyTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/ILS/Driver/SymphonyTest.php
index 88afb6c84c92bd5d2d8f898a07fcc33a716217a0..d5682b730702c7e92bb343bfeab15b684cbcb79b 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/ILS/Driver/SymphonyTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/ILS/Driver/SymphonyTest.php
@@ -46,7 +46,10 @@ class SymphonyTest extends \VuFindTest\Unit\TestCase
      */
     public function __construct()
     {
-        $this->driver = new Symphony();
+        $loader = $this->getMockBuilder('VuFind\Record\Loader')
+            ->disableOriginalConstructor()->getMock();
+
+        $this->driver = new Symphony($loader);
     }
 
     /**
@@ -56,10 +59,6 @@ class SymphonyTest extends \VuFindTest\Unit\TestCase
      */
     public function testBadBaseUrl()
     {
-        if (!version_compare(\PHP_VERSION, '5.3.4', '>=')) {
-            $this->markTestSkipped('Test requires PHP >= 5.3.4 (see VUFIND-660)');
-        }
-
         // Without SOAP functionality, we can't proceed:
         if (!class_exists('SoapClient')) {
             $this->markTestSkipped('SoapClient not installed');
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/Log/LoggerTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/Log/LoggerTest.php
index 76e765994dcdcf7aeb1be79ae118b13ae63498a3..44925b4fbd90bcee7bd949892ff684fbb6b1f517 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/Log/LoggerTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/Log/LoggerTest.php
@@ -77,7 +77,9 @@ CONTEXT;
                 && false !== strpos($a[5], 'function =')
                 && count($a) == 5;
         };
-        $logger = $this->getMock('VuFind\Log\Logger', ['log']);
+        $logger = $this->getMockBuilder('VuFind\Log\Logger')
+            ->setMethods(['log'])
+            ->getMock();
         $logger->expects($this->once())->method('log')->with($this->equalTo(Logger::CRIT), $this->callback($callback));
         try {
             throw new \Exception('test');
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/Mailer/MailerTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/Mailer/MailerTest.php
index 0d7319b426ac1732b076299ed28c8f84d546153d..5ec74e6fa07163704f56e993fc3693c949a5fa52 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/Mailer/MailerTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/Mailer/MailerTest.php
@@ -54,7 +54,7 @@ class MailerTest extends \VuFindTest\Unit\TestCase
                 && 'body' == $message->getBody()
                 && 'subject' == $message->getSubject();
         };
-        $transport = $this->getMock('Zend\Mail\Transport\TransportInterface');
+        $transport = $this->createMock('Zend\Mail\Transport\TransportInterface');
         $transport->expects($this->once())->method('send')->with($this->callback($callback));
         $mailer = new Mailer($transport);
         $mailer->send('to@example.com', 'from@example.com', 'subject', 'body');
@@ -74,7 +74,7 @@ class MailerTest extends \VuFindTest\Unit\TestCase
                 && 'body' == $message->getBody()
                 && 'subject' == $message->getSubject();
         };
-        $transport = $this->getMock('Zend\Mail\Transport\TransportInterface');
+        $transport = $this->createMock('Zend\Mail\Transport\TransportInterface');
         $transport->expects($this->once())->method('send')->with($this->callback($callback));
         $address = new Address('from@example.com', 'Sender TextName');
         $mailer = new Mailer($transport);
@@ -95,7 +95,7 @@ class MailerTest extends \VuFindTest\Unit\TestCase
                 && 'body' == $message->getBody()
                 && 'subject' == $message->getSubject();
         };
-        $transport = $this->getMock('Zend\Mail\Transport\TransportInterface');
+        $transport = $this->createMock('Zend\Mail\Transport\TransportInterface');
         $transport->expects($this->once())->method('send')->with($this->callback($callback));
         $address = new Address('to@example.com', 'Recipient TextName');
         $mailer = new Mailer($transport);
@@ -116,7 +116,7 @@ class MailerTest extends \VuFindTest\Unit\TestCase
                 && 'body' == $message->getBody()
                 && 'subject' == $message->getSubject();
         };
-        $transport = $this->getMock('Zend\Mail\Transport\TransportInterface');
+        $transport = $this->createMock('Zend\Mail\Transport\TransportInterface');
         $transport->expects($this->once())->method('send')->with($this->callback($callback));
         $list = new AddressList();
         $list->add(new Address('to@example.com', 'Recipient TextName'));
@@ -134,7 +134,7 @@ class MailerTest extends \VuFindTest\Unit\TestCase
      */
     public function testBadTo()
     {
-        $transport = $this->getMock('Zend\Mail\Transport\TransportInterface');
+        $transport = $this->createMock('Zend\Mail\Transport\TransportInterface');
         $mailer = new Mailer($transport);
         $mailer->send('bad@bad', 'from@example.com', 'subject', 'body');
     }
@@ -149,7 +149,7 @@ class MailerTest extends \VuFindTest\Unit\TestCase
      */
     public function testEmptyTo()
     {
-        $transport = $this->getMock('Zend\Mail\Transport\TransportInterface');
+        $transport = $this->createMock('Zend\Mail\Transport\TransportInterface');
         $mailer = new Mailer($transport);
         $mailer->send('', 'from@example.com', 'subject', 'body');
     }
@@ -164,7 +164,7 @@ class MailerTest extends \VuFindTest\Unit\TestCase
      */
     public function testTooManyRecipients()
     {
-        $transport = $this->getMock('Zend\Mail\Transport\TransportInterface');
+        $transport = $this->createMock('Zend\Mail\Transport\TransportInterface');
         $mailer = new Mailer($transport);
         $mailer->send('one@test.com;two@test.com', 'from@example.com', 'subject', 'body');
     }
@@ -179,7 +179,7 @@ class MailerTest extends \VuFindTest\Unit\TestCase
      */
     public function testBadFrom()
     {
-        $transport = $this->getMock('Zend\Mail\Transport\TransportInterface');
+        $transport = $this->createMock('Zend\Mail\Transport\TransportInterface');
         $mailer = new Mailer($transport);
         $mailer->send('to@example.com', 'bad@bad', 'subject', 'body');
     }
@@ -194,7 +194,7 @@ class MailerTest extends \VuFindTest\Unit\TestCase
      */
     public function testBadFromInAddressObject()
     {
-        $transport = $this->getMock('Zend\Mail\Transport\TransportInterface');
+        $transport = $this->createMock('Zend\Mail\Transport\TransportInterface');
         $mailer = new Mailer($transport);
         $mailer->send('to@example.com', new Address('bad@bad'), 'subject', 'body');
     }
@@ -209,7 +209,7 @@ class MailerTest extends \VuFindTest\Unit\TestCase
      */
     public function testTransportException()
     {
-        $transport = $this->getMock('Zend\Mail\Transport\TransportInterface');
+        $transport = $this->createMock('Zend\Mail\Transport\TransportInterface');
         $transport->expects($this->once())->method('send')->will($this->throwException(new \Exception('Boom')));
         $mailer = new Mailer($transport);
         $mailer->send('to@example.com', 'from@example.com', 'subject', 'body');
@@ -228,7 +228,8 @@ class MailerTest extends \VuFindTest\Unit\TestCase
                 && $in['from'] == 'from@example.com'
                 && $in['message'] == 'message';
         };
-        $view = $this->getMock('Zend\View\Renderer\PhpRenderer', ['partial']);
+        $view = $this->getMockBuilder(__NAMESPACE__ . '\MockEmailRenderer')
+            ->setMethods(['partial'])->getMock();
         $view->expects($this->once())->method('partial')
             ->with($this->equalTo('Email/share-link.phtml'), $this->callback($viewCallback))
             ->will($this->returnValue('body'));
@@ -243,7 +244,7 @@ class MailerTest extends \VuFindTest\Unit\TestCase
                 && 'body' == $message->getBody()
                 && 'Library Catalog Search Result' == $message->getSubject();
         };
-        $transport = $this->getMock('Zend\Mail\Transport\TransportInterface');
+        $transport = $this->createMock('Zend\Mail\Transport\TransportInterface');
         $transport->expects($this->once())->method('send')->with($this->callback($callback));
         $mailer = new Mailer($transport);
         $mailer->setMaxRecipients(2);
@@ -260,7 +261,7 @@ class MailerTest extends \VuFindTest\Unit\TestCase
      */
     public function testSendRecord()
     {
-        $driver = $this->getMock('VuFind\RecordDriver\AbstractBase');
+        $driver = $this->createMock('VuFind\RecordDriver\AbstractBase');
         $driver->expects($this->once())->method('getBreadcrumb')->will($this->returnValue('breadcrumb'));
 
         $viewCallback = function ($in) use ($driver) {
@@ -269,7 +270,8 @@ class MailerTest extends \VuFindTest\Unit\TestCase
                 && $in['from'] == 'from@example.com'
                 && $in['message'] == 'message';
         };
-        $view = $this->getMock('Zend\View\Renderer\PhpRenderer', ['partial']);
+        $view = $this->getMockBuilder(__NAMESPACE__ . '\MockEmailRenderer')
+            ->setMethods(['partial'])->getMock();
         $view->expects($this->once())->method('partial')
             ->with($this->equalTo('Email/record.phtml'), $this->callback($viewCallback))
             ->will($this->returnValue('body'));
@@ -280,9 +282,15 @@ class MailerTest extends \VuFindTest\Unit\TestCase
                 && 'body' == $message->getBody()
                 && 'Library Catalog Record: breadcrumb' == $message->getSubject();
         };
-        $transport = $this->getMock('Zend\Mail\Transport\TransportInterface');
+        $transport = $this->createMock('Zend\Mail\Transport\TransportInterface');
         $transport->expects($this->once())->method('send')->with($this->callback($callback));
         $mailer = new Mailer($transport);
         $mailer->sendRecord('to@example.com', 'from@example.com', 'message', $driver, $view);
     }
 }
+
+class MockEmailRenderer extends \Zend\View\Renderer\PhpRenderer
+{
+    public function partial($template, $driver) {
+    }
+}
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/QRCode/LoaderTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/QRCode/LoaderTest.php
index 737e0d3e8652b73f81a35bb553e29696156a4ef9..932a65e24cf71270db05c5dd6bfe92933e8f06d7 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/QRCode/LoaderTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/QRCode/LoaderTest.php
@@ -58,7 +58,8 @@ class LoaderTest extends \VuFindTest\Unit\TestCase
      */
     public function testUtterFailure()
     {
-        $theme = $this->getMock('VuFindTheme\ThemeInfo', [], ['foo', 'bar']);
+        $theme = $this->getMockBuilder('VuFindTheme\ThemeInfo')
+            ->setConstructorArgs(['foo', 'bar'])->getMock();
         $theme->expects($this->once())->method('findContainingTheme')->with($this->equalTo(['images/noQRCode.gif']))->will($this->returnValue(false));
         $loader = $this->getLoader([], $theme);
         $loader->getImage();
@@ -93,7 +94,10 @@ class LoaderTest extends \VuFindTest\Unit\TestCase
             $theme = new ThemeInfo($this->getThemeDir(), $this->testTheme);
         }
         if ($mock) {
-            return $this->getMock('VuFind\QRCode\Loader', $mock, [$config, $theme]);
+            return $this->getMockBuilder('VuFind\QRCode\Loader')
+                ->setMethods($mock)
+                ->setConstructorArgs([$config, $theme])
+                ->getMock();
         }
         return new Loader($config, $theme);
     }
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/Recommend/EuropeanaResultsTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/Recommend/EuropeanaResultsTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..ae9b739a6dfb830d4ed9667dabee55d0d6eaefe4
--- /dev/null
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/Recommend/EuropeanaResultsTest.php
@@ -0,0 +1,168 @@
+<?php
+
+/**
+ * EuropeanaResults tests.
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2017.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * @category VuFind
+ * @package  Tests
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development:testing:unit_tests Wiki
+ */
+namespace VuFindTest\Recommend;
+
+use VuFind\Recommend\EuropeanaResults;
+use VuFindHttp\HttpService;
+use VuFindTest\Unit\TestCase as TestCase;
+use Zend\Http\Client\Adapter\Test as TestAdapter;
+
+/**
+ * EuropeanaResults tests.
+ *
+ * @category VuFind
+ * @package  Tests
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development:testing:unit_tests Wiki
+ */
+class EuropeanaResultsTest extends TestCase
+{
+    /**
+     * Test that the module properly parses a sample response.
+     *
+     * This is a bare minimum test to confirm that Zend\Feed deals with the RSS
+     * response correctly. More work should be done to confirm that URL generation
+     * works appropriately, optional configuration parameters are respected, etc.
+     *
+     * @return void
+     */
+    public function testResponseParsing()
+    {
+        $europeana = new EuropeanaResults('fakekey');
+        $europeana->setHttpService($this->getHttpService());
+        $europeana->setConfig(''); // use defaults
+        $results = $this->getMockResults();
+        $query = new \Zend\StdLib\Parameters(['lookfor' => 'test']);
+        $europeana->init($results->getParams(), $query);
+        $europeana->process($results);
+        $this->assertEquals(
+            [
+                'worksArray' => [
+                    [
+                        'title' => 'Guiard des Moulins , Petite Bible historiale de Charles V. [Paris, BnF, MSS Français 5707]',
+                        'link' => 'http://www.europeana.eu/portal/record/92099/BibliographicResource_2000068736886.html',
+                        'enclosure' => null,
+                    ],
+                    [
+                        'title' => 'Guiard des Moulins , Bible Historiale de Jean de Berry. [Paris, BnF, MSS Français 20090]',
+                        'link' => 'http://www.europeana.eu/portal/record/92099/BibliographicResource_2000060239235.html',
+                        'enclosure' => null,
+                    ],
+                    [
+                        'title' => 'Saint Augustin , De civitate Dei (Livres XI-XXII) , traduit en français par Raoul de Presle. [Paris, BnF, MSS Français 173]',
+                        'link' => 'http://www.europeana.eu/portal/record/92099/BibliographicResource_1000157170726.html',
+                        'enclosure' => null,
+                    ],
+                    [
+                        'title' => 'Saint Augustin , La cité de Dieu [De Civitate Dei] , (Livres XI-XXII), traduit en français par Raoul de Presles. [Paris, BnF, MSS Français 174]',
+                        'link' => 'http://www.europeana.eu/portal/record/92099/BibliographicResource_1000157170711.html',
+                        'enclosure' => null,
+                    ],
+                    [
+                        'title' => 'Saint Augustin , De Civitate Dei , traduit en français par Raoul de Presles (Livre I-X). [Paris, BnF, MSS Français 22912]',
+                        'link' => 'http://www.europeana.eu/portal/record/92099/BibliographicResource_1000157170710.html',
+                        'enclosure' => null,
+                    ],
+                ],
+                'feedTitle' => 'Europeana.eu',
+                'sourceLink' =>
+                    'http://www.europeana.eu/portal/search.html?query=test',
+            ],
+            $europeana->getResults()
+        );
+    }
+
+    /**
+     * Return connector.
+     *
+     * @param string $fixture HTTP response fixture to load (optional)
+     *
+     * @return HttpClient
+     */
+    protected function getHttpService($fixture = 'europeana')
+    {
+        $adapter = new TestAdapter();
+        if ($fixture) {
+            $adapter->setResponse($this->loadResponse($fixture));
+        }
+        $service = new HttpService();
+        $service->setDefaultAdapter($adapter);
+        return $service;
+    }
+
+    /**
+     * Get a fixture response
+     *
+     * @return string
+     */
+    protected function loadResponse($file)
+    {
+        $fixturePath = realpath(__DIR__ . '/../../../../fixtures/recommend') . '/';
+        return file_get_contents($fixturePath . $file);
+    }
+
+    /**
+     * Get a mock results object.
+     *
+     * @param \VuFind\Search\Solr\Params $params Params to include in container.
+     *
+     * @return \VuFind\Search\Solr\Results
+     */
+    protected function getMockResults($params = null)
+    {
+        if (null === $params) {
+            $params = $this->getMockParams();
+        }
+        $results = $this->getMockBuilder('VuFind\Search\Solr\Results')
+            ->disableOriginalConstructor()->getMock();
+        $results->expects($this->any())->method('getParams')
+            ->will($this->returnValue($params));
+        return $results;
+    }
+
+    /**
+     * Get a mock params object.
+     *
+     * @param \VuFindSearch\Query\Query $query Query to include in container.
+     *
+     * @return \VuFind\Search\Solr\Params
+     */
+    protected function getMockParams($query = null)
+    {
+        if (null === $query) {
+            $query = new \VuFindSearch\Query\Query('foo', 'bar');
+        }
+        $params = $this->getMockBuilder('VuFind\Search\Solr\Params')
+            ->disableOriginalConstructor()->getMock();
+        $params->expects($this->any())->method('getQuery')
+            ->will($this->returnValue($query));
+        return $params;
+    }
+}
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/Recommend/RandomRecommendTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/Recommend/RandomRecommendTest.php
index df7e823d363ac21f5b35ed14ae848aea54960a93..27486bcee97bf3da604819091496c2199e00b13c 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/Recommend/RandomRecommendTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/Recommend/RandomRecommendTest.php
@@ -50,8 +50,8 @@ class RandomRecommendTest extends TestCase
     public function setup()
     {
         $this->recommend = new Random(
-            $this->getMock('VuFindSearch\Service'),
-            $this->getMock('VuFind\Search\Params\PluginManager')
+            $this->createMock('VuFindSearch\Service'),
+            $this->createMock('VuFind\Search\Params\PluginManager')
         );
     }
 
@@ -144,8 +144,8 @@ class RandomRecommendTest extends TestCase
      */
     public function testCanInitialise()
     {
-        $service = $this->getMock('VuFindSearch\Service');
-        $paramManager = $this->getMock('VuFind\Search\Params\PluginManager');
+        $service = $this->createMock('VuFindSearch\Service');
+        $paramManager = $this->createMock('VuFind\Search\Params\PluginManager');
         $recommend = new Random($service, $paramManager);
 
         // Use Solr since some Base components are abstract:
@@ -153,14 +153,14 @@ class RandomRecommendTest extends TestCase
             ->get('Solr');
         $query = $this->getFixture('query');
         $params->setBasicSearch($query->getString(), $query->getHandler());
-        $request = $this->getMock('\Zend\StdLib\Parameters');
+        $request = $this->createMock('\Zend\StdLib\Parameters');
 
         $service->expects($this->once())->method('random')
             ->with(
                 $this->equalTo("Solr"),
                 $this->equalTo($params->getQuery()),
                 $this->equalTo(10)
-            )->will($this->returnValue($this->getMock('VuFindSearch\Response\RecordCollectionInterface')));
+            )->will($this->returnValue($this->createMock('VuFindSearch\Response\RecordCollectionInterface')));
 
         $recommend->setConfig("Solr:10:mixed:retain:20:facet1:value1:facet2:value2");
         $recommend->init($params, $request);
@@ -173,8 +173,8 @@ class RandomRecommendTest extends TestCase
      */
     public function testCanInitialiseInDisregardMode()
     {
-        $service = $this->getMock('VuFindSearch\Service');
-        $paramManager = $this->getMock('VuFind\Search\Params\PluginManager');
+        $service = $this->createMock('VuFindSearch\Service');
+        $paramManager = $this->createMock('VuFind\Search\Params\PluginManager');
         $recommend = new Random($service, $paramManager);
 
         $paramManager->expects($this->once())->method('get')
@@ -191,11 +191,11 @@ class RandomRecommendTest extends TestCase
             ->get('Solr');
         $query = $this->getFixture('query');
         $params->setBasicSearch($query->getString(), $query->getHandler());
-        $request = $this->getMock('\Zend\StdLib\Parameters');
+        $request = $this->createMock('\Zend\StdLib\Parameters');
 
         $service->expects($this->once())->method('random')
             ->with($this->equalTo("Solr"))
-            ->will($this->returnValue($this->getMock('VuFindSearch\Response\RecordCollectionInterface')));
+            ->will($this->returnValue($this->createMock('VuFindSearch\Response\RecordCollectionInterface')));
 
         $recommend->setConfig("Solr:10:mixed:disregard:20:facet1:value1:facet2:value2");
         $recommend->init($params, $request);
@@ -208,8 +208,8 @@ class RandomRecommendTest extends TestCase
      */
     public function testWillReturnEmptyForMinimumResultLimit()
     {
-        $service = $this->getMock('VuFindSearch\Service');
-        $paramManager = $this->getMock('VuFind\Search\Params\PluginManager');
+        $service = $this->createMock('VuFindSearch\Service');
+        $paramManager = $this->createMock('VuFind\Search\Params\PluginManager');
         $recommend = new Random($service, $paramManager);
         $records = ["1", "2", "3", "4", "5"];
 
@@ -219,9 +219,9 @@ class RandomRecommendTest extends TestCase
         $params = $results->getParams();
         $query = $this->getFixture('query');
         $params->setBasicSearch($query->getString(), $query->getHandler());
-        $request = $this->getMock('\Zend\StdLib\Parameters');
+        $request = $this->createMock('\Zend\StdLib\Parameters');
 
-        $results = $this->getMock('VuFindSearch\Response\RecordCollectionInterface');
+        $results = $this->createMock('VuFindSearch\Response\RecordCollectionInterface');
         $results->expects($this->once())->method('getRecords')
             ->will($this->returnValue($records));
 
@@ -246,8 +246,8 @@ class RandomRecommendTest extends TestCase
      */
     public function testWillReturnResults()
     {
-        $service = $this->getMock('VuFindSearch\Service');
-        $paramManager = $this->getMock('VuFind\Search\Params\PluginManager');
+        $service = $this->createMock('VuFindSearch\Service');
+        $paramManager = $this->createMock('VuFind\Search\Params\PluginManager');
         $recommend = new Random($service, $paramManager);
         $records = ["1", "2", "3", "4", "5"];
 
@@ -257,9 +257,9 @@ class RandomRecommendTest extends TestCase
         $params = $results->getParams();
         $query = $this->getFixture('query');
         $params->setBasicSearch($query->getString(), $query->getHandler());
-        $request = $this->getMock('\Zend\StdLib\Parameters');
+        $request = $this->createMock('\Zend\StdLib\Parameters');
 
-        $results = $this->getMock('VuFindSearch\Response\RecordCollectionInterface');
+        $results = $this->createMock('VuFindSearch\Response\RecordCollectionInterface');
         $results->expects($this->once())->method('getRecords')
             ->will($this->returnValue($records));
 
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/Record/CacheTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/Record/CacheTest.php
index bebf604c43c9cf87d05c22c4d4326e7809f473f5..0a7ad313deafe95cadaf9daf1d3ef7fe9e4f3e5b 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/Record/CacheTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/Record/CacheTest.php
@@ -256,7 +256,8 @@ class CacheTest extends TestCase
             return false;
         };
 
-        $recordTable = $this->getMock('VuFind\Db\Table\Record');
+        $recordTable = $this->getMockBuilder('VuFind\Db\Table\Record')
+            ->disableOriginalConstructor()->getMock();
         $recordTable->method('findRecords')
             ->will($this->returnCallback($findRecordsCallback));
         $recordTable->method('findRecord')
@@ -283,7 +284,7 @@ class CacheTest extends TestCase
      */
     protected function getRecordFactoryManager()
     {
-        $recordFactoryManager = $this->getMock(
+        $recordFactoryManager = $this->createMock(
             'VuFind\RecordDriver\PluginManager'
         );
         $recordFactoryManager->method('getSolrRecord')->will(
@@ -323,7 +324,7 @@ class CacheTest extends TestCase
      */
     protected function getDriver($id = 'test', $source = 'Solr')
     {
-        $driver = $this->getMock('VuFind\RecordDriver\AbstractBase');
+        $driver = $this->createMock('VuFind\RecordDriver\AbstractBase');
         $driver->expects($this->any())
             ->method('getUniqueId')
             ->will($this->returnValue($id));
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/Record/LoaderTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/Record/LoaderTest.php
index 0406874f133bad42f1169885d6ceb14deac12848..99ce6b1f5dde62c394aeef83faa2ee0ec8f28959 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/Record/LoaderTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/Record/LoaderTest.php
@@ -57,7 +57,7 @@ class LoaderTest extends TestCase
     public function testMissingRecord()
     {
         $collection = $this->getCollection([]);
-        $service = $this->getMock('VuFindSearch\Service');
+        $service = $this->createMock('VuFindSearch\Service');
         $service->expects($this->once())->method('retrieve')
             ->with($this->equalTo('Solr'), $this->equalTo('test'))
             ->will($this->returnValue($collection));
@@ -73,12 +73,12 @@ class LoaderTest extends TestCase
     public function testToleratedMissingRecord()
     {
         $collection = $this->getCollection([]);
-        $service = $this->getMock('VuFindSearch\Service');
+        $service = $this->createMock('VuFindSearch\Service');
         $service->expects($this->once())->method('retrieve')
             ->with($this->equalTo('Solr'), $this->equalTo('test'))
             ->will($this->returnValue($collection));
         $missing = $this->getDriver('missing', 'Missing');
-        $factory = $this->getMock('VuFind\RecordDriver\PluginManager');
+        $factory = $this->createMock('VuFind\RecordDriver\PluginManager');
         $factory->expects($this->once())->method('get')
             ->with($this->equalTo('Missing'))
             ->will($this->returnValue($missing));
@@ -96,7 +96,7 @@ class LoaderTest extends TestCase
     {
         $driver = $this->getDriver();
         $collection = $this->getCollection([$driver]);
-        $service = $this->getMock('VuFindSearch\Service');
+        $service = $this->createMock('VuFindSearch\Service');
         $service->expects($this->once())->method('retrieve')
             ->with($this->equalTo('Solr'), $this->equalTo('test'))
             ->will($this->returnValue($collection));
@@ -120,12 +120,12 @@ class LoaderTest extends TestCase
         $collection2 = $this->getCollection([$driver3]);
         $collection3 = $this->getCollection([]);
 
-        $factory = $this->getMock('VuFind\RecordDriver\PluginManager');
+        $factory = $this->createMock('VuFind\RecordDriver\PluginManager');
         $factory->expects($this->once())->method('get')
             ->with($this->equalTo('Missing'))
             ->will($this->returnValue($missing));
 
-        $service = $this->getMock('VuFindSearch\Service');
+        $service = $this->createMock('VuFindSearch\Service');
         $service->expects($this->at(0))->method('retrieveBatch')
             ->with($this->equalTo('Solr'), $this->equalTo(['test1', 'test2']))
             ->will($this->returnValue($collection1));
@@ -154,7 +154,7 @@ class LoaderTest extends TestCase
      */
     protected function getDriver($id = 'test', $source = 'Solr')
     {
-        $driver = $this->getMock('VuFind\RecordDriver\AbstractBase');
+        $driver = $this->createMock('VuFind\RecordDriver\AbstractBase');
         $driver->expects($this->any())->method('getUniqueId')
             ->will($this->returnValue($id));
         $driver->expects($this->any())->method('getSourceIdentifier')
@@ -173,7 +173,7 @@ class LoaderTest extends TestCase
     protected function getLoader(SearchService $service, RecordFactory $factory = null)
     {
         if (null === $factory) {
-            $factory = $this->getMock('VuFind\RecordDriver\PluginManager');
+            $factory = $this->createMock('VuFind\RecordDriver\PluginManager');
         }
         return new Loader($service, $factory);
     }
@@ -187,7 +187,7 @@ class LoaderTest extends TestCase
      */
     protected function getCollection($records)
     {
-        $collection = $this->getMock('VuFindSearch\Response\RecordCollectionInterface');
+        $collection = $this->createMock('VuFindSearch\Response\RecordCollectionInterface');
         $collection->expects($this->any())->method('getRecords')->will($this->returnValue($records));
         $collection->expects($this->any())->method('count')->will($this->returnValue(count($records)));
         return $collection;
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/Record/RouterTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/Record/RouterTest.php
index fa405428915169704297ed23eb661b0474754429..1a4be2c7d2b6f8ed61a043bf2c4e609ee6f4e137 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/Record/RouterTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/Record/RouterTest.php
@@ -174,7 +174,7 @@ class RouterTest extends TestCase
      */
     protected function getDriver($id = 'test', $source = 'Solr')
     {
-        $driver = $this->getMock('VuFind\RecordDriver\AbstractBase');
+        $driver = $this->createMock('VuFind\RecordDriver\AbstractBase');
         $driver->expects($this->any())->method('getUniqueId')
             ->will($this->returnValue($id));
         $driver->expects($this->any())->method('getSourceIdentifier')
@@ -195,13 +195,13 @@ class RouterTest extends TestCase
         if (null === $record) {
             $record = $this->getDriver();
         }
-        $loader = $this->getMock(
-            'VuFind\Record\Loader', [],
-            [
-                $this->getMock('VuFindSearch\Service'),
-                $this->getMock('VuFind\RecordDriver\PluginManager')
-            ]
-        );
+        $loader = $this->getMockBuilder('VuFind\Record\Loader')
+            ->setConstructorArgs(
+                [
+                    $this->createMock('VuFindSearch\Service'),
+                    $this->createMock('VuFind\RecordDriver\PluginManager')
+                ]
+            )->getMock();
         $loader->expects($this->any())->method('load')
             ->will($this->returnValue($record));
 
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/RecordDriver/SolrMarcTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/RecordDriver/SolrMarcTest.php
index 248750950754f81654513f96eb8a90124125e5eb..458895121e37ba84733e5442504361d3e768e27c 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/RecordDriver/SolrMarcTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/RecordDriver/SolrMarcTest.php
@@ -93,6 +93,33 @@ class SolrMarcTest extends \VuFindTest\Unit\TestCase
         $this->assertEquals('2, pt. 1.', $series[0]['number']);
     }
 
+    /**
+     * Test regular and extended subject heading support.
+     *
+     * @return void
+     */
+    public function testSubjectHeadings()
+    {
+        $config = new \Zend\Config\Config([]);
+        $record = new \VuFind\RecordDriver\SolrMarc($config);
+        $fixture = $this->loadRecordFixture('testbug1.json');
+        $record->setRawData($fixture['response']['docs'][0]);
+        $this->assertEquals(
+            [['Matematica', 'Periodici.']],
+            $record->getAllSubjectHeadings()
+        );
+        $this->assertEquals(
+            [
+                [
+                    'heading' => ['Matematica', 'Periodici.'],
+                    'type' => '',
+                    'source' => ''
+                ],
+            ],
+            $record->getAllSubjectHeadings(true)
+        );
+    }
+
     /**
      * Load a fixture file.
      *
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/Related/SimilarTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/Related/SimilarTest.php
index 5b627aef27af46f5dbb1d13901f05783f4874d83..34f5c0af8ec18aa9099fd9e09d27d852f8c3552f 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/Related/SimilarTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/Related/SimilarTest.php
@@ -48,11 +48,15 @@ class SimilarTest extends \VuFindTest\Unit\TestCase
     {
         // Similar is really just a thin wrapper around the search service; make
         // sure it does its job properly with the help of some mocks.
-        $driver = $this->getMock('VuFind\RecordDriver\SolrDefault', ['getUniqueId']);
+        $driver = $this->getMockBuilder('VuFind\RecordDriver\SolrDefault')
+            ->setMethods(['getUniqueId'])
+            ->getMock();
         $driver->expects($this->once())
             ->method('getUniqueId')
             ->will($this->returnValue('fakeid'));
-        $service = $this->getMock('VuFindSearch\Service', ['similar']);
+        $service = $this->getMockBuilder('VuFindSearch\Service')
+            ->setMethods(['similar'])
+            ->getMock();
         $service->expects($this->once())
             ->method('similar')
             ->with($this->equalTo('Solr'), $this->equalTo('fakeid'))
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/Related/WorldCatSimilarTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/Related/WorldCatSimilarTest.php
index 19b67cf1b98f4a7b1f7c9289f9f7f9a431c7fafe..d1bc18b54a829a0d74b71ead4be6eadf5ddd1426 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/Related/WorldCatSimilarTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/Related/WorldCatSimilarTest.php
@@ -46,10 +46,9 @@ class WorldCatSimilarTest extends \VuFindTest\Unit\TestCase
      */
     public function testGetResults()
     {
-        $driver = $this->getMock(
-            'VuFind\RecordDriver\WorldCat',
-            ['tryMethod', 'getPrimaryAuthor', 'getAllSubjectHeadings', 'getTitle', 'getUniqueId', 'getSourceIdentifier']
-        );
+        $driver = $this->getMockBuilder('VuFind\RecordDriver\WorldCat')
+            ->setMethods(['tryMethod', 'getPrimaryAuthor', 'getAllSubjectHeadings', 'getTitle', 'getUniqueId', 'getSourceIdentifier'])
+            ->getMock();
         $driver->expects($this->once())
             ->method('tryMethod')
             ->with($this->equalTo('getDeweyCallNumber'))
@@ -69,9 +68,13 @@ class WorldCatSimilarTest extends \VuFindTest\Unit\TestCase
         $driver->expects($this->once())
             ->method('getSourceIdentifier')
             ->will($this->returnValue('WorldCat'));
-        $service = $this->getMock('VuFindSearch\Service', ['search']);
+        $service = $this->getMockBuilder('VuFindSearch\Service')
+            ->setMethods(['search'])->getMock();
         $expectedQuery = new Query('(srw.dd any "fakedc" or srw.au all "fakepa" or srw.su all "fakesh1a fakesh1b" or srw.su all "fakesh2" or srw.ti any "faketitle") not srw.no all "fakeid"');
-        $response = $this->getMock('VuFindSearch\Backend\WorldCat\Response\XML\RecordCollection', ['getRecords'], [['offset' => 0, 'total' => 0]]);
+        $response = $this->getMockBuilder('VuFindSearch\Backend\WorldCat\Response\XML\RecordCollection')
+            ->setMethods(['getRecords'])
+            ->setConstructorArgs([['offset' => 0, 'total' => 0]])
+            ->getMock();
         $response->expects($this->once())
             ->method('getRecords')
             ->will($this->returnValue(['fakeresponse']));
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/Resolver/Driver/EzbTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/Resolver/Driver/EzbTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..11d0dd2b88bf1470834c59089d9fa618eadbb277
--- /dev/null
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/Resolver/Driver/EzbTest.php
@@ -0,0 +1,168 @@
+<?php
+/**
+ * Ezb resolver driver test
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Leipzig University Library 2015.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * @category VuFind
+ * @package  Tests
+ * @author   André Lahmann <lahmann@ub.uni-leipzig.de>
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org Main Page
+ */
+namespace VuFindTest\Resolver\Driver;
+use VuFind\Resolver\Driver\Ezb;
+
+use Zend\Http\Client\Adapter\Test as TestAdapter;
+use Zend\Http\Response as HttpResponse;
+
+use InvalidArgumentException;
+
+/**
+ * Ezb resolver driver test
+ *
+ * @category VuFind
+ * @package  Tests
+ * @author   André Lahmann <lahmann@ub.uni-leipzig.de>
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org Main Page
+ */
+class EzbTest extends \VuFindTest\Unit\TestCase
+{
+    /**
+     * Test-Config
+     *
+     * @var array
+     */
+    protected $openUrlConfig = [
+        'OpenURL' => [
+            'url' => "http://services.d-nb.de/fize-service/gvr/full.xml",
+            'rfr_id' => "www.ub.uni-leipzig.de",
+            'resolver' => "ezb",
+            'window_settings' => "toolbar=no,location=no,directories=no,buttons=no,status=no,menubar=no,scrollbars=yes,resizable=yes,width=550,height=600",
+            'show_in_results' => false,
+            'show_in_record' => false,
+            'show_in_holdings' => true,
+            'embed' => true,
+            'replace_other_urls' => true
+        ],
+    ];
+
+    /**
+     * Test
+     *
+     * @return void
+     */
+    public function testParseLinks()
+    {
+        $conn = $this->createConnector('ezb.xml');
+
+        $openUrl = "url_ver=Z39.88-2004&ctx_ver=Z39.88-2004&ctx_enc=info%3Aofi%2Fenc%3AUTF-8&rfr_id=info%3Asid%2Fwww.ub.uni-leipzig.de%3Agenerator&rft.title=No%C3%BBs&rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Adc&rft.creator=&rft.pub=Wiley-Blackwell&rft.format=Journal&rft.language=English&rft.issn=0029-4624&zdbid=339287-9";
+        $result = $conn->parseLinks($conn->fetchLinks($openUrl));
+
+        $testResult = [
+            0 => [
+                'title' => 'Noûs : a Quarterly Journal of Philosophy (1997-)',
+                'coverage' => 'ab Vol. 31, Iss. 1 (1997)',
+                'access' => 'limited',
+                'href' => 'http://onlinelibrary.wiley.com/journal/10.1111/(ISSN)1468-0068',
+                'service_type' => 'getFullTxt'
+            ],
+            1 => [
+                'title' => 'Noûs (ältere Jahrgänge via JSTOR)',
+                'coverage' => 'ab Vol. 1, Iss. 1 (1967); für die Ausgaben der aktuellen 11 Jahrgänge nicht verfügbar',
+                'access' => 'limited',
+                'href' => 'http://www.jstor.org/action/showPublication?journalCode=nous',
+                'service_type' => 'getFullTxt'
+            ],
+            2 => [
+                'title' => 'Nous (via EBSCO Host)',
+                'coverage' => 'für die Ausgaben der vergangenen 12 Monate nicht verfügbar',
+                'access' => 'limited',
+                'href' => 'http://search.ebscohost.com/direct.asp?db=aph&jid=D97&scope=site',
+                'service_type' => 'getFullTxt'
+            ],
+            3 => [
+                'title' => 'Nous (via EBSCO Host)',
+                'coverage' => 'für die Ausgaben der vergangenen 12 Monate nicht verfügbar',
+                'access' => 'limited',
+                'href' => 'http://search.ebscohost.com/direct.asp?db=lfh&jid=D97&scope=site',
+                'service_type' => 'getFullTxt'
+            ],
+            4 => [
+                'title' => 'Philosophical Perspectives (aktuelle Jahrgänge)',
+                'coverage' => 'ab Vol. 17 (2003)',
+                'access' => 'limited',
+                'href' => 'http://onlinelibrary.wiley.com/journal/10.1111/%28ISSN%291520-8583',
+                'service_type' => 'getFullTxt'
+            ],
+            5 => [
+                'title' => 'Print available',
+                'coverage' => 'Philosophical perspectives; Leipzig UB; Nachweis als Serie',
+                'access' => 'open',
+                'href' => 'http://dispatch.opac.dnb.de/CHARSET=ISO-8859-1/DB=1.1/CMD?ACT=SRCHA&IKT=8509&SRT=LST_ty&TRM=IDN+011960027+or+IDN+01545794X&HLIB=009030085#009030085',
+                'service_type' => 'getHolding'
+            ],
+            6 => [
+                'title' => 'Print available',
+                'coverage' => 'Noûs; Leipzig UB // HB/FH/ Standortsignatur: 96-7-558; CA 5470 Magazin: 96-7-558; 1.1967 - 27.1993; 30.1996 - 43.2009; Letzten 15 Jg. Freihand',
+                'access' => 'open',
+                'service_type' => 'getHolding'
+            ]
+        ];
+
+        $this->assertEquals($result, $testResult);
+    }
+
+    /**
+     * Create connector with fixture file.
+     *
+     * @param string $fixture Fixture file
+     *
+     * @return Connector
+     *
+     * @throws InvalidArgumentException Fixture file does not exist
+     */
+    protected function createConnector($fixture = null)
+    {
+        $adapter = new TestAdapter();
+        if ($fixture) {
+            $file = realpath(
+                __DIR__ .
+                '/../../../../../../tests/fixtures/resolver/response/' . $fixture
+            );
+            if (!is_string($file) || !file_exists($file) || !is_readable($file)) {
+                throw new InvalidArgumentException(
+                    sprintf('Unable to load fixture file: %s ', $file)
+                );
+            }
+            $response = file_get_contents($file);
+            $responseObj = HttpResponse::fromString($response);
+            $adapter->setResponse($responseObj);
+        }
+        $_SERVER['REMOTE_ADDR'] = "127.0.0.1";
+
+        $client = new \Zend\Http\Client();
+        $client->setAdapter($adapter);
+
+        $conn = new Ezb($this->openUrlConfig['OpenURL']['url'], $client);
+        return $conn;
+    }
+}
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/Role/DynamicRoleProviderTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/Role/DynamicRoleProviderTest.php
index 76455cf40f7b5a9846f76c5a46ea6388178bc7cc..7cb020fc6a24da2540d991d29369dec533094d4f 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/Role/DynamicRoleProviderTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/Role/DynamicRoleProviderTest.php
@@ -101,7 +101,7 @@ class DynamicRoleProviderTest extends \VuFindTest\Unit\TestCase
     {
         $pm = new PluginManager();
         foreach (['a', 'b', 'c'] as $name) {
-            $pm->setService($name, $this->getMock('VuFind\Role\PermissionProvider\PermissionProviderInterface'));
+            $pm->setService($name, $this->createMock('VuFind\Role\PermissionProvider\PermissionProviderInterface'));
         }
         return $pm;
     }
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/SMS/ClickatellTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/SMS/ClickatellTest.php
index 29bbbf23964fc72f09a37aa76fd978fad84ed15b..6e907193f2d8e017b0a43f0f51e675c4fd6d9820 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/SMS/ClickatellTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/SMS/ClickatellTest.php
@@ -194,6 +194,6 @@ class ClickatellTest extends \VuFindTest\Unit\TestCase
      */
     protected function getMockClient()
     {
-        return $this->getMock('Zend\Http\Client');
+        return $this->createMock('Zend\Http\Client');
     }
 }
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/Search/Primo/OnCampusListenerTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/Search/Primo/OnCampusListenerTest.php
index 2f9971b24e825f5e4551de769349f4ffffa615d8..020d4d4301cb802c9a6abbd0bbd171866d7fb447 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/Search/Primo/OnCampusListenerTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/Search/Primo/OnCampusListenerTest.php
@@ -73,7 +73,7 @@ class OnCampusListenerTest extends TestCase
     public function testAttach()
     {
         $listener = new InjectOnCampusListener();
-        $mock = $this->getMock('Zend\EventManager\SharedEventManagerInterface');
+        $mock = $this->createMock('Zend\EventManager\SharedEventManagerInterface');
         $mock->expects($this->once())->method('attach')->with(
             $this->equalTo('VuFind\Search'),
             $this->equalTo('pre'),
@@ -93,7 +93,7 @@ class OnCampusListenerTest extends TestCase
             ->disableOriginalConstructor()
             ->getMock();
         $listener = new InjectOnCampusListener($mockPermController);
-        $mock = $this->getMock('Zend\EventManager\SharedEventManagerInterface');
+        $mock = $this->createMock('Zend\EventManager\SharedEventManagerInterface');
         $mock->expects($this->once())->method('attach')->with(
             $this->equalTo('VuFind\Search'),
             $this->equalTo('pre'),
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/Search/SearchTabsHelperTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/Search/SearchTabsHelperTest.php
index 4059477ccec9b05091861f87e0b09db1865d724e..fffe9d1aa6ccb9fb196448b91efd72ad6e38dcab 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/Search/SearchTabsHelperTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/Search/SearchTabsHelperTest.php
@@ -208,13 +208,13 @@ class SearchTabsHelperTest extends TestCase
     protected function getSearchTabsHelper($config = 'default_unfiltered',
         $filters = null
     ) {
-        $mockRequest = $this->getMock('Zend\Http\Request');
+        $mockRequest = $this->createMock('Zend\Http\Request');
         $mockRequest->expects($this->any())
             ->method('getQuery')
             ->with($this->equalTo('hiddenFilters'))
             ->willReturn($filters);
 
-        $configManager = $this->getMock('VuFind\Config\PluginManager');
+        $configManager = $this->createMock('VuFind\Config\PluginManager');
 
         $mockSolrOptions = $this->getMockBuilder('VuFind\Search\Solr\Options')
             ->disableOriginalConstructor()->getMock();
@@ -236,7 +236,7 @@ class SearchTabsHelperTest extends TestCase
                 new \VuFind\Search\Primo\Params($mockPrimoOptions, $configManager)
             );
 
-        $mockResults = $this->getMock('VuFind\Search\Results\PluginManager');
+        $mockResults = $this->createMock('VuFind\Search\Results\PluginManager');
         $mockResults->expects($this->any())
             ->method('get')
             ->will(
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/Search/Solr/ConditionalFilterListenerTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/Search/Solr/ConditionalFilterListenerTest.php
index e6ddeacf7d3281bf748900726086aeb7cb6099a2..321294694bbb059ce7ed19d05c7245dea7daa7b9 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/Search/Solr/ConditionalFilterListenerTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/Search/Solr/ConditionalFilterListenerTest.php
@@ -95,7 +95,7 @@ class ConditionalFilterListenerTest extends TestCase
     public function testAttach()
     {
         $listener = new InjectConditionalFilterListener(self::$emptySearchConfig);
-        $mock = $this->getMock('Zend\EventManager\SharedEventManagerInterface');
+        $mock = $this->createMock('Zend\EventManager\SharedEventManagerInterface');
         $mock->expects($this->once())->method('attach')->with(
             $this->equalTo('VuFind\Search'),
             $this->equalTo('pre'),
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/Search/Solr/FilterFieldConversionListenerTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/Search/Solr/FilterFieldConversionListenerTest.php
index 06653b6552644267d424876b387a14f2bb98b413..52a6580cc6dc17ff58c20f8a5951fce3f56e9830 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/Search/Solr/FilterFieldConversionListenerTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/Search/Solr/FilterFieldConversionListenerTest.php
@@ -53,7 +53,7 @@ class FilterFieldConversionListenerTest extends TestCase
     public function testAttach()
     {
         $listener = new FilterFieldConversionListener(['foo' => 'bar']);
-        $mock = $this->getMock('Zend\EventManager\SharedEventManagerInterface');
+        $mock = $this->createMock('Zend\EventManager\SharedEventManagerInterface');
         $mock->expects($this->once())->method('attach')->with(
             $this->equalTo('VuFind\Search'),
             $this->equalTo('pre'),
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/Search/Solr/HideFacetValueListenerTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/Search/Solr/HideFacetValueListenerTest.php
index c9cca9fa82968b07d8eb7bc1584342d27baa1270..d72b6add0771c94b7593ddd4d701731f5264a5cf 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/Search/Solr/HideFacetValueListenerTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/Search/Solr/HideFacetValueListenerTest.php
@@ -120,7 +120,7 @@ class HideFacetValueListenerTest extends TestCase
     public function testAttach()
     {
         $listener = $this->getListener();
-        $mock = $this->getMock('Zend\EventManager\SharedEventManagerInterface');
+        $mock = $this->createMock('Zend\EventManager\SharedEventManagerInterface');
         $mock->expects($this->once())->method('attach')->with(
             $this->equalTo('VuFind\Search'),
             $this->equalTo('post'),
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/Search/Solr/MultiIndexListenerTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/Search/Solr/MultiIndexListenerTest.php
index 86f245d869945f71dddf902a5b8dff8bb012bb3a..be777ed198c358a89137335eafd6660943ef9feb 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/Search/Solr/MultiIndexListenerTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/Search/Solr/MultiIndexListenerTest.php
@@ -182,7 +182,7 @@ class MultiIndexListenerTest extends TestCase
      */
     public function testAttach()
     {
-        $mock = $this->getMock('Zend\EventManager\SharedEventManagerInterface');
+        $mock = $this->createMock('Zend\EventManager\SharedEventManagerInterface');
         $mock->expects($this->once())->method('attach')->with(
             $this->equalTo('VuFind\Search'),
             $this->equalTo('pre'),
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/Search/UrlQueryHelperTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/Search/UrlQueryHelperTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..006ab35c103c9f9e4d7c24ad805362becd5f802e
--- /dev/null
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/Search/UrlQueryHelperTest.php
@@ -0,0 +1,161 @@
+<?php
+
+/**
+ * UrlQueryHelper unit tests.
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2010.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * @category VuFind
+ * @package  Tests
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development:testing:unit_tests Wiki
+ */
+namespace VuFindTest\Search;
+
+use VuFind\Search\UrlQueryHelper;
+use VuFind\Search\Factory\UrlQueryHelperFactory;
+use VuFindTest\Unit\TestCase as TestCase;
+use VuFindSearch\Query\Query;
+
+/**
+ * UrlQueryHelper unit tests.
+ *
+ * @category VuFind
+ * @package  Tests
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development:testing:unit_tests Wiki
+ */
+class UrlQueryHelperTest extends TestCase
+{
+    /**
+     * Test the basic functionality of the helper.
+     *
+     * @return void
+     */
+    public function testBasicFunctionality()
+    {
+        // Test basic getters
+        $query = new Query('search');
+        $helper = new UrlQueryHelper(['foo' => 'bar'], $query);
+        $this->assertEquals('?foo=bar&amp;lookfor=search', $helper->getParams());
+        $this->assertEquals('?foo=bar&amp;lookfor=search', (string)$helper);
+        $this->assertEquals(
+            ['foo' => 'bar', 'lookfor' => 'search'], $helper->getParamArray()
+        );
+        $this->assertEquals(
+            '<input type="hidden" name="foo" value="bar" />',
+            $helper->asHiddenFields(['lookfor' => '/.*/'])
+        );
+
+        // Test setDefaultParameters and disabling escaping
+        $this->assertEquals(
+            '?foo=baz&lookfor=search',
+            $helper->setDefaultParameter('foo', 'baz')->getParams(false)
+        );
+
+        // Test query suppression
+        $this->assertEquals(false, $helper->isQuerySuppressed());
+        $helper->setSuppressQuery(true);
+        $this->assertEquals(true, $helper->isQuerySuppressed());
+        $this->assertEquals('?foo=baz', $helper->getParams());
+        $helper->setSuppressQuery(false);
+        $this->assertEquals(false, $helper->isQuerySuppressed());
+        $this->assertEquals('?foo=baz&lookfor=search', $helper->getParams(false));
+
+        // Test replacing query terms
+        $this->assertEquals(
+            '?foo=baz&amp;lookfor=srch',
+            $helper->replaceTerm('search', 'srch')->getParams()
+        );
+        $this->assertEquals(
+            '?foo=baz&amp;lookfor=srch',
+            $helper->setSearchTerms('srch')->getParams()
+        );
+
+        // Test adding/removing facets and filters
+        $faceted = $helper->addFacet('f', '1')->addFilter('f:2');
+        $this->assertEquals(
+            '?foo=baz&lookfor=search&filter%5B%5D=f%3A%221%22&filter%5B%5D=f%3A2',
+            $faceted->getParams(false)
+        );
+        $this->assertEquals(
+            '?foo=baz&lookfor=search&filter%5B%5D=f%3A%221%22',
+            $faceted->removeFacet('f', '2')->getParams(false)
+        );
+        $this->assertEquals(
+            '?foo=baz&lookfor=search&filter%5B%5D=f%3A2',
+            $faceted->removeFilter('f:1')->getParams(false)
+        );
+        $this->assertEquals(
+            '?foo=baz&lookfor=search',
+            $faceted->removeAllFilters()->getParams(false)
+        );
+
+        // Test stacking setters
+        $this->assertEquals(
+            '?foo=baz&sort=title&view=grid&lookfor=search&type=x&limit=50&page=3',
+            $helper->setSort('title')->setViewParam('grid')->setHandler('x')
+                ->setLimit(50)->setPage(3)->getParams(false)
+        );
+    }
+
+    /**
+     * Test advanced search param building.
+     *
+     * @return void
+     */
+    public function testAdvancedSearch()
+    {
+        $fixturePath = realpath(__DIR__ . '/../../../../fixtures/searches') . '/advanced/';
+        $q = unserialize(file_get_contents($fixturePath . 'query'));
+        $helper = new UrlQueryHelper([], $q);
+        $this->assertEquals(
+            '?join=OR&bool0%5B%5D=AND&lookfor0%5B%5D=oranges&lookfor0%5B%5D=bananas'
+            . '&lookfor0%5B%5D=pears&type0%5B%5D=CallNumber&type0%5B%5D=toc'
+            . '&type0%5B%5D=ISN&bool1%5B%5D=OR&lookfor1%5B%5D=cars'
+            . '&lookfor1%5B%5D=trucks&type1%5B%5D=Title&type1%5B%5D=Subject'
+            . '&bool2%5B%5D=NOT&lookfor2%5B%5D=squid&type2%5B%5D=AllFields',
+            $helper->getParams(false)
+        );
+    }
+
+    /**
+     * Test that the factory does its job properly.
+     *
+     * @return void
+     */
+    public function testFactory()
+    {
+        $factory = new UrlQueryHelperFactory();
+        $config = $this->createMock('VuFind\Config\PluginManager');
+        $params = new \VuFindTest\Search\TestHarness\Params(
+            new \VuFindTest\Search\TestHarness\Options($config), $config
+        );
+        $params->setBasicSearch('foo', 'bar');
+        $params->setLimit(100);
+        $params->setPage(5);
+        $params->setView('grid');
+        $helper = $factory->fromParams($params);
+        $this->assertEquals(
+            '?limit=100&view=grid&page=5&lookfor=foo&type=bar',
+            $helper->getParams(false)
+        );
+    }
+}
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/View/Helper/Root/OpenUrlTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/View/Helper/Root/OpenUrlTest.php
index 6cd82aec1ce42b5021028cb4bfc6e7f974fef4ec..5c02af1a1c1b36edb35a4e84eb3e5dc375170e2e 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/View/Helper/Root/OpenUrlTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/View/Helper/Root/OpenUrlTest.php
@@ -295,7 +295,9 @@ class OpenUrlTest extends \VuFindTest\Unit\ViewHelperTestCase
         if (null === $mockContext) {
             $mockContext = $this->getMockContext();
         }
-        $openUrl = new OpenUrl($mockContext, $rules, new Config($config));
+        $mockPm = $this->getMockBuilder('VuFind\Resolver\Driver\PluginManager')
+            ->getMock();
+        $openUrl = new OpenUrl($mockContext, $rules, $mockPm, new Config($config));
         $openUrl->setView($this->getPhpRenderer());
         return $openUrl;
     }
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/View/Helper/Root/RecordDataFormatter/SpecBuilderTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/View/Helper/Root/RecordDataFormatter/SpecBuilderTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..4466b8fd6db46ef2bb3a67ecefcb50b335c4a664
--- /dev/null
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/View/Helper/Root/RecordDataFormatter/SpecBuilderTest.php
@@ -0,0 +1,86 @@
+<?php
+/**
+ * RecordDataFormatter spec builder Test Class
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2016.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * @category VuFind
+ * @package  Tests
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development:testing:unit_tests Wiki
+ */
+namespace VuFindTest\View\Helper\Root\RecordDataFormatter;
+use VuFind\View\Helper\Root\RecordDataFormatter\SpecBuilder;
+
+/**
+ * RecordDataFormatter spec builder Test Class
+ *
+ * @category VuFind
+ * @package  Tests
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development:testing:unit_tests Wiki
+ */
+class SpecBuilderTest extends \VuFindTest\Unit\ViewHelperTestCase
+{
+    /**
+     * Test the spec builder
+     *
+     * @return void
+     */
+    public function testBuilder()
+    {
+        $builder = new SpecBuilder();
+        $builder->setLine('foo', 'getFoo');
+        $builder->setLine('bar', 'getBar');
+        $builder->setTemplateLine('xyzzy', 'getXyzzy', 'xyzzy.phtml');
+        $expected = [
+            'foo' => [
+                'dataMethod' => 'getFoo',
+                'renderType' => null,
+                'pos' => 100,
+            ],
+            'bar' => [
+                'dataMethod' => 'getBar',
+                'renderType' => null,
+                'pos' => 200,
+            ],
+            'xyzzy' => [
+                'template' => 'xyzzy.phtml',
+                'dataMethod' => 'getXyzzy',
+                'renderType' => 'RecordDriverTemplate',
+                'pos' => 300,
+            ],
+        ];
+        $this->assertEquals($expected, $builder->getArray());
+        $builder->reorderKeys(['xyzzy', 'bar']);
+        $expected['xyzzy']['pos'] = 100;
+        $expected['bar']['pos'] = 200;
+        $expected['foo']['pos'] = 300;
+        $this->assertEquals($expected, $builder->getArray());
+        $builder->reorderKeys(['xyzzy', 'bar'], 0);
+        $expected['foo']['pos'] = 0;
+        $this->assertEquals($expected, $builder->getArray());
+        $builder->reorderKeys(['foo', 'baz', 'xyzzy', 'bar']);
+        $expected['xyzzy']['pos'] = 300;
+        $expected['bar']['pos'] = 400;
+        $expected['foo']['pos'] = 100;
+        $this->assertEquals($expected, $builder->getArray());
+    }
+}
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/View/Helper/Root/RecordDataFormatterTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/View/Helper/Root/RecordDataFormatterTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..4f5ee4842769cdde03e25444c98912f20b1d57da
--- /dev/null
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/View/Helper/Root/RecordDataFormatterTest.php
@@ -0,0 +1,198 @@
+<?php
+/**
+ * RecordDataFormatter Test Class
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2016.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * @category VuFind
+ * @package  Tests
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development:testing:unit_tests Wiki
+ */
+namespace VuFindTest\View\Helper\Root;
+use VuFind\View\Helper\Root\RecordDataFormatter;
+use VuFind\View\Helper\Root\RecordDataFormatterFactory;
+
+/**
+ * RecordDataFormatter Test Class
+ *
+ * @category VuFind
+ * @package  Tests
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development:testing:unit_tests Wiki
+ */
+class RecordDataFormatterTest extends \VuFindTest\Unit\ViewHelperTestCase
+{
+    /**
+     * Setup test case.
+     *
+     * Mark test skipped if short_open_tag is not enabled. The partial
+     * uses short open tags. This directive is PHP_INI_PERDIR,
+     * i.e. can only be changed via php.ini or a per-directory
+     * equivalent. The test will fail if the test is run on
+     * a system with short_open_tag disabled in the system-wide php
+     * ini-file.
+     *
+     * @return void
+     */
+    protected function setup()
+    {
+        parent::setup();
+        if (!ini_get('short_open_tag')) {
+            $this->markTestSkipped('Test requires short_open_tag to be enabled');
+        }
+    }
+
+    /**
+     * Get view helpers needed by test.
+     *
+     * @return array
+     */
+    protected function getViewHelpers()
+    {
+        $context = new \VuFind\View\Helper\Root\Context();
+        return [
+            'auth' => new \VuFind\View\Helper\Root\Auth($this->getMockBuilder('VuFind\Auth\Manager')->disableOriginalConstructor()->getMock()),
+            'context' => $context,
+            'openUrl' => new \VuFind\View\Helper\Root\OpenUrl($context, [], $this->getMockBuilder('VuFind\Resolver\Driver\PluginManager')->disableOriginalConstructor()->getMock()),
+            'proxyUrl' => new \VuFind\View\Helper\Root\ProxyUrl(),
+            'record' => new \VuFind\View\Helper\Root\Record(),
+            'recordLink' => new \VuFind\View\Helper\Root\RecordLink($this->getMockBuilder('VuFind\Record\Router')->disableOriginalConstructor()->getMock()),
+            'searchTabs' => $this->getMockBuilder('VuFind\View\Helper\Root\SearchTabs')->disableOriginalConstructor()->getMock(),
+            'transEsc' => new \VuFind\View\Helper\Root\TransEsc(),
+            'translate' => new \VuFind\View\Helper\Root\Translate(),
+            'usertags' => new \VuFind\View\Helper\Root\UserTags(),
+        ];
+    }
+
+    /**
+     * Get a record driver with fake data.
+     *
+     * @param array $overrides Fixture fields to override.
+     *
+     * @return SolrDefault
+     */
+    protected function getDriver($overrides = [])
+    {
+        // "Mock out" tag functionality to avoid database access:
+        $record = $this->getMockBuilder('VuFind\RecordDriver\SolrDefault')
+            ->setMethods(['getBuilding', 'getContainerTitle', 'getTags'])
+            ->getMock();
+        $record->expects($this->any())->method('getTags')
+            ->will($this->returnValue([]));
+        // Force a return value of zero so we can test this edge case value (even
+        // though in the context of "building"/"container title" it makes no sense):
+        $record->expects($this->any())->method('getBuilding')
+            ->will($this->returnValue(0));
+        $record->expects($this->any())->method('getContainerTitle')
+            ->will($this->returnValue('0'));
+
+        // Load record data from fixture file:
+        $fixture = json_decode(
+            file_get_contents(
+                realpath(
+                    VUFIND_PHPUNIT_MODULE_PATH . '/fixtures/misc/testbug2.json'
+                )
+            ),
+            true
+        );
+        $record->setRawData($overrides + $fixture['response']['docs'][0]);
+        return $record;
+    }
+
+    /**
+     * Build a formatter, including necessary mock view w/ helpers.
+     *
+     * @return RecordDataFormatter
+     */
+    protected function getFormatter()
+    {
+        // Build the formatter:
+        $factory = new RecordDataFormatterFactory();
+        $formatter = $factory->__invoke();
+
+        // Create a view object with a set of helpers:
+        $helpers = $this->getViewHelpers();
+        $view = $this->getPhpRenderer($helpers);
+
+        // Mock out the router to avoid errors:
+        $match = new \Zend\Mvc\Router\RouteMatch([]);
+        $match->setMatchedRouteName('foo');
+        $view->plugin('url')
+            ->setRouter($this->createMock('Zend\Mvc\Router\RouteStackInterface'))
+            ->setRouteMatch($match);
+
+        // Inject the view object into all of the helpers:
+        $formatter->setView($view);
+        foreach ($helpers as $helper) {
+            $helper->setView($view);
+        }
+
+        return $formatter;
+    }
+
+    /**
+     * Test citation generation
+     *
+     * @return void
+     */
+    public function testFormatting()
+    {
+        $formatter = $this->getFormatter();
+        $spec = $formatter->getDefaults('core');
+        $spec['Building'] = [
+            'dataMethod' => 'getBuilding', 'pos' => 0, 'context' => ['foo' => 1]
+        ];
+
+        $expected = [
+            'Building' => '0',
+            'Published in' => '0',
+            'Main Author' => 'Vico, Giambattista, 1668-1744.',
+            'Other Authors' => 'Pandolfi, Claudia.',
+            'Format' => 'Book',
+            'Language' => 'ItalianLatin',
+            'Published' => 'Centro di Studi Vichiani, 1992',
+            'Edition' => 'Fictional edition.',
+            'Series' => 'Vico, Giambattista, 1668-1744. Works. 1982 ;',
+            'Subjects' => 'Naples (Kingdom) History Spanish rule, 1442-1707 Sources',
+            'Online Access' => 'http://fictional.com/sample/url',
+            'Tags' => 'Add Tag No Tags, Be the first to tag this record!',
+        ];
+        $driver = $this->getDriver();
+        $results = $formatter->getData($driver, $spec);
+
+        // Check for expected array keys
+        $this->assertEquals(array_keys($expected), array_keys($results));
+
+        // Check for expected text (with markup stripped)
+        foreach ($expected as $key => $value) {
+            $this->assertEquals(
+                $value,
+                trim(preg_replace('/\s+/', ' ', strip_tags($results[$key]['value'])))
+            );
+        }
+
+        // Check for exact markup in representative example:
+        $this->assertEquals('Italian<br />Latin', $results['Language']['value']);
+
+        // Check for context in Building:
+        $this->assertEquals(['foo' => 1], $results['Building']['context']);
+    }
+}
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/View/Helper/Root/RecordTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/View/Helper/Root/RecordTest.php
index 32434ba4980ac5431759f638493f3ce6406512ca..ae657c33920cec2897632ec2815d4f1b44c04514 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/View/Helper/Root/RecordTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/View/Helper/Root/RecordTest.php
@@ -160,7 +160,7 @@ class RecordTest extends \PHPUnit_Framework_TestCase
      */
     public function testGetListEntry()
     {
-        $driver = $this->getMock('VuFind\RecordDriver\AbstractBase');
+        $driver = $this->createMock('VuFind\RecordDriver\AbstractBase');
         $driver->expects($this->once())->method('getContainingLists')
             ->with($this->equalTo(42))
             ->will($this->returnValue([1, 2, 3]));
@@ -271,10 +271,10 @@ class RecordTest extends \PHPUnit_Framework_TestCase
     {
         $context = $this->getMockContext();
         $context->expects($this->at(1))->method('renderInContext')
-            ->with($this->equalTo('record/checkbox.phtml'), $this->equalTo(['id' => 'Solr|000105196', 'count' => 0, 'prefix' => 'bar']))
+            ->with($this->equalTo('record/checkbox.phtml'), $this->equalTo(['id' => 'Solr|000105196', 'count' => 0, 'prefix' => 'bar', 'formAttr' => 'foo']))
             ->will($this->returnValue('success'));
         $context->expects($this->at(2))->method('renderInContext')
-            ->with($this->equalTo('record/checkbox.phtml'), $this->equalTo(['id' => 'Solr|000105196', 'count' => 1, 'prefix' => 'bar']))
+            ->with($this->equalTo('record/checkbox.phtml'), $this->equalTo(['id' => 'Solr|000105196', 'count' => 1, 'prefix' => 'bar', 'formAttr' => 'foo']))
             ->will($this->returnValue('success'));
         $record = $this->getRecord(
             $this->loadRecordFixture('testbug1.json'), [], $context
@@ -490,7 +490,7 @@ class RecordTest extends \PHPUnit_Framework_TestCase
         if (null === $context) {
             $context = $this->getMockContext();
         }
-        $view = $this->getMock('Zend\View\Renderer\PhpRenderer');
+        $view = $this->createMock('Zend\View\Renderer\PhpRenderer');
         if ($url) {
             $url = $this->getMockUrl($url);
         }
@@ -530,7 +530,7 @@ class RecordTest extends \PHPUnit_Framework_TestCase
      */
     protected function getMockResolver()
     {
-        return $this->getMock('Zend\View\Resolver\ResolverInterface');
+        return $this->createMock('Zend\View\Resolver\ResolverInterface');
     }
 
     /**
@@ -540,7 +540,7 @@ class RecordTest extends \PHPUnit_Framework_TestCase
      */
     protected function getMockContext()
     {
-        $context = $this->getMock('VuFind\View\Helper\Root\Context');
+        $context = $this->createMock('VuFind\View\Helper\Root\Context');
         $context->expects($this->any())->method('__invoke')
             ->will($this->returnValue($context));
         return $context;
@@ -555,7 +555,7 @@ class RecordTest extends \PHPUnit_Framework_TestCase
      */
     protected function getMockUrl($expectedRoute)
     {
-        $url = $this->getMock('Zend\View\Helper\Url');
+        $url = $this->createMock('Zend\View\Helper\Url');
         $url->expects($this->once())->method('__invoke')
             ->with($this->equalTo($expectedRoute))
             ->will($this->returnValue('http://foo/bar'));
@@ -571,7 +571,7 @@ class RecordTest extends \PHPUnit_Framework_TestCase
      */
     protected function getMockServerUrl()
     {
-        $url = $this->getMock('Zend\View\Helper\ServerUrl');
+        $url = $this->createMock('Zend\View\Helper\ServerUrl');
         $url->expects($this->once())->method('__invoke')
             ->will($this->returnValue('http://server-foo/baz'));
         return $url;
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/View/Helper/Root/SafeMoneyFormatTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/View/Helper/Root/SafeMoneyFormatTest.php
index afda8fa117bcbfbb5f882fa848e4552a95ae951e..0eb8852ef2fbe231256039e8f84b1404d2f449cf 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/View/Helper/Root/SafeMoneyFormatTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/View/Helper/Root/SafeMoneyFormatTest.php
@@ -80,7 +80,7 @@ class SafeMoneyFormatTest extends \PHPUnit_Framework_TestCase
     public function testFormatting()
     {
         $escaper = new \Zend\View\Helper\EscapeHtml();
-        $view = $this->getMock('Zend\View\Renderer\PhpRenderer');
+        $view = $this->createMock('Zend\View\Renderer\PhpRenderer');
         $view->expects($this->any())->method('plugin')
             ->with($this->equalTo('escapeHtml'))
             ->will($this->returnValue($escaper));
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/View/Helper/Root/TranslateTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/View/Helper/Root/TranslateTest.php
index 466e5067de2a4139fcac7d4e86ba01874d6779f2..63f4d8d279ac9ccbf337766f2537392338052db0 100644
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/View/Helper/Root/TranslateTest.php
+++ b/module/VuFind/tests/unit-tests/src/VuFindTest/View/Helper/Root/TranslateTest.php
@@ -219,7 +219,7 @@ class TranslateTest extends \PHPUnit_Framework_TestCase
     public function testLocaleWithTranslator()
     {
         $translate = new Translate();
-        $translator = $this->getMock('Zend\I18n\Translator\Translator');
+        $translator = $this->createMock('Zend\I18n\Translator\Translator');
         $translator->expects($this->once())->method('getLocale')
             ->will($this->returnValue('foo'));
         $translate->setTranslator($translator);
@@ -234,7 +234,7 @@ class TranslateTest extends \PHPUnit_Framework_TestCase
     public function testGetTranslator()
     {
         $translate = new Translate();
-        $translator = $this->getMock('Zend\I18n\Translator\TranslatorInterface');
+        $translator = $this->createMock('Zend\I18n\Translator\TranslatorInterface');
         $translate->setTranslator($translator);
         $this->assertEquals($translator, $translate->getTranslator());
     }
@@ -252,7 +252,7 @@ class TranslateTest extends \PHPUnit_Framework_TestCase
             return isset($translations[$domain][$str])
                 ? $translations[$domain][$str] : $str;
         };
-        $translator = $this->getMock('Zend\I18n\Translator\TranslatorInterface');
+        $translator = $this->createMock('Zend\I18n\Translator\TranslatorInterface');
         $translator->expects($this->any())->method('translate')
             ->will($this->returnCallback($callback));
         return $translator;
diff --git a/module/VuFind/tests/unit-tests/src/VuFindTest/View/Helper/jQueryMobile/MobileMenuTest.php b/module/VuFind/tests/unit-tests/src/VuFindTest/View/Helper/jQueryMobile/MobileMenuTest.php
deleted file mode 100644
index 13af03b02b3958abb13d46c69879fe9231f55bb9..0000000000000000000000000000000000000000
--- a/module/VuFind/tests/unit-tests/src/VuFindTest/View/Helper/jQueryMobile/MobileMenuTest.php
+++ /dev/null
@@ -1,85 +0,0 @@
-<?php
-/**
- * MobileMenu view helper Test Class
- *
- * PHP version 5
- *
- * Copyright (C) Villanova University 2010.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- *
- * @category VuFind
- * @package  Tests
- * @author   Demian Katz <demian.katz@villanova.edu>
- * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
- * @link     https://vufind.org/wiki/development:testing:unit_tests Wiki
- */
-namespace VuFindTest\View\Helper\jQueryMobile;
-use VuFind\View\Helper\jQueryMobile\MobileMenu;
-
-/**
- * MobileMenu view helper Test Class
- *
- * @category VuFind
- * @package  Tests
- * @author   Demian Katz <demian.katz@villanova.edu>
- * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
- * @link     https://vufind.org/wiki/development:testing:unit_tests Wiki
- */
-class MobileMenuTest extends \PHPUnit_Framework_TestCase
-{
-    /**
-     * Test header()
-     *
-     * @return void
-     */
-    public function testHeader()
-    {
-        $extras = ['bar' => 'baz'];
-        $mm = $this->getMobileMenu('header.phtml', $extras);
-        $this->assertEquals('foo', $mm->header($extras));
-    }
-
-    /**
-     * Test footer()
-     *
-     * @return void
-     */
-    public function testFooter()
-    {
-        $extras = ['bar' => 'baz'];
-        $mm = $this->getMobileMenu('footer.phtml', $extras);
-        $this->assertEquals('foo', $mm->footer($extras));
-    }
-
-    /**
-     * Get mocked out MobileMenu helper
-     *
-     * @param string $template Template name expected
-     * @param array  $extras   Extra parameters expected
-     *
-     * @return MobileMenu
-     */
-    protected function getMobileMenu($template, $extras)
-    {
-        $context = $this->getMock('VuFind\View\Helper\Root\Context');
-        $view = $this->getMock('Zend\View\Renderer\PhpRenderer');
-        $view->expects($this->once())->method('plugin')->with($this->equalTo('context'))->will($this->returnValue($context));
-        $context->expects($this->once())->method('__invoke')->with($this->equalTo($view))->will($this->returnValue($context));
-        $context->expects($this->once())->method('renderInContext')->with($this->equalTo($template), $this->equalTo($extras))->will($this->returnValue('foo'));
-        $mm = new MobileMenu();
-        $mm->setView($view);
-        return $mm;
-    }
-}
diff --git a/module/VuFindAdmin/config/module.config.php b/module/VuFindAdmin/config/module.config.php
index aea385703d45e26b43eba25e0f41d5fee6c7f7eb..e22e45d90f7331f5dbec73d79f4aeeaabe9b8cb4 100644
--- a/module/VuFindAdmin/config/module.config.php
+++ b/module/VuFindAdmin/config/module.config.php
@@ -3,13 +3,13 @@ namespace VuFindAdmin\Module\Configuration;
 
 $config = [
     'controllers' => [
-        'invokables' => [
-            'admin' => 'VuFindAdmin\Controller\AdminController',
-            'adminconfig' => 'VuFindAdmin\Controller\ConfigController',
-            'adminsocial' => 'VuFindAdmin\Controller\SocialstatsController',
-            'adminmaintenance' => 'VuFindAdmin\Controller\MaintenanceController',
-            'adminstatistics' => 'VuFindAdmin\Controller\StatisticsController',
-            'admintags' => 'VuFindAdmin\Controller\TagsController',
+        'factories' => [
+            'admin' => 'VuFindAdmin\Controller\Factory::getAdminController',
+            'adminconfig' => 'VuFindAdmin\Controller\Factory::getConfigController',
+            'adminsocial' => 'VuFindAdmin\Controller\Factory::getSocialstatsController',
+            'adminmaintenance' => 'VuFindAdmin\Controller\Factory::getMaintenanceController',
+            'adminstatistics' => 'VuFindAdmin\Controller\Factory::getStatisticsController',
+            'admintags' => 'VuFindAdmin\Controller\Factory::getTagsController',
         ],
     ],
     'router' => [
diff --git a/module/VuFindAdmin/src/VuFindAdmin/Controller/AbstractAdmin.php b/module/VuFindAdmin/src/VuFindAdmin/Controller/AbstractAdmin.php
index af23318cc2dcb67ba4f93fe60bd97f8d94076f9c..b24fe4248f3551debcebeffa1aa846d10eca6c58 100644
--- a/module/VuFindAdmin/src/VuFindAdmin/Controller/AbstractAdmin.php
+++ b/module/VuFindAdmin/src/VuFindAdmin/Controller/AbstractAdmin.php
@@ -27,6 +27,7 @@
  */
 namespace VuFindAdmin\Controller;
 use Zend\Mvc\MvcEvent;
+use Zend\ServiceManager\ServiceLocatorInterface;
 
 /**
  * VuFind Admin Controller Base
@@ -41,10 +42,12 @@ class AbstractAdmin extends \VuFind\Controller\AbstractBase
 {
     /**
      * Constructor
+     *
+     * @param ServiceLocatorInterface $sm Service locator
      */
-    public function __construct()
+    public function __construct(ServiceLocatorInterface $sm)
     {
-        parent::__construct();
+        parent::__construct($sm);
         $this->accessPermission = 'access.AdminModule';
     }
 
@@ -70,7 +73,7 @@ class AbstractAdmin extends \VuFind\Controller\AbstractBase
         // Block access to everyone when module is disabled:
         $config = $this->getConfig();
         if (!isset($config->Site->admin_enabled) || !$config->Site->admin_enabled) {
-            $pluginManager  = $this->getServiceLocator()
+            $pluginManager  = $this->serviceLocator
                 ->get('Zend\Mvc\Controller\PluginManager');
             $redirectPlugin = $pluginManager->get('redirect');
             return $redirectPlugin->toRoute('admin/disabled');
diff --git a/module/VuFindAdmin/src/VuFindAdmin/Controller/AdminController.php b/module/VuFindAdmin/src/VuFindAdmin/Controller/AdminController.php
index 6a92e21145f2a3fc23076e5fe828327625ceb83a..901709eaedd5163fffc206b7a6c6d97e5a0204f7 100644
--- a/module/VuFindAdmin/src/VuFindAdmin/Controller/AdminController.php
+++ b/module/VuFindAdmin/src/VuFindAdmin/Controller/AdminController.php
@@ -58,7 +58,7 @@ class AdminController extends AbstractAdmin
         $config = $this->getConfig();
         $xml = false;
         if (isset($config->Index->url)) {
-            $response = $this->getServiceLocator()->get('VuFind\Http')
+            $response = $this->serviceLocator->get('VuFind\Http')
                 ->get($config->Index->url . '/admin/multicore');
             $xml = $response->isSuccess() ? $response->getBody() : false;
         }
diff --git a/module/VuFindAdmin/src/VuFindAdmin/Controller/ConfigController.php b/module/VuFindAdmin/src/VuFindAdmin/Controller/ConfigController.php
index 0640ecafc9f7dfabc34118e444a12db30d335cb1..b585e5f5ec12e04fb09d5a1c64c388a35bcc83b9 100644
--- a/module/VuFindAdmin/src/VuFindAdmin/Controller/ConfigController.php
+++ b/module/VuFindAdmin/src/VuFindAdmin/Controller/ConfigController.php
@@ -70,7 +70,7 @@ class ConfigController extends AbstractAdmin
 
             // Reload config now that it has been edited (otherwise, old setting
             // will persist in cache):
-            $this->getServiceLocator()->get('VuFind\Config')->reload('config');
+            $this->serviceLocator->get('VuFind\Config')->reload('config');
         } else {
             $this->flashMessenger()->addMessage(
                 'Could not enable auto-configuration; check permissions on '
diff --git a/module/VuFindAdmin/src/VuFindAdmin/Controller/Factory.php b/module/VuFindAdmin/src/VuFindAdmin/Controller/Factory.php
new file mode 100644
index 0000000000000000000000000000000000000000..b7273fa3d9a057b931be92b0530db4dda6f16246
--- /dev/null
+++ b/module/VuFindAdmin/src/VuFindAdmin/Controller/Factory.php
@@ -0,0 +1,80 @@
+<?php
+/**
+ * Factory for controllers.
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2014.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * @category VuFind
+ * @package  Controller
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development Wiki
+ */
+namespace VuFindAdmin\Controller;
+use Zend\ServiceManager\ServiceManager;
+
+/**
+ * Factory for controllers.
+ *
+ * @category VuFind
+ * @package  Controller
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development Wiki
+ *
+ * @codeCoverageIgnore
+ */
+class Factory
+{
+    /**
+     * Construct a generic controller.
+     *
+     * @param string         $name Name of table to construct (fully qualified
+     * class name, or else a class name within the current namespace)
+     * @param ServiceManager $sm   Service manager
+     *
+     * @return object
+     */
+    public static function getGenericController($name, ServiceManager $sm)
+    {
+        // Prepend the current namespace unless we receive a FQCN:
+        $class = (strpos($name, '\\') === false)
+            ? __NAMESPACE__ . '\\' . $name : $name;
+        if (!class_exists($class)) {
+            throw new \Exception('Cannot construct ' . $class);
+        }
+        return new $class($sm->getServiceLocator());
+    }
+
+    /**
+     * Construct a generic controller.
+     *
+     * @param string $name Method name being called
+     * @param array  $args Method arguments
+     *
+     * @return object
+     */
+    public static function __callStatic($name, $args)
+    {
+        // Strip "get" from method name to get name of class; pass first argument
+        // on assumption that it should be the ServiceManager object.
+        return static::getGenericController(
+            substr($name, 3), isset($args[0]) ? $args[0] : null
+        );
+    }
+}
diff --git a/module/VuFindAdmin/src/VuFindAdmin/Controller/MaintenanceController.php b/module/VuFindAdmin/src/VuFindAdmin/Controller/MaintenanceController.php
index 672c3bfb0b0ca7b97d276d3678a7b6a6104d6c0d..885b98f10c2ef6e3b83ebb0ecaa1bd1cda722c9f 100644
--- a/module/VuFindAdmin/src/VuFindAdmin/Controller/MaintenanceController.php
+++ b/module/VuFindAdmin/src/VuFindAdmin/Controller/MaintenanceController.php
@@ -46,7 +46,7 @@ class MaintenanceController extends AbstractAdmin
     public function homeAction()
     {
         $view = $this->createViewModel();
-        $view->caches = $this->getServiceLocator()->get('VuFind\CacheManager')
+        $view->caches = $this->serviceLocator->get('VuFind\CacheManager')
             ->getCacheList();
         $view->setTemplate('admin/maintenance/home');
         return $view;
@@ -59,7 +59,7 @@ class MaintenanceController extends AbstractAdmin
      */
     public function clearcacheAction()
     {
-        $cacheManager = $this->getServiceLocator()->get('VuFind\CacheManager');
+        $cacheManager = $this->serviceLocator->get('VuFind\CacheManager');
         foreach ($this->params()->fromQuery('cache', []) as $cache) {
             $cacheManager->getCache($cache)->flush();
         }
diff --git a/module/VuFindAdmin/src/VuFindAdmin/Controller/StatisticsController.php b/module/VuFindAdmin/src/VuFindAdmin/Controller/StatisticsController.php
deleted file mode 100644
index 676923e2d8f872eeeb47ed904524641d13e610d7..0000000000000000000000000000000000000000
--- a/module/VuFindAdmin/src/VuFindAdmin/Controller/StatisticsController.php
+++ /dev/null
@@ -1,109 +0,0 @@
-<?php
-/**
- * Admin Statistics Controller
- *
- * PHP version 5
- *
- * Copyright (C) Villanova University 2010.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- *
- * @category VuFind
- * @package  Controller
- * @author   Demian Katz <demian.katz@villanova.edu>
- * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
- * @link     https://vufind.org Main Site
- */
-namespace VuFindAdmin\Controller;
-
-/**
- * Class controls VuFind statistical data.
- *
- * @category VuFind
- * @package  Controller
- * @author   Demian Katz <demian.katz@villanova.edu>
- * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
- * @link     https://vufind.org Main Site
- */
-class StatisticsController extends AbstractAdmin
-{
-    /**
-     * Statistics reporting
-     *
-     * @return \Zend\View\Model\ViewModel
-     */
-    public function homeAction()
-    {
-       
-        $view = $this->createViewModel();
-        $view->setTemplate('admin/statistics/home');
-        $config = $this->getConfig();
-
-        // Search statistics
-        $search = $this->getServiceLocator()->get('VuFind\SearchStats');
-        $view->searchesBySource = $config->Statistics->searchesBySource ?: false;
-        $searchSummary = $search->getStatsSummary(7, $view->searchesBySource);
-        foreach (['top', 'empty', 'total'] as $section) {
-            $key = $section . 'Searches';
-            $view->$key = isset($searchSummary[$section])
-                ? $searchSummary[$section] : null;
-        }
-
-        // Record statistics
-        $records = $this->getServiceLocator()->get('VuFind\RecordStats');
-        $view->recordsBySource = $config->Statistics->recordsBySource ?: false;
-        $recordSummary = $records->getStatsSummary(5, $view->recordsBySource);
-        $view->topRecords = isset($recordSummary['top'])
-            ? $recordSummary['top'] : null;
-        $view->totalRecordViews = isset($recordSummary['total'])
-            ? $recordSummary['total'] : null;
-
-        // Browser statistics
-        $view->currentBrowser = $search->getBrowser(
-            $this->getRequest()->getServer('HTTP_USER_AGENT')
-        );
-
-        // Look for universal statistics recorder
-        $matchFound = false;
-        foreach ($search->getDriversForSource(null) as $currentDriver) {
-            $browserStats = $currentDriver->getBrowserStats(false, 5);
-            if (!empty($browserStats)) {
-                $matchFound = true;
-                break;
-            }
-        }
-
-        // If no full coverage mode found, take the first valid source
-        if (!$matchFound) {
-            $drivers = $search->getDriversForSource(null, true);
-            foreach ($drivers as $currentDriver) {
-                $browserStats = $currentDriver->getBrowserStats(false, 5);
-                if (!empty($browserStats)) {
-                    $matchFound = true;
-                    break;
-                }
-            }
-        }
-
-        // Initialize browser/version data in view based on what we found above:
-        if ($matchFound) {
-            $view->browserStats = $browserStats;
-            $view->topVersions = $currentDriver->getBrowserStats(true, 5);
-        } else {
-            $view->browserStats = $view->topVersions = null;
-        }
-
-        return $view;
-    }
-}
diff --git a/module/VuFindAdmin/tests/unit-tests/src/VuFindTest/Controller/SocialstatsControllerTest.php b/module/VuFindAdmin/tests/unit-tests/src/VuFindTest/Controller/SocialstatsControllerTest.php
index 182ecd0f1c3e31f71e4d87daa8a34e458a776302..1058e786afe7143a48cfa7185020ff9496e696f8 100644
--- a/module/VuFindAdmin/tests/unit-tests/src/VuFindTest/Controller/SocialstatsControllerTest.php
+++ b/module/VuFindAdmin/tests/unit-tests/src/VuFindTest/Controller/SocialstatsControllerTest.php
@@ -47,14 +47,19 @@ class SocialstatsControllerTest extends \VuFindTest\Unit\TestCase
     public function testHome()
     {
         // Create mocks to simulate database lookups:
-        $c = $this->getMock('VuFindAdmin\Controller\SocialstatsController', ['getTable']);
-        $comments = $this->getMock('VuFind\Db\Table\Comments', ['getStatistics']);
+        $c = $this->getMockBuilder('VuFindAdmin\Controller\SocialstatsController')
+            ->setMethods(['getTable'])->disableOriginalConstructor()->getMock();
+        $comments = $this->getMockBuilder('VuFind\Db\Table\Comments')
+            ->disableOriginalConstructor()->setMethods(['getStatistics'])->getMock();
         $comments->expects($this->once())->method('getStatistics')->will($this->returnValue('comments-data'));
         $c->expects($this->at(0))->method('getTable')->with($this->equalTo('comments'))->will($this->returnValue($comments));
-        $userresource = $this->getMock('VuFind\Db\Table\UserResource', ['getStatistics']);
+        $userresource = $this->getMockBuilder('VuFind\Db\Table\UserResource')
+            ->setMethods(['getStatistics'])->disableOriginalConstructor()->getMock();
         $userresource->expects($this->once())->method('getStatistics')->will($this->returnValue('userresource-data'));
         $c->expects($this->at(1))->method('getTable')->with($this->equalTo('userresource'))->will($this->returnValue($userresource));
-        $resourcetags = $this->getMock('VuFind\Db\Table\ResourceTags', ['getStatistics']);
+        $resourcetags = $this->getMockBuilder('VuFind\Db\Table\ResourceTags')
+            ->disableOriginalConstructor()->setMethods(['getStatistics'])
+            ->getMock();
         $resourcetags->expects($this->once())->method('getStatistics')->will($this->returnValue('resourcetags-data'));
         $c->expects($this->at(2))->method('getTable')->with($this->equalTo('resourcetags'))->will($this->returnValue($resourcetags));
 
diff --git a/module/VuFindApi/Module.php b/module/VuFindApi/Module.php
new file mode 100644
index 0000000000000000000000000000000000000000..b439aec4319007fd62624e8e0b8b5263581ab7b3
--- /dev/null
+++ b/module/VuFindApi/Module.php
@@ -0,0 +1,68 @@
+<?php
+/**
+ * VuFind Api module.
+ *
+ * PHP version 5
+ *
+ * Copyright (C) The National Library of Finland 2016.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * @category VuFind
+ * @package  Module
+ * @author   Ere Maijala <ere.maijala@helsinki.fi>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development
+ */
+namespace VuFindApi;
+use Zend\ModuleManager\ModuleManager,
+    Zend\Mvc\MvcEvent;
+
+/**
+ * VuFind Api module.
+ *
+ * @category VuFind
+ * @package  Module
+ * @author   Ere Maijala <ere.maijala@helsinki.fi>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development
+ */
+class Module
+{
+    /**
+     * Get module configuration
+     *
+     * @return array
+     */
+    public function getConfig()
+    {
+        return include __DIR__ . '/config/module.config.php';
+    }
+
+    /**
+     * Get autoloader configuration
+     *
+     * @return array
+     */
+    public function getAutoloaderConfig()
+    {
+        return [
+            'Zend\Loader\StandardAutoloader' => [
+                'namespaces' => [
+                    __NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__,
+                ],
+            ],
+        ];
+    }
+}
diff --git a/module/VuFindApi/config/module.config.php b/module/VuFindApi/config/module.config.php
new file mode 100644
index 0000000000000000000000000000000000000000..8214f56894a0de267144ba4b6866097ee2b2df52
--- /dev/null
+++ b/module/VuFindApi/config/module.config.php
@@ -0,0 +1,50 @@
+<?php
+namespace VuFindApi\Module\Configuration;
+
+$config = [
+    'controllers' => [
+        'factories' => [
+            'api' => 'VuFindApi\Controller\Factory::getApiController',
+            'searchapi' => 'VuFindApi\Controller\Factory::getSearchApiController',
+        ]
+    ],
+    'router' => [
+        'routes' => [
+            'apiHome' => [
+                'type' => 'Zend\Mvc\Router\Http\Segment',
+                'verb' => 'get,post,options',
+                'options' => [
+                    'route'    => '/api[/v1][/]',
+                    'defaults' => [
+                        'controller' => 'Api',
+                        'action'     => 'Index',
+                    ]
+                ],
+            ],
+            'searchApiv1' => [
+                'type' => 'Zend\Mvc\Router\Http\Literal',
+                'verb' => 'get,post,options',
+                'options' => [
+                    'route'    => '/api/v1/search',
+                    'defaults' => [
+                        'controller' => 'SearchApi',
+                        'action'     => 'search',
+                    ]
+                ]
+            ],
+            'recordApiv1' => [
+                'type' => 'Zend\Mvc\Router\Http\Literal',
+                'verb' => 'get,post,options',
+                'options' => [
+                    'route'    => '/api/v1/record',
+                    'defaults' => [
+                        'controller' => 'SearchApi',
+                        'action'     => 'record',
+                    ]
+                ]
+            ]
+        ],
+    ],
+];
+
+return $config;
diff --git a/module/VuFindApi/src/VuFindApi/Controller/ApiController.php b/module/VuFindApi/src/VuFindApi/Controller/ApiController.php
new file mode 100644
index 0000000000000000000000000000000000000000..9d7d795ca9d8419f134e1af08bfe00b0dbe40605
--- /dev/null
+++ b/module/VuFindApi/src/VuFindApi/Controller/ApiController.php
@@ -0,0 +1,129 @@
+<?php
+/**
+ * API Controller
+ *
+ * PHP Version 5
+ *
+ * Copyright (C) The National Library of Finland 2015-2016.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.    See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA    02111-1307    USA
+ *
+ * @category VuFind
+ * @package  Controller
+ * @author   Ere Maijala <ere.maijala@helsinki.fi>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development:plugins:controllers Wiki
+ */
+namespace VuFindApi\Controller;
+
+/**
+ * API Controller
+ *
+ * Controls the API functionality
+ *
+ * @category VuFind
+ * @package  Controller
+ * @author   Ere Maijala <ere.maijala@helsinki.fi>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development:plugins:controllers Wiki
+ */
+class ApiController extends \VuFind\Controller\AbstractBase
+{
+    use ApiTrait;
+
+    /**
+     * Array of available API controllers
+     *
+     * @var array
+     */
+    protected $apiControllers = [];
+
+    /**
+     * Add an API controller to the list of available controllers
+     *
+     * @param Zend\Mvc\Controller\AbstractActionController $controller API Controller
+     *
+     * @return void
+     */
+    public function addApi($controller)
+    {
+        if (!in_array($controller, $this->apiControllers)) {
+            $this->apiControllers[] = $controller;
+        }
+    }
+
+    /**
+     * Index action
+     *
+     * Return Swagger specification or redirect to Swagger UI
+     *
+     * @return \Zend\Http\Response
+     */
+    public function indexAction()
+    {
+        // Disable session writes
+        $this->disableSessionWrites();
+
+        if (null === $this->getRequest()->getQuery('swagger')) {
+            $urlHelper = $this->getViewRenderer()->plugin('url');
+            $base = rtrim($urlHelper('home'), '/');
+            $url = "$base/swagger-ui/?url="
+                . urlencode("$base/api?swagger");
+            return $this->redirect()->toUrl($url);
+        }
+        $response = $this->getResponse();
+        $headers = $response->getHeaders();
+        $headers->addHeaderLine('Content-type', 'application/json');
+        $config = $this->getConfig();
+        $params = [
+            'config' => $config,
+            'version' => \VuFind\Config\Version::getBuildVersion(),
+            'specs' => $this->getApiSpecs()
+        ];
+        $json = $this->getViewRenderer()->render('api/swagger', $params);
+        $response->setContent($json);
+        return $response;
+    }
+
+    /**
+     * Get specification fragments from all APIs as JSON
+     *
+     * @return string
+     */
+    protected function getApiSpecs()
+    {
+        $results = [];
+
+        foreach ($this->apiControllers as $controller) {
+            $api = $controller->getSwaggerSpecFragment();
+            $specs = json_decode($api, true);
+            if (null === $specs) {
+                throw new \Exception(
+                    'Could not parse Swagger spec fragment of '
+                    . get_class($controller)
+                );
+            }
+            foreach ($specs as $key => $spec) {
+                if (isset($results[$key])) {
+                    $results[$key] = array_merge($results[$key], $spec);
+                } else {
+                    $results[$key] = $spec;
+                }
+            }
+        }
+
+        // Return the fragment without the enclosing curly brackets
+        return substr(trim(json_encode($results, JSON_PRETTY_PRINT)), 1, -1);
+    }
+}
diff --git a/module/VuFindApi/src/VuFindApi/Controller/ApiInterface.php b/module/VuFindApi/src/VuFindApi/Controller/ApiInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..37b57e267628c14029331f9548b947979d2c6710
--- /dev/null
+++ b/module/VuFindApi/src/VuFindApi/Controller/ApiInterface.php
@@ -0,0 +1,52 @@
+<?php
+/**
+ * Additional functionality for API controllers.
+ *
+ * PHP version 5
+ *
+ * Copyright (C) The National Library 2015.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * @category VuFind
+ * @package  Controller
+ * @author   Ere Maijala <ere.maijala@helsinki.fi>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development:plugins:controllers Wiki
+ */
+namespace VuFindApi\Controller;
+
+/**
+ * Additional functionality for API controllers.
+ *
+ * @category VuFind
+ * @package  Controller
+ * @author   Ere Maijala <ere.maijala@helsinki.fi>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development:plugins:controllers Wiki
+ */
+interface ApiInterface
+{
+    // define some status constants
+    const STATUS_OK = 'OK';                  // good
+    const STATUS_ERROR = 'ERROR';            // bad
+
+    /**
+     * Get Swagger specification JSON fragment for services provided by the
+     * controller
+     *
+     * @return string
+     */
+    public function getSwaggerSpecFragment();
+}
diff --git a/module/VuFindApi/src/VuFindApi/Controller/ApiTrait.php b/module/VuFindApi/src/VuFindApi/Controller/ApiTrait.php
new file mode 100644
index 0000000000000000000000000000000000000000..4fcbf09d9c3dbb1e3a32e1e4e9330d7f08ec4d72
--- /dev/null
+++ b/module/VuFindApi/src/VuFindApi/Controller/ApiTrait.php
@@ -0,0 +1,169 @@
+<?php
+/**
+ * Additional functionality for API controllers.
+ *
+ * PHP version 5
+ *
+ * Copyright (C) The National Library 2015-2016.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * @category VuFind
+ * @package  Controller
+ * @author   Ere Maijala <ere.maijala@helsinki.fi>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development:plugins:controllers Wiki
+ */
+namespace VuFindApi\Controller;
+
+/**
+ * Additional functionality for API controllers.
+ *
+ * @category VuFind
+ * @package  Controller
+ * @author   Ere Maijala <ere.maijala@helsinki.fi>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development:plugins:controllers Wiki
+ */
+trait ApiTrait
+{
+    /**
+     * Callback function in JSONP mode
+     *
+     * @var string
+     */
+    protected $jsonpCallback = null;
+
+    /**
+     * Whether to pretty-print JSON
+     *
+     * @var bool
+     */
+    protected $jsonPrettyPrint = false;
+
+    /**
+     * Type of output to use
+     *
+     * @var string
+     */
+    protected $outputMode = 'json';
+
+    /**
+     * Execute the request
+     *
+     * @param \Zend\Mvc\MvcEvent $e Event
+     *
+     * @return mixed
+     * @throws Exception\DomainException
+     */
+    public function onDispatch(\Zend\Mvc\MvcEvent $e)
+    {
+        // Add CORS headers and handle OPTIONS requests. This is a simplistic
+        // approach since we allow any origin. For more complete CORS handling
+        // a module like zfr-cors could be used.
+        $response = $this->getResponse();
+        $headers = $response->getHeaders();
+        $headers->addHeaderLine('Access-Control-Allow-Origin: *');
+        $request = $this->getRequest();
+        if ($request->getMethod() == 'OPTIONS') {
+            // Disable session writes
+            $this->disableSessionWrites();
+            $headers->addHeaderLine(
+                'Access-Control-Allow-Methods', 'GET, POST, OPTIONS'
+            );
+            $headers->addHeaderLine('Access-Control-Max-Age', '86400');
+
+            return $this->output(null, 204);
+        }
+        return parent::onDispatch($e);
+    }
+
+    /**
+     * Determine the correct output mode based on content negotiation or the
+     * view parameter
+     *
+     * @return void
+     */
+    protected function determineOutputMode()
+    {
+        $request = $this->getRequest();
+        $this->jsonpCallback
+            = $request->getQuery('callback', $request->getPost('callback', null));
+        $this->jsonPrettyPrint = $request->getQuery(
+            'prettyPrint', $request->getPost('prettyPrint', false)
+        );
+        $this->outputMode = empty($this->jsonpCallback) ? 'json' : 'jsonp';
+    }
+
+    /**
+     * Check whether access is denied and return the appropriate message or false.
+     *
+     * @param string $permission Permission to check
+     *
+     * @return \Zend\Http\Response|boolean
+     */
+    protected function isAccessDenied($permission)
+    {
+        $auth = $this->serviceLocator->get('ZfcRbac\Service\AuthorizationService');
+        if (!$auth->isGranted($permission)) {
+            return $this->output([], self::STATUS_ERROR, 403, 'Permission denied');
+        }
+        return false;
+    }
+
+    /**
+     * Send output data and exit.
+     *
+     * @param mixed  $data     The response data
+     * @param string $status   Status of the request
+     * @param int    $httpCode A custom HTTP Status Code
+     * @param string $message  Status message
+     *
+     * @return \Zend\Http\Response
+     * @throws \Exception
+     */
+    protected function output($data, $status, $httpCode = null, $message = '')
+    {
+        $response = $this->getResponse();
+        $headers = $response->getHeaders();
+        if ($httpCode !== null) {
+            $response->setStatusCode($httpCode);
+        }
+        if (null === $data) {
+            return $response;
+        }
+        $output = $data;
+        if (!isset($output['status'])) {
+            $output['status'] = $status;
+        }
+        if ($message && !isset($output['statusMessage'])) {
+            $output['statusMessage'] = $message;
+        }
+        $jsonOptions = $this->jsonPrettyPrint ? JSON_PRETTY_PRINT : 0;
+        if ($this->outputMode == 'json') {
+            $headers->addHeaderLine('Content-type', 'application/json');
+            $response->setContent(json_encode($output, $jsonOptions));
+            return $response;
+        } elseif ($this->outputMode == 'jsonp') {
+            $headers->addHeaderLine('Content-type', 'application/javascript');
+            $response->setContent(
+                $this->jsonpCallback . '(' . json_encode($output, $jsonOptions)
+                . ');'
+            );
+            return $response;
+        } else {
+            throw new \Exception('Invalid output mode');
+        }
+    }
+}
diff --git a/module/VuFindApi/src/VuFindApi/Controller/Factory.php b/module/VuFindApi/src/VuFindApi/Controller/Factory.php
new file mode 100644
index 0000000000000000000000000000000000000000..611ce55d48ffb450d3a017a888c4942913204845
--- /dev/null
+++ b/module/VuFindApi/src/VuFindApi/Controller/Factory.php
@@ -0,0 +1,76 @@
+<?php
+/**
+ * Factory for controllers.
+ *
+ * PHP version 5
+ *
+ * Copyright (C) The National Library of Finland 2016.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * @category VuFind
+ * @package  Controller
+ * @author   Ere Maijala <ere.maijala@helsinki.fi>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development:plugins:controllers Wiki
+ */
+namespace VuFindApi\Controller;
+use VuFindApi\Formatter\FacetFormatter;
+use VuFindApi\Formatter\RecordFormatter;
+use Zend\ServiceManager\ServiceManager;
+
+/**
+ * Factory for controllers.
+ *
+ * @category VuFind
+ * @package  Controller
+ * @author   Ere Maijala <ere.maijala@helsinki.fi>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development:plugins:controllers Wiki
+ *
+ * @codeCoverageIgnore
+ */
+class Factory
+{
+    /**
+     * Construct the ApiController.
+     *
+     * @param ServiceManager $sm Service manager.
+     *
+     * @return ApiController
+     */
+    public static function getApiController(ServiceManager $sm)
+    {
+        $controller = new ApiController($sm);
+        $controller->addApi($sm->get('SearchApi'));
+        return $controller;
+    }
+
+    /**
+     * Construct the SearchApiController.
+     *
+     * @param ServiceManager $sm Service manager.
+     *
+     * @return SearchApiController
+     */
+    public static function getSearchApiController(ServiceManager $sm)
+    {
+        $recordFields = $sm->getServiceLocator()
+            ->get('VuFind\YamlReader')->get('SearchApiRecordFields.yaml');
+        $helperManager = $sm->getServiceLocator()->get('ViewHelperManager');
+        $rf = new RecordFormatter($recordFields, $helperManager);
+        $controller = new SearchApiController($sm, $rf, new FacetFormatter());
+        return $controller;
+    }
+}
diff --git a/module/VuFindApi/src/VuFindApi/Controller/SearchApiController.php b/module/VuFindApi/src/VuFindApi/Controller/SearchApiController.php
new file mode 100644
index 0000000000000000000000000000000000000000..385d2c818e2ac002a0a533bbe6ac5cfaa3f33202
--- /dev/null
+++ b/module/VuFindApi/src/VuFindApi/Controller/SearchApiController.php
@@ -0,0 +1,374 @@
+<?php
+/**
+ * Search API Controller
+ *
+ * PHP Version 5
+ *
+ * Copyright (C) The National Library of Finland 2015-2016.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.    See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA    02111-1307    USA
+ *
+ * @category VuFind
+ * @package  Controller
+ * @author   Ere Maijala <ere.maijala@helsinki.fi>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development:plugins:controllers Wiki
+ */
+namespace VuFindApi\Controller;
+
+use VuFindApi\Formatter\FacetFormatter;
+use VuFindApi\Formatter\RecordFormatter;
+use Zend\ServiceManager\ServiceLocatorInterface;
+
+/**
+ * Search API Controller
+ *
+ * Controls the Search API functionality
+ *
+ * @category VuFind
+ * @package  Service
+ * @author   Ere Maijala <ere.maijala@helsinki.fi>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development:plugins:controllers Wiki
+ */
+class SearchApiController extends \VuFind\Controller\AbstractSearch
+    implements ApiInterface
+{
+    use ApiTrait;
+
+    /**
+     * Record formatter
+     *
+     * @var RecordFormatter
+     */
+    protected $recordFormatter;
+
+    /**
+     * Facet formatter
+     *
+     * @var FacetFormatter
+     */
+    protected $facetFormatter;
+
+    /**
+     * Default record fields to return if a request does not define the fields
+     *
+     * @var array
+     */
+    protected $defaultRecordFields = [];
+
+    /**
+     * Permission required for the record endpoint
+     *
+     * @var string
+     */
+    protected $recordAccessPermission = 'access.api.Record';
+
+    /**
+     * Permission required for the search endpoint
+     *
+     * @var string
+     */
+    protected $searchAccessPermission = 'access.api.Search';
+
+    /**
+     * Constructor
+     *
+     * @param ServiceLocatorInterface $sm Service manager
+     * @param RecordFormatter         $rf Record formatter
+     * @param FacetFormatter          $ff Facet formatter
+     */
+    public function __construct(ServiceLocatorInterface $sm, RecordFormatter $rf,
+        FacetFormatter $ff
+    ) {
+        parent::__construct($sm);
+        $this->recordFormatter = $rf;
+        $this->facetFormatter = $ff;
+        foreach ($rf->getRecordFields() as $fieldName => $fieldSpec) {
+            if (!empty($fieldSpec['vufind.default'])) {
+                $this->defaultRecordFields[] = $fieldName;
+            }
+        }
+    }
+
+    /**
+     * Get Swagger specification JSON fragment for services provided by the
+     * controller
+     *
+     * @return string
+     */
+    public function getSwaggerSpecFragment()
+    {
+        $config = $this->getConfig();
+        $results = $this->getResultsManager()->get($this->searchClassId);
+        $options = $results->getOptions();
+        $params = $results->getParams();
+        $params->activateAllFacets();
+
+        $viewParams = [
+            'config' => $config,
+            'version' => \VuFind\Config\Version::getBuildVersion(),
+            'searchTypes' => $options->getBasicHandlers(),
+            'defaultSearchType' => $options->getDefaultHandler(),
+            'recordFields' => $this->recordFormatter->getRecordFieldSpec(),
+            'defaultFields' => $this->defaultRecordFields,
+            'facetConfig' => $params->getFacetConfig(),
+            'sortOptions' => $options->getSortOptions(),
+            'defaultSort' => $options->getDefaultSortByHandler()
+        ];
+        $json = $this->getViewRenderer()->render(
+            'searchapi/swagger', $viewParams
+        );
+        return $json;
+    }
+
+    /**
+     * Execute the request
+     *
+     * @param \Zend\Mvc\MvcEvent $e Event
+     *
+     * @return mixed
+     * @throws Exception\DomainException
+     */
+    public function onDispatch(\Zend\Mvc\MvcEvent $e)
+    {
+        // Add CORS headers and handle OPTIONS requests. This is a simplistic
+        // approach since we allow any origin. For more complete CORS handling
+        // a module like zfr-cors could be used.
+        $response = $this->getResponse();
+        $headers = $response->getHeaders();
+        $headers->addHeaderLine('Access-Control-Allow-Origin: *');
+        $request = $this->getRequest();
+        if ($request->getMethod() == 'OPTIONS') {
+            // Disable session writes
+            $this->disableSessionWrites();
+            $headers->addHeaderLine(
+                'Access-Control-Allow-Methods', 'GET, POST, OPTIONS'
+            );
+            $headers->addHeaderLine('Access-Control-Max-Age', '86400');
+
+            return $this->output(null, 204);
+        }
+        if (null !== $request->getQuery('swagger')) {
+            return $this->createSwaggerSpec();
+        }
+        return parent::onDispatch($e);
+    }
+
+    /**
+     * Record action
+     *
+     * @return \Zend\Http\Response
+     */
+    public function recordAction()
+    {
+        // Disable session writes
+        $this->disableSessionWrites();
+
+        $this->determineOutputMode();
+
+        if ($result = $this->isAccessDenied($this->recordAccessPermission)) {
+            return $result;
+        }
+
+        $request = $this->getRequest()->getQuery()->toArray()
+            + $this->getRequest()->getPost()->toArray();
+
+        if (!isset($request['id'])) {
+            return $this->output([], self::STATUS_ERROR, 400, 'Missing id');
+        }
+
+        $loader = $this->serviceLocator->get('VuFind\RecordLoader');
+        try {
+            if (is_array($request['id'])) {
+                $results = $loader->loadBatchForSource($request['id']);
+            } else {
+                $results[] = $loader->load($request['id']);
+            }
+        } catch (\Exception $e) {
+            return $this->output(
+                [], self::STATUS_ERROR, 400,
+                'Error loading record'
+            );
+        }
+
+        $response = [
+            'resultCount' => count($results)
+        ];
+        $requestedFields = $this->getFieldList($request);
+        if ($records = $this->recordFormatter->format($results, $requestedFields)) {
+            $response['records'] = $records;
+        }
+
+        return $this->output($response, self::STATUS_OK);
+    }
+
+    /**
+     * Search action
+     *
+     * @return \Zend\Http\Response
+     */
+    public function searchAction()
+    {
+        // Disable session writes
+        $this->disableSessionWrites();
+
+        $this->determineOutputMode();
+
+        if ($result = $this->isAccessDenied($this->searchAccessPermission)) {
+            return $result;
+        }
+
+        // Send both GET and POST variables to search class:
+        $request = $this->getRequest()->getQuery()->toArray()
+            + $this->getRequest()->getPost()->toArray();
+
+        if (isset($request['limit'])
+            && (!ctype_digit($request['limit'])
+            || $request['limit'] < 0 || $request['limit'] > 100)
+        ) {
+            return $this->output([], self::STATUS_ERROR, 400, 'Invalid limit');
+        }
+
+        // Sort by relevance by default
+        if (!isset($request['sort'])) {
+            $request['sort'] = 'relevance';
+        }
+
+        $requestedFields = $this->getFieldList($request);
+
+        $facetConfig = $this->getConfig('facets');
+        $hierarchicalFacets = isset($facetConfig->SpecialFacets->hierarchical)
+            ? $facetConfig->SpecialFacets->hierarchical->toArray()
+            : [];
+
+        $runner = $this->serviceLocator->get('VuFind\SearchRunner');
+        try {
+            $results = $runner->run(
+                $request,
+                $this->searchClassId,
+                function ($runner, $params, $searchId) use (
+                    $hierarchicalFacets, $request, $requestedFields
+                ) {
+                    foreach (isset($request['facet']) ? $request['facet'] : []
+                       as $facet
+                    ) {
+                        if (!isset($hierarchicalFacets[$facet])) {
+                            $params->addFacet($facet);
+                        }
+                    }
+                    if ($requestedFields) {
+                        $limit = isset($request['limit']) ? $request['limit'] : 20;
+                        $params->setLimit($limit);
+                    } else {
+                        $params->setLimit(0);
+                    }
+                }
+            );
+        } catch (\Exception $e) {
+            return $this->output([], self::STATUS_ERROR, 400, $e->getMessage());
+        }
+
+        // If we received an EmptySet back, that indicates that the real search
+        // failed due to some kind of syntax error, and we should display a
+        // warning to the user; otherwise, we should proceed with normal post-search
+        // processing.
+        if ($results instanceof \VuFind\Search\EmptySet\Results) {
+            return $this->output([], self::STATUS_ERROR, 400, 'Invalid search');
+        }
+
+        $response = ['resultCount' => $results->getResultTotal()];
+
+        $records = $this->recordFormatter->format(
+            $results->getResults(), $requestedFields
+        );
+        if ($records) {
+            $response['records'] = $records;
+        }
+
+        $requestedFacets = isset($request['facet']) ? $request['facet'] : [];
+        $hierarchicalFacetData = $this->getHierarchicalFacetData(
+            array_intersect($requestedFacets, $hierarchicalFacets)
+        );
+        $facets = $this->facetFormatter->format(
+            $request, $results, $hierarchicalFacetData
+        );
+        if ($facets) {
+            $response['facets'] = $facets;
+        }
+
+        return $this->output($response, self::STATUS_OK);
+    }
+
+    /**
+     * Get hierarchical facet data for the given facet fields
+     *
+     * @param array $facets Facet fields
+     *
+     * @return array
+     */
+    protected function getHierarchicalFacetData($facets)
+    {
+        if (!$facets) {
+            return [];
+        }
+        $results = $this->getResultsManager()->get('Solr');
+        $params = $results->getParams();
+        foreach ($facets as $facet) {
+            $params->addFacet($facet, null, false);
+        }
+        $params->initFromRequest($this->getRequest()->getQuery());
+
+        $facetResults = $results->getFullFieldFacets($facets, false, -1, 'count');
+
+        $facetHelper = $this->serviceLocator
+            ->get('VuFind\HierarchicalFacetHelper');
+
+        $facetList = [];
+        foreach ($facets as $facet) {
+            if (empty($facetResults[$facet]['data']['list'])) {
+                $facetList[$facet] = [];
+                continue;
+            }
+            $facetList[$facet] = $facetHelper->buildFacetArray(
+                $facet,
+                $facetResults[$facet]['data']['list'],
+                $results->getUrlQuery(),
+                false
+            );
+        }
+
+        return $facetList;
+    }
+
+    /**
+     * Get field list based on the request
+     *
+     * @param array $request Request params
+     *
+     * @return array
+     */
+    protected function getFieldList($request)
+    {
+        $fieldList = [];
+        if (isset($request['field'])) {
+            if (!empty($request['field']) && is_array($request['field'])) {
+                $fieldList = $request['field'];
+            }
+        } else {
+            $fieldList = $this->defaultRecordFields;
+        }
+        return $fieldList;
+    }
+}
diff --git a/module/VuFindApi/src/VuFindApi/Formatter/BaseFormatter.php b/module/VuFindApi/src/VuFindApi/Formatter/BaseFormatter.php
new file mode 100644
index 0000000000000000000000000000000000000000..e4d762b50582456c76e6db94536781059f42b1c2
--- /dev/null
+++ b/module/VuFindApi/src/VuFindApi/Formatter/BaseFormatter.php
@@ -0,0 +1,85 @@
+<?php
+/**
+ * Base formatter for API responses
+ *
+ * PHP Version 5
+ *
+ * Copyright (C) The National Library of Finland 2015-2016.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.    See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA    02111-1307    USA
+ *
+ * @category VuFind
+ * @package  API_Formatter
+ * @author   Ere Maijala <ere.maijala@helsinki.fi>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development:plugins:controllers Wiki
+ */
+namespace VuFindApi\Formatter;
+
+/**
+ * Base formatter for API responses
+ *
+ * @category VuFind
+ * @package  API_Formatter
+ * @author   Ere Maijala <ere.maijala@helsinki.fi>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development:plugins:controllers Wiki
+ */
+class BaseFormatter
+{
+    /**
+     * Recursive function to filter array fields:
+     * - remove empty values
+     * - convert boolean values to 0/1
+     * - force numerically indexed (non-associative) arrays to have numeric keys.
+     *
+     * @param array $array Array to check
+     *
+     * @return void
+     */
+    protected function filterArrayValues(&$array)
+    {
+        foreach ($array as $key => &$value) {
+            if (is_array($value) && !empty($value)) {
+                $this->filterArrayValues($value);
+                $this->resetArrayIndices($value);
+            }
+
+            if ((is_array($value) && empty($value))
+                || (is_bool($value) && !$value)
+                || $value === null || $value === ''
+            ) {
+                unset($array[$key]);
+            } else if (is_bool($value) || $value === 'true' || $value === 'false') {
+                $array[$key] = $value === true || $value === 'true' ? 1 : 0;
+            }
+        }
+        $this->resetArrayIndices($array);
+    }
+
+    /**
+     * Reset numerical array indices.
+     *
+     * @param array $array Array
+     *
+     * @return void
+     */
+    protected function resetArrayIndices(&$array)
+    {
+        $isNumeric = count(array_filter(array_keys($array), 'is_string')) === 0;
+        if ($isNumeric) {
+            $array = array_values($array);
+        }
+    }
+}
diff --git a/module/VuFindApi/src/VuFindApi/Formatter/FacetFormatter.php b/module/VuFindApi/src/VuFindApi/Formatter/FacetFormatter.php
new file mode 100644
index 0000000000000000000000000000000000000000..cfc9a721be9400f3db1ed8df16f8cabae7fc0960
--- /dev/null
+++ b/module/VuFindApi/src/VuFindApi/Formatter/FacetFormatter.php
@@ -0,0 +1,192 @@
+<?php
+/**
+ * Facet formatter for API responses
+ *
+ * PHP Version 5
+ *
+ * Copyright (C) The National Library of Finland 2015-2016.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.    See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA    02111-1307    USA
+ *
+ * @category VuFind
+ * @package  API_Formatter
+ * @author   Ere Maijala <ere.maijala@helsinki.fi>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development:plugins:controllers Wiki
+ */
+namespace VuFindApi\Formatter;
+use VuFind\Search\Base\Results;
+
+/**
+ * Facet formatter for API responses
+ *
+ * @category VuFind
+ * @package  API_Formatter
+ * @author   Ere Maijala <ere.maijala@helsinki.fi>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development:plugins:controllers Wiki
+ */
+class FacetFormatter extends BaseFormatter
+{
+    /**
+     * Build an array of facet filters from the request params
+     *
+     * @param array $request Request params
+     *
+     * @return array
+     */
+    protected function buildFacetFilters($request)
+    {
+        $facetFilters = [];
+        if (isset($request['facetFilter'])) {
+            foreach ($request['facetFilter'] as $filter) {
+                list($facetField, $regex) = explode(':', $filter, 2);
+                $regex = trim($regex);
+                if (substr($regex, 0, 1)  == '"') {
+                    $regex = substr($regex, 1);
+                }
+                if (substr($regex, -1, 1) == '"') {
+                    $regex = substr($regex, 0, -1);
+                }
+                $facetFilters[$facetField][] = $regex;
+            }
+        }
+        return $facetFilters;
+    }
+
+    /**
+     * Match a facet item with the filters.
+     *
+     * @param array $facet   Facet
+     * @param array $filters Facet filters
+     *
+     * @return boolean
+     */
+    protected function matchFacetItem($facet, $filters)
+    {
+        $discard = true;
+        array_walk_recursive(
+            $facet,
+            function ($item, $key) use (&$discard, $filters) {
+                if ($discard && $key == 'value') {
+                    foreach ($filters as $filter) {
+                        $pattern = '/' . addcslashes($filter, '/') . '/';
+                        if (preg_match($pattern, $item) === 1) {
+                            $discard = false;
+                            break;
+                        }
+                    }
+                }
+            }
+        );
+        return !$discard;
+    }
+
+    /**
+     * Recursive function to create a facet value list for a single facet
+     *
+     * @param array $list    Facet items
+     * @param array $filters Facet filters
+     *
+     * @return array
+     */
+    protected function buildFacetValues($list, $filters = false)
+    {
+        $result = [];
+        $fields = [
+            'value', 'displayText', 'count',
+            'children', 'href', 'isApplied'
+        ];
+        foreach ($list as $value) {
+            $resultValue = [];
+            if ($filters && !$this->matchFacetItem($value, $filters)) {
+                continue;
+            }
+
+            foreach ($value as $key => $item) {
+                if (!in_array($key, $fields)) {
+                    continue;
+                }
+                if ($key == 'children') {
+                    if (!empty($item)) {
+                        $resultValue[$key]
+                            = $this->buildFacetValues(
+                                $item, $filters
+                            );
+                    }
+                } else {
+                    if ($key == 'displayText') {
+                        $key = 'translated';
+                    }
+                    $resultValue[$key] = $item;
+                }
+            }
+            $result[] = $resultValue;
+        }
+        return $result;
+    }
+
+    /**
+     * Create the result facet list
+     *
+     * @param array   $request               Request parameters
+     * @param Results $results               Search results
+     * @param array   $hierarchicalFacetData Hierarchical facet data
+     *
+     * @return array
+     */
+    public function format($request, Results $results, $hierarchicalFacetData)
+    {
+        if ($results->getResultTotal() == 0 || empty($request['facet'])) {
+            return [];
+        }
+
+        $filters = $this->buildFacetFilters($request);
+        $facets = $results->getFacetList();
+
+        // Format hierarchical facets, if any
+        if ($hierarchicalFacetData) {
+            foreach ($hierarchicalFacetData as $facet => $data) {
+                $facets[$facet]['list'] = $data;
+            }
+        }
+
+        // Add "missing" fields to non-hierarchical facets to make them similar
+        // to hierarchical facets for easier consumption.
+        $urlHelper = $results->getUrlQuery();
+        foreach ($facets as $facetKey => &$facetItems) {
+            if (isset($hierarchicalFacetData[$facetKey])) {
+                continue;
+            }
+
+            foreach ($facetItems['list'] as &$item) {
+                $href = !$item['isApplied']
+                    ? $urlHelper->addFacet(
+                        $facetKey, $item['value'], $item['operator']
+                    )->getParams(false) : $urlHelper->getParams(false);
+                $item['href'] = $href;
+            }
+        }
+        $this->filterArrayValues($facets);
+
+        $result = [];
+        foreach ($facets as $facetName => $facetData) {
+            $result[$facetName] = $this->buildFacetValues(
+                $facetData['list'],
+                !empty($filters[$facetName]) ? $filters[$facetName] : false
+            );
+        }
+        return $result;
+    }
+}
diff --git a/module/VuFindApi/src/VuFindApi/Formatter/RecordFormatter.php b/module/VuFindApi/src/VuFindApi/Formatter/RecordFormatter.php
new file mode 100644
index 0000000000000000000000000000000000000000..063259d002877c42eb3fdb7374498186faffa418
--- /dev/null
+++ b/module/VuFindApi/src/VuFindApi/Formatter/RecordFormatter.php
@@ -0,0 +1,256 @@
+<?php
+/**
+ * Record formatter for API responses
+ *
+ * PHP Version 5
+ *
+ * Copyright (C) The National Library of Finland 2015-2016.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.    See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA    02111-1307    USA
+ *
+ * @category VuFind
+ * @package  API_Formatter
+ * @author   Ere Maijala <ere.maijala@helsinki.fi>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development:plugins:controllers Wiki
+ */
+namespace VuFindApi\Formatter;
+use VuFind\I18n\TranslatableString;
+use Zend\View\HelperPluginManager;
+
+/**
+ * Record formatter for API responses
+ *
+ * @category VuFind
+ * @package  API_Formatter
+ * @author   Ere Maijala <ere.maijala@helsinki.fi>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development:plugins:controllers Wiki
+ */
+class RecordFormatter extends BaseFormatter
+{
+    /**
+     * Record field definitions
+     *
+     * @var array
+     */
+    protected $recordFields;
+
+    /**
+     * View helper plugin manager
+     *
+     * @var HelperPluginManager
+     */
+    protected $helperManager;
+
+    /**
+     * Constructor
+     *
+     * @param array               $recordFields  Record field definitions
+     * @param HelperPluginManager $helperManager View helper plugin manager
+     */
+    public function __construct($recordFields, HelperPluginManager $helperManager
+    ) {
+        $this->recordFields = $recordFields;
+        $this->helperManager = $helperManager;
+    }
+
+    /**
+     * Get dedup IDs
+     *
+     * @param \VuFind\RecordDriver\AbstractBase $record Record driver
+     *
+     * @return array|null
+     */
+    protected function getDedupIds($record)
+    {
+        if (!($dedupData = $record->tryMethod('getDedupData'))) {
+            return null;
+        }
+        $result = [];
+        foreach ($dedupData as $item) {
+            $result[] = $item['id'];
+        }
+        return $result ? $result : null;
+    }
+
+    /**
+     * Get extended subject headings
+     *
+     * @param \VuFind\RecordDriver\SolrDefault $record Record driver
+     *
+     * @return array|null
+     */
+    protected function getExtendedSubjectHeadings($record)
+    {
+        $result = $record->getAllSubjectHeadings(true);
+        // Make sure that the record driver returned the additional information and
+        // return data only if it did
+        return $result && isset($result[0]['heading']) ? $result : null;
+    }
+
+    /**
+     * Get full record for a record as XML
+     *
+     * @param \VuFind\RecordDriver\AbstractBase $record Record driver
+     *
+     * @return string|null
+     */
+    protected function getFullRecord($record)
+    {
+        if ($xml = $record->tryMethod('getFilteredXML')) {
+            return $xml;
+        }
+        $rawData = $record->tryMethod('getRawData');
+        return isset($rawData['fullrecord']) ? $rawData['fullrecord'] : null;
+    }
+
+    /**
+     * Get raw data for a record as an array
+     *
+     * @param \VuFind\RecordDriver\AbstractBase $record Record driver
+     *
+     * @return array
+     */
+    protected function getRawData($record)
+    {
+        $rawData = $record->tryMethod('getRawData');
+
+        // Leave out spelling data
+        unset($rawData['spelling']);
+
+        return $rawData;
+    }
+
+    /**
+     * Get (relative) link to record page
+     *
+     * @param \VuFind\RecordDriver\AbstractBase $record Record driver
+     *
+     * @return string
+     */
+    protected function getRecordPage($record)
+    {
+        $urlHelper = $this->helperManager->get('recordLink');
+        return $urlHelper->getUrl($record);
+    }
+
+    /**
+     * Get URLs
+     *
+     * @param \VuFind\RecordDriver\AbstractBase $record Record driver
+     *
+     * @return array
+     */
+    protected function getURLs($record)
+    {
+        $recordHelper = $this->helperManager->get('Record');
+        return $recordHelper($record)->getLinkDetails();
+    }
+
+    /**
+     * Get fields from a record as an array
+     *
+     * @param \VuFind\RecordDriver\AbstractBase $record Record driver
+     * @param array                             $fields Fields to get
+     *
+     * @return array
+     */
+    protected function getFields($record, $fields)
+    {
+        $result = [];
+        foreach ($fields as $field) {
+            if (!isset($this->recordFields[$field])) {
+                continue;
+            }
+            $method = $this->recordFields[$field]['vufind.method'];
+            if (strncmp($method, 'Formatter::', 11) == 0) {
+                $value = $this->{substr($method, 11)}($record);
+            } else {
+                $value = $record->tryMethod($method);
+            }
+            $result[$field] = $value;
+        }
+        // Convert any translation aware string classes to strings
+        $translator = $this->helperManager->get('translate');
+        array_walk_recursive(
+            $result,
+            function (&$value) use ($translator) {
+                if (is_object($value)) {
+                    if ($value instanceof TranslatableString) {
+                        $value = [
+                            'value' => (string)$value,
+                            'translated' => $translator->translate($value)
+                        ];
+                    } else {
+                        $value = (string)$value;
+                    }
+                }
+            }
+        );
+
+        return $result;
+    }
+
+    /**
+     * Get record field definitions.
+     *
+     * @return array
+     */
+    public function getRecordFields()
+    {
+        return $this->recordFields;
+    }
+
+    /**
+     * Return record field specs for the Swagger specification
+     *
+     * @return array
+     */
+    public function getRecordFieldSpec()
+    {
+        $fields = array_map(
+            function ($item) {
+                foreach (array_keys($item) as $key) {
+                    if (strncmp($key, 'vufind.', 7) == 0) {
+                        unset($item[$key]);
+                    }
+                }
+                return $item;
+            },
+            $this->recordFields
+        );
+        return $fields;
+    }
+
+    /**
+     * Format the results.
+     *
+     * @param array $results         Results to process (array of record drivers)
+     * @param array $requestedFields Fields to include in response
+     *
+     * @return array
+     */
+    public function format($results, $requestedFields)
+    {
+        $records = [];
+        foreach ($results as $result) {
+            $records[] = $this->getFields($result, $requestedFields);
+        }
+
+        $this->filterArrayValues($records);
+
+        return $records;
+    }
+}
diff --git a/module/VuFindApi/tests/unit-tests/src/VuFindTest/Formatter/FacetFormatterTest.php b/module/VuFindApi/tests/unit-tests/src/VuFindTest/Formatter/FacetFormatterTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..3dc10384df6b1797a1e5433168c42609de21e8ef
--- /dev/null
+++ b/module/VuFindApi/tests/unit-tests/src/VuFindTest/Formatter/FacetFormatterTest.php
@@ -0,0 +1,329 @@
+<?php
+
+/**
+ * Unit tests for facet formatter.
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2016.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * @category VuFind
+ * @package  Tests
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org
+ */
+namespace VuFindTest\Formatter;
+
+use VuFindTest\Search\TestHarness\Options;
+use VuFindTest\Search\TestHarness\Params;
+use VuFindTest\Search\TestHarness\Results;
+
+/**
+ * Unit tests for facet formatter.
+ *
+ * @category VuFind
+ * @package  Tests
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org
+ */
+class FacetFormatterTest extends \VuFindTest\Unit\TestCase
+{
+    /**
+     * Get fake facet data.
+     *
+     * @param bool $includeOr Include OR facet data?
+     *
+     * @return array
+     */
+    protected function getFakeFacetData($includeOr = false)
+    {
+        $data = [
+            'foo' => [
+                'label' => 'Foo Facet',
+                'list' => [
+                    [
+                        'value' => 'bar',
+                        'displayText' => 'translated(bar)',
+                        'count' => 100,
+                        'operator' => 'AND',
+                        'isApplied' => false,
+                    ],
+                    [
+                        'value' => 'baz',
+                        'displayText' => 'translated(baz)',
+                        'count' => 150,
+                        'operator' => 'AND',
+                        'isApplied' => true,
+                    ]
+                ]
+            ],
+            'xyzzy' => [
+                'label' => 'Xyzzy Facet',
+                'list' => [
+                    [
+                        'value' => 'val1',
+                        'displayText' => 'translated(val1)',
+                        'count' => 10,
+                        'operator' => 'OR',
+                        'isApplied' => false,
+                    ],
+                    [
+                        'value' => 'val2',
+                        'displayText' => 'translated(val2)',
+                        'count' => 15,
+                        'operator' => 'OR',
+                        'isApplied' => true,
+                    ],
+                    [
+                        'value' => 'val3',
+                        'displayText' => 'translated(val3)',
+                        'count' => 5,
+                        'operator' => 'OR',
+                        'isApplied' => true,
+                    ]
+                ]
+            ]
+        ];
+        if (!$includeOr) {
+            unset($data['xyzzy']);
+            unset($data['hierarchical_xyzzy']);
+        }
+        return $data;
+    }
+
+    /**
+     * Get fake hierarchical facet data.
+     *
+     * @param array $request   Request params
+     * @param bool  $includeOr Include OR facet data?
+     *
+     * @return array
+     */
+    protected function getFakeHierarchicalFacetData($request, $includeOr = false)
+    {
+        $data = [
+            'hierarchical_foo' => [
+                [
+                    'value' => '0/bar/',
+                    'displayText' => 'translated(bar)',
+                    'count' => 100,
+                    'operator' => 'AND',
+                    'isApplied' => false,
+                ],
+                [
+                    'value' => '1/bar/cookie/',
+                    'displayText' => 'translated(cookie)',
+                    'count' => 150,
+                    'operator' => 'AND',
+                    'isApplied' => true,
+                ]
+            ],
+            'hierarchical_xyzzy' => [
+                [
+                    'value' => '0/val1/',
+                    'displayText' => 'translated(val1)',
+                    'count' => 10,
+                    'operator' => 'OR',
+                    'isApplied' => false,
+                ],
+                [
+                    'value' => '1/val1/val2/',
+                    'displayText' => 'translated(val2)',
+                    'count' => 15,
+                    'operator' => 'OR',
+                    'isApplied' => true,
+                ]
+            ]
+        ];
+        if (!$includeOr) {
+            unset($data['hierarchical_xyzzy']);
+        }
+
+        $results = [];
+        $helper = new \VuFind\Search\Solr\HierarchicalFacetHelper();
+        $configManager = $this->createMock('VuFind\Config\PluginManager');
+        $params = new Params(new Options($configManager), $configManager);
+        $requestParams = new \Zend\StdLib\Parameters($request);
+        $params->initFromRequest($requestParams);
+        $factory = new \VuFind\Search\Factory\UrlQueryHelperFactory();
+        $urlQuery = $factory->fromParams($params);
+        foreach ($data as $facet => $values) {
+            $results[$facet] = $helper->buildFacetArray(
+                $facet, $values, $urlQuery, false
+            );
+        }
+
+        return $results;
+    }
+
+    /**
+     * Get fake results object.
+     *
+     * @param array $request   Request parameters.
+     * @param array $facetData Facet data to inject into results.
+     *
+     * @return Results
+     */
+    protected function getFakeResults($request, $facetData)
+    {
+        $configManager = $this->createMock('VuFind\Config\PluginManager');
+        $params = new Params(new Options($configManager), $configManager);
+        $params->initFromRequest(new \Zend\Stdlib\Parameters($request));
+        $ss = $this->getMockBuilder('VuFindSearch\Service')
+            ->disableOriginalConstructor()->getMock();
+        $rl = $this->getMockBuilder('VuFind\Record\Loader')
+            ->disableOriginalConstructor()->getMock();
+        return new Results($params, $ss, $rl, 100, $facetData);
+    }
+
+    /**
+     * Test the facet formatter
+     *
+     * @return void
+     */
+    public function testFormatter()
+    {
+        $formatter = new \VuFindApi\Formatter\FacetFormatter();
+        $request = [
+            'facet' => ['foo', 'hierarchical_foo'],
+            'filter' => ['foo:baz', 'hierarchical_foo:1/bar/cookie/'],
+        ];
+        $formatted = $formatter->format(
+            $request, $this->getFakeResults($request, $this->getFakeFacetData()),
+            $this->getFakeHierarchicalFacetData($request)
+        );
+
+        $expected = [
+            'foo' => [
+                [
+                    'value' => 'bar',
+                    'translated' => 'translated(bar)',
+                    'count' => 100,
+                    'href' => '?filter%5B%5D=foo%3A%22baz%22&filter%5B%5D=hierarchical_foo%3A%221%2Fbar%2Fcookie%2F%22&filter%5B%5D=foo%3A%22bar%22',
+                ],
+                [
+                    'value' => 'baz',
+                    'translated' => 'translated(baz)',
+                    'count' => 150,
+                    'isApplied' => 1,
+                    'href' => '?filter%5B%5D=foo%3A%22baz%22&filter%5B%5D=hierarchical_foo%3A%221%2Fbar%2Fcookie%2F%22',
+                ],
+            ],
+            'hierarchical_foo' => [
+                [
+                    'value' => '0/bar/',
+                    'translated' => 'translated(bar)',
+                    'count' => 100,
+                    'href' => '?filter%5B%5D=foo%3A%22baz%22&filter%5B%5D=hierarchical_foo%3A%221%2Fbar%2Fcookie%2F%22&filter%5B%5D=hierarchical_foo%3A%220%2Fbar%2F%22',
+                    'children' => [
+                        [
+                            'value' => '1/bar/cookie/',
+                            'translated' => 'translated(cookie)',
+                            'count' => 150,
+                            'isApplied' => 1,
+                            'href' => '?filter%5B%5D=foo%3A%22baz%22',
+                        ]
+                    ]
+                ]
+            ],
+        ];
+        $this->assertEquals($expected, $formatted);
+    }
+
+    /**
+     * Test the facet formatter with filtering turned on
+     *
+     * @return void
+     */
+    public function testFormatterWithFiltering()
+    {
+        $formatter = new \VuFindApi\Formatter\FacetFormatter();
+        $request = [
+            'facet' => ['foo', 'xyzzy'],
+            'filter' => ['foo:baz', 'hierarchical_foo:1/bar/cookie/', '~xyzzy:val2', '~xyzzy:val3', 'hierarchical_xyzzy:1/val1/val2/'],
+            'facetFilter' => ['foo:..z', 'xyzzy:val(2|3)'],
+        ];
+        $formatted = $formatter->format(
+            $request, $this->getFakeResults($request, $this->getFakeFacetData(true)),
+            $this->getFakeHierarchicalFacetData($request, true)
+        );
+
+        $expected = [
+            'foo' => [
+                [
+                    'value' => 'baz',
+                    'translated' => 'translated(baz)',
+                    'count' => 150,
+                    'isApplied' => 1,
+                    'href' => '?filter%5B%5D=foo%3A%22baz%22&filter%5B%5D=hierarchical_foo%3A%221%2Fbar%2Fcookie%2F%22&filter%5B%5D=%7Exyzzy%3A%22val2%22&filter%5B%5D=%7Exyzzy%3A%22val3%22&filter%5B%5D=hierarchical_xyzzy%3A%221%2Fval1%2Fval2%2F%22',
+                ],
+            ],
+            'xyzzy' => [
+                [
+                    'value' => 'val2',
+                    'translated' => 'translated(val2)',
+                    'count' => 15,
+                    'href' => '?filter%5B%5D=foo%3A%22baz%22&filter%5B%5D=hierarchical_foo%3A%221%2Fbar%2Fcookie%2F%22&filter%5B%5D=%7Exyzzy%3A%22val2%22&filter%5B%5D=%7Exyzzy%3A%22val3%22&filter%5B%5D=hierarchical_xyzzy%3A%221%2Fval1%2Fval2%2F%22',
+                    'isApplied' => 1,
+                ],
+                [
+                    'value' => 'val3',
+                    'translated' => 'translated(val3)',
+                    'count' => 5,
+                    'href' => '?filter%5B%5D=foo%3A%22baz%22&filter%5B%5D=hierarchical_foo%3A%221%2Fbar%2Fcookie%2F%22&filter%5B%5D=%7Exyzzy%3A%22val2%22&filter%5B%5D=%7Exyzzy%3A%22val3%22&filter%5B%5D=hierarchical_xyzzy%3A%221%2Fval1%2Fval2%2F%22',
+                    'isApplied' => 1,
+                ],
+            ],
+            'hierarchical_foo' => [
+                [
+                    'value' => '0/bar/',
+                    'translated' => 'translated(bar)',
+                    'count' => 100,
+                    'href' => '?filter%5B%5D=foo%3A%22baz%22&filter%5B%5D=hierarchical_foo%3A%221%2Fbar%2Fcookie%2F%22&filter%5B%5D=%7Exyzzy%3A%22val2%22&filter%5B%5D=%7Exyzzy%3A%22val3%22&filter%5B%5D=hierarchical_xyzzy%3A%221%2Fval1%2Fval2%2F%22&filter%5B%5D=hierarchical_foo%3A%220%2Fbar%2F%22',
+                    'children' => [
+                        [
+                            'value' => '1/bar/cookie/',
+                            'translated' => 'translated(cookie)',
+                            'count' => 150,
+                            'isApplied' => 1,
+                            'href' => '?filter%5B%5D=foo%3A%22baz%22&filter%5B%5D=%7Exyzzy%3A%22val2%22&filter%5B%5D=%7Exyzzy%3A%22val3%22&filter%5B%5D=hierarchical_xyzzy%3A%221%2Fval1%2Fval2%2F%22',
+                        ]
+                    ]
+                ]
+            ],
+            'hierarchical_xyzzy' => [
+                [
+                    'value' => '0/val1/',
+                    'translated' => 'translated(val1)',
+                    'count' => 10,
+                    'href' => '?filter%5B%5D=foo%3A%22baz%22&filter%5B%5D=hierarchical_foo%3A%221%2Fbar%2Fcookie%2F%22&filter%5B%5D=%7Exyzzy%3A%22val2%22&filter%5B%5D=%7Exyzzy%3A%22val3%22&filter%5B%5D=hierarchical_xyzzy%3A%221%2Fval1%2Fval2%2F%22&filter%5B%5D=%7Ehierarchical_xyzzy%3A%220%2Fval1%2F%22',
+                    'children' => [
+                        [
+                            'value' => '1/val1/val2/',
+                            'translated' => 'translated(val2)',
+                            'count' => 15,
+                            'isApplied' => 1,
+                            'href' => '?filter%5B%5D=foo%3A%22baz%22&filter%5B%5D=hierarchical_foo%3A%221%2Fbar%2Fcookie%2F%22&filter%5B%5D=%7Exyzzy%3A%22val2%22&filter%5B%5D=%7Exyzzy%3A%22val3%22&filter%5B%5D=hierarchical_xyzzy%3A%221%2Fval1%2Fval2%2F%22',
+                        ]
+                    ]
+                ]
+            ]
+        ];
+        $this->assertEquals($expected, $formatted);
+    }
+}
diff --git a/module/VuFindApi/tests/unit-tests/src/VuFindTest/Formatter/RecordFormatterTest.php b/module/VuFindApi/tests/unit-tests/src/VuFindTest/Formatter/RecordFormatterTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..61f1406840874104bd41f6a7d26a21ba45c8d72b
--- /dev/null
+++ b/module/VuFindApi/tests/unit-tests/src/VuFindTest/Formatter/RecordFormatterTest.php
@@ -0,0 +1,200 @@
+<?php
+
+/**
+ * Unit tests for record formatter.
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2016.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * @category VuFind
+ * @package  Tests
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org
+ */
+namespace VuFindTest\Formatter;
+use VuFindApi\Formatter\RecordFormatter;
+use VuFind\I18n\TranslatableString;
+
+/**
+ * Unit tests for record formatter.
+ *
+ * @category VuFind
+ * @package  Tests
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org
+ */
+class RecordFormatterTest extends \VuFindTest\Unit\TestCase
+{
+    /**
+     * Get default configuration to use in tests when no overrides are specified.
+     *
+     * @return array
+     */
+    protected function getDefaultDefs()
+    {
+        return [
+            'cleanDOI' => [
+                'vufind.method' => 'getCleanDOI',
+                'description' => 'First valid DOI',
+                'type' => 'string'
+            ],
+            'dedupIds' => [
+                'vufind.method' => 'Formatter::getDedupIds',
+                'description' => 'IDs of all records deduplicated',
+                'type' => 'array',
+                'items' => ['type' => 'string']
+            ],
+            'fullRecord' => ['vufind.method' => 'Formatter::getFullRecord'],
+            'rawData' => ['vufind.method' => 'Formatter::getRawData'],
+            'buildings' => ['vufind.method' => 'getBuilding'],
+            'recordPage' => ['vufind.method' => 'Formatter::getRecordPage'],
+            'subjectsExtended' => [
+                'vufind.method' => 'Formatter::getExtendedSubjectHeadings'
+            ],
+        ];
+    }
+
+    /**
+     * Get a helper plugin manager for the RecordFormatter.
+     *
+     * @return \Zend\View\HelperPluginManager
+     */
+    protected function getHelperPluginManager()
+    {
+        $hm = new \Zend\View\HelperPluginManager();
+        $hm->setService('translate', new \VuFind\View\Helper\Root\Translate());
+
+        $mockRecordLink = $this->getMockBuilder('VuFind\View\Helper\Root\RecordLink')
+            ->disableOriginalConstructor()->getMock();
+        $mockRecordLink->expects($this->any())->method('getUrl')
+            ->will($this->returnValue('http://record'));
+        $hm->setService('recordLink', $mockRecordLink);
+        return $hm;
+    }
+
+    /**
+     * Get a formatter to test with.
+     *
+     * @param array $defs Configuration for formatter
+     *
+     * @return RecordFormatter
+     */
+    protected function getFormatter($defs = null)
+    {
+        return new RecordFormatter(
+            $defs ?: $this->getDefaultDefs(), $this->getHelperPluginManager()
+        );
+    }
+
+    /**
+     * Get a record driver to test with.
+     *
+     * @return \VuFindTest\RecordDriver\TestHarness
+     */
+    protected function getDriver()
+    {
+        $driver = new \VuFindTest\RecordDriver\TestHarness();
+        $driver->setRawData(
+            [
+                'CleanDOI' => 'foo',
+                'DedupData' => [['id' => 'bar']],
+                'fullrecord' => 'xyzzy',
+                'spelling' => 's',
+                'Building' => ['foo', new TranslatableString('bar', 'xyzzy')],
+                'AllSubjectHeadings' => [['heading' => 'subject']],
+            ]
+        );
+        return $driver;
+    }
+
+    /**
+     * Test the record formatter.
+     *
+     * @return void
+     */
+    public function testFormatter()
+    {
+        $formatter = $this->getFormatter();
+
+        $driver = $this->getDriver();
+
+        // Test requesting no fields.
+        $this->assertEquals([], $formatter->format([$driver], []));
+
+        // Test requesting fields:
+        $results = $formatter->format(
+            [$driver], array_keys($this->getDefaultDefs())
+        );
+        $expectedRaw = $driver->getRawData();
+        unset($expectedRaw['spelling']);
+        $expectedRaw['Building'] = [
+            'foo', ['value' => 'bar', 'translated' => 'xyzzy']
+        ];
+        $expected = [
+            [
+                'cleanDOI' => 'foo',
+                'dedupIds' => ['bar'],
+                'fullRecord' => 'xyzzy',
+                'rawData' => $expectedRaw,
+                'buildings' => ['foo', ['value' => 'bar', 'translated' => 'xyzzy']],
+                'recordPage' => 'http://record',
+                'subjectsExtended' => [['heading' => 'subject']],
+            ],
+        ];
+        $this->assertEquals($expected, $results);
+
+        // Test filtered XML
+        $filtered = '<filtered></filtered>';
+        $driver->setFilteredXML($filtered);
+        $results = $formatter->format(
+            [$driver], array_keys($this->getDefaultDefs())
+        );
+        $expected[0]['fullRecord'] = $filtered;
+        $expected[0]['rawData']['FilteredXML'] = $filtered;
+        $this->assertEquals($expected, $results);
+    }
+
+    /**
+     * Test getting the field specs.
+     *
+     * @return void
+     */
+    public function testFieldSpecs()
+    {
+        $formatter = $this->getFormatter();
+        $results = $formatter->getRecordFieldSpec();
+        $expected = [
+            'cleanDOI' => [
+                'description' => 'First valid DOI',
+                'type' => 'string'
+            ],
+            'dedupIds' => [
+                'description' => 'IDs of all records deduplicated',
+                'type' => 'array',
+                'items' => ['type' => 'string']
+            ],
+            'fullRecord' => [],
+            'rawData' => [],
+            'buildings' => [],
+            'recordPage' => [],
+            'subjectsExtended' => [],
+        ];
+        $this->assertEquals($expected, $results);
+    }
+}
diff --git a/module/VuFindConsole/Module.php b/module/VuFindConsole/Module.php
index 016f39db18ab8eb9e4ccf0f386a0754a1c2dc693..25daa33b94d9ddc168f015b13f7504673d851d9c 100644
--- a/module/VuFindConsole/Module.php
+++ b/module/VuFindConsole/Module.php
@@ -37,7 +37,8 @@ use Zend\Console\Adapter\AdapterInterface as Console;
  * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
  * @link     https://vufind.org/wiki/development
  */
-class Module implements \Zend\ModuleManager\Feature\ConsoleUsageProviderInterface
+class Module implements \Zend\ModuleManager\Feature\ConsoleUsageProviderInterface,
+    \Zend\ModuleManager\Feature\ConsoleBannerProviderInterface
 {
     /**
      * Get module configuration
@@ -65,6 +66,24 @@ class Module implements \Zend\ModuleManager\Feature\ConsoleUsageProviderInterfac
         ];
     }
 
+    /**
+     * Returns a string containing a banner text, that describes the module and/or
+     * the application.
+     * The banner is shown in the console window, when the user supplies invalid
+     * command-line parameters or invokes the application with no parameters.
+     *
+     * The method is called with active Zend\Console\Adapter\AdapterInterface that
+     * can be used to directly access Console and send output.
+     *
+     * @param Console $console Console adapter
+     *
+     * @return string|null
+     */
+    public function getConsoleBanner(Console $console)
+    {
+        return 'VuFind';
+    }
+
     /**
      * Return usage information
      *
@@ -77,9 +96,9 @@ class Module implements \Zend\ModuleManager\Feature\ConsoleUsageProviderInterfac
     public function getConsoleUsage(Console $console)
     {
         return [
+            'generate dynamicroute' => 'Add a dynamic route',
             'generate extendservice' => 'Override a service with a new child class',
             'generate nontabrecordaction' => 'Add routes for non-tab record action',
-            'generate dynamicroute' => 'Add a dynamic route',
             'generate recordroute' => 'Add a record route',
             'generate staticroute' => 'Add a static route',
             'harvest harvest_oai' => 'OAI-PMH harvester',
@@ -96,15 +115,17 @@ class Module implements \Zend\ModuleManager\Feature\ConsoleUsageProviderInterfac
             'util createHierarchyTrees' => 'Cache populator for hierarchies',
             'util cssBuilder' => 'LESS compiler',
             'util deletes' => 'Tool for deleting Solr records',
+            'util expire_external_sessions'
+                => 'Database external_session table cleanup',
             'util expire_searches' => 'Database search table cleanup',
             'util expire_sessions' => 'Database session table cleanup',
             'util index_reserves' => 'Solr reserves indexer',
             'util optimize' => 'Solr optimize tool',
             'util sitemap' => 'XML sitemap generator',
+            'util suppressed' => 'Remove ILS-suppressed records from Solr',
             'util switch_db_hash' => 'Switch the hashing algorithm in the database '
                 . 'and config. Expects new algorithm and (optional) new key as'
                 . ' parameters.',
-            'util suppressed' => 'Remove ILS-suppressed records from Solr',
         ];
     }
 }
diff --git a/module/VuFindConsole/config/module.config.php b/module/VuFindConsole/config/module.config.php
index 5f14cab092d4a0368f55b04667b8ebea34b11b93..d02890ccae53b1286cc29ab6104d472f8d10458b 100644
--- a/module/VuFindConsole/config/module.config.php
+++ b/module/VuFindConsole/config/module.config.php
@@ -3,17 +3,29 @@ namespace VuFindConsole\Module\Configuration;
 
 $config = [
     'controllers' => [
-        'invokables' => [
-            'generate' => 'VuFindConsole\Controller\GenerateController',
-            'harvest' => 'VuFindConsole\Controller\HarvestController',
-            'import' => 'VuFindConsole\Controller\ImportController',
-            'language' => 'VuFindConsole\Controller\LanguageController',
-            'util' => 'VuFindConsole\Controller\UtilController',
+        'factories' => [
+            'generate' => 'VuFindConsole\Controller\Factory::getGenerateController',
+            'harvest' => 'VuFindConsole\Controller\Factory::getHarvestController',
+            'import' => 'VuFindConsole\Controller\Factory::getImportController',
+            'language' => 'VuFindConsole\Controller\Factory::getLanguageController',
+            'redirect' => 'VuFindConsole\Controller\Factory::getRedirectController',
+            'util' => 'VuFindConsole\Controller\Factory::getUtilController',
         ],
     ],
     'console' => [
         'router'  => [
-          'router_class'  => 'VuFindConsole\Mvc\Router\ConsoleRouter',
+            'routes'  => [
+                'default-route' => [
+                    'type' => 'catchall',
+                    'options' => [
+                        'route' => '',
+                        'defaults' => [
+                            'controller' => 'redirect',
+                            'action' => 'consoledefault',
+                        ],
+                    ],
+                ],
+            ],
         ],
     ],
     'view_manager' => [
@@ -22,4 +34,36 @@ $config = [
     ],
 ];
 
+$routes = [
+    'generate/dynamicroute' => 'generate dynamicroute [<name>] [<newController>] [<newAction>] [<module>]',
+    'generate/extendservice' => 'generate extendservice [<source>] [<target>]',
+    'generate/nontabrecordaction' => 'generate nontabrecordaction [<newAction>] [<module>]',
+    'generate/recordroute' => 'generate recordroute [<base>] [<newController>] [<module>]',
+    'generate/staticroute' => 'generate staticroute [<name>] [<module>]',
+    // harvest/harvest_oai is too complex to represent here; we need to rely on default-route
+    'harvest/merge-marc' => 'harvest merge-marc [<dir>]',
+    'import/import-xsl' => 'import import-xsl [--test-only] [--index=] [<xml>] [<properties>]',
+    'import/webcrawl' => 'import webcrawl [--test-only] [--index=]',
+    'language/addusingtemplate' => 'language addusingtemplate [<target>] [<template>]',
+    'language/copystring' => 'language copystring [<source>] [<target>]',
+    'language/delete' => 'language delete [<target>]',
+    'language/normalize' => 'language normalize [<target>]',
+    'util/cleanup_record_cache' => 'util (cleanuprecordcache|cleanup_record_cache) [--help|-h]',
+    'util/commit' => 'util commit [<core>]',
+    'util/createHierarchyTrees' => 'util createHierarchyTrees [--skip-xml|-sx] [--skip-json|-sj] [--help|-h]',
+    // util/cssBuilder relies on default-route because it has an arbitrary number of parameters
+    'util/deletes' => 'util deletes [--verbose] [<filename>] [<format>] [<index>]',
+    'util/expire_external_sessions' => 'util expire_external_sessions [--help|-h] [--batch=] [--sleep=] [<daysOld>]',
+    'util/expire_searches' => 'util expire_searches [--help|-h] [--batch=] [--sleep=] [<daysOld>]',
+    'util/expire_sessions' => 'util expire_sessions [--help|-h] [--batch=] [--sleep=] [<daysOld>]',
+    'util/index_reserves' => 'util index_reserves [--help|-h] [-d=s] [-t=s] [-f=s]',
+    'util/optimize' => 'util optimize [<core>]',
+    'util/sitemap' => 'util sitemap',
+    'util/suppressed' => 'util suppressed [--help|-h] [--authorities] [--outfile=s]',
+    'util/switch_db_hash' => 'util switch_db_hash [<newhash>] [<newkey>]',
+];
+
+$routeGenerator = new \VuFindConsole\Route\RouteGenerator();
+$routeGenerator->addRoutes($config, $routes);
+
 return $config;
diff --git a/module/VuFindConsole/src/VuFindConsole/Controller/AbstractBase.php b/module/VuFindConsole/src/VuFindConsole/Controller/AbstractBase.php
index dfc34ed0c95f40eb354571135a06504004d8bd7d..aff3bfdc4e45150c39e5d63791ed4ae61957f2f0 100644
--- a/module/VuFindConsole/src/VuFindConsole/Controller/AbstractBase.php
+++ b/module/VuFindConsole/src/VuFindConsole/Controller/AbstractBase.php
@@ -27,7 +27,8 @@
  * @link     https://vufind.org/wiki/development:plugins:controllers Wiki
  */
 namespace VuFindConsole\Controller;
-use Zend\Console\Console, Zend\Console\Getopt,
+use Zend\Console\Console,
+    Zend\ServiceManager\ServiceLocatorInterface,
     Zend\Mvc\Controller\AbstractActionController;
 
 /**
@@ -42,28 +43,22 @@ use Zend\Console\Console, Zend\Console\Getopt,
  */
 class AbstractBase extends AbstractActionController
 {
-    /**
-     * Console options
-     *
-     * @var Getopt
-     */
-    protected $consoleOpts;
-
     /**
      * Constructor
+     *
+     * @param ServiceLocatorInterface $sm Service locator
      */
-    public function __construct()
+    public function __construct(ServiceLocatorInterface $sm)
     {
         // This controller should only be accessed from the command line!
         if (PHP_SAPI != 'cli') {
             throw new \Exception('Access denied to command line tools.');
         }
 
-        // Get access to information about the CLI request.
-        $this->consoleOpts = new Getopt([]);
+        $this->setServiceLocator($sm);
 
         // Switch the context back to the original working directory so that
-        // relative paths work as expected.  (This constant is set in
+        // relative paths work as expected. (This constant is set in
         // public/index.php)
         if (defined('ORIGINAL_WORKING_DIRECTORY')) {
             chdir(ORIGINAL_WORKING_DIRECTORY);
@@ -121,7 +116,7 @@ class AbstractBase extends AbstractActionController
      */
     public function getConfig($id = 'config')
     {
-        return $this->getServiceLocator()->get('VuFind\Config')->get($id);
+        return $this->serviceLocator->get('VuFind\Config')->get($id);
     }
 
     /**
@@ -131,7 +126,7 @@ class AbstractBase extends AbstractActionController
      */
     public function getILS()
     {
-        return $this->getServiceLocator()->get('VuFind\ILSConnection');
+        return $this->serviceLocator->get('VuFind\ILSConnection');
     }
 
     /**
@@ -143,7 +138,7 @@ class AbstractBase extends AbstractActionController
      */
     public function getTable($table)
     {
-        return $this->getServiceLocator()->get('VuFind\DbTablePluginManager')
+        return $this->serviceLocator->get('VuFind\DbTablePluginManager')
             ->get($table);
     }
 }
diff --git a/module/VuFindConsole/src/VuFindConsole/Controller/Factory.php b/module/VuFindConsole/src/VuFindConsole/Controller/Factory.php
new file mode 100644
index 0000000000000000000000000000000000000000..110efc00109a66fb0b7d2722ab11ff66ec03a386
--- /dev/null
+++ b/module/VuFindConsole/src/VuFindConsole/Controller/Factory.php
@@ -0,0 +1,80 @@
+<?php
+/**
+ * Factory for controllers.
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2014.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * @category VuFind
+ * @package  Controller
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development Wiki
+ */
+namespace VuFindConsole\Controller;
+use Zend\ServiceManager\ServiceManager;
+
+/**
+ * Factory for controllers.
+ *
+ * @category VuFind
+ * @package  Controller
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development Wiki
+ *
+ * @codeCoverageIgnore
+ */
+class Factory
+{
+    /**
+     * Construct a generic controller.
+     *
+     * @param string         $name Name of table to construct (fully qualified
+     * class name, or else a class name within the current namespace)
+     * @param ServiceManager $sm   Service manager
+     *
+     * @return object
+     */
+    public static function getGenericController($name, ServiceManager $sm)
+    {
+        // Prepend the current namespace unless we receive a FQCN:
+        $class = (strpos($name, '\\') === false)
+            ? __NAMESPACE__ . '\\' . $name : $name;
+        if (!class_exists($class)) {
+            throw new \Exception('Cannot construct ' . $class);
+        }
+        return new $class($sm->getServiceLocator());
+    }
+
+    /**
+     * Construct a generic controller.
+     *
+     * @param string $name Method name being called
+     * @param array  $args Method arguments
+     *
+     * @return object
+     */
+    public static function __callStatic($name, $args)
+    {
+        // Strip "get" from method name to get name of class; pass first argument
+        // on assumption that it should be the ServiceManager object.
+        return static::getGenericController(
+            substr($name, 3), isset($args[0]) ? $args[0] : null
+        );
+    }
+}
diff --git a/module/VuFindConsole/src/VuFindConsole/Controller/GenerateController.php b/module/VuFindConsole/src/VuFindConsole/Controller/GenerateController.php
index 7058b9800231de3e57dc622c56269ed6b01b6956..310e54c74aa659d2d5cef4b025a96c0a7dae5f43 100644
--- a/module/VuFindConsole/src/VuFindConsole/Controller/GenerateController.php
+++ b/module/VuFindConsole/src/VuFindConsole/Controller/GenerateController.php
@@ -50,11 +50,15 @@ class GenerateController extends AbstractBase
      */
     public function dynamicrouteAction()
     {
-        $argv = $this->consoleOpts->getRemainingArgs();
-        if (!isset($argv[3])) {
+        $request = $this->getRequest();
+        $route = $request->getParam('name');
+        $controller = $request->getParam('newController');
+        $action = $request->getParam('newAction');
+        $module = $request->getParam('module');
+        if (empty($module)) {
             Console::writeLine(
-                "Usage: {$_SERVER['argv'][0]} [route] [controller] [action]"
-                . " [target_module]"
+                'Usage: ' . $request->getScriptName() . ' generate dynamicroute'
+                . ' [route] [controller] [action] [target_module]'
             );
             Console::writeLine(
                 "\troute - the route name (used by router), e.g. customList"
@@ -71,11 +75,6 @@ class GenerateController extends AbstractBase
             return $this->getFailureResponse();
         }
 
-        $route = $argv[0];
-        $controller = $argv[1];
-        $action = $argv[2];
-        $module = $argv[3];
-
         // Create backup of configuration
         $configPath = $this->getModuleConfigPath($module);
         $this->backUpFile($configPath);
@@ -98,10 +97,13 @@ class GenerateController extends AbstractBase
     public function extendserviceAction()
     {
         // Display help message if parameters missing:
-        $argv = $this->consoleOpts->getRemainingArgs();
-        if (!isset($argv[1])) {
+        $request = $this->getRequest();
+        $source = $request->getParam('source');
+        $target = $request->getParam('target');
+        if (empty($source) || empty($target)) {
             Console::writeLine(
-                "Usage: {$_SERVER['argv'][0]} [config_path] [target_module]"
+                'Usage: ' . $request->getScriptName() . ' generate extendservice'
+                . ' [config_path] [target_module]'
             );
             Console::writeLine(
                 "\tconfig_path - the path to the service in the framework config"
@@ -113,9 +115,6 @@ class GenerateController extends AbstractBase
             return $this->getFailureResponse();
         }
 
-        $source = $argv[0];
-        $target = $argv[1];
-
         $parts = explode('/', $source);
         $partCount = count($parts);
         if ($partCount < 3) {
@@ -166,10 +165,13 @@ class GenerateController extends AbstractBase
      */
     public function nontabrecordactionAction()
     {
-        $argv = $this->consoleOpts->getRemainingArgs();
-        if (!isset($argv[1])) {
+        $request = $this->getRequest();
+        $action = $request->getParam('newAction');
+        $module = $request->getParam('module');
+        if (empty($action) || empty($module)) {
             Console::writeLine(
-                "Usage: {$_SERVER['argv'][0]} [action] [target_module]"
+                'Usage: ' . $request->getScriptName()
+                . ' generate nontabrecordaction [action] [target_module]'
             );
             Console::writeLine(
                 "\taction - new action to add"
@@ -180,9 +182,6 @@ class GenerateController extends AbstractBase
             return $this->getFailureResponse();
         }
 
-        $action = $argv[0];
-        $module = $argv[1];
-
         // Create backup of configuration
         $configPath = $this->getModuleConfigPath($module);
         $this->backUpFile($configPath);
@@ -191,7 +190,7 @@ class GenerateController extends AbstractBase
         $config = include $configPath;
 
         // Append the route
-        $mainConfig = $this->getServiceLocator()->get('Config');
+        $mainConfig = $this->serviceLocator->get('Config');
         foreach ($mainConfig['router']['routes'] as $key => $val) {
             if (isset($val['options']['route'])
                 && substr($val['options']['route'], -14) == '[:id[/[:tab]]]'
@@ -221,10 +220,14 @@ class GenerateController extends AbstractBase
      */
     public function recordrouteAction()
     {
-        $argv = $this->consoleOpts->getRemainingArgs();
-        if (!isset($argv[2])) {
+        $request = $this->getRequest();
+        $base = $request->getParam('base');
+        $controller = $request->getParam('newController');
+        $module = $request->getParam('module');
+        if (empty($module)) {
             Console::writeLine(
-                "Usage: {$_SERVER['argv'][0]} [base] [controller] [target_module]"
+                'Usage: ' . $request->getScriptName() . ' generate recordroute'
+                . ' [base] [controller] [target_module]'
             );
             Console::writeLine(
                 "\tbase - the base route name (used by router), e.g. record"
@@ -238,10 +241,6 @@ class GenerateController extends AbstractBase
             return $this->getFailureResponse();
         }
 
-        $base = $argv[0];
-        $controller = $argv[1];
-        $module = $argv[2];
-
         // Create backup of configuration
         $configPath = $this->getModuleConfigPath($module);
         $this->backUpFile($configPath);
@@ -263,10 +262,13 @@ class GenerateController extends AbstractBase
      */
     public function staticrouteAction()
     {
-        $argv = $this->consoleOpts->getRemainingArgs();
-        if (!isset($argv[1])) {
+        $request = $this->getRequest();
+        $route = $request->getParam('name');
+        $module = $request->getParam('module');
+        if (empty($module)) {
             Console::writeLine(
-                "Usage: {$_SERVER['argv'][0]} [route_definition] [target_module]"
+                'Usage: ' . $request->getScriptName() . ' generate staticroute'
+                . ' [route_definition] [target_module]'
             );
             Console::writeLine(
                 "\troute_definition - a Controller/Action string, e.g. Search/Home"
@@ -277,9 +279,6 @@ class GenerateController extends AbstractBase
             return $this->getFailureResponse();
         }
 
-        $route = $argv[0];
-        $module = $argv[1];
-
         // Create backup of configuration
         $configPath = $this->getModuleConfigPath($module);
         $this->backUpFile($configPath);
@@ -604,7 +603,7 @@ class GenerateController extends AbstractBase
      */
     protected function retrieveConfig(array $path)
     {
-        $config = $this->getServiceLocator()->get('config');
+        $config = $this->serviceLocator->get('config');
         foreach ($path as $part) {
             if (!isset($config[$part])) {
                 return false;
diff --git a/module/VuFindConsole/src/VuFindConsole/Controller/HarvestController.php b/module/VuFindConsole/src/VuFindConsole/Controller/HarvestController.php
index bddc17f97346d2b3bb380c72cecb5c6043c843bf..b5bd7aa9d09bbc559be2ef5ad4f2ca9e4db0cc36 100644
--- a/module/VuFindConsole/src/VuFindConsole/Controller/HarvestController.php
+++ b/module/VuFindConsole/src/VuFindConsole/Controller/HarvestController.php
@@ -81,7 +81,7 @@ class HarvestController extends AbstractBase
         }
 
         // Get the default VuFind HTTP client:
-        $client = $this->getServiceLocator()->get('VuFind\Http')->createClient();
+        $client = $this->serviceLocator->get('VuFind\Http')->createClient();
 
         // Run the job!
         $runner = new HarvesterConsoleRunner(
@@ -101,10 +101,12 @@ class HarvestController extends AbstractBase
     {
         $this->checkLocalSetting();
 
-        $argv = $this->consoleOpts->getRemainingArgs();
-        $dir = isset($argv[0]) ? rtrim($argv[0], '/') : '';
+        $dir = rtrim($this->getRequest()->getParam('dir', ''), '/');
         if (empty($dir)) {
             $scriptName = $this->getRequest()->getScriptName();
+            if (substr($scriptName, -9) === 'index.php') {
+                $scriptName .= ' harvest merge-marc';
+            }
             Console::writeLine('Merge MARC XML files into a single <collection>;');
             Console::writeLine('writes to stdout.');
             Console::writeLine('');
diff --git a/module/VuFindConsole/src/VuFindConsole/Controller/ImportController.php b/module/VuFindConsole/src/VuFindConsole/Controller/ImportController.php
index 91a9473e313810d4c1f4145063c03f383699cbf0..a9c75d86e25b24354f2ad0c4bf1a0d6836eec6b0 100644
--- a/module/VuFindConsole/src/VuFindConsole/Controller/ImportController.php
+++ b/module/VuFindConsole/src/VuFindConsole/Controller/ImportController.php
@@ -46,22 +46,19 @@ class ImportController extends AbstractBase
      */
     public function importXslAction()
     {
-        // Parse switches:
-        $this->consoleOpts->addRules(
-            ['test-only' => 'Use test mode', 'index-s' => 'Solr index to use']
-        );
-        $testMode = $this->consoleOpts->getOption('test-only') ? true : false;
-        $index = $this->consoleOpts->getOption('index');
-        if (empty($index)) {
-            $index = 'Solr';
-        }
-
-        // Display help message if parameters missing:
-        $argv = $this->consoleOpts->getRemainingArgs();
-        if (!isset($argv[1])) {
+        $request = $this->getRequest();
+        $testMode = $request->getParam('test-only') ? true : false;
+        $index = $request->getParam('index', 'Solr');
+        $xml = $request->getParam('xml');
+        $properties = $request->getParam('properties');
+        if (empty($properties)) {
+            $scriptName = $this->getRequest()->getScriptName();
+            if (substr($scriptName, -9) === 'index.php') {
+                $scriptName .= ' import import-xsl';
+            }
             Console::writeLine(
-                "Usage: import-xsl.php [--test-only] [--index <type>] "
-                . "XML_file properties_file"
+                "Usage: $scriptName [--test-only] [--index <type>] "
+                . 'XML_file properties_file'
             );
             Console::writeLine("\tXML_file - source file to index");
             Console::writeLine("\tproperties_file - import configuration file");
@@ -95,7 +92,7 @@ class ImportController extends AbstractBase
 
         // Try to import the document if successful:
         try {
-            $this->performImport($argv[0], $argv[1], $index, $testMode);
+            $this->performImport($xml, $properties, $index, $testMode);
         } catch (\Exception $e) {
             Console::writeLine("Fatal error: " . $e->getMessage());
             if (is_callable([$e, 'getPrevious']) && $e = $e->getPrevious()) {
@@ -107,7 +104,7 @@ class ImportController extends AbstractBase
             return $this->getFailureResponse();
         }
         if (!$testMode) {
-            Console::writeLine("Successfully imported {$argv[0]}...");
+            Console::writeLine("Successfully imported $xml...");
         }
         return $this->getSuccessResponse();
     }
@@ -125,8 +122,7 @@ class ImportController extends AbstractBase
     protected function performImport($xml, $properties, $index = 'Solr',
         $testMode = false
     ) {
-        $importer = new Importer();
-        $importer->setServiceLocator($this->getServiceLocator());
+        $importer = new Importer($this->serviceLocator);
         $importer->save($xml, $properties, $index, $testMode);
     }
 
@@ -137,17 +133,12 @@ class ImportController extends AbstractBase
      */
     public function webcrawlAction()
     {
-        // Parse switches:
-        $this->consoleOpts->addRules(
-            ['test-only' => 'Use test mode', 'index-s' => 'Solr index to use']
-        );
-        $testMode = $this->consoleOpts->getOption('test-only') ? true : false;
-        $index = $this->consoleOpts->getOption('index');
-        if (empty($index)) {
-            $index = 'SolrWeb';
-        }
+        // Get command line parameters:
+        $request = $this->getRequest();
+        $testMode = $request->getParam('test-only') ? true : false;
+        $index = $request->getParam('index', 'SolrWeb');
 
-        $configLoader = $this->getServiceLocator()->get('VuFind\Config');
+        $configLoader = $this->serviceLocator->get('VuFind\Config');
         $crawlConfig = $configLoader->get('webcrawl');
 
         // Get the time we started indexing -- we'll delete records older than this
@@ -166,7 +157,7 @@ class ImportController extends AbstractBase
 
         // Skip Solr operations if we're in test mode.
         if (!$testMode) {
-            $solr = $this->getServiceLocator()->get('VuFind\Solr\Writer');
+            $solr = $this->serviceLocator->get('VuFind\Solr\Writer');
             if ($verbose) {
                 Console::writeLine("Deleting old records (prior to $startTime)...");
             }
diff --git a/module/VuFindConsole/src/VuFindConsole/Controller/LanguageController.php b/module/VuFindConsole/src/VuFindConsole/Controller/LanguageController.php
index ba600720d038d1b4e3ddcc96251caeac96029bc6..deb3d9f91a1022491e77de8f064fc15ab7b42b9b 100644
--- a/module/VuFindConsole/src/VuFindConsole/Controller/LanguageController.php
+++ b/module/VuFindConsole/src/VuFindConsole/Controller/LanguageController.php
@@ -49,10 +49,13 @@ class LanguageController extends AbstractBase
     public function copystringAction()
     {
         // Display help message if parameters missing:
-        $argv = $this->consoleOpts->getRemainingArgs();
-        if (!isset($argv[1])) {
+        $request = $this->getRequest();
+        $source = $request->getParam('source');
+        $target = $request->getParam('target');
+        if (empty($source) || empty($target)) {
             Console::writeLine(
-                "Usage: {$_SERVER['argv'][0]} [source] [target]"
+                'Usage: ' . $request->getScriptName()
+                . ' language copystring [source] [target]'
             );
             Console::writeLine("\tsource - the source key to read");
             Console::writeLine("\ttarget - the target key to write");
@@ -64,8 +67,8 @@ class LanguageController extends AbstractBase
 
         $reader = new ExtendedIniReader();
         $normalizer = new ExtendedIniNormalizer();
-        list($sourceDomain, $sourceKey) = $this->extractTextDomain($argv[0]);
-        list($targetDomain, $targetKey) = $this->extractTextDomain($argv[1]);
+        list($sourceDomain, $sourceKey) = $this->extractTextDomain($source);
+        list($targetDomain, $targetKey) = $this->extractTextDomain($target);
 
         if (!($sourceDir = $this->getLangDir($sourceDomain))
             || !($targetDir = $this->getLangDir($targetDomain, true))
@@ -114,10 +117,13 @@ class LanguageController extends AbstractBase
     public function addusingtemplateAction()
     {
         // Display help message if parameters missing:
-        $argv = $this->consoleOpts->getRemainingArgs();
-        if (!isset($argv[1])) {
+        $request = $this->getRequest();
+        $target = $request->getParam('target');
+        $template = $request->getParam('template');
+        if (empty($template)) {
             Console::writeLine(
-                "Usage: {$_SERVER['argv'][0]} [target] [template]"
+                'Usage: ' . $request->getScriptName()
+                . ' language addusingtemplate [target] [template]'
             );
             Console::writeLine(
                 "\ttarget - the target key to add "
@@ -129,13 +135,12 @@ class LanguageController extends AbstractBase
         }
 
         // Make sure a valid target has been specified:
-        list($targetDomain, $targetKey) = $this->extractTextDomain($argv[0]);
+        list($targetDomain, $targetKey) = $this->extractTextDomain($target);
         if (!($targetDir = $this->getLangDir($targetDomain, true))) {
             return $this->getFailureResponse();
         }
 
         // Extract required source values from template:
-        $template = $argv[1];
         preg_match_all('/\|\|[^|]+\|\|/', $template, $matches);
         $lookups = [];
         foreach ($matches[0] as $current) {
@@ -208,10 +213,11 @@ class LanguageController extends AbstractBase
     public function deleteAction()
     {
         // Display help message if parameters missing:
-        $argv = $this->consoleOpts->getRemainingArgs();
-        if (!isset($argv[0])) {
+        $request = $this->getRequest();
+        $target = $request->getParam('target');
+        if (empty($target)) {
             Console::writeLine(
-                "Usage: {$_SERVER['argv'][0]} [target]"
+                'Usage: ' . $request->getScriptName() . ' language delete [target]'
             );
             Console::writeLine(
                 "\ttarget - the target key to remove "
@@ -221,7 +227,7 @@ class LanguageController extends AbstractBase
         }
 
         $normalizer = new ExtendedIniNormalizer();
-        list($domain, $key) = $this->extractTextDomain($argv[0]);
+        list($domain, $key) = $this->extractTextDomain($target);
         $target = $key . ' = "';
 
         if (!($dir = $this->getLangDir($domain))) {
@@ -258,17 +264,18 @@ class LanguageController extends AbstractBase
     public function normalizeAction()
     {
         // Display help message if parameters missing:
-        $argv = $this->consoleOpts->getRemainingArgs();
-        if (!isset($argv[0])) {
+        $request = $this->getRequest();
+        $target = $request->getParam('target');
+        if (empty($target)) {
             Console::writeLine(
-                "Usage: {$_SERVER['argv'][0]} [target]"
+                'Usage: ' . $request->getScriptName()
+                . ' language normalize [target]'
             );
             Console::writeLine("\ttarget - a file or directory to normalize");
             return $this->getFailureResponse();
         }
 
         $normalizer = new ExtendedIniNormalizer();
-        $target = $argv[0];
         if (is_dir($target)) {
             $normalizer->normalizeDirectory($target);
         } else if (is_file($target)) {
diff --git a/module/VuFindConsole/src/VuFindConsole/Controller/RedirectController.php b/module/VuFindConsole/src/VuFindConsole/Controller/RedirectController.php
new file mode 100644
index 0000000000000000000000000000000000000000..ac40a88c278fa275c73589fa837a8193a61725ba
--- /dev/null
+++ b/module/VuFindConsole/src/VuFindConsole/Controller/RedirectController.php
@@ -0,0 +1,100 @@
+<?php
+/**
+ * Redirect Controller
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2016.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * @category VuFind
+ * @package  Controller
+ * @author   Chris Hallberg <challber@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development:plugins:controllers Wiki
+ */
+namespace VuFindConsole\Controller;
+use Zend\Console\Console;
+use Zend\Mvc\Application;
+
+/**
+ * This controller handles various command-line tools
+ *
+ * @category VuFind
+ * @package  Controller
+ * @author   Chris Hallberg <challber@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development:plugins:controllers Wiki
+ */
+class RedirectController extends \Zend\Mvc\Controller\AbstractActionController
+{
+    /**
+     * Get a usage message with the help of the RouteNotFoundStrategy.
+     *
+     * @return mixed
+     */
+    protected function getUsage()
+    {
+        $strategy = $this->serviceLocator->get('ConsoleRouteNotFoundStrategy');
+        $event = $this->getEvent();
+        $event->setError(Application::ERROR_ROUTER_NO_MATCH);
+        $strategy->handleRouteNotFoundError($event);
+        return $event->getResult();
+    }
+
+    /**
+     * Use the first two command line parameters to redirect the user to an
+     * appropriate controller.
+     *
+     * @return mixed
+     */
+    public function consoledefaultAction()
+    {
+        // We need to modify the $_SERVER superglobals so that \Zend\Console\GetOpt
+        // will behave correctly after we've manipulated the CLI parameters. Let's
+        // use references for convenience.
+        $argv = & $_SERVER['argv'];
+        $argc = & $_SERVER['argc'];
+
+        // Pull the script name off the front of the argument array:
+        $script = array_shift($argv);
+
+        // Fail if we don't have at least two arguments (controller/action):
+        if ($argc < 2) {
+            return $this->getUsage();
+        }
+
+        // Pull off the controller and action.
+        $controller = array_shift($argv);
+        $action = array_shift($argv);
+
+        // In case later scripts are displaying $argv[0] for the script name,
+        // let's push the full invocation into that position when index.php is
+        // used. We want to eliminate the $controller and $action values as separate
+        // parts of the array since they'll confuse subsequent parameter processing.
+        if (substr($script, -9) === 'index.php') {
+            $script .= " $controller $action";
+        }
+        array_unshift($argv, $script);
+        $argc -= 2;
+
+        try {
+            return $this->forward()->dispatch($controller, compact('action'));
+        } catch (\Exception $e) {
+            Console::writeLine('ERROR: ' . $e->getMessage());
+            return $this->getUsage();
+        }
+    }
+}
diff --git a/module/VuFindConsole/src/VuFindConsole/Controller/UtilController.php b/module/VuFindConsole/src/VuFindConsole/Controller/UtilController.php
index 8611b72c1f8b11af77901dd6a06b99f7c4d7f9dc..78040f23b5bfa354a862056d33fa7bf116a3992a 100644
--- a/module/VuFindConsole/src/VuFindConsole/Controller/UtilController.php
+++ b/module/VuFindConsole/src/VuFindConsole/Controller/UtilController.php
@@ -32,7 +32,7 @@ use VuFind\Config\Writer as ConfigWriter;
 use VuFindSearch\Backend\Solr\Document\UpdateDocument;
 use VuFindSearch\Backend\Solr\Record\SerializableRecord;
 use Zend\Console\Console;
-use Zend\Crypt\Symmetric\Mcrypt,
+use Zend\Crypt\Symmetric\Openssl,
     Zend\Crypt\BlockCipher as BlockCipher;
 
 /**
@@ -93,7 +93,7 @@ class UtilController extends AbstractBase
         Console::writeLine(
             '     Default template is BIB_ID,COURSE,INSTRUCTOR,DEPARTMENT'
         );
-        Console::writeLine(' -h or -? display this help information.');
+        Console::writeLine(' -h or --help display this help information.');
 
         return $this->getFailureResponse();
     }
@@ -108,26 +108,14 @@ class UtilController extends AbstractBase
         ini_set('memory_limit', '50M');
         ini_set('max_execution_time', '3600');
 
-        $this->consoleOpts->setOptions(
-            [\Zend\Console\Getopt::CONFIG_CUMULATIVE_PARAMETERS => true]
-        );
-        $this->consoleOpts->addRules(
-            [
-                'h|help' => 'Get help',
-                'd-s' => 'Delimiter',
-                't-s' => 'Template',
-                'f-s' => 'File',
-            ]
-        );
+        $request = $this->getRequest();
 
-        if ($this->consoleOpts->getOption('h')
-            || $this->consoleOpts->getOption('help')
-        ) {
+        if ($request->getParam('h') || $request->getParam('help')) {
             return $this->indexReservesHelp();
-        } elseif ($file = $this->consoleOpts->getOption('f')) {
+        } elseif ($file = $request->getParam('f')) {
             try {
-                $delimiter = ($d = $this->consoleOpts->getOption('d')) ? $d : ',';
-                $template = ($t = $this->consoleOpts->getOption('t')) ? $t : null;
+                $delimiter = $request->getParam('d', ',');
+                $template = $request->getParam('t');
                 $reader = new \VuFind\Reserves\CsvReader(
                     $file, $delimiter, $template
                 );
@@ -138,9 +126,9 @@ class UtilController extends AbstractBase
             } catch (\Exception $e) {
                 return $this->indexReservesHelp($e->getMessage());
             }
-        } elseif ($this->consoleOpts->getOption('d')) {
+        } elseif ($request->getParam('d')) {
             return $this->indexReservesHelp('-d is meaningless without -f');
-        } elseif ($this->consoleOpts->getOption('t')) {
+        } elseif ($request->getParam('t')) {
             return $this->indexReservesHelp('-t is meaningless without -f');
         } else {
             try {
@@ -161,7 +149,7 @@ class UtilController extends AbstractBase
             && !empty($reserves)
         ) {
             // Setup Solr Connection
-            $solr = $this->getServiceLocator()->get('VuFind\Solr\Writer');
+            $solr = $this->serviceLocator->get('VuFind\Solr\Writer');
 
             // Delete existing records
             $solr->deleteAll('SolrReserves');
@@ -270,13 +258,11 @@ class UtilController extends AbstractBase
         ini_set('memory_limit', '50M');
         ini_set('max_execution_time', '3600');
 
-        // Setup Solr Connection -- Allow core to be specified as first command line
-        // param.
-        $argv = $this->consoleOpts->getRemainingArgs();
-        $core = isset($argv[0]) ? $argv[0] : 'Solr';
+        // Setup Solr Connection -- Allow core to be specified from command line.
+        $core = $this->getRequest()->getParam('core', 'Solr');
 
         // Commit and Optimize the Solr Index
-        $solr = $this->getServiceLocator()->get('VuFind\Solr\Writer');
+        $solr = $this->serviceLocator->get('VuFind\Solr\Writer');
         $solr->commit($core);
         if ($optimize) {
             $solr->optimize($core);
@@ -292,9 +278,9 @@ class UtilController extends AbstractBase
     public function sitemapAction()
     {
         // Build sitemap and display appropriate warnings if needed:
-        $configLoader = $this->getServiceLocator()->get('VuFind\Config');
+        $configLoader = $this->serviceLocator->get('VuFind\Config');
         $generator = new Sitemap(
-            $this->getServiceLocator()->get('VuFind\Search\BackendManager'),
+            $this->serviceLocator->get('VuFind\Search\BackendManager'),
             $configLoader->get('config')->Site->url, $configLoader->get('sitemap')
         );
         $generator->generate();
@@ -314,23 +300,22 @@ class UtilController extends AbstractBase
         // Parse the command line parameters -- check verbosity, see if we are in
         // "flat file" mode, find out what file we are reading in, and determine
         // the index we are affecting!
-        $this->consoleOpts->addRules(
-            [
-                'verbose' => 'Verbose mode',
-            ]
-        );
-        $verbose = $this->consoleOpts->getOption('verbose');
-        $argv = $this->consoleOpts->getRemainingArgs();
-        $filename = isset($argv[0]) ? $argv[0] : null;
-        $mode = isset($argv[1]) ? $argv[1] : 'marc';
-        $index = isset($argv[2]) ? $argv[2] : 'Solr';
+        $request = $this->getRequest();
+        $verbose = $request->getParam('verbose');
+        $filename = $request->getParam('filename');
+        $mode = $request->getParam('format', 'marc');
+        $index = $request->getParam('index', 'Solr');
 
         // No filename specified?  Give usage guidelines:
         if (empty($filename)) {
+            $scriptName = $this->getRequest()->getScriptName();
+            if (substr($scriptName, -9) === 'index.php') {
+                $scriptName .= ' util deletes';
+            }
             Console::writeLine("Delete records from VuFind's index.");
             Console::writeLine('');
             Console::writeLine(
-                'Usage: deletes.php [--verbose] FILENAME FORMAT INDEX'
+                'Usage: ' . $scriptName . ' [--verbose] FILENAME FORMAT INDEX'
             );
             Console::writeLine('');
             Console::writeLine(
@@ -411,7 +396,7 @@ class UtilController extends AbstractBase
                     . implode(', ', $ids)
                 );
             }
-            $writer = $this->getServiceLocator()->get('VuFind\Solr\Writer');
+            $writer = $this->serviceLocator->get('VuFind\Solr\Writer');
             $writer->deleteRecords($index, $ids);
             if ($verbose) {
                 Console::writeLine('Delete operation completed.');
@@ -431,20 +416,13 @@ class UtilController extends AbstractBase
      */
     public function cleanuprecordcacheAction()
     {
-        $this->consoleOpts->addRules(
-            [
-                'h|help' => 'Get help',
-            ]
-        );
-
-        if ($this->consoleOpts->getOption('h')
-            || $this->consoleOpts->getOption('help')
-        ) {
+        $request = $this->getRequest();
+        if ($request->getParam('help') || $request->getParam('h')) {
             Console::writeLine('Clean up unused cached records from the database.');
             return $this->getFailureResponse();
         }
 
-        $recordTable = $this->getServiceLocator()->get('VuFind\DbTablePluginManager')
+        $recordTable = $this->serviceLocator->get('VuFind\DbTablePluginManager')
             ->get('Record');
 
         $count = $recordTable->cleanup();
@@ -494,15 +472,8 @@ class UtilController extends AbstractBase
      */
     public function expiresearchesAction()
     {
-        $this->consoleOpts->addRules(
-            [
-                'h|help' => 'Get help',
-                'batch=i' => 'Batch size',
-                'sleep=i' => 'Sleep interval between batches'
-            ]
-        );
-
-        if ($this->consoleOpts->getOption('h')) {
+        $request = $this->getRequest();
+        if ($request->getParam('help') || $request->getParam('h')) {
             return $this->expirationHelp('searches');
         }
 
@@ -521,15 +492,8 @@ class UtilController extends AbstractBase
      */
     public function expiresessionsAction()
     {
-        $this->consoleOpts->addRules(
-            [
-                'h|help' => 'Get help',
-                'batch=i' => 'Batch size',
-                'sleep=i' => 'Sleep interval between batches'
-            ]
-        );
-
-        if ($this->consoleOpts->getOption('h')) {
+        $request = $this->getRequest();
+        if ($request->getParam('help') || $request->getParam('h')) {
             return $this->expirationHelp('sessions');
         }
 
@@ -540,6 +504,26 @@ class UtilController extends AbstractBase
         );
     }
 
+    /**
+     * Command-line tool to clear unwanted entries
+     * from external_session database table.
+     *
+     * @return \Zend\Console\Response
+     */
+    public function expireExternalSessionsAction()
+    {
+        $request = $this->getRequest();
+        if ($request->getParam('help') || $request->getParam('h')) {
+            return $this->expirationHelp('external sessions');
+        }
+
+        return $this->expire(
+            'ExternalSession',
+            '%%count%% expired external sessions deleted.',
+            'No expired external sessions to delete.'
+        );
+    }
+
     /**
      * Command-line tool to delete suppressed records from the index.
      *
@@ -547,15 +531,23 @@ class UtilController extends AbstractBase
      */
     public function suppressedAction()
     {
+        $request = $this->getRequest();
+        if ($request->getParam('help') || $request->getParam('h')) {
+            Console::writeLine('Available switches:');
+            Console::writeLine(
+                '--authorities =>'
+                . ' Delete authority records instead of bibliographic records'
+            );
+            Console::writeLine('--help or -h => Show this message');
+            Console::writeLine(
+                '--outfile=[/path/to/file] => Write the ID list to the specified'
+                . ' file instead of updating Solr (optional)'
+            );
+            return $this->getFailureResponse();
+        }
+
         // Setup Solr Connection
-        $this->consoleOpts->addRules(
-            [
-                'authorities' =>
-                    'Delete authority records instead of bibliographic records'
-            ]
-        );
-        $backend = $this->consoleOpts->getOption('authorities')
-            ? 'SolrAuth' : 'Solr';
+        $backend = $request->getParam('authorities') ? 'SolrAuth' : 'Solr';
 
         // Make ILS Connection
         try {
@@ -577,11 +569,19 @@ class UtilController extends AbstractBase
             return $this->getSuccessResponse();
         }
 
-        // Get Suppressed Records and Delete from index
-        $solr = $this->getServiceLocator()->get('VuFind\Solr\Writer');
-        $solr->deleteRecords($backend, $result);
-        $solr->commit($backend);
-        $solr->optimize($backend);
+        // If 'outfile' set, write the list
+        if ($file = $request->getParam('outfile')) {
+            if (!file_put_contents($file, implode("\n", $result))) {
+                Console::writeLine("Problem writing to $file");
+                return $this->getFailureResponse();
+            }
+        } else {
+            // Default behavior: Get Suppressed Records and Delete from index
+            $solr = $this->serviceLocator->get('VuFind\Solr\Writer');
+            $solr->deleteRecords($backend, $result);
+            $solr->commit($backend);
+            $solr->optimize($backend);
+        }
         return $this->getSuccessResponse();
     }
 
@@ -738,17 +738,23 @@ class UtilController extends AbstractBase
      */
     public function createhierarchytreesAction()
     {
-        $recordLoader = $this->getServiceLocator()->get('VuFind\RecordLoader');
-        // Parse switches:
-        $this->consoleOpts->addRules(
-            [
-                'skip-xml|sx' => 'Skip the XML cache',
-                'skip-json|sj' => 'Skip the JSON cache'
-            ]
-        );
-        $hierarchies = $this->getServiceLocator()
+        $request = $this->getRequest();
+        if ($request->getParam('help') || $request->getParam('h')) {
+            Console::writeLine('Available switches:');
+            Console::writeLine('--skip-xml or -sx => Skip the XML cache');
+            Console::writeLine('--skip-json or -sj => Skip the JSON cache');
+            Console::writeLine('--help or -h => Show this message');
+            return $this->getFailureResponse();
+        }
+        $skipJson = $request->getParam('skip-json') || $request->getParam('sj');
+        $skipXml = $request->getParam('skip-xml') || $request->getParam('sx');
+        $recordLoader = $this->serviceLocator->get('VuFind\RecordLoader');
+        $hierarchies = $this->serviceLocator
             ->get('VuFind\SearchResultsPluginManager')->get('Solr')
             ->getFullFieldFacets(['hierarchy_top_id']);
+        if (!isset($hierarchies['hierarchy_top_id']['data']['list'])) {
+            $hierarchies['hierarchy_top_id']['data']['list'] = [];
+        }
         foreach ($hierarchies['hierarchy_top_id']['data']['list'] as $hierarchy) {
             $recordid = $hierarchy['value'];
             $count = $hierarchy['count'];
@@ -764,7 +770,7 @@ class UtilController extends AbstractBase
                 // Only do this if the record is actually a hierarchy type record
                 if ($driver->getHierarchyType()) {
                     // JSON
-                    if (!$this->consoleOpts->getOption('skip-json')) {
+                    if (!$skipJson) {
                         Console::writeLine("\t\tJSON cache...");
                         $driver->getHierarchyDriver()->getTreeSource()->getJSON(
                             $recordid, ['refresh' => true]
@@ -773,7 +779,7 @@ class UtilController extends AbstractBase
                         Console::writeLine("\t\tJSON skipped.");
                     }
                     // XML
-                    if (!$this->consoleOpts->getOption('skip-xml')) {
+                    if (!$skipXml) {
                         Console::writeLine("\t\tXML cache...");
                         $driver->getHierarchyDriver()->getTreeSource()->getXML(
                             $recordid, ['refresh' => true]
@@ -802,12 +808,12 @@ class UtilController extends AbstractBase
      */
     public function cssbuilderAction()
     {
-        $argv = $this->consoleOpts->getRemainingArgs();
+        $opts = new \Zend\Console\Getopt([]);
         $compiler = new \VuFindTheme\LessCompiler(true);
-        $cacheManager = $this->getServiceLocator()->get('VuFind\CacheManager');
+        $cacheManager = $this->serviceLocator->get('VuFind\CacheManager');
         $cacheDir = $cacheManager->getCacheDir() . 'less/';
         $compiler->setTempPath($cacheDir);
-        $compiler->compile($argv);
+        $compiler->compile(array_unique($opts->getRemainingArgs()));
         return $this->getSuccessResponse();
     }
 
@@ -825,15 +831,14 @@ class UtilController extends AbstractBase
     protected function expire($tableName, $successString, $failString, $minAge = 2)
     {
         // Get command-line arguments
-        $argv = $this->consoleOpts->getRemainingArgs();
+        $request = $this->getRequest();
 
         // Use command line value as expiration age, or default to $minAge.
-        $daysOld = isset($argv[0]) ? intval($argv[0]) : $minAge;
+        $daysOld = intval($request->getParam('daysOld', $minAge));
 
         // Use command line values for batch size and sleep time if specified.
-        $options = $this->consoleOpts->getArguments();
-        $batchSize = isset($options['batch']) ? $options['batch'] : 1000;
-        $sleepTime = isset($options['sleep']) ? $options['sleep'] : 100;
+        $batchSize = $request->getParam('batch', 1000);
+        $sleepTime = $request->getParam('sleep', 100);
 
         // Abort if we have an invalid expiration age.
         if ($daysOld < 2) {
@@ -900,8 +905,9 @@ class UtilController extends AbstractBase
     public function switchdbhashAction()
     {
         // Validate command line arguments:
-        $argv = $this->consoleOpts->getRemainingArgs();
-        if (count($argv) < 1) {
+        $request = $this->getRequest();
+        $newhash = $request->getParam('newhash');
+        if (empty($newhash)) {
             Console::writeLine(
                 'Expected parameters: newmethod [newkey]'
             );
@@ -923,8 +929,7 @@ class UtilController extends AbstractBase
         }
 
         // Pull new encryption settings from arguments:
-        $newhash = $argv[0];
-        $newkey = isset($argv[1]) ? $argv[1] : $oldkey;
+        $newkey = $request->getParam('newkey', $oldkey);
 
         // No key specified AND no key on file = fatal error:
         if ($newkey === null) {
@@ -938,13 +943,13 @@ class UtilController extends AbstractBase
             return $this->getSuccessResponse();
         }
 
-        // Initialize Mcrypt first, so we can catch any illegal algorithms before
+        // Initialize Openssl first, so we can catch any illegal algorithms before
         // making any changes:
         try {
             if ($oldhash != 'none') {
-                $oldCrypt = new Mcrypt(['algorithm' => $oldhash]);
+                $oldCrypt = new Openssl(['algorithm' => $oldhash]);
             }
-            $newCrypt = new Mcrypt(['algorithm' => $newhash]);
+            $newCrypt = new Openssl(['algorithm' => $newhash]);
         } catch (\Exception $e) {
             Console::writeLine($e->getMessage());
             return $this->getFailureResponse();
@@ -964,7 +969,7 @@ class UtilController extends AbstractBase
         }
 
         // Now do the database rewrite:
-        $userTable = $this->getServiceLocator()->get('VuFind\DbTablePluginManager')
+        $userTable = $this->serviceLocator->get('VuFind\DbTablePluginManager')
             ->get('User');
         $users = $userTable->select(
             function ($select) {
diff --git a/module/VuFindConsole/src/VuFindConsole/Mvc/Router/ConsoleRouter.php b/module/VuFindConsole/src/VuFindConsole/Mvc/Router/ConsoleRouter.php
deleted file mode 100644
index a1503295c2f43cc279388cccadf6ee171a08dc73..0000000000000000000000000000000000000000
--- a/module/VuFindConsole/src/VuFindConsole/Mvc/Router/ConsoleRouter.php
+++ /dev/null
@@ -1,167 +0,0 @@
-<?php
-/**
- * VuFind Console Router
- *
- * PHP version 5
- *
- * Copyright (C) Villanova University 2010.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- *
- * @category VuFind
- * @package  Mvc_Router
- * @author   Demian Katz <demian.katz@villanova.edu>
- * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
- * @link     https://vufind.org Main Site
- */
-namespace VuFindConsole\Mvc\Router;
-use Zend\Mvc\Router\Http\RouteMatch,
-    Zend\Stdlib\RequestInterface as Request;
-use Zend\Mvc\Router\Console\SimpleRouteStack;
-
-/**
- * VuFind Console Router
- *
- * @category VuFind
- * @package  Mvc_Router
- * @author   Demian Katz <demian.katz@villanova.edu>
- * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
- * @link     https://vufind.org Main Site
- */
-class ConsoleRouter extends SimpleRouteStack
-{
-    /**
-     * Present working directory
-     *
-     * @var string
-     */
-    protected $pwd = '';
-
-    /**
-     * Extract controller and action from command line when user directly accesses
-     * the index.php file.
-     *
-     * @return array Array with 0 => controller, 1 => action
-     */
-    protected function extractFromCommandLine()
-    {
-        // We need to modify the $_SERVER superglobals so that \Zend\Console\GetOpt
-        // will behave correctly after we've manipulated the CLI parameters. Let's
-        // use references for convenience.
-        $argv = & $_SERVER['argv'];
-        $argc = & $_SERVER['argc'];
-
-        // Pull the script name off the front of the argument array:
-        $script = array_shift($argv);
-
-        // Pull off the controller and action; if they are missing, we'll fill
-        // in dummy values for consistency's sake, which also requires us to
-        // adjust the argument count.
-        if ($argc > 0) {
-            $controller = array_shift($argv);
-        } else {
-            $controller = "undefined";
-            $argc++;
-        }
-        if ($argc > 1) {
-            $action = array_shift($argv);
-        } else {
-            $action = "undefined";
-            $argc++;
-        }
-
-        // In case later scripts are displaying $argv[0] for the script name,
-        // let's push the full invocation into that position. We want to eliminate
-        // the $controller and $action values as separate parts of the array since
-        // they'll confuse subsequent command line processing logic.
-        array_unshift($argv, "$script $controller $action");
-        $argc -= 2;
-
-        return [$controller, $action];
-    }
-
-    /**
-     * Check CLIDIR
-     *
-     * @return string
-     */
-    public function getCliDir()
-    {
-        if ($this->pwd == '' && defined('CLI_DIR')) {
-            $this->pwd = CLI_DIR;
-        }
-        return $this->pwd;
-    }
-
-    /**
-     * Set CLIDIR (used primarily for testing)
-     *
-     * @param string $pwd Present directory
-     *
-     * @return void
-     */
-    public function setCliDir($pwd)
-    {
-        $this->pwd = $pwd;
-    }
-
-    /**
-     * Legacy handling for scripts: Match a given request.
-     *
-     * @param Request $request Request to match
-     *
-     * @return RouteMatch
-     */
-    public function match(Request $request)
-    {
-        // Get command line arguments and present working directory from
-        // server superglobal:
-        $filename = $request->getScriptName();
-
-        // WARNING: cwd is $VUFIND_HOME, so that throws off realpath!
-        //
-        // Convert base filename (minus .php extension and underscores) and
-        // containing directory name into action and controller, respectively:
-        $base = basename($filename, ".php");
-        $actionName = str_replace('_', '', $base);      // action is the easy part
-
-        $dir = dirname($filename);
-        if ($dir == false || $dir == '' || $dir == '.' || basename($dir) == '.') {
-            // legacy style: cd to subdir, but set CLI_DIR
-            $dir  = $this->getCliDir();
-            $path = $dir . '/' . $filename;
-        } else {
-            // modern style: invoked as, e.g. $base=util/ping.php, already has path
-            $level1 = basename(dirname($filename));
-            // but we need to re-orient relative to VUFIND_HOME
-            $path   = $level1 . '/' . basename($filename);
-        }
-        $controller = basename($dir);       // the last directory part
-
-        // Special case: if user is accessing index.php directly, we expect
-        // controller and action as first two parameters.
-        if ($controller == 'public' && $actionName == 'index') {
-            list($controller, $actionName) = $this->extractFromCommandLine();
-        }
-
-        $routeMatch = new RouteMatch(
-            ['controller' => $controller, 'action' => $actionName], 1
-        );
-
-        // Override standard routing:
-        $routeMatch->setMatchedRouteName('default');
-        return $routeMatch;
-    }
-
-}
diff --git a/module/VuFind/src/VuFind/View/Helper/jQueryMobile/MobileMenu.php b/module/VuFindConsole/src/VuFindConsole/Route/RouteGenerator.php
similarity index 56%
rename from module/VuFind/src/VuFind/View/Helper/jQueryMobile/MobileMenu.php
rename to module/VuFindConsole/src/VuFindConsole/Route/RouteGenerator.php
index a3c4d8d99a02bbac2203d54f29111fc2556463c0..0ac97026acdc2fcb22ea05c43ca1fb330fd7f48b 100644
--- a/module/VuFind/src/VuFind/View/Helper/jQueryMobile/MobileMenu.php
+++ b/module/VuFindConsole/src/VuFindConsole/Route/RouteGenerator.php
@@ -1,6 +1,6 @@
 <?php
 /**
- * MobileMenu view helper
+ * Route Generator Class
  *
  * PHP version 5
  *
@@ -20,50 +20,43 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
  * @category VuFind
- * @package  View_Helpers
+ * @package  Route
  * @author   Demian Katz <demian.katz@villanova.edu>
  * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
  * @link     https://vufind.org/wiki/development Wiki
  */
-namespace VuFind\View\Helper\jQueryMobile;
-use Zend\View\Helper\AbstractHelper;
+namespace VuFindConsole\Route;
 
 /**
- * MobileMenu view helper
+ * Route Generator Class
  *
  * @category VuFind
- * @package  View_Helpers
+ * @package  Route
  * @author   Demian Katz <demian.katz@villanova.edu>
  * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
  * @link     https://vufind.org/wiki/development Wiki
  */
-class MobileMenu extends AbstractHelper
+class RouteGenerator
 {
     /**
-     * Display the top menu.
+     * Add console routes to the configuration.
      *
-     * @param array $extras Associative array of extra parameters to send to the
-     * view template.
+     * @param array $config Configuration array to update
+     * @param array $routes Array of Controller/Action strings => route values
      *
-     * @return string
+     * @return void
      */
-    public function header($extras = [])
+    public function addRoutes(& $config, $routes)
     {
-        $context = $this->getView()->plugin('context');
-        return $context($this->getView())->renderInContext('header.phtml', $extras);
-    }
-
-    /**
-     * Display the bottom menu.
-     *
-     * @param array $extras Associative array of extra parameters to send to the
-     * view template.
-     *
-     * @return string
-     */
-    public function footer($extras = [])
-    {
-        $context = $this->getView()->plugin('context');
-        return $context($this->getView())->renderInContext('footer.phtml', $extras);
+        foreach ($routes as $key => $route) {
+            list($controller, $action) = explode('/', $key);
+            $name = $controller . '-' . $action;
+            $config['console']['router']['routes'][$name] = [
+                'options' => [
+                    'route' => $route,
+                    'defaults' => compact('controller', 'action'),
+                ]
+            ];
+        }
     }
 }
diff --git a/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Route/RouteGeneratorTest.php b/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Route/RouteGeneratorTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..dfff0982e36910f6ad83c91e32629bbf78aa3144
--- /dev/null
+++ b/module/VuFindConsole/tests/unit-tests/src/VuFindTest/Route/RouteGeneratorTest.php
@@ -0,0 +1,85 @@
+<?php
+
+/**
+ * Route generator tests.
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2016.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * @category VuFind
+ * @package  Tests
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development:testing:unit_tests Wiki
+ */
+namespace VuFindConsoleTest\Route;
+use VuFindConsole\Route\RouteGenerator;
+
+/**
+ * Route generator tests.
+ *
+ * @category VuFind
+ * @package  Tests
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development:testing:unit_tests Wiki
+ */
+class CacheTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * Test route generation
+     *
+     * @return void
+     */
+    public function testGeneration()
+    {
+        $config = [];
+        $routes = [
+            'controller1/action1' => 'controller1 action1',
+            'controller2/action2' => 'controller2 action2',
+        ];
+        $generator = new RouteGenerator();
+        $generator->addRoutes($config, $routes);
+        $expected = [
+            'console' => [
+                'router' => [
+                    'routes' => [
+                        'controller1-action1' => [
+                            'options' => [
+                                'route' => 'controller1 action1',
+                                'defaults' => [
+                                    'controller' => 'controller1',
+                                    'action' => 'action1',
+                                ],
+                            ],
+                        ],
+                        'controller2-action2' => [
+                            'options' => [
+                                'route' => 'controller2 action2',
+                                'defaults' => [
+                                    'controller' => 'controller2',
+                                    'action' => 'action2',
+                                ],
+                            ],
+                        ],
+                    ],
+                ],
+            ],
+        ];
+        $this->assertEquals($expected, $config);
+    }
+}
diff --git a/module/VuFindDevTools/config/module.config.php b/module/VuFindDevTools/config/module.config.php
index a5c2b285d05a16e31387ca9528e29069525d48a7..dbe3315d235f2adca33c57fbd21bcb13364d1d24 100644
--- a/module/VuFindDevTools/config/module.config.php
+++ b/module/VuFindDevTools/config/module.config.php
@@ -3,8 +3,42 @@ namespace VuFindLocalTemplate\Module\Configuration;
 
 $config = [
     'controllers' => [
-        'invokables' => [
-            'devtools' => 'VuFindDevTools\Controller\DevtoolsController',
+        'factories' => [
+            'devtools' => 'VuFindDevTools\Controller\Factory::getDevtoolsController',
+        ],
+    ],
+    'router' => [
+        'routes' => [
+            'devtools-deminify' => [
+                'type' => 'Zend\Mvc\Router\Http\Literal',
+                'options' => [
+                    'route'    => '/devtools/deminify',
+                    'defaults' => [
+                        'controller' => 'DevTools',
+                        'action'     => 'Deminify',
+                    ]
+                ]
+            ],
+            'devtools-home' => [
+                'type' => 'Zend\Mvc\Router\Http\Literal',
+                'options' => [
+                    'route'    => '/devtools/home',
+                    'defaults' => [
+                        'controller' => 'DevTools',
+                        'action'     => 'Home',
+                    ]
+                ]
+            ],
+            'devtools-language' => [
+                'type' => 'Zend\Mvc\Router\Http\Literal',
+                'options' => [
+                    'route'    => '/devtools/language',
+                    'defaults' => [
+                        'controller' => 'DevTools',
+                        'action'     => 'Language',
+                    ]
+                ]
+            ],
         ],
     ],
 ];
diff --git a/module/VuFindDevTools/src/VuFindDevTools/Controller/DevtoolsController.php b/module/VuFindDevTools/src/VuFindDevTools/Controller/DevtoolsController.php
index 752bb3eb3a175a122652088a64a90bd63f3736a3..ef74ef7de9497db237ebbc5513dca2c3ff4a7615 100644
--- a/module/VuFindDevTools/src/VuFindDevTools/Controller/DevtoolsController.php
+++ b/module/VuFindDevTools/src/VuFindDevTools/Controller/DevtoolsController.php
@@ -42,6 +42,27 @@ use VuFindDevTools\LanguageHelper;
  */
 class DevtoolsController extends \VuFind\Controller\AbstractBase
 {
+    /**
+     * Fetch the query builder for the specified search backend. Return null if
+     * unavailable.
+     *
+     * @param string $id Backend ID
+     *
+     * @return object
+     */
+    protected function getQueryBuilder($id)
+    {
+        try {
+            $backend = $this->serviceLocator
+                ->get('VuFind\Search\BackendManager')
+                ->get($id);
+        } catch (\Exception $e) {
+            return null;
+        }
+        return is_callable([$backend, 'getQueryBuilder'])
+            ? $backend->getQueryBuilder() : null;
+    }
+
     /**
      * Deminify action
      *
@@ -56,7 +77,7 @@ class DevtoolsController extends \VuFind\Controller\AbstractBase
         }
         if (isset($view->min) && $view->min) {
             $view->results = $view->min->deminify(
-                $this->getServiceLocator()->get('VuFind\SearchResultsPluginManager')
+                $this->serviceLocator->get('VuFind\SearchResultsPluginManager')
             );
         }
         if (isset($view->results) && $view->results) {
@@ -66,21 +87,23 @@ class DevtoolsController extends \VuFind\Controller\AbstractBase
                 $view->backendParams = $params->getBackendParameters()
                     ->getArrayCopy();
             }
-            try {
-                $backend = $this->getServiceLocator()
-                    ->get('VuFind\Search\BackendManager')
-                    ->get($params->getSearchClassId());
-            } catch (\Exception $e) {
-                $backend = false;
-            }
-            if ($backend && is_callable([$backend, 'getQueryBuilder'])) {
-                $builder = $backend->getQueryBuilder();
+            if ($builder = $this->getQueryBuilder($params->getSearchClassId())) {
                 $view->queryParams = $builder->build($view->query)->getArrayCopy();
             }
         }
         return $view;
     }
 
+    /**
+     * Home action
+     *
+     * @return \Zend\View\Model\ViewModel
+     */
+    public function homeAction()
+    {
+        return $this->createViewModel();
+    }
+
     /**
      * Language action
      *
diff --git a/module/VuFindDevTools/src/VuFindDevTools/Controller/Factory.php b/module/VuFindDevTools/src/VuFindDevTools/Controller/Factory.php
new file mode 100644
index 0000000000000000000000000000000000000000..694fd97f14a6089368daaaed9fc097478eacfb93
--- /dev/null
+++ b/module/VuFindDevTools/src/VuFindDevTools/Controller/Factory.php
@@ -0,0 +1,80 @@
+<?php
+/**
+ * Factory for controllers.
+ *
+ * PHP version 5
+ *
+ * Copyright (C) Villanova University 2014.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * @category VuFind
+ * @package  Controller
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development Wiki
+ */
+namespace VuFindDevTools\Controller;
+use Zend\ServiceManager\ServiceManager;
+
+/**
+ * Factory for controllers.
+ *
+ * @category VuFind
+ * @package  Controller
+ * @author   Demian Katz <demian.katz@villanova.edu>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development Wiki
+ *
+ * @codeCoverageIgnore
+ */
+class Factory
+{
+    /**
+     * Construct a generic controller.
+     *
+     * @param string         $name Name of table to construct (fully qualified
+     * class name, or else a class name within the current namespace)
+     * @param ServiceManager $sm   Service manager
+     *
+     * @return object
+     */
+    public static function getGenericController($name, ServiceManager $sm)
+    {
+        // Prepend the current namespace unless we receive a FQCN:
+        $class = (strpos($name, '\\') === false)
+            ? __NAMESPACE__ . '\\' . $name : $name;
+        if (!class_exists($class)) {
+            throw new \Exception('Cannot construct ' . $class);
+        }
+        return new $class($sm->getServiceLocator());
+    }
+
+    /**
+     * Construct a generic controller.
+     *
+     * @param string $name Method name being called
+     * @param array  $args Method arguments
+     *
+     * @return object
+     */
+    public static function __callStatic($name, $args)
+    {
+        // Strip "get" from method name to get name of class; pass first argument
+        // on assumption that it should be the ServiceManager object.
+        return static::getGenericController(
+            substr($name, 3), isset($args[0]) ? $args[0] : null
+        );
+    }
+}
diff --git a/module/VuFindDevTools/tests/unit-tests/src/VuFindTest/Controller/DevtoolsControllerTest.php b/module/VuFindDevTools/tests/unit-tests/src/VuFindTest/Controller/DevtoolsControllerTest.php
index 292f92dbb5ac8125f974484b6aa053a28e645d3e..d81a66ac999205fd0532d20fada0e1185fb6f3e1 100644
--- a/module/VuFindDevTools/tests/unit-tests/src/VuFindTest/Controller/DevtoolsControllerTest.php
+++ b/module/VuFindDevTools/tests/unit-tests/src/VuFindTest/Controller/DevtoolsControllerTest.php
@@ -84,7 +84,8 @@ class DevtoolsControllerTest extends \VuFindTest\Unit\TestCase
     protected function getMockController()
     {
         $config = new Config(['Languages' => ['en' => 'English']]);
-        $c = $this->getMock('VuFindDevTools\Controller\DevtoolsController', ['getConfig']);
+        $c = $this->getMockBuilder('VuFindDevTools\Controller\DevtoolsController')
+            ->setMethods(['getConfig'])->disableOriginalConstructor()->getMock();
         $c->expects($this->any())->method('getConfig')->will($this->returnValue($config));
         return $c;
     }
diff --git a/module/VuFindDevTools/tests/unit-tests/src/VuFindTest/LanguageHelperTest.php b/module/VuFindDevTools/tests/unit-tests/src/VuFindTest/LanguageHelperTest.php
index f64aa53e340e674993056e87731eb3a2fc0af8ea..f0acfed76559bfef41f73223422198792d5605e7 100644
--- a/module/VuFindDevTools/tests/unit-tests/src/VuFindTest/LanguageHelperTest.php
+++ b/module/VuFindDevTools/tests/unit-tests/src/VuFindTest/LanguageHelperTest.php
@@ -90,7 +90,7 @@ class LanguageHelperTest extends \VuFindTest\Unit\TestCase
     {
         $config = new Config(['Languages' => ['en' => 'English']]);
         return new LanguageHelper(
-            $this->getMock('VuFind\I18n\Translator\Loader\ExtendedIni'),
+            $this->createMock('VuFind\I18n\Translator\Loader\ExtendedIni'),
             $config
         );
     }
diff --git a/module/VuFindSearch/src/VuFindSearch/Backend/EDS/Backend.php b/module/VuFindSearch/src/VuFindSearch/Backend/EDS/Backend.php
index 0c739c570dac853068ac1917fb1d0a4d5850699c..455048dd800bf06338b563a0b589482b077f6ab8 100644
--- a/module/VuFindSearch/src/VuFindSearch/Backend/EDS/Backend.php
+++ b/module/VuFindSearch/src/VuFindSearch/Backend/EDS/Backend.php
@@ -314,6 +314,10 @@ class Backend extends AbstractBackend
                     throw new BackendException($e->getMessage(), $e->getCode(), $e);
                 }
                 break;
+            case 135:
+                // DbId not in profile, fall through to treat as "record not found"
+                $response = [];
+                break;
             default:
                 throw $e;
             }
diff --git a/module/VuFindSearch/src/VuFindSearch/Backend/EDS/Exception.php b/module/VuFindSearch/src/VuFindSearch/Backend/EDS/Exception.php
index b347cae4e4f12b49d55811e97a41e1ef740ea29f..0a1245b013e8ae61204c6131d99be3406330d67a 100644
--- a/module/VuFindSearch/src/VuFindSearch/Backend/EDS/Exception.php
+++ b/module/VuFindSearch/src/VuFindSearch/Backend/EDS/Exception.php
@@ -35,7 +35,7 @@
  * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
  * @link     https://vufind.org
  */
-class EbscoEdsApiException extends Exception
+class EbscoEdsApiException extends \VuFindSearch\Backend\Exception\BackendException
 {
     /**
      * Error message details returned from the API
@@ -53,7 +53,10 @@ class EbscoEdsApiException extends Exception
     {
         if (is_array($apiErrorMessage)) {
             $this->setApiError($apiErrorMessage);
-            parent::__construct();
+            parent::__construct(
+                isset($this->apiErrorDetails['Description'])
+                ? $this->apiErrorDetails['Description'] : ''
+            );
         } else {
             parent::__construct($apiErrorMessage);
         }
@@ -83,7 +86,6 @@ class EbscoEdsApiException extends Exception
             $this->apiErrorDetails['Description'] = $message['ErrorDescription'];
             $this->apiErrorDetails['DetailedDescription']
                 = $message['DetailedErrorDescription'];
-
         }
     }
 
diff --git a/module/VuFindSearch/src/VuFindSearch/Backend/Solr/Backend.php b/module/VuFindSearch/src/VuFindSearch/Backend/Solr/Backend.php
index d2247ddcfbaacbc3374259a22255530465bcaf7c..acbd44f240efcab625d2f5a516c0f9e743241a41 100644
--- a/module/VuFindSearch/src/VuFindSearch/Backend/Solr/Backend.php
+++ b/module/VuFindSearch/src/VuFindSearch/Backend/Solr/Backend.php
@@ -235,20 +235,43 @@ class Backend extends AbstractBackend
      *
      * @return Terms
      */
-    public function terms($field, $start, $limit, ParamBag $params = null)
-    {
+    public function terms($field = null, $start = null, $limit = null,
+        ParamBag $params = null
+    ) {
+        // Support alternate syntax with ParamBag as first parameter:
+        if ($field instanceof ParamBag && $params === null) {
+            $params = $field;
+            $field = null;
+        }
+
+        // Create empty ParamBag if none provided:
         $params = $params ?: new ParamBag();
         $this->injectResponseWriter($params);
 
+        // Always enable terms:
         $params->set('terms', 'true');
-        $params->set('terms.fl', $field);
-        $params->set('terms.lower', $start);
-        $params->set('terms.limit', $limit);
-        $params->set('terms.lower.incl', 'false');
-        $params->set('terms.sort', 'index');
+
+        // Use parameters if provided:
+        if (null !== $field) {
+            $params->set('terms.fl', $field);
+        }
+        if (null !== $start) {
+            $params->set('terms.lower', $start);
+        }
+        if (null !== $limit) {
+            $params->set('terms.limit', $limit);
+        }
+
+        // Set defaults unless overridden:
+        if (!$params->hasParam('terms.lower.incl')) {
+            $params->set('terms.lower.incl', 'false');
+        }
+        if (!$params->hasParam('terms.sort')) {
+            $params->set('terms.sort', 'index');
+        }
 
         $response = $this->connector->terms($params);
-        $terms    = new Terms($this->deserialize($response));
+        $terms = new Terms($this->deserialize($response));
         return $terms;
     }
 
diff --git a/module/VuFindSearch/src/VuFindSearch/Backend/Solr/Connector.php b/module/VuFindSearch/src/VuFindSearch/Backend/Solr/Connector.php
index b0e8adf61e307f150ad4806960acba9b108950a3..dc07c896f85f2d9fc7165b3a6558a4d7fff2a5d2 100644
--- a/module/VuFindSearch/src/VuFindSearch/Backend/Solr/Connector.php
+++ b/module/VuFindSearch/src/VuFindSearch/Backend/Solr/Connector.php
@@ -35,12 +35,14 @@ use VuFindSearch\Query\Query;
 use VuFindSearch\ParamBag;
 
 use VuFindSearch\Backend\Exception\HttpErrorException;
+use VuFindSearch\Backend\Exception\RequestErrorException;
 
 use VuFindSearch\Backend\Solr\Document\AbstractDocument;
 
 use Zend\Http\Request;
 use Zend\Http\Client as HttpClient;
 use Zend\Http\Client\Adapter\AdapterInterface;
+use Zend\Http\Client\Adapter\Exception\TimeoutException;
 
 use InvalidArgumentException;
 
@@ -361,6 +363,19 @@ class Connector implements \Zend\Log\LoggerAwareInterface
         return $this->trySolrUrls($method, $urlSuffix, $callback);
     }
 
+    /**
+     * Check if an exception from a Solr request should be thrown rather than retried
+     *
+     * @param \Exception $ex Exception
+     *
+     * @return bool
+     */
+    protected function isRethrowableSolrException($ex)
+    {
+        return $ex instanceof TimeoutException
+            || $ex instanceof RequestErrorException;
+    }
+
     /**
      * Try all Solr URLs until we find one that works (or throw an exception).
      *
@@ -388,6 +403,9 @@ class Connector implements \Zend\Log\LoggerAwareInterface
             try {
                 return $this->send($client);
             } catch (\Exception $ex) {
+                if ($this->isRethrowableSolrException($ex)) {
+                    throw $ex;
+                }
                 $exception = $ex;
             }
         }
diff --git a/module/VuFindSearch/src/VuFindSearch/Backend/Solr/QueryBuilder.php b/module/VuFindSearch/src/VuFindSearch/Backend/Solr/QueryBuilder.php
index 0c9d8e95019b4bc65feb530ae0a59f7c332d30e0..3367b23e789a8fc3fc1bb2e66385d1e23c2773ab 100644
--- a/module/VuFindSearch/src/VuFindSearch/Backend/Solr/QueryBuilder.php
+++ b/module/VuFindSearch/src/VuFindSearch/Backend/Solr/QueryBuilder.php
@@ -130,16 +130,15 @@ class QueryBuilder implements QueryBuilderInterface
         }
 
         if ($query instanceof QueryGroup) {
-            $query = $this->reduceQueryGroup($query);
+            $finalQuery = $this->reduceQueryGroup($query);
         } else {
-            $query->setString(
-                $this->getLuceneHelper()->normalizeSearchString($query->getString())
-            );
+            // Clone the query to avoid modifying the original user-visible query
+            $finalQuery = clone($query);
+            $finalQuery->setString($this->getNormalizedQueryString($query));
         }
+        $string = $finalQuery->getString() ?: '*:*';
 
-        $string  = $query->getString() ?: '*:*';
-
-        if ($handler = $this->getSearchHandler($query->getHandler(), $string)) {
+        if ($handler = $this->getSearchHandler($finalQuery->getHandler(), $string)) {
             if (!$handler->hasExtendedDismax()
                 && $this->getLuceneHelper()->containsAdvancedLuceneSyntax($string)
             ) {
@@ -155,13 +154,6 @@ class QueryBuilder implements QueryBuilderInterface
                     }
                 }
             } else if ($handler->hasDismax()) {
-                // If we're using extended dismax, we'll miss out on the question
-                // mark fix in createAdvancedInnerSearchString(), so we should
-                // apply it here. If other query munges arise that are valuable
-                // to both dismax and edismax, we should add a wrapper function
-                // around them and call it from here instead of this one very
-                // specific check.
-                $string = $this->fixTrailingQuestionMarks($string);
                 $params->set('qf', implode(' ', $handler->getDismaxFields()));
                 $params->set('qt', $handler->getDismaxHandler());
                 foreach ($handler->getDismaxParams() as $param) {
@@ -329,8 +321,7 @@ class QueryBuilder implements QueryBuilderInterface
                 );
             }
         } else {
-            $searchString  = $this->getLuceneHelper()
-                ->normalizeSearchString($component->getString());
+            $searchString = $this->getNormalizedQueryString($component);
             $searchHandler = $this->getSearchHandler(
                 $component->getHandler(),
                 $searchString
@@ -378,7 +369,9 @@ class QueryBuilder implements QueryBuilderInterface
      */
     protected function fixTrailingQuestionMarks($string)
     {
-        $multiword = preg_match('/[^\s]\s+[^\s]/', $string);
+        // Treat colon and whitespace as word separators -- in either case, we
+        // should add parentheses for accuracy.
+        $multiword = preg_match('/[^\s][\s:]+[^\s]/', $string);
         $callback = function ($matches) use ($multiword) {
             // Make sure all question marks are properly escaped (first unescape
             // any that are already escaped to prevent double-escapes, then escape
@@ -394,11 +387,27 @@ class QueryBuilder implements QueryBuilderInterface
         // Use a lookahead to skip matches found within quoted phrases.
         $lookahead = '(?=(?:[^\"]*+\"[^\"]*+\")*+[^\"]*+$)';
         $string = preg_replace_callback(
-            '/([^\s]+\?)(\s|$)' . $lookahead . '/', $callback, $string
+            '/([^\s:()]+\?)(\s|$)' . $lookahead . '/', $callback, $string
         );
         return rtrim($string);
     }
 
+    /**
+     * Given a Query object, return a fully normalized version of the query string.
+     *
+     * @param Query $query Query object
+     *
+     * @return string
+     */
+    protected function getNormalizedQueryString($query)
+    {
+        return $this->fixTrailingQuestionMarks(
+            $this->getLuceneHelper()->normalizeSearchString(
+                $query->getString()
+            )
+        );
+    }
+
     /**
      * Return advanced inner search string based on input and handler.
      *
@@ -423,9 +432,6 @@ class QueryBuilder implements QueryBuilderInterface
             return $string;
         }
 
-        // Account for trailing question marks:
-        $string = $this->fixTrailingQuestionMarks($string);
-
         return $handler
             ? $handler->createAdvancedQueryString($string, false) : $string;
     }
diff --git a/module/VuFindSearch/src/VuFindSearch/Backend/Solr/Response/Json/Spellcheck.php b/module/VuFindSearch/src/VuFindSearch/Backend/Solr/Response/Json/Spellcheck.php
index a6d6bff7e774396b1bdebfd213dec7a42501f2ac..0c34d88359466d981b4e78968bf2643bd94b4327 100644
--- a/module/VuFindSearch/src/VuFindSearch/Backend/Solr/Response/Json/Spellcheck.php
+++ b/module/VuFindSearch/src/VuFindSearch/Backend/Solr/Response/Json/Spellcheck.php
@@ -75,7 +75,9 @@ class Spellcheck implements IteratorAggregate, Countable
     public function __construct(array $spellcheck, $query)
     {
         $this->terms = new ArrayObject();
-        $list = new NamedList($spellcheck);
+        // Solr 6.4 and before use an array of arrays with two elements, while
+        // from Solr 6.5 on the array is associative.
+        $list = isset($spellcheck[0]) ? new NamedList($spellcheck) : $spellcheck;
         foreach ($list as $term => $info) {
             if (is_array($info)) {
                 $this->terms->offsetSet($term, $info);
diff --git a/module/VuFindSearch/src/VuFindSearch/ParamBag.php b/module/VuFindSearch/src/VuFindSearch/ParamBag.php
index 8a9a06142dc12c6d807642a077d0884d6be8ea25..2702c40e27eddf41aa2d41b30e45579e4812747f 100644
--- a/module/VuFindSearch/src/VuFindSearch/ParamBag.php
+++ b/module/VuFindSearch/src/VuFindSearch/ParamBag.php
@@ -76,6 +76,18 @@ class ParamBag
         return isset($this->params[$name]) ? $this->params[$name] : null;
     }
 
+    /**
+     * Return true if the bag contains any value(s) for the specified parameter.
+     *
+     * @param string $name Parameter name
+     *
+     * @return bool
+     */
+    public function hasParam($name)
+    {
+        return isset($this->params[$name]);
+    }
+
     /**
      * Return true if the bag contains a parameter-value-pair.
      *
diff --git a/module/VuFindSearch/src/VuFindSearch/Service.php b/module/VuFindSearch/src/VuFindSearch/Service.php
index 8fc4fe86b7d117c7c2868253550c91ff5025379d..775b6733a933a667f72214c5b043456799978663 100644
--- a/module/VuFindSearch/src/VuFindSearch/Service.php
+++ b/module/VuFindSearch/src/VuFindSearch/Service.php
@@ -75,10 +75,15 @@ class Service
     /**
      * Constructor.
      *
+     * @param EventManagerInterface $events Event manager (optional)
+     *
      * @return void
      */
-    public function __construct()
+    public function __construct(EventManagerInterface $events = null)
     {
+        if (null !== $events) {
+            $this->setEventManager($events);
+        }
         $this->backends = [];
     }
 
@@ -349,13 +354,13 @@ class Service
     protected function resolve($backend, $args)
     {
         if (!isset($this->backends[$backend])) {
-            $response = $this->getEventManager()->trigger(
-                self::EVENT_RESOLVE,
-                $this,
-                $args,
+            $response = $this->getEventManager()->triggerUntil(
                 function ($o) {
                     return ($o instanceof BackendInterface);
-                }
+                },
+                self::EVENT_RESOLVE,
+                $this,
+                $args
             );
             if (!$response->stopped()) {
                 throw new Exception\RuntimeException(
diff --git a/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/EDS/BackendTest.php b/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/EDS/BackendTest.php
index b5e01ac1e35ad4f8d4983faf3d691056008bec4a..83f7c2f51619ab5c2b93f42fe099fe4cd6f36f69 100644
--- a/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/EDS/BackendTest.php
+++ b/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/EDS/BackendTest.php
@@ -144,7 +144,7 @@ class BackendTest extends \VuFindTest\Unit\TestCase
      */
     public function testConstructorSetters()
     {
-        $fact = $this->getMock('VuFindSearch\Response\RecordCollectionFactoryInterface');
+        $fact = $this->createMock('VuFindSearch\Response\RecordCollectionFactoryInterface');
         $conn = $this->getConnectorMock();
         $config = [
             'EBSCO_Account' => [
@@ -191,10 +191,11 @@ class BackendTest extends \VuFindTest\Unit\TestCase
      */
     protected function getConnectorMock(array $mock = [])
     {
-        $client = $this->getMock('Zend\Http\Client');
-        return $this->getMock(
-            'VuFindSearch\Backend\EDS\Zend2', $mock, [[], $client]
-        );
+        $client = $this->createMock('Zend\Http\Client');
+        return $this->getMockBuilder('VuFindSearch\Backend\EDS\Zend2')
+            ->setMethods($mock)
+            ->setConstructorArgs([[], $client])
+            ->getMock();
     }
 
     /**
@@ -210,10 +211,10 @@ class BackendTest extends \VuFindTest\Unit\TestCase
     protected function getBackend($connector, $factory = null, $cache = null, $container = null, $settings = [], $mock = null)
     {
         if (null === $factory) {
-            $factory = $this->getMock('VuFindSearch\Response\RecordCollectionFactoryInterface');
+            $factory = $this->createMock('VuFindSearch\Response\RecordCollectionFactoryInterface');
         }
         if (null === $cache) {
-            $cache = $this->getMock('Zend\Cache\Storage\Adapter\Filesystem');
+            $cache = $this->createMock('Zend\Cache\Storage\Adapter\Filesystem');
         }
         if (null === $container) {
             $container = $this->getMockBuilder('Zend\Session\Container')
@@ -223,7 +224,10 @@ class BackendTest extends \VuFindTest\Unit\TestCase
             return new Backend($connector, $factory, $cache, $container, new \Zend\Config\Config($settings));
         } else {
             $params = [$connector, $factory, $cache, $container, new \Zend\Config\Config($settings)];
-            return $this->getMock('VuFindSearch\Backend\EDS\Backend', $mock, $params);
+            return $this->getMockBuilder(__NAMESPACE__ . '\BackendMock')
+                ->setMethods($mock)
+                ->setConstructorArgs($params)
+                ->getMock();
         }
     }
 
@@ -243,3 +247,10 @@ class BackendTest extends \VuFindTest\Unit\TestCase
     }
 
 }
+
+class BackendMock extends \VuFindSearch\Backend\EDS\Backend
+{
+    public function getAuthenticationToken($isInvalid = false)
+    {
+    }
+}
diff --git a/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/EIT/BackendTest.php b/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/EIT/BackendTest.php
index 504a1b632b8711af6c257104e8c5b95ccf8552c8..8445ea96657de54f16f67eaf572f2086c2705f1a 100644
--- a/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/EIT/BackendTest.php
+++ b/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/EIT/BackendTest.php
@@ -128,7 +128,7 @@ class BackendTest extends \VuFindTest\Unit\TestCase
      */
     public function testConstructorSetters()
     {
-        $fact = $this->getMock('VuFindSearch\Response\RecordCollectionFactoryInterface');
+        $fact = $this->createMock('VuFindSearch\Response\RecordCollectionFactoryInterface');
         $conn = $this->getConnectorMock();
         $back = new Backend($conn, $fact);
         $this->assertEquals($fact, $back->getRecordCollectionFactory());
@@ -164,11 +164,11 @@ class BackendTest extends \VuFindTest\Unit\TestCase
      */
     protected function getConnectorMock(array $mock = [])
     {
-        $client = $this->getMock('Zend\Http\Client');
-        return $this->getMock(
-            'VuFindSearch\Backend\EIT\Connector', $mock,
-            ['http://fake', $client, 'profile', 'pwd', 'dbs']
-        );
+        $client = $this->createMock('Zend\Http\Client');
+        return $this->getMockBuilder(__NAMESPACE__ . '\ConnectorMock')
+            ->setMethods($mock)
+            ->setConstructorArgs(['http://fake', $client, 'profile', 'pwd', 'dbs'])
+            ->getMock();
     }
 
     /**
@@ -186,3 +186,10 @@ class BackendTest extends \VuFindTest\Unit\TestCase
         return new \VuFindSearch\Backend\EIT\Response\XML\RecordCollectionFactory($callback);
     }
 }
+
+class ConnectorMock extends \VuFindSearch\Backend\EIT\Connector
+{
+    public function call($method = 'GET', $params = null)
+    {
+    }
+}
diff --git a/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/LibGuides/BackendTest.php b/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/LibGuides/BackendTest.php
index 1a92ff7ee17f5c51576d972e899df7ecaa399b44..0f9484ef118255cc6a4ee3d356c21ac9e335e39e 100644
--- a/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/LibGuides/BackendTest.php
+++ b/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/LibGuides/BackendTest.php
@@ -121,7 +121,7 @@ class BackendTest extends \VuFindTest\Unit\TestCase
      */
     public function testConstructorSetters()
     {
-        $fact = $this->getMock('VuFindSearch\Response\RecordCollectionFactoryInterface');
+        $fact = $this->createMock('VuFindSearch\Response\RecordCollectionFactoryInterface');
         $conn = $this->getConnector();
         $back = new Backend($conn, $fact);
         $this->assertEquals($fact, $back->getRecordCollectionFactory());
@@ -243,11 +243,11 @@ class BackendTest extends \VuFindTest\Unit\TestCase
      */
     protected function getConnectorMock(array $mock = [])
     {
-        $client = $this->getMock('Zend\Http\Client');
-        return $this->getMock(
-            'VuFindSearch\Backend\LibGuides\Connector', $mock,
-            ['fakeid', $client]
-        );
+        $client = $this->createMock('Zend\Http\Client');
+        return $this->getMockBuilder('VuFindSearch\Backend\LibGuides\Connector')
+            ->setMethods($mock)
+            ->setConstructorArgs(['fakeid', $client])
+            ->getMock();
     }
 
     /**
diff --git a/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/Pazpar2/BackendTest.php b/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/Pazpar2/BackendTest.php
index 7f5d0fc23407b637f73432a592b3fcffd193aefb..21ac2db7599af46f5073582130c3be02c6185ee8 100644
--- a/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/Pazpar2/BackendTest.php
+++ b/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/Pazpar2/BackendTest.php
@@ -51,13 +51,12 @@ class BackendTest extends TestCase
      */
     public function testGetConnector()
     {
-        $connector = $this->getMock(
-            'VuFindSearch\Backend\Pazpar2\Connector', [],
-            ['http://fake', $this->getMock('Zend\Http\Client')]
-        );
+        $connector = $this->getMockBuilder('VuFindSearch\Backend\Pazpar2\Connector')
+            ->setConstructorArgs(['http://fake', $this->createMock('Zend\Http\Client')])
+            ->getMock();
         $back = new Backend(
             $connector,
-            $this->getMock('VuFindSearch\Response\RecordCollectionFactoryInterface')
+            $this->createMock('VuFindSearch\Response\RecordCollectionFactoryInterface')
         );
         $this->assertEquals($connector, $back->getConnector());
     }
@@ -150,10 +149,11 @@ class BackendTest extends TestCase
      */
     protected function getConnectorMock(array $mock = [])
     {
-        $client = $this->getMock('Zend\Http\Client');
-        return $this->getMock(
-            'VuFindSearch\Backend\Pazpar2\Connector', $mock, ['fake', $client]
-        );
+        $client = $this->createMock('Zend\Http\Client');
+        return $this->getMockBuilder('VuFindSearch\Backend\Pazpar2\Connector')
+            ->setMethods($mock)
+            ->setConstructorArgs(['fake', $client])
+            ->getMock();
     }
 
     /**
diff --git a/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/Primo/BackendTest.php b/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/Primo/BackendTest.php
index 0de237bb03fe90848d7b7a5203f9aa029dffa0f4..48c1aaf06ce41e3eea34221a62e846280324c8f8 100644
--- a/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/Primo/BackendTest.php
+++ b/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/Primo/BackendTest.php
@@ -121,7 +121,7 @@ class BackendTest extends \VuFindTest\Unit\TestCase
      */
     public function testConstructorSetters()
     {
-        $fact = $this->getMock('VuFindSearch\Response\RecordCollectionFactoryInterface');
+        $fact = $this->createMock('VuFindSearch\Response\RecordCollectionFactoryInterface');
         $conn = $this->getConnectorMock();
         $back = new Backend($conn, $fact);
         $this->assertEquals($fact, $back->getRecordCollectionFactory());
@@ -209,10 +209,10 @@ class BackendTest extends \VuFindTest\Unit\TestCase
      */
     protected function getConnectorMock(array $mock = [])
     {
-        $client = $this->getMock('Zend\Http\Client');
-        return $this->getMock(
-            'VuFindSearch\Backend\Primo\Connector', $mock,
-            ['http://fakeaddress.none', 'inst-id', $client]
-        );
+        $client = $this->createMock('Zend\Http\Client');
+        return $this->getMockBuilder('VuFindSearch\Backend\Primo\Connector')
+            ->setMethods($mock)
+            ->setConstructorArgs(['http://fakeaddress.none', 'inst-id', $client])
+            ->getMock();
     }
 }
diff --git a/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/Solr/BackendTest.php b/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/Solr/BackendTest.php
index b49adf79a0c69b912782d392f06bcf74ed277745..3aaf2144ae9ac8bca50be3979f24ef6d7803235a 100644
--- a/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/Solr/BackendTest.php
+++ b/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/Solr/BackendTest.php
@@ -143,6 +143,29 @@ class BackendTest extends PHPUnit_Framework_TestCase
         $this->assertCount(10, $terms->getFieldTerms('author'));
     }
 
+    /**
+     * Test terms component (using ParamBag as first param).
+     *
+     * @return void
+     */
+    public function testTermsWithParamBagAsFirstParameter()
+    {
+        $resp = $this->loadResponse('terms');
+        $conn = $this->getConnectorMock(['query']);
+        $conn->expects($this->once())
+            ->method('query')
+            ->will($this->returnValue($resp->getBody()));
+        $back = new Backend($conn);
+        $back->setIdentifier('test');
+        $bag = new ParamBag();
+        $bag->set('terms.fl', 'author');
+        $bag->set('terms.lower', '');
+        $bag->set('terms.limit', '-1');
+        $terms = $back->terms($bag);
+        $this->assertTrue($terms->hasFieldTerms('author'));
+        $this->assertCount(10, $terms->getFieldTerms('author'));
+    }
+
     /**
      * Test handling of a bad JSON response.
      *
@@ -263,16 +286,17 @@ class BackendTest extends PHPUnit_Framework_TestCase
     public function testRandom()
     {
         // Test that random sort parameter is added:
-        $params = $this->getMock('VuFindSearch\ParamBag', ['set']);
+        $params = $this->getMockBuilder('VuFindSearch\ParamBag')
+            ->setMethods(['set'])->getMock();
         $params->expects($this->once())->method('set')
             ->with($this->equalTo('sort'), $this->matchesRegularExpression('/[0-9]+_random asc/'));
 
         // Test that random proxies search; stub out injectResponseWriter() to prevent it
         // from injecting unwanted extra parameters into $params:
-        $back = $this->getMock(
-            'VuFindSearch\Backend\Solr\Backend', ['search', 'injectResponseWriter'],
-            [$this->getConnectorMock()]
-        );
+        $back = $this->getMockBuilder(__NAMESPACE__ . '\BackendMock')
+            ->setMethods(['search', 'injectResponseWriter'])
+            ->setConstructorArgs([$this->getConnectorMock()])
+            ->getMock();
         $back->expects($this->once())->method('injectResponseWriter');
         $back->expects($this->once())->method('search')
             ->will($this->returnValue('dummy'));
@@ -327,6 +351,16 @@ class BackendTest extends PHPUnit_Framework_TestCase
     protected function getConnectorMock(array $mock = [])
     {
         $map = new HandlerMap(['select' => ['fallback' => true]]);
-        return $this->getMock('VuFindSearch\Backend\Solr\Connector', $mock, ['http://example.org/', $map]);
+        return $this->getMockBuilder('VuFindSearch\Backend\Solr\Connector')
+            ->setMethods($mock)
+            ->setConstructorArgs(['http://example.org/', $map])
+            ->getMock();
+    }
+}
+
+class BackendMock extends \VuFindSearch\Backend\Solr\Backend
+{
+    public function injectResponseWriter(\VuFindSearch\ParamBag $params)
+    {
     }
 }
diff --git a/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/Solr/ConnectorTest.php b/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/Solr/ConnectorTest.php
index 7f8b7f516271e5edac1ee0e99cd6e83829d7b937..173736cd15e200ec02abe98caeb6b50726aa9c85 100644
--- a/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/Solr/ConnectorTest.php
+++ b/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/Solr/ConnectorTest.php
@@ -134,7 +134,7 @@ class ConnectorTest extends PHPUnit_Framework_TestCase
     public function testSaveThrowsUnknownFormat()
     {
         $conn = $this->createConnector();
-        $document = $this->getMock('VuFindSearch\Backend\Solr\Document\UpdateDocument');
+        $document = $this->createMock('VuFindSearch\Backend\Solr\Document\UpdateDocument');
         $conn->write($document, 'unknown', 'update');
     }
 
diff --git a/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/Solr/QueryBuilderTest.php b/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/Solr/QueryBuilderTest.php
index f966c234a59b5d3bef4faff3f3c00d92f8894ee9..d9560012a96de0a688e430d37829b227bd7a5415 100644
--- a/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/Solr/QueryBuilderTest.php
+++ b/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/Solr/QueryBuilderTest.php
@@ -108,41 +108,140 @@ class QueryBuilderTest extends \VuFindTest\Unit\TestCase
      */
     protected function getQuestionTests()
     {
+        // Format: [input, expected output, flags array]
         // @codingStandardsIgnoreStart
         return [
-            ['this?', '(this?) OR (this\?)'], // trailing question mark
-            ['this? that', '((this?) OR (this\?)) that'], // question mark after first word
-            ['start this? that', 'start ((this?) OR (this\?)) that'], // question mark after the middle word
-            ['start AND this? AND that', 'start AND ((this?) OR (this\?)) AND that'], // question mark with boolean operators
-            ['start t?his that', 'start t?his that'], // question mark as a wildcard in the middle of a word
-            ['start? this?', '((start?) OR (start\?)) ((this?) OR (this\?))'], // multiple ? terms
-            ['this? that? this?', '((this?) OR (this\?)) ((that?) OR (that\?)) ((this?) OR (this\?))'], // repeating ? term
-            ['"this? that?"', '"this? that?"'], // ? terms inside quoted phrase
+            // trailing question mark:
+            ['this?', '(this?) OR (this\?)', []],
+            // question mark after first word:
+            ['this? that', '((this?) OR (this\?)) that', []],
+            // question mark after the middle word:
+            ['start this? that', 'start ((this?) OR (this\?)) that', []],
+            // question mark with boolean operators:
+            ['start AND this? AND that', 'start AND ((this?) OR (this\?)) AND that', []],
+            // question mark as a wildcard in the middle of a word:
+            ['start t?his that', 'start t?his that', []],
+            // multiple ? terms:
+            ['start? this?', '((start?) OR (start\?)) ((this?) OR (this\?))', []],
+            // ? term in field-specific context:
+            ['xyzzy:this?', 'xyzzy:((this?) OR (this\?))', []],
+            // ? term in field-specific context w/ extra term:
+            ['xyzzy:(this? that)', 'xyzzy:(((this?) OR (this\?)) that)', []],
+            // Multiple fields, one w/ ? term:
+            ['foo:this? OR bar:tha?t', 'foo:((this?) OR (this\?)) OR bar:tha?t', []],
+            // repeating ? term:
+            ['this? that? this?', '((this?) OR (this\?)) ((that?) OR (that\?)) ((this?) OR (this\?))', []],
+            // ? terms inside quoted phrase (basic flag set to indicate that
+            // this does not contain any syntax unsupported by basic Dismax):
+            ['"this? that?"', '"this? that?"', ['basic' => true]],
         ];
         // @codingStandardsIgnoreEnd
     }
 
     /**
-     * Test generation with a query handler
+     * Run a test case through a basic query.
+     *
+     * @param QueryBuilder $qb      Query builder
+     * @param string       $handler Search handler: dismax|edismax|standard
+     * @param array        $test    Test to run
      *
      * @return void
      */
-    public function testQueryHandler()
+    protected function runBasicQuestionTest($qb, $handler, $test)
+    {
+        list($input, $output, $flags) = $test;
+        if ($handler === 'standard'
+            || ($handler === 'dismax' && empty($flags['basic']))
+        ) {
+            // We expect an extra set of parentheses to be added, unless the
+            // string contains a colon, in which case some processing will be
+            // skipped due to field-specific query behavior.
+            $basicOutput = strstr($output, ':') ? $output : '(' . $output . ')';
+        } else {
+            $basicOutput = $output;
+        }
+        $q = new Query($input, 'test');
+        $before = $q->getString();
+        $response = $qb->build($q);
+        // Make sure the query builder had no side effects on the query object:
+        $this->assertEquals($before, $q->getString());
+        $processedQ = $response->get('q');
+        $this->assertEquals($basicOutput, $processedQ[0]);
+    }
+
+    /**
+     * Run a test case through an advanced query.
+     *
+     * @param QueryBuilder $qb      Query builder
+     * @param string       $handler Search handler: dismax|edismax|standard
+     * @param array        $test    Test to run
+     *
+     * @return void
+     */
+    protected function runAdvancedQuestionTest($qb, $handler, $test)
+    {
+        list($input, $output, $flags) = $test;
+        if ($handler === 'standard'
+            || ($handler === 'dismax' && empty($flags['basic']))
+        ) {
+            $advOutput = '((' . $output . '))';
+        } else {
+            $mm = $handler == 'dismax' ? '100%' : '0%';
+            $advOutput = "((_query_:\"{!$handler qf=\\\"foo\\\" mm=\\'$mm\\'}"
+                . addslashes($output) . '"))';
+        }
+        $advancedQ = new QueryGroup('AND', [new Query($input, 'test')]);
+        $advResponse = $qb->build($advancedQ);
+        $advProcessedQ = $advResponse->get('q');
+        $this->assertEquals($advOutput, $advProcessedQ[0]);
+    }
+
+    /**
+     * Run the standard suite of question mark tests, accounting for differences
+     * between stanard Lucene, basic Dismax and eDismax handlers.
+     *
+     * @param array  $builderParams Parameters for QueryBuilder constructor
+     * @param string $handler       Search handler: dismax|edismax|standard
+     *
+     * @return void
+     */
+    protected function runQuestionTests($builderParams, $handler)
     {
         // Set up an array of expected inputs and outputs:
         $tests = $this->getQuestionTests();
-        $qb = new QueryBuilder(
+        $qb = new QueryBuilder($builderParams);
+        foreach ($tests as $test) {
+            $this->runBasicQuestionTest($qb, $handler, $test);
+            $this->runAdvancedQuestionTest($qb, $handler, $test);
+        }
+    }
+
+    /**
+     * Test generation with a query handler
+     *
+     * @return void
+     */
+    public function testQueryHandler()
+    {
+        $this->runQuestionTests(
             [
                 'test' => []
-            ]
+            ], 'standard'
+        );
+    }
+
+    /**
+     * Test generation with a query handler with regular dismax
+     *
+     * @return void
+     */
+    public function testQueryHandlerWithDismax()
+    {
+        $this->runQuestionTests(
+            [
+                'test' => ['DismaxHandler' => 'dismax', 'DismaxFields' => ['foo']]
+            ], 'dismax'
         );
-        foreach ($tests as $test) {
-            list($input, $output) = $test;
-            $q = new Query($input, 'test');
-            $response = $qb->build($q);
-            $processedQ = $response->get('q');
-            $this->assertEquals('(' . $output . ')', $processedQ[0]);
-        }
     }
 
     /**
@@ -152,21 +251,11 @@ class QueryBuilderTest extends \VuFindTest\Unit\TestCase
      */
     public function testQueryHandlerWithEdismax()
     {
-        // Set up an array of expected inputs and outputs:
-        $tests = $this->getQuestionTests();
-
-        $qb = new QueryBuilder(
+        $this->runQuestionTests(
             [
                 'test' => ['DismaxHandler' => 'edismax', 'DismaxFields' => ['foo']]
-            ]
+            ], 'edismax'
         );
-        foreach ($tests as $test) {
-            list($input, $output) = $test;
-            $q = new Query($input, 'test');
-            $response = $qb->build($q);
-            $processedQ = $response->get('q');
-            $this->assertEquals($output, $processedQ[0]);
-        }
     }
 
     /**
diff --git a/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/Solr/Response/Json/RecordCollectionTest.php b/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/Solr/Response/Json/RecordCollectionTest.php
index e33db1d255c297c53fadf0c216dede9cfbc6da67..51eaf142b6bcd2cfd6c073164aa81f448c83b6d4 100644
--- a/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/Solr/Response/Json/RecordCollectionTest.php
+++ b/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/Solr/Response/Json/RecordCollectionTest.php
@@ -78,7 +78,7 @@ class RecordCollectionTest extends PHPUnit_Framework_TestCase
             ]
         );
         for ($i = 0; $i < 5; $i++) {
-            $coll->add($this->getMock('VuFindSearch\Response\RecordInterface'));
+            $coll->add($this->createMock('VuFindSearch\Response\RecordInterface'));
         }
         $coll->rewind();
         $this->assertEquals(5, $coll->key());
diff --git a/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/Summon/BackendTest.php b/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/Summon/BackendTest.php
index cdd350d7382dbd3d2232bbda29774f2e0e055d01..691079adf27e57b82242d3cfafdc1aa2b9a5109b 100644
--- a/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/Summon/BackendTest.php
+++ b/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/Summon/BackendTest.php
@@ -125,7 +125,7 @@ class BackendTest extends TestCase
      */
     public function testRetrieveWrapsSummonException()
     {
-        $fact = $this->getMock('VuFindSearch\Response\RecordCollectionFactoryInterface');
+        $fact = $this->createMock('VuFindSearch\Response\RecordCollectionFactoryInterface');
         $conn = $this->getConnectorMock(['getRecord']);
         $conn->expects($this->once())
             ->method('getRecord')
@@ -177,7 +177,7 @@ class BackendTest extends TestCase
      */
     public function testSearchWrapsSummonException()
     {
-        $fact = $this->getMock('VuFindSearch\Response\RecordCollectionFactoryInterface');
+        $fact = $this->createMock('VuFindSearch\Response\RecordCollectionFactoryInterface');
         $conn = $this->getConnectorMock(['query']);
         $conn->expects($this->once())
             ->method('query')
@@ -211,7 +211,7 @@ class BackendTest extends TestCase
      */
     public function testConstructorSetters()
     {
-        $fact = $this->getMock('VuFindSearch\Response\RecordCollectionFactoryInterface');
+        $fact = $this->createMock('VuFindSearch\Response\RecordCollectionFactoryInterface');
         $conn = $this->getConnectorMock();
         $back = new Backend($conn, $fact);
         $this->assertEquals($fact, $back->getRecordCollectionFactory());
@@ -260,8 +260,9 @@ class BackendTest extends TestCase
      */
     protected function getConnectorMock(array $mock = [])
     {
-        return $this->getMock(
-            'SerialsSolutions\Summon\Zend2', $mock, ['id', 'key']
-        );
+        return $this->getMockBuilder('SerialsSolutions\Summon\Zend2')
+            ->setMethods($mock)
+            ->setConstructorArgs(['id', 'key'])
+            ->getMock();
     }
 }
diff --git a/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/WorldCat/BackendTest.php b/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/WorldCat/BackendTest.php
index 2b9e8b29f04eee66acc56805bbfccefdae62715f..d17a2b55c00da8df71ea6eba25bf435942c7adbc 100644
--- a/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/WorldCat/BackendTest.php
+++ b/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/WorldCat/BackendTest.php
@@ -113,7 +113,7 @@ class BackendTest extends PHPUnit_Framework_TestCase
      */
     public function testConstructorSetters()
     {
-        $fact = $this->getMock('VuFindSearch\Response\RecordCollectionFactoryInterface');
+        $fact = $this->createMock('VuFindSearch\Response\RecordCollectionFactoryInterface');
         $conn = $this->getConnectorMock();
         $back = new Backend($conn, $fact);
         $this->assertEquals($fact, $back->getRecordCollectionFactory());
@@ -149,10 +149,10 @@ class BackendTest extends PHPUnit_Framework_TestCase
      */
     protected function getConnectorMock(array $mock = [])
     {
-        $client = $this->getMock('Zend\Http\Client');
-        return $this->getMock(
-            'VuFindSearch\Backend\WorldCat\Connector',
-            $mock, ['fake', $client]
-        );
+        $client = $this->createMock('Zend\Http\Client');
+        return $this->getMockBuilder('VuFindSearch\Backend\WorldCat\Connector')
+            ->setMethods($mock)
+            ->setConstructorArgs(['fake', $client])
+            ->getMock();
     }
 }
diff --git a/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/WorldCat/ConnectorTest.php b/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/WorldCat/ConnectorTest.php
index 6c1870124d787875b5fa43b6da5113a4eac0f839..cea0d5d3ea3a140ed518bde2f00a1dc95e65df12 100644
--- a/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/WorldCat/ConnectorTest.php
+++ b/module/VuFindSearch/tests/unit-tests/src/VuFindTest/Backend/WorldCat/ConnectorTest.php
@@ -49,7 +49,7 @@ class ConnectorTest extends \PHPUnit_Framework_TestCase
      */
     public function testGetHoldings()
     {
-        $client = $this->getMock('Zend\Http\Client');
+        $client = $this->createMock('Zend\Http\Client');
         $connector = new Connector('key', $client);
         $client->expects($this->once())->method('setMethod')
             ->with($this->equalTo('POST'))
@@ -57,7 +57,7 @@ class ConnectorTest extends \PHPUnit_Framework_TestCase
         $client->expects($this->once())->method('setUri')
             ->with($this->equalTo('http://www.worldcat.org/webservices/catalog/content/libraries/baz?wskey=key&servicelevel=full'));
         $body = '<foo>bar</foo>';
-        $response = $this->getMock('Zend\Http\Response');
+        $response = $this->createMock('Zend\Http\Response');
         $response->expects($this->once())->method('getBody')
             ->will($this->returnValue($body));
         $response->expects($this->any())->method('isSuccess')
@@ -77,12 +77,12 @@ class ConnectorTest extends \PHPUnit_Framework_TestCase
      */
     public function testGetHoldingsHttpFailure()
     {
-        $client = $this->getMock('Zend\Http\Client');
+        $client = $this->createMock('Zend\Http\Client');
         $connector = new Connector('key', $client);
         $client->expects($this->once())->method('setMethod')
             ->with($this->equalTo('POST'))
             ->will($this->returnValue($client));
-        $response = $this->getMock('Zend\Http\Response');
+        $response = $this->createMock('Zend\Http\Response');
         $response->expects($this->any())->method('isSuccess')
             ->will($this->returnValue(false));
         $client->expects($this->once())->method('send')
@@ -97,7 +97,7 @@ class ConnectorTest extends \PHPUnit_Framework_TestCase
      */
     public function testGetRecord()
     {
-        $client = $this->getMock('Zend\Http\Client');
+        $client = $this->createMock('Zend\Http\Client');
         $connector = new Connector('key', $client);
         $client->expects($this->once())->method('setMethod')
             ->with($this->equalTo('POST'))
@@ -105,7 +105,7 @@ class ConnectorTest extends \PHPUnit_Framework_TestCase
         $client->expects($this->once())->method('setUri')
             ->with($this->equalTo('http://www.worldcat.org/webservices/catalog/content/baz?servicelevel=full&wskey=key'));
         $body = '<foo>bar</foo>';
-        $response = $this->getMock('Zend\Http\Response');
+        $response = $this->createMock('Zend\Http\Response');
         $response->expects($this->once())->method('getBody')
             ->will($this->returnValue($body));
         $response->expects($this->any())->method('isSuccess')
@@ -123,7 +123,7 @@ class ConnectorTest extends \PHPUnit_Framework_TestCase
      */
     public function testGetRecordWithError()
     {
-        $client = $this->getMock('Zend\Http\Client');
+        $client = $this->createMock('Zend\Http\Client');
         $connector = new Connector('key', $client);
         $client->expects($this->once())->method('setMethod')
             ->with($this->equalTo('POST'))
@@ -131,7 +131,7 @@ class ConnectorTest extends \PHPUnit_Framework_TestCase
         $client->expects($this->once())->method('setUri')
             ->with($this->equalTo('http://www.worldcat.org/webservices/catalog/content/baz?servicelevel=full&wskey=key'));
         $body = '<foo><diagnostic>bad</diagnostic></foo>';
-        $response = $this->getMock('Zend\Http\Response');
+        $response = $this->createMock('Zend\Http\Response');
         $response->expects($this->once())->method('getBody')
             ->will($this->returnValue($body));
         $response->expects($this->any())->method('isSuccess')
@@ -149,7 +149,7 @@ class ConnectorTest extends \PHPUnit_Framework_TestCase
      */
     public function testSearch()
     {
-        $client = $this->getMock('Zend\Http\Client');
+        $client = $this->createMock('Zend\Http\Client');
         $connector = new Connector('key', $client);
         $client->expects($this->once())->method('setMethod')
             ->with($this->equalTo('POST'))
@@ -157,7 +157,7 @@ class ConnectorTest extends \PHPUnit_Framework_TestCase
         $client->expects($this->once())->method('setUri')
             ->with($this->equalTo('http://www.worldcat.org/webservices/catalog/search/sru?version=1.1&x=y&startRecord=0&maximumRecords=20&servicelevel=full&wskey=key'));
         $body = '<foo>,<numberOfRecords>1</numberOfRecords><records><record><recordData>bar</recordData></record></records></foo>';
-        $response = $this->getMock('Zend\Http\Response');
+        $response = $this->createMock('Zend\Http\Response');
         $response->expects($this->once())->method('getBody')
             ->will($this->returnValue($body));
         $response->expects($this->any())->method('isSuccess')
diff --git a/module/VuFindSearch/tests/unit-tests/src/VuFindTest/ParamBagTest.php b/module/VuFindSearch/tests/unit-tests/src/VuFindTest/ParamBagTest.php
index 482b69f42141edb6e35538435966eee867ac01e4..4b359057bf8ab14be43856468934559841d2c494 100644
--- a/module/VuFindSearch/tests/unit-tests/src/VuFindTest/ParamBagTest.php
+++ b/module/VuFindSearch/tests/unit-tests/src/VuFindTest/ParamBagTest.php
@@ -43,6 +43,33 @@ use PHPUnit_Framework_TestCase as TestCase;
  */
 class ParamBagTest extends TestCase
 {
+    /**
+     * Test "contains"
+     *
+     * @return void
+     */
+    public function testContains()
+    {
+        $bag = new ParamBag();
+        $bag->set('foo', 'bar');
+        $this->assertTrue($bag->contains('foo', 'bar'));
+        $this->assertFalse($bag->contains('bar', 'foo'));
+        $this->assertFalse($bag->contains('foo', 'baz'));
+    }
+
+    /**
+     * Test "hasParam"
+     *
+     * @return void
+     */
+    public function testHasParam()
+    {
+        $bag = new ParamBag();
+        $bag->set('foo', 'bar');
+        $this->assertTrue($bag->hasParam('foo'));
+        $this->assertFalse($bag->hasParam('bar'));
+    }
+
     /**
      * Test "remove"
      *
diff --git a/module/VuFindSearch/tests/unit-tests/src/VuFindTest/SearchServiceTest.php b/module/VuFindSearch/tests/unit-tests/src/VuFindTest/SearchServiceTest.php
index c55501c9f42eb158970687de96fae0dd1288be2d..7f2035071e4c896c7573a835965a8635f9d810aa 100644
--- a/module/VuFindSearch/tests/unit-tests/src/VuFindTest/SearchServiceTest.php
+++ b/module/VuFindSearch/tests/unit-tests/src/VuFindTest/SearchServiceTest.php
@@ -136,7 +136,7 @@ class SearchServiceTest extends TestCase
     public function testRetrieveBatchInterface()
     {
         // Use a special backend for this test...
-        $this->backend = $this->getMock('VuFindTest\TestClassForRetrieveBatchInterface');
+        $this->backend = $this->createMock('VuFindTest\TestClassForRetrieveBatchInterface');
 
         $service = $this->getService();
         $backend = $this->getBackend();
@@ -165,7 +165,7 @@ class SearchServiceTest extends TestCase
     {
         $service = $this->getService();
         $backend = $this->getBackend();
-        $mockRecord = $this->getMock('VuFindSearch\Response\RecordInterface');
+        $mockRecord = $this->createMock('VuFindSearch\Response\RecordInterface');
         $response1 = $this->getRecordCollection();
         $response1->expects($this->once())->method('add')
             ->with($this->equalTo($mockRecord));
@@ -198,7 +198,7 @@ class SearchServiceTest extends TestCase
     public function testRetrieveBatchInterfaceException()
     {
         // Use a special backend for this test...
-        $this->backend = $this->getMock('VuFindTest\TestClassForRetrieveBatchInterface');
+        $this->backend = $this->createMock('VuFindTest\TestClassForRetrieveBatchInterface');
 
         $service = $this->getService();
         $backend = $this->getBackend();
@@ -253,7 +253,7 @@ class SearchServiceTest extends TestCase
     public function testRandomInterface()
     {
         // Use a special backend for this test...
-        $this->backend = $this->getMock('VuFindTest\TestClassForRandomInterface');
+        $this->backend = $this->createMock('VuFindTest\TestClassForRandomInterface');
 
         $service = $this->getService();
         $backend = $this->getBackend();
@@ -291,7 +291,7 @@ class SearchServiceTest extends TestCase
     public function testRandomInterfaceWithException()
     {
         // Use a special backend for this test...
-        $this->backend = $this->getMock('VuFindTest\TestClassForRandomInterface');
+        $this->backend = $this->createMock('VuFindTest\TestClassForRandomInterface');
 
         $service = $this->getService();
         $backend = $this->getBackend();
@@ -348,7 +348,7 @@ class SearchServiceTest extends TestCase
         for ($i = 1; $i < $limit + 1; $i++) {
             $response = $this->getRecordCollection();
             $response->expects($this->any())->method('first')
-                ->will($this->returnValue($this->getMock('VuFindSearch\Response\RecordInterface')));
+                ->will($this->returnValue($this->createMock('VuFindSearch\Response\RecordInterface')));
             $backend->expects($this->at($i))->method('search')
                 ->with(
                     $this->equalTo($query),
@@ -575,7 +575,7 @@ class SearchServiceTest extends TestCase
     public function testSimilar()
     {
         // Use a special backend for this test...
-        $this->backend = $this->getMock('VuFindTest\TestBackendClassForSimilar');
+        $this->backend = $this->createMock('VuFindTest\TestBackendClassForSimilar');
 
         $service = $this->getService();
         $backend = $this->getBackend();
@@ -621,7 +621,7 @@ class SearchServiceTest extends TestCase
     public function testSimilarException()
     {
         // Use a special backend for this test...
-        $this->backend = $this->getMock('VuFindTest\TestBackendClassForSimilar');
+        $this->backend = $this->createMock('VuFindTest\TestBackendClassForSimilar');
 
         $service = $this->getService();
         $backend = $this->getBackend();
@@ -651,13 +651,15 @@ class SearchServiceTest extends TestCase
      */
     public function testFailedResolve()
     {
-        $mockResponse = $this->getMock('Zend\EventManager\ResponseCollection');
+        $mockResponse = $this->createMock('Zend\EventManager\ResponseCollection');
         $mockResponse->expects($this->any())->method('stopped')->will($this->returnValue(false));
-        $em = $this->getMock('Zend\EventManager\EventManagerInterface');
+        $em = $this->createMock('Zend\EventManager\EventManagerInterface');
         $service = new Service();
-        $em->expects($this->any())->method('trigger')
-            ->with($this->equalTo('resolve'), $this->equalTo($service))
-            ->will($this->returnValue($mockResponse));
+        $em->expects($this->any())->method('triggerUntil')
+            ->with(
+                $this->anything(), $this->equalTo('resolve'),
+                $this->equalTo($service)
+            )->will($this->returnValue($mockResponse));
         $service->setEventManager($em);
         $service->retrieve('junk', 'foo');
     }
@@ -672,7 +674,7 @@ class SearchServiceTest extends TestCase
     protected function getBackend()
     {
         if (!$this->backend) {
-            $this->backend = $this->getMock('VuFindSearch\Backend\BackendInterface');
+            $this->backend = $this->createMock('VuFindSearch\Backend\BackendInterface');
         }
         return $this->backend;
     }
@@ -684,10 +686,8 @@ class SearchServiceTest extends TestCase
      */
     protected function getService()
     {
-        $em = $this->getMock('Zend\EventManager\EventManagerInterface');
-        $service = $this->getMock('VuFindSearch\Service', ['resolve']);
-        $service->expects($this->any())->method('resolve')
-            ->will($this->returnValue($this->getBackend()));
+        $em = $this->createMock('Zend\EventManager\EventManagerInterface');
+        $service = new SearchServiceMock($this->getBackend());
         $service->setEventManager($em);
         return $service;
     }
@@ -701,7 +701,7 @@ class SearchServiceTest extends TestCase
      */
     protected function getRecordCollection()
     {
-        return $this->getMock('VuFindSearch\Response\AbstractRecordCollection');
+        return $this->createMock('VuFindSearch\Response\AbstractRecordCollection');
     }
 }
 
@@ -728,3 +728,38 @@ abstract class TestClassForRandomInterface
 implements BackendInterface, RandomInterface
 {
 }
+
+/**
+ * Mock class to stub 'resolve'
+ */
+class SearchServiceMock extends \VuFindSearch\Service
+{
+    /**
+     * Service backend
+     *
+     * @var Service
+     */
+    protected $backend;
+
+    /**
+     * Constructor.
+     *
+     * @param Service $backendMock Return value for resolve
+     *
+     * @return void
+     */
+    public function __construct($backendMock)
+    {
+        $this->backend = $backendMock;
+    }
+
+    /**
+     * Generate a fake service.
+     *
+     * @return Service
+     */
+    protected function resolve($backend, $args)
+    {
+        return $this->backend;
+    }
+}
diff --git a/module/VuFindTheme/src/VuFindTheme/Initializer.php b/module/VuFindTheme/src/VuFindTheme/Initializer.php
index 563625e4747c7c05c152850799b76c6b3ec14d0b..161a6c7dbaf1188dbbeb7cf2a766a0d5d500a632 100644
--- a/module/VuFindTheme/src/VuFindTheme/Initializer.php
+++ b/module/VuFindTheme/src/VuFindTheme/Initializer.php
@@ -26,9 +26,10 @@
  * @link     https://vufind.org Main Site
  */
 namespace VuFindTheme;
-use Zend\Config\Config,
-    Zend\Mvc\MvcEvent,
-    Zend\Stdlib\RequestInterface as Request;
+use Zend\Config\Config;
+use Zend\Mvc\MvcEvent;
+use Zend\Mvc\View\Http\InjectTemplateListener as BaseInjectTemplateListener;
+use Zend\Stdlib\RequestInterface as Request;
 
 /**
  * VuFind Theme Initializer
@@ -140,23 +141,23 @@ class Initializer
 
         // Detach the default listener:
         $listeners = $sharedEvents->getListeners(
-            'Zend\Stdlib\DispatchableInterface', MvcEvent::EVENT_DISPATCH
+            ['Zend\Stdlib\DispatchableInterface'], MvcEvent::EVENT_DISPATCH
         );
-        foreach ($listeners as $listener) {
-            $metadata = $listener->getMetadata();
-            $callback = $listener->getCallback();
-            if (is_a($callback[0], 'Zend\Mvc\View\Http\InjectTemplateListener')) {
-                $priority = $metadata['priority'];
-                $sharedEvents->detach(
-                    'Zend\Stdlib\DispatchableInterface', $listener
-                );
-                break;
+        foreach ($listeners as $priority => $priorityGroup) {
+            foreach ($priorityGroup as $callback) {
+                if ($callback[0] instanceof BaseInjectTemplateListener) {
+                    $injectTemplatePriority = $priority;
+                    $sharedEvents->detach(
+                        $callback, 'Zend\Stdlib\DispatchableInterface'
+                    );
+                    break 2;
+                }
             }
         }
 
         // If we didn't successfully detach a listener above, priority will not be
         // set.  This is an unexpected situation, so we should throw an exception.
-        if (!isset($priority)) {
+        if (!isset($injectTemplatePriority)) {
             throw new \Exception('Unable to detach InjectTemplateListener');
         }
 
@@ -164,7 +165,7 @@ class Initializer
         $injectTemplateListener  = new InjectTemplateListener();
         $sharedEvents->attach(
             'Zend\Stdlib\DispatchableInterface', MvcEvent::EVENT_DISPATCH,
-            [$injectTemplateListener, 'injectTemplate'], $priority
+            [$injectTemplateListener, 'injectTemplate'], $injectTemplatePriority
         );
     }
 
@@ -310,7 +311,7 @@ class Initializer
     protected function setUpThemeViewHelpers($helpers)
     {
         // Grab the helper loader from the view manager:
-        $loader = $this->serviceManager->get('viewmanager')->getHelperManager();
+        $loader = $this->serviceManager->get('ViewHelperManager');
 
         // Register all the helpers:
         $config = new \Zend\ServiceManager\Config($helpers);
@@ -376,7 +377,7 @@ class Initializer
         }
 
         // Inject the path stack generated above into the view resolver:
-        $resolver = $this->serviceManager->get('viewmanager')->getResolver();
+        $resolver = $this->serviceManager->get('ViewResolver');
         if (!is_a($resolver, 'Zend\View\Resolver\AggregateResolver')) {
             throw new \Exception('Unexpected resolver: ' . get_class($resolver));
         }
diff --git a/module/VuFindTheme/src/VuFindTheme/Minify/CSS.php b/module/VuFindTheme/src/VuFindTheme/Minify/CSS.php
new file mode 100644
index 0000000000000000000000000000000000000000..77460d4ef0593bd0297d1b317bb4e752481c9bae
--- /dev/null
+++ b/module/VuFindTheme/src/VuFindTheme/Minify/CSS.php
@@ -0,0 +1,54 @@
+<?php
+/**
+ * CSS minifier extension
+ *
+ * PHP version 5
+ *
+ * Copyright (C) The National Library of Finland 2017.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * @category VuFind
+ * @package  View_Helpers
+ * @author   Ere Maijala <ere.maijala@helsinki.fi>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development Wiki
+ */
+namespace VuFindTheme\Minify;
+
+/**
+ * CSS minifier extensions
+ *
+ * @category VuFind
+ * @package  View_Helpers
+ * @author   Ere Maijala <ere.maijala@helsinki.fi>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development:testing:unit_tests Wiki
+ */
+class CSS extends \MatthiasMullie\Minify\CSS
+{
+    /**
+     * Return a converter to update relative paths to be relative to the new
+     * destination.
+     *
+     * @param string $source Source path
+     * @param string $target Target path
+     *
+     * @return \MatthiasMullie\PathConverter\ConverterInterface
+     */
+    protected function getPathConverter($source, $target)
+    {
+        return new PathConverter($source, $target);
+    }
+}
diff --git a/module/VuFindTheme/src/VuFindTheme/Minify/PathConverter.php b/module/VuFindTheme/src/VuFindTheme/Minify/PathConverter.php
new file mode 100644
index 0000000000000000000000000000000000000000..1b2254c153f7bff7bb91abb7e8d3a7195f00b866
--- /dev/null
+++ b/module/VuFindTheme/src/VuFindTheme/Minify/PathConverter.php
@@ -0,0 +1,56 @@
+<?php
+/**
+ * CSS path converter extension
+ *
+ * PHP version 5
+ *
+ * Copyright (C) The National Library of Finland 2017.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * @category VuFind
+ * @package  View_Helpers
+ * @author   Ere Maijala <ere.maijala@helsinki.fi>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development Wiki
+ */
+namespace VuFindTheme\Minify;
+
+/**
+ * CSS path converter extension
+ *
+ * @category VuFind
+ * @package  View_Helpers
+ * @author   Ere Maijala <ere.maijala@helsinki.fi>
+ * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
+ * @link     https://vufind.org/wiki/development Wiki
+ */
+class PathConverter extends \MatthiasMullie\PathConverter\Converter
+{
+    /**
+     * Normalize path.
+     *
+     * @param string $path Path
+     *
+     * @return string
+     */
+    protected function normalize($path)
+    {
+        $path = parent::normalize($path);
+
+        $path = str_replace('/local/cache/public', '/cache', $path);
+
+        return $path;
+    }
+}
diff --git a/module/VuFindTheme/src/VuFindTheme/Mobile.php b/module/VuFindTheme/src/VuFindTheme/Mobile.php
index ce148f2b820f53b854296136a7eaee0e200e589b..c1b47f2ced9ce90177537306c881d38f5721df1d 100644
--- a/module/VuFindTheme/src/VuFindTheme/Mobile.php
+++ b/module/VuFindTheme/src/VuFindTheme/Mobile.php
@@ -29,7 +29,7 @@
  * @package  Theme
  * @author   Andrew S. Nagy <vufind-tech@lists.sourceforge.net>
  * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
- * @link     http://code.google.com/p/mobileesp/ MobileESP Project
+ * @link     https://github.com/ahand/mobileesp MobileESP Project
  */
 namespace VuFindTheme;
 use uagent_info;
@@ -41,7 +41,7 @@ use uagent_info;
  * @package  Theme
  * @author   Andrew S. Nagy <vufind-tech@lists.sourceforge.net>
  * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
- * @link     http://code.google.com/p/mobileesp/ MobileESP Project
+ * @link     https://github.com/ahand/mobileesp MobileESP Project
  */
 class Mobile
 {
diff --git a/module/VuFindTheme/src/VuFindTheme/View/Helper/ConcatTrait.php b/module/VuFindTheme/src/VuFindTheme/View/Helper/ConcatTrait.php
index db948a36f30879645efd1d41731f4f5010583a50..94b27cdea4acbb2b144db751c0d9eb09ceea642b 100644
--- a/module/VuFindTheme/src/VuFindTheme/View/Helper/ConcatTrait.php
+++ b/module/VuFindTheme/src/VuFindTheme/View/Helper/ConcatTrait.php
@@ -24,7 +24,7 @@
  * @package  View_Helpers
  * @author   Demian Katz <demian.katz@villanova.edu>
  * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
- * @link     https://vufind.org/wiki/development:testing:unit_tests Wiki
+ * @link     https://vufind.org/wiki/development Wiki
  */
 namespace VuFindTheme\View\Helper;
 use VuFindTheme\ThemeInfo;
@@ -89,6 +89,8 @@ trait ConcatTrait
      * @param stdClass $item Link element object
      *
      * @return string
+     *
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
      */
     public function getType($item)
     {
@@ -151,7 +153,7 @@ trait ConcatTrait
 
         $this->getContainer()->ksort();
 
-        foreach ($this as $key => $item) {
+        foreach ($this as $item) {
             if ($this->isExcludedFromConcat($item)) {
                 $this->groups[] = [
                     'other' => true,
@@ -192,7 +194,12 @@ trait ConcatTrait
      */
     protected function getResourceCacheDir()
     {
-        return $this->themeInfo->getBaseDir() . '/../local/cache/public/';
+        if (!defined('LOCAL_CACHE_DIR')) {
+            throw new \Exception(
+                'Asset pipeline feature depends on the LOCAL_CACHE_DIR constant.'
+            );
+        }
+        return LOCAL_CACHE_DIR . '/public/';
     }
 
     /**
@@ -291,8 +298,13 @@ trait ConcatTrait
     protected function isPipelineActive()
     {
         if ($this->usePipeline) {
-            $cacheDir = $this->getResourceCacheDir();
-            if (!is_writable($cacheDir)) {
+            try {
+                $cacheDir = $this->getResourceCacheDir();
+            } catch (\Exception $e) {
+                $this->usePipeline = $cacheDir = false;
+                error_log($e->getMessage());
+            }
+            if ($cacheDir && !is_writable($cacheDir)) {
                 $this->usePipeline = false;
                 error_log("Cannot write to $cacheDir; disabling asset pipeline.");
             }
diff --git a/module/VuFindTheme/src/VuFindTheme/View/Helper/HeadLink.php b/module/VuFindTheme/src/VuFindTheme/View/Helper/HeadLink.php
index 0fbd23405da3c75e28618051df5bdcb4a373d4bc..c9478a4ae3d52b35e0a82900a5453e34dbc6ac47 100644
--- a/module/VuFindTheme/src/VuFindTheme/View/Helper/HeadLink.php
+++ b/module/VuFindTheme/src/VuFindTheme/View/Helper/HeadLink.php
@@ -203,6 +203,6 @@ class HeadLink extends \Zend\View\Helper\HeadLink
      */
     protected function getMinifier()
     {
-        return new \MatthiasMullie\Minify\CSS();
+        return new \VuFindTheme\Minify\CSS();
     }
 }
diff --git a/module/VuFindTheme/tests/unit-tests/src/VuFindTest/ThemeMobileTest.php b/module/VuFindTheme/tests/unit-tests/src/VuFindTest/ThemeMobileTest.php
index 74ba2f2156df026e5e7e39982a113f7f854e69c8..10b71d33c7485b865d7d4f4d399a0ad03fd50dfe 100644
--- a/module/VuFindTheme/tests/unit-tests/src/VuFindTest/ThemeMobileTest.php
+++ b/module/VuFindTheme/tests/unit-tests/src/VuFindTest/ThemeMobileTest.php
@@ -64,7 +64,9 @@ class ThemeMobileTest extends Unit\TestCase
      */
     public function testDetection()
     {
-        $detector = $this->getMock('uagent_info', ['DetectMobileLong']);
+        $detector = $this->getMockBuilder('uagent_info')
+            ->setMethods(['DetectMobileLong'])
+            ->getMock();
         $detector->expects($this->once())
             ->method('DetectMobileLong')->will($this->returnValue(true));
         $mobile = new Mobile($detector);
diff --git a/module/VuFindTheme/tests/unit-tests/src/VuFindTest/View/Helper/HeadThemeResourcesTest.php b/module/VuFindTheme/tests/unit-tests/src/VuFindTest/View/Helper/HeadThemeResourcesTest.php
index 67615920c126872dce35309fa43c96ff90f6cda4..d741648849cc082d3a531b1241df93753d60be2a 100644
--- a/module/VuFindTheme/tests/unit-tests/src/VuFindTest/View/Helper/HeadThemeResourcesTest.php
+++ b/module/VuFindTheme/tests/unit-tests/src/VuFindTest/View/Helper/HeadThemeResourcesTest.php
@@ -90,7 +90,7 @@ class HeadThemeResourcesTest extends \VuFindTest\Unit\TestCase
      */
     protected function getMockView()
     {
-        $view = $this->getMock('Zend\View\Renderer\PhpRenderer');
+        $view = $this->createMock('Zend\View\Renderer\PhpRenderer');
         $view->expects($this->at(0))->method('plugin')
             ->with($this->equalTo('headmeta'))
             ->will($this->returnValue($this->getMockHeadMeta()));
diff --git a/package.json b/package.json
index f61c89e97efc9b3fbe5f812715a9da0711ad6711..4ba6b092fbd49917f284b32f747d33bdc53e862a 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "vufind",
-  "version": "3.1.2",
+  "version": "4.0.1",
   "description": "Dev tools to handle css preprocessing, js magic, and compression",
   "repository": {
     "type": "git",
diff --git a/packages/DEBIAN/changelog b/packages/DEBIAN/changelog
index 5bb619c7b69753c69189ce6ba328bb5368cbc148..c58a34de07e786f8951556dd8635352767e0d39c 100644
--- a/packages/DEBIAN/changelog
+++ b/packages/DEBIAN/changelog
@@ -1,150 +1,168 @@
+vufind 4.0.1 distribution; urgency=low
+
+  * VuFind 4.0.1 release (see http://vufind.org/wiki/changelog for details)
+
+ -- maintainer VuFind Project Administration Team <vufind-admins@lists.sourceforge.net>  Mo 28 Aug 2017 08:11:48 UTC
+
+vufind 4.0 distribution; urgency=low
+
+  * VuFind 4.0 release (see http://vufind.org/wiki/changelog for details)
+
+ -- maintainer VuFind Project Administration Team <vufind-admins@lists.sourceforge.net>  Mo 10 Jul 2017 09:30:33 UTC
+
+vufind 3.1.4 distribution; urgency=low
+
+  * VuFind 3.1.4 release (see http://vufind.org/wiki/changelog for details)
+
+ -- maintainer VuFind Project Administration Team <vufind-admins@lists.sourceforge.net>  Mo 10 Jul 2017 09:30:33 UTC
+
 vufind 3.1.3 distribution; urgency=low
 
-  * VuFind 3.1.3 release (see http://vufind.org/wiki/changelog for details) 
+  * VuFind 3.1.3 release (see http://vufind.org/wiki/changelog for details)
 
  -- maintainer VuFind Project Administration Team <vufind-admins@lists.sourceforge.net>  Mo 13 Mar 2017 08:44:17 UTC
 
 vufind 3.1.2 distribution; urgency=low
 
-  * VuFind 3.1.2 release (see http://vufind.org/wiki/changelog for details) 
+  * VuFind 3.1.2 release (see http://vufind.org/wiki/changelog for details)
 
  -- maintainer VuFind Project Administration Team <vufind-admins@lists.sourceforge.net>  Mo 16 Jan 2017 07:21:54 UTC
 
 vufind 3.1.1 distribution; urgency=low
 
-  * VuFind 3.1.1 release (see http://vufind.org/wiki/changelog for details) 
+  * VuFind 3.1.1 release (see http://vufind.org/wiki/changelog for details)
 
  -- maintainer VuFind Project Administration Team <vufind-admins@lists.sourceforge.net>  Mo 31 Oct 2016 08:44:19 UTC
 
 vufind 3.1 distribution; urgency=low
 
-  * VuFind 3.1 release (see http://vufind.org/wiki/changelog for details) 
+  * VuFind 3.1 release (see http://vufind.org/wiki/changelog for details)
 
  -- maintainer VuFind Project Administration Team <vufind-admins@lists.sourceforge.net>  Mo 26 Sep 2016 10:30:43 UTC
 
 vufind 3.0.3 distribution; urgency=low
 
-  * VuFind 3.0.3 release (see http://vufind.org/wiki/changelog for details) 
+  * VuFind 3.0.3 release (see http://vufind.org/wiki/changelog for details)
 
  -- maintainer VuFind Project Administration Team <vufind-admins@lists.sourceforge.net>  Mo 1 Aug 2016 09:01:21 UTC
 
 vufind 3.0.2 distribution; urgency=low
 
-  * VuFind 3.0.2 release (see http://vufind.org/wiki/changelog for details) 
+  * VuFind 3.0.2 release (see http://vufind.org/wiki/changelog for details)
 
  -- maintainer VuFind Project Administration Team <vufind-admins@lists.sourceforge.net>  Tu 5 Jul 2016 12:02:33 UTC
 
 vufind 3.0.1 distribution; urgency=low
 
-  * VuFind 3.0.1 release (see http://vufind.org/wiki/changelog for details) 
+  * VuFind 3.0.1 release (see http://vufind.org/wiki/changelog for details)
 
  -- maintainer VuFind Project Administration Team <vufind-admins@lists.sourceforge.net>  Fr 27 May 2016 12:00:49 UTC
 
 vufind 3.0 distribution; urgency=low
 
-  * VuFind 3.0 release (see http://vufind.org/wiki/changelog for details) 
+  * VuFind 3.0 release (see http://vufind.org/wiki/changelog for details)
 
  -- maintainer VuFind Project Administration Team <vufind-admins@lists.sourceforge.net>  Mo 25 Apr 2016 09:28:51 UTC
 
 vufind 2.5.4 distribution; urgency=low
 
-  * VuFind 2.5.4 release (see http://vufind.org/wiki/changelog for details) 
+  * VuFind 2.5.4 release (see http://vufind.org/wiki/changelog for details)
 
  -- maintainer VuFind Project Administration Team <vufind-admins@lists.sourceforge.net>  Mo 25 Apr 2016 07:12:54 UTC
 
 vufind 2.5.3 distribution; urgency=low
 
-  * VuFind 2.5.3 release (see http://vufind.org/wiki/changelog for details) 
+  * VuFind 2.5.3 release (see http://vufind.org/wiki/changelog for details)
 
  -- maintainer VuFind Project Administration Team <vufind-admins@lists.sourceforge.net>  Mo 18 Apr 2016 09:50:46 UTC
 
 vufind 2.5.2 distribution; urgency=low
 
-  * VuFind 2.5.2 release (see http://vufind.org/wiki/changelog for details) 
+  * VuFind 2.5.2 release (see http://vufind.org/wiki/changelog for details)
 
  -- maintainer VuFind Project Administration Team <vufind-admins@lists.sourceforge.net>  We 3 Feb 2016 10:52:27 UTC
 
 vufind 2.5.1 distribution; urgency=low
 
-  * VuFind 2.5.1 release (see http://vufind.org/wiki/changelog for details) 
+  * VuFind 2.5.1 release (see http://vufind.org/wiki/changelog for details)
 
  -- maintainer VuFind Project Administration Team <vufind-admins@lists.sourceforge.net>  Mo 11 Jan 2016 09:30:11 UTC
 
 vufind 2.5 distribution; urgency=low
 
-  * VuFind 2.5 release (see http://vufind.org/wiki/changelog for details) 
+  * VuFind 2.5 release (see http://vufind.org/wiki/changelog for details)
 
  -- maintainer VuFind Project Administration Team <vufind-admins@lists.sourceforge.net>  Mo 28 Sep 2015 09:00:00 UTC
 
 vufind 2.4.1 distribution; urgency=low
 
-  * VuFind 2.4.1 release (see http://vufind.org/wiki/changelog for details) 
+  * VuFind 2.4.1 release (see http://vufind.org/wiki/changelog for details)
 
  -- maintainer VuFind Project Administration Team <vufind-admins@lists.sourceforge.net>  Mo 25 May 2015 08:41:27 UTC
 
 vufind 2.4 distribution; urgency=low
 
-  * VuFind 2.4 release (see http://vufind.org/wiki/changelog for details) 
+  * VuFind 2.4 release (see http://vufind.org/wiki/changelog for details)
 
  -- maintainer VuFind Project Administration Team <vufind-admins@lists.sourceforge.net>  Mo 23 Mar 2015 09:21:49 UTC
 
 vufind 2.3.1 distribution; urgency=low
 
-  * VuFind 2.3.1 release (see http://vufind.org/wiki/changelog for details) 
+  * VuFind 2.3.1 release (see http://vufind.org/wiki/changelog for details)
 
  -- maintainer VuFind Project Administration Team <vufind-admins@lists.sourceforge.net>  Mo 17 Nov 2014 08:31:51 UTC
 
 vufind 2.3 distribution; urgency=low
 
-  * VuFind 2.3 release (see http://vufind.org/wiki/changelog for details) 
+  * VuFind 2.3 release (see http://vufind.org/wiki/changelog for details)
 
  -- maintainer VuFind Project Administration Team <vufind-admins@lists.sourceforge.net>  Mo 11 Aug 2014 08:57:22 UTC
 
 vufind 2.2.1 distribution; urgency=low
 
-  * VuFind 2.2.1 release (see http://vufind.org/wiki/changelog for details) 
+  * VuFind 2.2.1 release (see http://vufind.org/wiki/changelog for details)
 
  -- maintainer VuFind Project Administration Team <vufind-admins@lists.sourceforge.net>  Mo 26 Feb 2014 09:11:36 UTC
 
 vufind 2.2 distribution; urgency=low
 
-  * VuFind 2.2 release (see http://vufind.org/wiki/changelog for details) 
+  * VuFind 2.2 release (see http://vufind.org/wiki/changelog for details)
 
  -- maintainer VuFind Project Administration Team <vufind-admins@lists.sourceforge.net>  Mo 27 Jan 2014 09:13:52 UTC
 
 vufind 2.1.1 distribution; urgency=low
 
-  * VuFind 2.1.1 release (see http://vufind.org/wiki/changelog for details) 
+  * VuFind 2.1.1 release (see http://vufind.org/wiki/changelog for details)
 
  -- maintainer VuFind Project Administration Team <vufind-admins@lists.sourceforge.net>  Mo 9 Sep 2013 11:26:51 UTC
 
 vufind 2.1 distribution; urgency=low
 
-  * VuFind 2.1 release (see http://vufind.org/wiki/changelog for details) 
+  * VuFind 2.1 release (see http://vufind.org/wiki/changelog for details)
 
  -- maintainer VuFind Project Administration Team <vufind-admins@lists.sourceforge.net>  Mo 26 Aug 2013 08:43:11 UTC
 
 vufind 2.0.1 distribution; urgency=low
 
-  * VuFind 2.0.1 release (see http://vufind.org/wiki/changelog for details) 
+  * VuFind 2.0.1 release (see http://vufind.org/wiki/changelog for details)
 
  -- maintainer VuFind Project Administration Team <vufind-admins@lists.sourceforge.net>  Mo 25 Jun 2013 10:35:52 UTC
 
 vufind 2.0 distribution; urgency=low
 
-  * VuFind 2.0 release (see http://vufind.org/wiki/changelog for details) 
+  * VuFind 2.0 release (see http://vufind.org/wiki/changelog for details)
 
  -- maintainer VuFind Project Administration Team <vufind-admins@lists.sourceforge.net>  Mo 24 Jun 2013 09:13:27 UTC
 
 vufind 2.0RC1 distribution; urgency=low
 
-  * VuFind 2.0RC1 release (see http://vufind.org/wiki/changelog for details) 
+  * VuFind 2.0RC1 release (see http://vufind.org/wiki/changelog for details)
 
  -- maintainer VuFind Project Administration Team <vufind-admins@lists.sourceforge.net>  Mo 29 Apr 2013 12:03:19 UTC
 
 vufind 2.0beta distribution; urgency=low
 
-  * VuFind 2.0beta release (see http://vufind.org/wiki/changelog for details) 
+  * VuFind 2.0beta release (see http://vufind.org/wiki/changelog for details)
 
  -- maintainer VuFind Project Administration Team <vufind-admins@lists.sourceforge.net>  Mo 1 Oct 2012 12:07:33 UTC
 
diff --git a/packages/DEBIAN/control b/packages/DEBIAN/control
index afe834be47c28b80403c9b2e267693c24ee4e018..94f19df21eec4ed950c20831f846390c4325f2c8 100644
--- a/packages/DEBIAN/control
+++ b/packages/DEBIAN/control
@@ -1,5 +1,5 @@
 Package: vufind
-Version: 3.1.3
+Version: 4.0.1
 Section: World Wide Web
 Priority: Optional
 Architecture: all
@@ -15,7 +15,6 @@ Depends: apache2,
          php5-intl | php-intl,
          php5-json | php-json,
          php5-ldap | php-ldap,
-         php5-mcrypt | php-mcrypt,
          php5-mysql | php-mysql,
          php5-xsl | php-xml
 Maintainer: VuFind Project Administration Team <vufind-admins@lists.sourceforge.net>
diff --git a/public/index.php b/public/index.php
index 5022468b6f55aa273981ab4c1db9d300d4ae6175..0ffe5e85396512b70feb5a0b9e2e6c0dd61ac54f 100644
--- a/public/index.php
+++ b/public/index.php
@@ -7,6 +7,8 @@ use Zend\Mvc\Service\ServiceManagerConfig;
 $xhprof = getenv('VUFIND_PROFILER_XHPROF');
 if (!empty($xhprof) && extension_loaded('xhprof')) {
     xhprof_enable();
+} else if (extension_loaded('tideways')) {
+    tideways_enable();
 } else {
     $xhprof = false;
 }
@@ -82,12 +84,14 @@ Zend\Mvc\Application::init(require 'config/application.config.php')->run();
 
 // Handle final profiling details, if necessary:
 if ($xhprof) {
-    $xhprofData = xhprof_disable();
-    include_once "xhprof_lib/utils/xhprof_lib.php";
-    include_once "xhprof_lib/utils/xhprof_runs.php";
-    $xhprofRuns = new XHProfRuns_Default();
+    $xhprofData = extension_loaded('xhprof') ? xhprof_disable() : tideways_disable();
+    $xhprofRunId = uniqid();
     $suffix = 'vufind';
-    $xhprofRunId = $xhprofRuns->save_run($xhprofData, $suffix);
+    $dir = ini_get('xhprof.output_dir');
+    if (empty($dir)) {
+        $dir = sys_get_temp_dir();
+    }
+    file_put_contents("$dir/$xhprofRunId.$suffix.xhprof", serialize($xhprofData));
     $url = "$xhprof?run=$xhprofRunId&source=$suffix";
     echo "<a href='$url'>Profiler output</a>";
 }
diff --git a/solr.bat b/solr.bat
index 13b1577c59143d77bdd0cf49e56b73f89781bcd8..e4a16c9174909f93fce0b051bcae6e5f0fc121a9 100644
--- a/solr.bat
+++ b/solr.bat
@@ -21,6 +21,12 @@ rem
 rem JAVA_HOME
 rem   Home of Java installation (not directly used by this script, but passed along to
 rem   the standard Solr control script).
+rem
+rem SOLR_ADDITIONAL_START_OPTIONS
+rem   Additional options to pass to the solr binary at startup.
+rem
+rem SOLR_ADDITIONAL_JVM_OPTIONS
+rem   Additional options to pass to the JVM when launching Solr.
 
 rem Make sure that environment edits are local and that we have access to the
 rem Windows command extensions.
@@ -35,7 +41,7 @@ if "!%1!"=="!!" goto usage
 
 rem Set VUFIND_HOME (if not already set)
 if not "!%VUFIND_HOME%!"=="!!" goto vufindhomefound
-rem VUFIND_HOME not set -- try to call env.bat to 
+rem VUFIND_HOME not set -- try to call env.bat to
 rem fix the problem before we give up completely
 if exist env.bat goto useenvbat
 rem If env.bat doesn't exist, the user hasn't run the installer yet.
@@ -74,7 +80,7 @@ if not "!%SOLR_PORT%!"=="!!" goto solrportset
 set SOLR_PORT=8080
 :solrportset
 
-call %SOLR_BIN%\solr.cmd %1 -p %SOLR_PORT% -s %SOLR_HOME% -m %SOLR_HEAP% -a "-Dsolr.log=%SOLR_LOGS_DIR%"
+call %SOLR_BIN%\solr.cmd %1 %SOLR_ADDITIONAL_START_OPTIONS% -p %SOLR_PORT% -s %SOLR_HOME% -m %SOLR_HEAP% -a "-Dsolr.log=%SOLR_LOGS_DIR% %SOLR_ADDITIONAL_JVM_OPTIONS%"
 goto end
 
 :usage
diff --git a/solr.sh b/solr.sh
index 2a4956dc0dbead52f653eeea05cb095f20b63e95..49fe26e9a28b8f30ba3be88c4edc6b8d41913efb 100755
--- a/solr.sh
+++ b/solr.sh
@@ -23,6 +23,12 @@
 #   Home of Java installation (not directly used by this script, but passed along to
 #   the standard Solr control script).
 #
+# SOLR_ADDITIONAL_START_OPTIONS
+#   Additional options to pass to the solr binary at startup.
+#
+# SOLR_ADDITIONAL_JVM_OPTIONS
+#   Additional options to pass to the JVM when launching Solr.
+#
 
 usage()
 {
@@ -64,5 +70,15 @@ then
   SOLR_PORT="8080"
 fi
 
+if [ -z "$SOLR_ADDITIONAL_START_OPTIONS" ]
+then
+  SOLR_ADDITIONAL_START_OPTIONS=""
+fi
+
+if [ -z "$SOLR_ADDITIONAL_JVM_OPTIONS" ]
+then
+  SOLR_ADDITIONAL_JVM_OPTIONS=""
+fi
+
 export SOLR_LOGS_DIR=$SOLR_LOGS_DIR
-"$SOLR_BIN/solr" "$1" -p "$SOLR_PORT" -s "$SOLR_HOME" -m "$SOLR_HEAP" -a "-Dsolr.log=$SOLR_LOGS_DIR"
+"$SOLR_BIN/solr" "$1" ${SOLR_ADDITIONAL_START_OPTIONS} -p "$SOLR_PORT" -s "$SOLR_HOME" -m "$SOLR_HEAP" -a "-Dsolr.log=$SOLR_LOGS_DIR $SOLR_ADDITIONAL_JVM_OPTIONS"
diff --git a/tests/data/geo.mrc b/tests/data/geo.mrc
index 42f35e0e55684076d1095dc77fac3758c6666e54..87b489eeb3d8927b2fc87fdc037ec6e82e293c37 100644
--- a/tests/data/geo.mrc
+++ b/tests/data/geo.mrc
@@ -1 +1 @@
-00362naaa 2200109zu 4500001000800000005001500008008004100023034007400064034007000138100001700208245002700225  2000120160513104939730000s1973    coAa          0  0  EL  d0 aad+129.95348029e+129.95348029f-55.29356577g-55.29356577zSite 3740 aad+92.58856498e+92.58856498f+35.0285559g+35.0285559zSite 4511 aHurt, Millie10aTest Publication 2000100364naaa 2200109zu 4500001000800000005001500008008004100023034007000064034007200134100002100206245002700227  2000220160513104939730000s1973    coAa          0  0  EL  d0 aad+10.05908843e+10.05908843f-5.75031466g-5.75031466zSite 4400 aad+46.45283977e+46.45283977f+31.50720239g+31.50720239zSite 4471 aWinrow, Sanjuana10aTest Publication 2000200360naaa 2200109zu 4500001000800000005001500008008004100023034007200064034007200136100001500208245002700223  2000320160513104939730000s1973    coAa          0  0  EL  d0 aad-35.26826575e-35.26826575f+27.26620523g+27.26620523zSite 4000 aad-15.10285454e-15.10285454f+14.80524368g+14.80524368zSite 1631 aRudd, Jann10aTest Publication 2000300613naaa 2200145zu 4500001000800000005001500008008004100023034007200064034007200136034006600208034007400274034007200348100002000420245002700440  2000420160513104939730000s1973    coAa          0  0  EL  d0 aad-56.86690649e-56.86690649f+15.77554895g+15.77554895zSite 4790 aad+159.74574799e+159.74574799f-20.9661451g-20.9661451zSite 4340 aad+7.9676261e+7.9676261f+6.62658415g+6.62658415zSite 4480 aad+135.37478775e+135.37478775f+46.27024658g+46.27024658zSite 5530 aad-105.9279514e-105.9279514f+35.25445142g+35.25445142zSite 3061 aWalston, Verlie10aTest Publication 2000400526naaa 2200133zu 4500001000800000005001500008008004100023034007200064034007200136034006600208034007200274100001900346245002700365  2000520160513104939730000s1973    coAa          0  0  EL  d0 aad+83.63104693e+83.63104693f+21.46845472g+21.46845472zSite 3140 aad+156.17691966e+156.17691966f-9.22226407g-9.22226407zSite 1400 aad-7.6873641e-7.6873641f+49.3997425g+49.3997425zSite 1050 aad-85.11852582e-85.11852582f-32.54764684g-32.54764684zSite 2661 aPakele, Marina10aTest Publication 2000500365naaa 2200109zu 4500001000800000005001500008008004100023034007400064034007000138100002000208245002700228  2000620160513104939730000s1973    coAa          0  0  EL  d0 aadE119.53888243eE119.53888243fN62.91327942gN62.91327942zSite 2550 aadE67.8057745eE67.8057745fN36.44414008gN36.44414008zSite 5461 aMcglasson, Rich10aTest Publication 2000600627naaa 2200145zu 4500001000800000005001500008008004100023034007400064034007400138034007200212034007400284034007400358100002200432245002700454  2000720160513104939730000s1973    coAa          0  0  EL  d0 aadE121.59566053eE121.59566053fN23.86811097gN23.86811097zSite 3610 aadE151.51785078eE151.51785078fN13.91875447gN13.91875447zSite 1050 aadW86.72014286eW86.72014286fS10.73770388gS10.73770388zSite 4880 aadE134.89543887eE134.89543887fN25.94241103gN25.94241103zSite 2060 aadE161.78292166eE161.78292166fN10.15327259gN10.15327259zSite 3501 aRottman, Serafina10aTest Publication 2000700621naaa 2200145zu 4500001000800000005001500008008004100023034007400064034007400138034007200212034007200284034007200356100002000428245002700448  2000820160513104939730000s1973    coAa          0  0  EL  d0 aadW103.57340238eW103.57340238fS22.78804289gS22.78804289zSite 2170 aadW175.68166135eW175.68166135fS69.41361345gS69.41361345zSite 4970 aadE48.51599542eE48.51599542fS58.33629524gS58.33629524zSite 3550 aadE65.04196038eE65.04196038fN32.99243302gN32.99243302zSite 4860 aadW111.45384173eW111.45384173fS7.22546191gS7.22546191zSite 1131 aHaberle, Manuel10aTest Publication 2000800616naaa 2200145zu 4500001000800000005001500008008004100023034007000064034007000134034007400204034007200278034007000350100002300420245002700443  2000920160513104939730000s1973    coAa          0  0  EL  d0 aadE1.55144883eE1.55144883fS15.91268613gS15.91268613zSite 4710 aadE0.46771867eE0.46771867fS53.88776866gS53.88776866zSite 1390 aadE120.96526676eE120.96526676fN22.40092028gN22.40092028zSite 2390 aadW43.86881638eW43.86881638fS29.38831583gS29.38831583zSite 1970 aadW158.26944205eW158.26944205fS0.7378453gS0.7378453zSite 3941 aRuvalcaba, Letisha10aTest Publication 2000900326naaa 2200109zu 4500001000800000005001500008008004100023034005400064034005400118100001700172245002700189  2001020160513104939730000s1973    coAa          0  0  EL  d0 aadE0870709eE0870709fS065613gS065613zSite 1200 aadE1242258eE1242258fS110713gS110713zSite 2231 aBogard, Noma10aTest Publication 2001000525naaa 2200145zu 4500001000800000005001500008008004100023034005400064034005400118034005400172034005400226034005400280100001800334245002700352  2001120160513104939730000s1973    coAa          0  0  EL  d0 aadE0025331eE0025331fS493930gS493930zSite 3010 aadE0013038eE0013038fN444623gN444623zSite 1560 aadW0483141eW0483141fS452235gS452235zSite 4630 aadW0703406eW0703406fS373129gS373129zSite 3630 aadW1172630eW1172630fN661503gN661503zSite 3931 aPutman, Davis10aTest Publication 2001100526naaa 2200145zu 4500001000800000005001500008008004100023034005400064034005400118034005400172034005400226034005400280100001900334245002700353  2001220160513104939730000s1973    coAa          0  0  EL  d0 aadE1741450eE1741450fN154310gN154310zSite 5490 aadW0570821eW0570821fS415337gS415337zSite 2360 aadE1773647eE1773647fS330258gS330258zSite 4620 aadE0710915eE0710915fN400408gN400408zSite 3550 aadW0401638eW0401638fN093759gN093759zSite 5471 aBucher, Margit10aTest Publication 2001200528naaa 2200145zu 4500001000800000005001500008008004100023034005400064034005400118034005400172034005400226034005400280100002100334245002700355  2001320160513104939730000s1973    coAa          0  0  EL  d0 aadW1511513eW1511513fS055042gS055042zSite 1050 aadW1465931eW1465931fS261609gS261609zSite 4840 aadW0790538eW0790538fS512156gS512156zSite 5440 aadW1415343eW1415343fS185901gS185901zSite 4230 aadW1304431eW1304431fS502042gS502042zSite 1291 aDobyns, Wilfredo10aTest Publication 2001300463naaa 2200133zu 4500001000800000005001500008008004100023034005400064034005400118034005400172034005400226100002200280245002700302  2001420160513104939730000s1973    coAa          0  0  EL  d0 aadE1742335eE1742335fN191726gN191726zSite 2130 aadW1570705eW1570705fN435341gN435341zSite 5090 aadW1020233eW1020233fN203933gN203933zSite 2910 aadW1290413eW1290413fS691417gS691417zSite 2251 aMilbourne, Milton10aTest Publication 2001400328naaa 2200109zu 4500001000800000005001500008008004100023034005400064034005400118100001900172245002700191  2001520160513104939730000s1973    coAa          0  0  EL  d0 aadW0755517eW0755517fN151326gN151326zSite 3270 aadW0932259eW0932259fN020021gN020021zSite 1521 aMirsky, Dionna10aTest Publication 2001500536naaa 2200133zu 4500001000800000005001500008008004100023034007400064034007400138034007100212034007200283100002000355245002700375  2001620160513104939730000s1973    coAa          0  0  EL  d0 aad+100.64194149e+150.64194149f+76.29679349g+46.29679349zSite 3250 aad+140.41485857e+150.41485857f-59.57999928g-69.57999928zSite 1980 aad-14.23933962e-9.23933962f-27.72727724g-57.72727724zSite 3170 aad-175.1864435e-172.1864435f-10.03581345g-20.03581345zSite 1721 aInnocent, Leisa10aTest Publication 2001600615naaa 2200145zu 4500001000800000005001500008008004100023034006800064034007100132034007200203034007200275034007200347100002300419245002700442  2001720160513104939730000s1973    coAa          0  0  EL  d0 aad-165.6004414e-115.6004414f-14.509653g-24.509653zSite 2190 aad-172.2069375e-132.2069375f+10.76133978g+5.76133978zSite 2500 aad-162.8898108e-142.8898108f-15.07237354g-25.07237354zSite 5040 aad+71.03685744e+81.03685744f-66.09831516g-76.09831516zSite 1810 aad-160.1490595e-140.1490595f+68.15731704g+58.15731704zSite 4201 aCornforth, Desiree10aTest Publication 2001700613naaa 2200145zu 4500001000800000005001500008008004100023034007000064034007200134034007000206034007200276034007300348100001900421245002700440  2001820160513104939730000s1973    coAa          0  0  EL  d0 aad-91.5895638e-61.5895638f+74.14618546g+44.14618546zSite 1140 aad+64.41336345e+74.41336345f+79.74325176g+49.74325176zSite 1270 aad-7.44081494e-2.44081494f+68.18607023g+58.18607023zSite 1210 aad-170.1177443e-130.1177443f-63.43626229g-73.43626229zSite 4440 aad+95.39073945e+145.39073945f+42.45583955g+22.45583955zSite 2461 aKarter, Marvis10aTest Publication 2001800441naaa 2200121zu 4500001000800000005001500008008004100023034006800064034007000132034007200202100001800274245002700292  2001920160513104939730000s1973    coAa          0  0  EL  d0 aad+10.5670584e+15.5670584f-21.6083379g-41.6083379zSite 2070 aad+41.53787448e+51.53787448f+77.9847143g+57.9847143zSite 5480 aad+129.0839142e+139.0839142f+78.85096117g+68.85096117zSite 2721 aClaro, Bobbie10aTest Publication 2001900620naaa 2200145zu 4500001000800000005001500008008004100023034007400064034006900138034007200207034007400279034007400353100002000427245002700447  2002020160513104939730000s1973    coAa          0  0  EL  d0 aadW163.70412537eW143.70412537fN23.98046062gN13.98046062zSite 2460 aadW37.45857716eW27.45857716fN11.7990193gN6.7990193zSite 4110 aadW92.34562344eW62.34562344fS25.81496714gS55.81496714zSite 4880 aadE144.53537717eE174.53537717fS28.13599649gS58.13599649zSite 5160 aadW177.82278613eW117.82278613fS32.33211767gS62.33211767zSite 2831 aBeckett, Tamala10aTest Publication 2002000364naaa 2200109zu 4500001000800000005001500008008004100023034007400064034007200138100001700210245002700227  2002120160513104939730000s1973    coAa          0  0  EL  d0 aadE114.22094565eE144.22094565fS37.22983935gS77.22983935zSite 4160 aadW167.75647806eW147.75647806fN8.67140253gN3.67140253zSite 3961 aLam, Cristen10aTest Publication 2002100528naaa 2200133zu 4500001000800000005001500008008004100023034007200064034007200136034007200208034007000280100001700350245002700367  2002220160513104939730000s1973    coAa          0  0  EL  d0 aadW97.44010063eW67.44010063fN69.57202273gN39.57202273zSite 3650 aadW79.40943037eW59.40943037fN63.76345804gN43.76345804zSite 2300 aadW103.46816014eW73.46816014fS9.60188743gS14.60188743zSite 2350 aadW16.35276413eW11.35276413fS4.27200773gS9.27200773zSite 2451 aDalke, Isiah10aTest Publication 2002200618naaa 2200145zu 4500001000800000005001500008008004100023034007400064034007200138034007400210034007200284034007400356100001500430245002700445  2002320160513104939730000s1973    coAa          0  0  EL  d0 aadE127.23972147eE137.23972147fN63.12317768gN43.12317768zSite 2080 aadE129.15557267eE149.15557267fN45.7443194gN25.7443194zSite 1020 aadW151.73434552eW101.73434552fS55.73496457gS75.73496457zSite 1080 aadE54.94955124eE64.94955124fS34.71609174gS64.71609174zSite 5370 aadE106.81774118eE156.81774118fS29.05905321gS59.05905321zSite 4111 aOram, Donn10aTest Publication 2002300367naaa 2200109zu 4500001000800000005001500008008004100023034007400064034007100138100002100209245002700230  2002420160513104939730000s1973    coAa          0  0  EL  d0 aadE129.86022987eE149.86022987fN51.68020143gN31.68020143zSite 4760 aadE5.86815575eE15.86815575fN60.95617804gN40.95617804zSite 1761 aRupp, Georgeanna10aTest Publication 2002400450naaa 2200121zu 4500001000800000005001500008008004100023034007400064034007200138034007200210100001900282245002700301  2002520160513104939730000s1973    coAa          0  0  EL  d0 aadW156.11673622eW106.11673622fN78.32587133gN68.32587133zSite 3370 aadE47.92289733eE57.92289733fN77.17739015gN67.17739015zSite 1040 aadW32.89273609eW22.89273609fS40.70960814gS60.70960814zSite 4531 aWalter, Jasper10aTest Publication 2002500532naaa 2200133zu 4500001000800000005001500008008004100023034007300064034007400137034007300211034006800284100001900352245002700371  2002620160513104939730000s1973    coAa          0  0  EL  d0 aadE96.70798372eE146.70798372fN54.00011075gN34.00011075zSite 2710 aadE145.51684204eE165.51684204fN27.98976019gN17.98976019zSite 2660 aadW106.32772299eW76.32772299fN46.24201475gN26.24201475zSite 2860 aadE20.1511411eE25.1511411fN6.07910182gN1.07910182zSite 2421 aHultgren, Josh10aTest Publication 2002600328naaa 2200109zu 4500001000800000005001500008008004100023034005400064034005400118100001900172245002700191  2002720160513104939730000s1973    coAa          0  0  EL  d0 aadW0170403eW0120403fN755211gN455211zSite 4560 aadW1740209eW1340209fN794749gN694749zSite 3851 aGalasso, Tatum10aTest Publication 2002700333naaa 2200109zu 4500001000800000005001500008008004100023034005400064034005400118100002400172245002700196  2002820160513104939730000s1973    coAa          0  0  EL  d0 aadE0710106eE0810106fS111308gS211308zSite 5310 aadE0132703eE0182703fN541236gN341236zSite 3481 aCantrell, Cornelius10aTest Publication 2002800399naaa 2200121zu 4500001000800000005001500008008004100023034005400064034005400118034005400172100002400226245002700250  2002920160513104939730000s1973    coAa          0  0  EL  d0 aadW1693838eW1193838fN122531gN072531zSite 4150 aadE0844331eE1044331fS693723gS793723zSite 1320 aadE0062611eE0162611fN681512gN381512zSite 5031 aGreenblatt, Sherill10aTest Publication 2002900327naaa 2200109zu 4500001000800000005001500008008004100023034005400064034005400118100001800172245002700190  2003020160513104939730000s1973    coAa          0  0  EL  d0 aadE1053451eE1553451fS183256gS383256zSite 2870 aadE0830412eE1030412fS174644gS374644zSite 1801 aPerine, Alisa10aTest Publication 2003000393naaa 2200121zu 4500001000800000005001500008008004100023034005400064034005400118034005400172100001800226245002700244  2003120160513104939730000s1973    coAa          0  0  EL  d0 aadE0202657eE0252657fS470042gS770042zSite 2360 aadW1594422eW1094422fS562802gS762802zSite 4950 aadW0254325eW0204325fS591429gS691429zSite 3241 aSuen, Lanette10aTest Publication 2003100460naaa 2200133zu 4500001000800000005001500008008004100023034005400064034005400118034005400172034005400226100001900280245002700299  2003220160513104939730000s1973    coAa          0  0  EL  d0 aadW1331944eW0931944fN402114gN202114zSite 3060 aadW1780423eW1700423fN584511gN284511zSite 4340 aadW1600712eW1500712fN454326gN254326zSite 3810 aadW1752336eW1652336fN731737gN631737zSite 5211 aIverson, Beryl10aTest Publication 2003200459naaa 2200133zu 4500001000800000005001500008008004100023034005400064034005400118034005400172034005400226100001800280245002700298  2003320160513104939730000s1973    coAa          0  0  EL  d0 aadE1423151eE1523151fS521748gS721748zSite 2580 aadW1691508eW1391508fS131306gS231306zSite 5220 aadE1345235eE1745235fS630056gS730056zSite 3540 aadW1640324eW1140324fS330005gS630005zSite 1441 aBoyland, Bebe10aTest Publication 2003300394naaa 2200121zu 4500001000800000005001500008008004100023034005400064034005400118034005400172100001900226245002700245  2003420160513104939730000s1973    coAa          0  0  EL  d0 aadE1590126eE1690126fS341136gS641136zSite 3030 aadW1054117eW0754117fS354552gS754552zSite 3730 aadW0994125eW0694125fS434119gS634119zSite 3551 aArechiga, Moon10aTest Publication 2003400457naaa 2200133zu 4500001000800000005001500008008004100023034005400064034005400118034005400172034005400226100001600280245002700296  2003520160513104939730000s1973    coAa          0  0  EL  d0 aadW1405617eW1205617fS555856gS755856zSite 4800 aadE1073429eE1573429fS022601gS072601zSite 3730 aadE0913431eE1011343fS422933gS622933zSite 5360 aadE1131855eE1231855fS682514gS782514zSite 3241 aRozar, Josh10aTest Publication 2003500521naaa 2200133zu 4500001000800000005001500008008004100023034006800064034007200132034006800204034007000272100001800342245002700360  2003620160513104939730000s1973    coAa          0  0  EL  d0 aad-169.415256e-169.415256f+29.8815696g+29.8815696zSite 5600 aad-151.5560527e-151.5560527f-36.13307132g-36.13307132zSite 2020 aad-87.4479458e-87.4479458f+9.11816125g+9.11816125zSite 5400 aad-149.4183832e-149.4183832f+29.1541857g+29.1541857zSite 5571 aGuynn, Mayola10aTest Publication 2003600366naaa 2200109zu 4500001000800000005001500008008004100023034007200064034007200136100002100208245002700229  2003720160513104939730000s1973    coAa          0  0  EL  d0 aad+86.55263228e+86.55263228f-28.95862432g-28.95862432zSite 1680 aad-149.3464366e-129.3464366f+27.28202333g+17.28202333zSite 1341 aEngelhard, Marco10aTest Publication 2003700366naaa 2200109zu 4500001000800000005001500008008004100023034007400064034007200138100001900210245002700229  2003820160513104939730000s1973    coAa          0  0  EL  d0 aad+118.90296884e+118.90296884f+27.65389383g+27.65389383zSite 3970 aad-135.3498909e-95.34989087f+60.71524151g+40.71524151zSite 2231 aBornstein, Dia10aTest Publication 2003800363naaa 2200109zu 4500001000800000005001500008008004100023034007000064034007200134100002000206245002700226  2003920160513104939730000s1973    coAa          0  0  EL  d0 aad+15.7081159e+15.7081159f+10.51847859g+10.51847859zSite 1540 aad-65.34590317e-45.34590317f-16.22908424g-36.22908424zSite 4341 aMathisen, Dayle10aTest Publication 2003900356naaa 2200109zu 4500001000800000005001500008008004100023034007000064034007000134100001500204245002700219  2004020160513104939730000s1973    coAa          0  0  EL  d0 aad+120.07557262e+120.07557262f-7.8300017g-7.8300017zSite 4600 aad-78.33685724e-58.33685724f-20.7677353g-40.7677353zSite 3351 aOrtiz, Tia10aTest Publication 2004000370naaa 2200109zu 4500001000800000005001500008008004100023034007400064034007200138100002300210245002700233  2004120160513104939730000s1973    coAa          0  0  EL  d0 aad+179.11624407e+179.11624407f+49.45597061g+49.45597061zSite 1290 aad+18.65135762e+23.65135762f+75.67582839g+65.67582839zSite 3251 aSteffensen, Bianca10aTest Publication 2004100365naaa 2200109zu 4500001000800000005001500008008004100023034007200064034007200136100002000208245002700228  2004220160513104939730000s1973    coAa          0  0  EL  d0 aad-69.44473478e-69.44473478f+16.37800971g+16.37800971zSite 5180 aad-31.50294667e-21.50294667f-31.33882964g-61.33882964zSite 3511 aLaurich, Stuart10aTest Publication 2004200369naaa 2200109zu 4500001000800000005001500008008004100023034007400064034007200138100002200210245002700232  2004320160513104939730000s1973    coAa          0  0  EL  d0 aad+154.29238217e+154.29238217f-50.92756335g-50.92756335zSite 2970 aad-66.00381134e-46.00381134f-41.48033844g-61.48033844zSite 1781 aBeveridge, Albina10aTest Publication 2004300367naaa 2200109zu 4500001000800000005001500008008004100023034007000064034007400134100002200208245002700230  2004420160513104939730000s1973    coAa          0  0  EL  d0 aadE24.1857034eE24.1857034fS66.87278415gS66.87278415zSite 1290 aadW166.03284101eW156.03284101fN65.01324719gN35.01324719zSite 3991 aLetsinger, Tamiko10aTest Publication 2004400366naaa 2200109zu 4500001000800000005001500008008004100023034007000064034007400134100002100208245002700229  2004520160513104939730000s1973    coAa          0  0  EL  d0 aadE25.0293899eE25.0293899fS12.28047561gS12.28047561zSite 5060 aadW169.45170238eW119.45170238fN38.14274122gN18.14274122zSite 1251 aCounter, Modesto10aTest Publication 2004500531naaa 2200133zu 4500001000800000005001500008008004100023034007200064034007200136034007200208034007300280100001700353245002700370  2004620160513104939730000s1973    coAa          0  0  EL  d0 aadE86.99902059eE86.99902059fS41.27856855gS41.27856855zSite 3990 aadE133.71880822eE143.71880822fN8.13138602gN3.13138602zSite 4030 aadE171.49599516eE171.49599516fS56.3556026gS56.3556026zSite 1530 aadE119.63111094eE169.63111094fN11.62690851gN6.62690851zSite 1201 aValois, Arie10aTest Publication 2004600528naaa 2200133zu 4500001000800000005001500008008004100023034006800064034007200132034007200204034007400276100001700350245002700367  2004720160513104939730000s1973    coAa          0  0  EL  d0 aadW23.6918351eW23.6918351fN5.50055924gN5.50055924zSite 4950 aadW71.72678006eW51.72678006fN80.68048573gN72.68048573zSite 4190 aadW72.47081023eW72.47081023fS13.50689659gS13.50689659zSite 5050 aadW159.51582506eW109.51582506fS12.01041499gS22.01041499zSite 3211 aGiard, Dodie10aTest Publication 2004700364naaa 2200109zu 4500001000800000005001500008008004100023034007200064034007200136100001900208245002700227  2004820160513104939730000s1973    coAa          0  0  EL  d0 aadW98.39221287eW98.39221287fN20.00645186gN20.00645186zSite 1400 aadW35.22129012eW25.22129012fS11.27828226gS21.27828226zSite 1821 aDryer, Verlene10aTest Publication 2004800365naaa 2200109zu 4500001000800000005001500008008004100023034007400064034007400138100001600212245002700228  2004920160513104939730000s1973    coAa          0  0  EL  d0 aadW126.87139449eW126.87139449fS18.74530167gS18.74530167zSite 4470 aadW159.94018465eW109.94018465fS57.54337933gS67.54337933zSite 4601 aKohn, Clora10aTest Publication 2004900366naaa 2200109zu 4500001000800000005001500008008004100023034007200064034007200136100002100208245002700229  2005020160513104939730000s1973    coAa          0  0  EL  d0 aadW159.88627958eW109.88627958fS3.02307754gS8.02307754zSite 3560 aadE109.5707309eE119.5707309fS48.38262915gS78.38262915zSite 5401 aSutter, Katheryn10aTest Publication 2005000358naaa 2200109zu 4500001000800000005001500008008004100023034007000064034007000134100001700204245002700221  2005120160513104939730000s1973    coAa          0  0  EL  d0 aadE19.87166027eE24.87166027fS35.8561532gS75.8561532zSite 3760 aadE71.3886803eE81.3886803fS25.17975703gS55.17975703zSite 1071 aWalberg, Pia10aTest Publication 2005100590naaa 2200157zu 4500001000800000005001500008008004100023034005400064034005400118034005400172034005400226034005400280034005400334100001700388245002700405  2005220160513104939730000s1973    coAa          0  0  EL  d0 aadE0475840eE0475840fN315244gN315244zSite 3620 aadE0250120eE0250120fS051344gS051344zSite 4610 aadE0392838eE0392838fN123637gN123637zSite 3470 aadW0041819eW0041819fN670212gN670212zSite 3540 aadW0514641eW0514641fS325055gS325055zSite 5520 aadW0532607eW0432607fN401312gN201312zSite 2221 aHove, Armand10aTest Publication 2005200329naaa 2200109zu 4500001000800000005001500008008004100023034005400064034005400118100002000172245002700192  2005320160513104939730000s1973    coAa          0  0  EL  d0 aadW0670504eW0670504fS394806gS394806zSite 3640 aadW0380213eW0280213fN411500gN211500zSite 1091 aWestray, Shizue10aTest Publication 2005300326naaa 2200109zu 4500001000800000005001500008008004100023034005400064034005400118100001700172245002700189  2005420160513104939730000s1973    coAa          0  0  EL  d0 aadW0254536eW0254536fS244501gS244501zSite 2570 aadW0934339eW0634339fN451934gN251934zSite 5111 aOros, Cierra10aTest Publication 2005400330naaa 2200109zu 4500001000800000005001500008008004100023034005400064034005400118100002100172245002700193  2005520160513104939730000s1973    coAa          0  0  EL  d0 aadW1652138eW1652138fN004809gN004809zSite 3750 aadE0435513eE0535513fN510216gN310216zSite 2421 aBlacker, Minerva10aTest Publication 2005500329naaa 2200109zu 4500001000800000005001500008008004100023034005400064034005400118100002000172245002700192  2005620160513104939730000s1973    coAa          0  0  EL  d0 aadW1043920eW1043920fS011057gS011057zSite 2450 aadW0234238eW0184238fN682608gN382608zSite 4221 aLaurich, Stuart10aTest Publication 2005600328naaa 2200109zu 4500001000800000005001500008008004100023034005400064034005400118100001900172245002700191  2005720160513104939730000s1973    coAa          0  0  EL  d0 aadW1722040eW1722040fS352841gS352841zSite 2820 aadW1665858eW1565858fN683913gN383913zSite 1871 aKarter, Marvis10aTest Publication 2005700264naaa 2200097zu 4500001000800000005001500008008004100023034005400064100002100118245002700139  2005820160513104939730000s1973    coAa          0  0  EL  d0 aadW0981303eW0981303fN194221gN194221zSite 1021 aFavela, Lorretta10aTest Publication 2005800262naaa 2200097zu 4500001000800000005001500008008004100023034005400064100001900118245002700137  2005920160513104939730000s1973    coAa          0  0  EL  d0 aadW1612904eW1412904fS130045gS230045zSite 4881 aHultgren, Josh10aTest Publication 2005900327naaa 2200109zu 4500001000800000005001500008008004100023034005400064034005400118100001800172245002700190  2006020160513104939730000s1973    coAa          0  0  EL  d0 aadW0960543eW0960543fS052755gS052755zSite 5170 aadW1062423eW0762423fN181516gN081516zSite 1581 aMain, Neville10aTest Publication 2006000326naaa 2200109zu 4500001000800000005001500008008004100023034005400064034005400118100001700172245002700189  2006120160513104939730000s1973    coAa          0  0  EL  d0 aadW1681205eW1681205fN335749gN335749zSite 1440 aadW1684935eW1384935fS551611gS751611zSite 2101 aShaw, Denice10aTest Publication 2006100278naaa 2200097zu 4500001000800000005001500008008004100023034007000064100001900134245002700153  2006220160513104939730000s1973    coAa          0  0  EL  d0 aad+72.62860542e+72.62860542f-50.0640401g-50.0640401zSite 3861 aJasik, Micaela10aTest Publication 2006200280naaa 2200097zu 4500001000800000005001500008008004100023034007000064100002100134245002700155  2006320160513104939730000s1973    coAa          0  0  EL  d0 aad+79.53785174e+79.53785174f+6.56562911g+6.56562911zSite 1381 aRupp, Georgeanna10aTest Publication 2006300277naaa 2200097zu 4500001000800000005001500008008004100023034007200064100001600136245002700152  2006420160513104939730000s1973    coAa          0  0  EL  d0 aad+91.40655977e+91.40655977f-68.68188538g-68.68188538zSite 3761 aSears, Meri10aTest Publication 2006400280naaa 2200097zu 4500001000800000005001500008008004100023034007000064100002100134245002700155  2006520160513104939730000s1973    coAa          0  0  EL  d0 aad+90.5240303e+90.5240303f+16.31382075g+16.31382075zSite 2991 aWinrow, Sanjuana10aTest Publication 2006500279naaa 2200097zu 4500001000800000005001500008008004100023034007000064100002000134245002700154  2006620160513104939730000s1973    coAa          0  0  EL  d0 aad+51.37763177e+51.37763177f+0.65207263g+0.65207263zSite 4471 aSutter, Karolyn10aTest Publication 2006600280naaa 2200097zu 4500001000800000005001500008008004100023034007200064100001900136245002700155  2006720160513104939730000s1973    coAa          0  0  EL  d0 aad+173.34512334e+173.34512334f+28.0049181g+28.0049181zSite 1541 aArechiga, Moon10aTest Publication 2006700277naaa 2200097zu 4500001000800000005001500008008004100023034007200064100001600136245002700152  2006820160513104939730000s1973    coAa          0  0  EL  d0 aad-15.99213608e-15.99213608f+13.65438911g+13.65438911zSite 4251 aSaar, Danna10aTest Publication 2006800280naaa 2200097zu 4500001000800000005001500008008004100023034007200064100001900136245002700155  2006920160513104939730000s1973    coAa          0  0  EL  d0 aad+137.98717735e+137.98717735f-65.0442013g-65.0442013zSite 1001 aMirabito, Shin10aTest Publication 2006900278naaa 2200097zu 4500001000800000005001500008008004100023034007200064100001700136245002700153  2007020160513104939730000s1973    coAa          0  0  EL  d0 aad-117.4711533e-117.4711533f+38.23863124g+38.23863124zSite 3651 aWalberg, Pia10aTest Publication 2007000282naaa 2200097zu 4500001000800000005001500008008004100023034007200064100002100136245002700157  2007120160513104939730000s1973    coAa          0  0  EL  d0 aad+95.03142217e+95.03142217f-14.54137057g-14.54137057zSite 2361 aBalicki, Nicolas10aTest Publication 2007100276naaa 2200097zu 4500001000800000005001500008008004100023034007200064100001500136245002700151  2007220160513104939730000s1973    coAa          0  0  EL  d0 aad+34.55902657e+34.55902657f-27.96661882g-27.96661882zSite 5541 aOram, Donn10aTest Publication 2007200279naaa 2200097zu 4500001000800000005001500008008004100023034007200064100001800136245002700154  2007320160513104939730000s1973    coAa          0  0  EL  d0 aad+125.34051527e+125.34051527f+9.81883652g+9.81883652zSite 1211 aMurden, Claud10aTest Publication 2007300279naaa 2200097zu 4500001000800000005001500008008004100023034007400064100001600138245002700154  2007420160513104939730000s1973    coAa          0  0  EL  d0 aad+110.92377605e+110.92377605f+31.06593861g+31.06593861zSite 4421 aPerla, Jong10aTest Publication 2007400284naaa 2200097zu 4500001000800000005001500008008004100023034007400064100002100138245002700159  2007520160513104939730000s1973    coAa          0  0  EL  d0 aad+111.98924724e+111.98924724f+52.12174162g+52.12174162zSite 1501 aDobyns, Wilfredo10aTest Publication 2007500282naaa 2200097zu 4500001000800000005001500008008004100023034007000064100002300134245002700157  2007620160513104939730000s1973    coAa          0  0  EL  d0 aad+155.34616323e+155.34616323f-7.8061926g-7.8061926zSite 3231 aGrizzell, Griselda10aTest Publication 2007600282naaa 2200097zu 4500001000800000005001500008008004100023034007200064100002100136245002700157  2007720160513104939730000s1973    coAa          0  0  EL  d0 aad-45.37116744e-45.37116744f-45.10756474g-45.10756474zSite 1551 aSharrow, Sherron10aTest Publication 2007700279naaa 2200097zu 4500001000800000005001500008008004100023034007200064100001800136245002700154  2007820160513104939730000s1973    coAa          0  0  EL  d0 aad-125.8758505e-125.8758505f+37.66553345g+37.66553345zSite 4951 aOverall, Lula10aTest Publication 2007800280naaa 2200097zu 4500001000800000005001500008008004100023034007200064100001900136245002700155  2007920160513104939730000s1973    coAa          0  0  EL  d0 aad-125.7131481e-125.7131481f-65.01937325g-65.01937325zSite 2721 aHersh, Sheldon10aTest Publication 2007900278naaa 2200097zu 4500001000800000005001500008008004100023034007200064100001700136245002700153  2008020160513104939730000s1973    coAa          0  0  EL  d0 aad-167.5160645e-167.5160645f+48.54645955g+48.54645955zSite 4591 aFouche, Hsiu10aTest Publication 2008000281naaa 2200097zu 4500001000800000005001500008008004100023034007400064100001800138245002700156  2008120160513104939730000s1973    coAa          0  0  EL  d0 aadE118.55522501eE118.55522501fS59.40043873gS59.40043873zSite 4161 aPerine, Alisa10aTest Publication 2008100280naaa 2200097zu 4500001000800000005001500008008004100023034007200064100001900136245002700155  2008220160513104939730000s1973    coAa          0  0  EL  d0 aadE19.95358751eE19.95358751fN66.64677012gN66.64677012zSite 4031 aWalter, Jasper10aTest Publication 2008200285naaa 2200097zu 4500001000800000005001500008008004100023034007200064100002400136245002700160  2008320160513104939730000s1973    coAa          0  0  EL  d0 aadW61.22077604eW61.22077604fS26.01320081gS26.01320081zSite 3771 aGreenblatt, Sherill10aTest Publication 2008300283naaa 2200097zu 4500001000800000005001500008008004100023034007200064100002200136245002700158  2008420160513104939730000s1973    coAa          0  0  EL  d0 aadW38.52101948eW38.52101948fN42.22226461gN42.22226461zSite 5481 aCrafts, Claudette10aTest Publication 2008400284naaa 2200097zu 4500001000800000005001500008008004100023034007400064100002100138245002700159  2008520160513104939730000s1973    coAa          0  0  EL  d0 aadE132.70789703eE132.70789703fN38.04866994gN38.04866994zSite 1881 aCounter, Modesto10aTest Publication 2008500281naaa 2200097zu 4500001000800000005001500008008004100023034007200064100002000136245002700156  2008620160513104939730000s1973    coAa          0  0  EL  d0 aadW89.35020317eW89.35020317fN47.93266336gN47.93266336zSite 3091 aCrowder, Carlee10aTest Publication 2008600280naaa 2200097zu 4500001000800000005001500008008004100023034007200064100001900136245002700155  2008720160513104939730000s1973    coAa          0  0  EL  d0 aadW125.32764205eW125.32764205fS4.19255958gS4.19255958zSite 3411 aJone, Federico10aTest Publication 2008700282naaa 2200097zu 4500001000800000005001500008008004100023034007200064100002100136245002700157  2008820160513104939730000s1973    coAa          0  0  EL  d0 aadW168.93025338eW168.93025338fS6.02872258gS6.02872258zSite 2641 aSchock, Lisandra10aTest Publication 2008800282naaa 2200097zu 4500001000800000005001500008008004100023034007000064100002300134245002700157  2008920160513104939730000s1973    coAa          0  0  EL  d0 aadW98.77347908eW98.77347908fS42.6798184gS42.6798184zSite 1191 aSpadaro, Geraldine10aTest Publication 2008900278naaa 2200097zu 4500001000800000005001500008008004100023034007000064100001900134245002700153  2009020160513104939730000s1973    coAa          0  0  EL  d0 aadE85.8591623eE85.8591623fN66.00524174gN66.00524174zSite 3251 aSwanson, Mario10aTest Publication 2009000286naaa 2200097zu 4500001000800000005001500008008004100023034007400064100002300138245002700161  2009120160513104939730000s1973    coAa          0  0  EL  d0 aadE137.11729029eE137.11729029fN39.84518323gN39.84518323zSite 1601 aCornforth, Desiree10aTest Publication 2009100276naaa 2200097zu 4500001000800000005001500008008004100023034007000064100001700134245002700151  2009220160513104939730000s1973    coAa          0  0  EL  d0 aadW65.3799254eW65.3799254fS46.40296668gS46.40296668zSite 3221 aLam, Cristen10aTest Publication 2009200283naaa 2200097zu 4500001000800000005001500008008004100023034007400064100002000138245002700158  2009320160513104939730000s1973    coAa          0  0  EL  d0 aadE176.53377147eE176.53377147fN22.77971971gN22.77971971zSite 3131 aFrankum, Thomas10aTest Publication 2009300284naaa 2200097zu 4500001000800000005001500008008004100023034007200064100002300136245002700159  2009420160513104939730000s1973    coAa          0  0  EL  d0 aadW27.45737117eW27.45737117fS55.67694086gS55.67694086zSite 3631 aMagallon, Christia10aTest Publication 2009400282naaa 2200097zu 4500001000800000005001500008008004100023034007400064100001900138245002700157  2009520160513104939730000s1973    coAa          0  0  EL  d0 aadE175.12324693eE175.12324693fS38.39888377gS38.39888377zSite 4401 aIverson, Beryl10aTest Publication 2009500274naaa 2200097zu 4500001000800000005001500008008004100023034007000064100001500134245002700149  2009620160513104939730000s1973    coAa          0  0  EL  d0 aadW23.4142272eW23.4142272fN29.80880028gN29.80880028zSite 3131 aOrtiz, Tia10aTest Publication 2009600276naaa 2200097zu 4500001000800000005001500008008004100023034007000064100001700134245002700151  2009720160513104939730000s1973    coAa          0  0  EL  d0 aadW18.33091801eW18.33091801fS6.31305738gS6.31305738zSite 3991 aBogard, Noma10aTest Publication 2009700281naaa 2200097zu 4500001000800000005001500008008004100023034007200064100002000136245002700156  2009820160513104939730000s1973    coAa          0  0  EL  d0 aadW72.31173246eW72.31173246fS46.75721273gS46.75721273zSite 3311 aWalston, Verlie10aTest Publication 2009800281naaa 2200097zu 4500001000800000005001500008008004100023034007200064100002000136245002700156  2009920160513104939730000s1973    coAa          0  0  EL  d0 aadW48.97356546eW48.97356546fN36.74731237gN36.74731237zSite 3291 aInnocent, Leisa10aTest Publication 2009900277naaa 2200097zu 4500001000800000005001500008008004100023034007200064100001600136245002700152  2010020160513104939730000s1973    coAa          0  0  EL  d0 aadW91.61595667eW91.61595667fN11.85462394gN11.85462394zSite 2661 aKohn, Clora10aTest Publication 2010000280naaa 2200097zu 4500001000800000005001500008008004100023034007200064100001900136245002700155  2010120160513104939730000s1973    coAa          0  0  EL  d0 aadW99.81880793eW99.81880793fN56.31339558gN56.31339558zSite 1271 aLinney, Samual10aTest Publication 2010100283naaa 2200097zu 4500001000800000005001500008008004100023034007400064100002000138245002700158  2010220160513104939730000s1973    coAa          0  0  EL  d0 aadW125.07883932eW125.07883932fS45.00178881gS45.00178881zSite 2591 aMerrifield, Kym10aTest Publication 2010200262naaa 2200097zu 4500001000800000005001500008008004100023034005400064100001900118245002700137  2010320160513104939730000s1973    coAa          0  0  EL  d0 aadE0362614eE0362614fS011543gS011543zSite 1811 aBucher, Margit10aTest Publication 2010300264naaa 2200097zu 4500001000800000005001500008008004100023034005400064100002100118245002700139  2010420160513104939730000s1973    coAa          0  0  EL  d0 aadE0181242eE0181242fS291354gS291354zSite 2271 aSteenberg, Shila10aTest Publication 2010400264naaa 2200097zu 4500001000800000005001500008008004100023034005400064100002100118245002700139  2010520160513104939730000s1973    coAa          0  0  EL  d0 aadE0983727eE0983727fN682744gN682744zSite 5311 aBlacker, Minerva10aTest Publication 2010500261naaa 2200097zu 4500001000800000005001500008008004100023034005400064100001800118245002700136  2010620160513104939730000s1973    coAa          0  0  EL  d0 aadE0963319eE0963319fN151338gN151338zSite 1301 aHanley, Karla10aTest Publication 2010600264naaa 2200097zu 4500001000800000005001500008008004100023034005400064100002100118245002700139  2010720160513104939730000s1973    coAa          0  0  EL  d0 aadW0753627eW0753627fN265359gN265359zSite 3661 aMackson, Yolanda10aTest Publication 2010700263naaa 2200097zu 4500001000800000005001500008008004100023034005400064100002000118245002700138  2010820160513104939730000s1973    coAa          0  0  EL  d0 aadE1792143eE1792143fS752257gS752257zSite 5231 aHarrill, Mariko10aTest Publication 2010800265naaa 2200097zu 4500001000800000005001500008008004100023034005400064100002200118245002700140  2010920160513104939730000s1973    coAa          0  0  EL  d0 aadW0953048eW0953048fS170735gS170735zSite 4021 aBehringer, Anitra10aTest Publication 2010900258naaa 2200097zu 4500001000800000005001500008008004100023034005400064100001500118245002700133  2011020160513104939730000s1973    coAa          0  0  EL  d0 aadW1184933eW1184933fN152720gN152720zSite 3511 aRowse, Ida10aTest Publication 2011000264naaa 2200097zu 4500001000800000005001500008008004100023034005400064100002100118245002700139  2011120160513104939730000s1973    coAa          0  0  EL  d0 aadW1374144eW1374144fS081546gS081546zSite 1531 aSutter, Katheryn10aTest Publication 2011100263naaa 2200097zu 4500001000800000005001500008008004100023034005400064100002000118245002700138  2011220160513104939730000s1973    coAa          0  0  EL  d0 aadW1705954eW1705954fS082612gS082612zSite 3541 aBeckett, Tamala10aTest Publication 2011200259naaa 2200097zu 4500001000800000005001500008008004100023034005400064100001600118245002700134  2011320160513104939730000s1973    coAa          0  0  EL  d0 aadE0783553eE0783553fS255532gS255532zSite 4171 aBetty, Eryn10aTest Publication 2011300265naaa 2200097zu 4500001000800000005001500008008004100023034005400064100002200118245002700140  2011420160513104939730000s1973    coAa          0  0  EL  d0 aadE1284246eE1284246fS020216gS020216zSite 2121 aLetsinger, Tamiko10aTest Publication 2011400267naaa 2200097zu 4500001000800000005001500008008004100023034005400064100002400118245002700142  2011520160513104939730000s1973    coAa          0  0  EL  d0 aadE0521421eE0521421fS022222gS022222zSite 4701 aCantrell, Cornelius10aTest Publication 2011500260naaa 2200097zu 4500001000800000005001500008008004100023034005400064100001700118245002700135  2011620160513104939730000s1973    coAa          0  0  EL  d0 aadE0331639eE0331639fS283049gS283049zSite 4771 aLeyva, Marie10aTest Publication 2011600265naaa 2200097zu 4500001000800000005001500008008004100023034005400064100002200118245002700140  2011720160513104939730000s1973    coAa          0  0  EL  d0 aadE0760744eE0760744fN480042gN480042zSite 4401 aBeveridge, Albina10aTest Publication 2011700261naaa 2200097zu 4500001000800000005001500008008004100023034005400064100001800118245002700136  2011820160513104939730000s1973    coAa          0  0  EL  d0 aadW0712539eW0712539fN295730gN295730zSite 5271 aBramhall, Ria10aTest Publication 2011800260naaa 2200097zu 4500001000800000005001500008008004100023034005400064100001700118245002700135  2011920160513104939730000s1973    coAa          0  0  EL  d0 aadE1681553eE1681553fN524510gN524510zSite 1391 aHurt, Millie10aTest Publication 2011900260naaa 2200097zu 4500001000800000005001500008008004100023034005400064100001700118245002700135  2012020160513104939730000s1973    coAa          0  0  EL  d0 aadW0140130eW0140130fS010120gS010120zSite 4641 aWulff, Nilsa10aTest Publication 2012000263naaa 2200097zu 4500001000800000005001500008008004100023034005400064100002000118245002700138  2012120160513104939730000s1973    coAa          0  0  EL  d0 aadW0782218eW0782218fS753724gS753724zSite 5041 aFirth, Theressa10aTest Publication 2012100263naaa 2200097zu 4500001000800000005001500008008004100023034005400064100002000118245002700138  2012220160513104939730000s1973    coAa          0  0  EL  d0 aadW1330422eW1330422fN034324gN034324zSite 4511 aWorster, Marita10aTest Publication 2012200265naaa 2200097zu 4500001000800000005001500008008004100023034005400064100002200118245002700140  2012320160513104939730000s1973    coAa          0  0  EL  d0 aadW0843206eW0843206fS553424gS553424zSite 2961 aOlveda, Jenniffer10aTest Publication 2012300263naaa 2200097zu 4500001000800000005001500008008004100023034005400064100002000118245002700138  2012420160513104939730000s1973    coAa          0  0  EL  d0 aadW1582630eW1582630fS142429gS142429zSite 2791 aMessner, Leanna10aTest Publication 2012400275naaa 2200097zu 4500001000800000005001500008008004100023034006900064100001700133245002700150  2012520160513104939730000s1973    coAa          0  0  EL  d0 aad-12.49085466e-7.49085466f+9.71187917g+4.71187917zSite 1731 aBevill, Sook10aTest Publication 2012500282naaa 2200097zu 4500001000800000005001500008008004100023034007200064100002100136245002700157  2012620160513104939730000s1973    coAa          0  0  EL  d0 aad+71.12605143e+81.12605143f+20.40214021g+10.40214021zSite 1211 aSchock, Lisandra10aTest Publication 2012600281naaa 2200097zu 4500001000800000005001500008008004100023034007400064100001800138245002700156  2012720160513104939730000s1973    coAa          0  0  EL  d0 aad+104.20929332e+154.20929332f+23.15670674g+13.15670674zSite 2831 aAbner, Shelli10aTest Publication 2012700282naaa 2200097zu 4500001000800000005001500008008004100023034007200064100002100136245002700157  2012820160513104939730000s1973    coAa          0  0  EL  d0 aad-130.3358613e-90.33586126f+54.37067475g+34.37067475zSite 3061 aNecessary, Dante10aTest Publication 2012800277naaa 2200097zu 4500001000800000005001500008008004100023034007300064100001500137245002700152  2012920160513104939730000s1973    coAa          0  0  EL  d0 aad+89.51162859e+109.51162859f-22.88853952g-42.88853952zSite 1271 aAmyx, Lyle10aTest Publication 2012900281naaa 2200097zu 4500001000800000005001500008008004100023034007400064100001800138245002700156  2013020160513104939730000s1973    coAa          0  0  EL  d0 aad+120.94552421e+130.94552421f+80.21089126g+77.21089126zSite 5191 aGranda, Isiah10aTest Publication 2013000280naaa 2200097zu 4500001000800000005001500008008004100023034007000064100002100134245002700155  2013120160513104939730000s1973    coAa          0  0  EL  d0 aad+166.31983556e+176.31983556f-64.114475g-74.114475zSite 1291 aFavela, Lorretta10aTest Publication 2013100277naaa 2200097zu 4500001000800000005001500008008004100023034007200064100001600136245002700152  2013220160513104939730000s1973    coAa          0  0  EL  d0 aad-33.35817709e-23.35817709f-26.04958019g-56.04958019zSite 3441 aDaub, Lloyd10aTest Publication 2013200278naaa 2200097zu 4500001000800000005001500008008004100023034007200064100001700136245002700153  2013320160513104939730000s1973    coAa          0  0  EL  d0 aad+100.28119821e+150.28119821f-39.5929073g-79.5929073zSite 2811 aFines, Gregg10aTest Publication 2013300279naaa 2200097zu 4500001000800000005001500008008004100023034006800064100002200132245002700154  2013420160513104939730000s1973    coAa          0  0  EL  d0 aad-98.724204e-38.72420401f+40.4924143g+20.4924143zSite 4941 aWalcott, Porfirio10aTest Publication 2013400280naaa 2200097zu 4500001000800000005001500008008004100023034007300064100001800137245002700155  2013520160513104939730000s1973    coAa          0  0  EL  d0 aad-170.45022257e-156.4502226f+25.08138959g+15.08138959zSite 4151 aGranda, Isiah10aTest Publication 2013500281naaa 2200097zu 4500001000800000005001500008008004100023034007300064100001900137245002700156  2013620160513104939730000s1973    coAa          0  0  EL  d0 aad+93.74890612e+143.74890612f-13.32263614g-23.32263614zSite 2561 aCutter, Annika10aTest Publication 2013600279naaa 2200097zu 4500001000800000005001500008008004100023034007200064100001800136245002700154  2013720160513104939730000s1973    coAa          0  0  EL  d0 aad-66.87358455e-46.87358455f+70.98897026g+50.98897026zSite 5431 aHanley, Karla10aTest Publication 2013700276naaa 2200097zu 4500001000800000005001500008008004100023034007000064100001700134245002700151  2013820160513104939730000s1973    coAa          0  0  EL  d0 aad-172.9265117e-162.9265117f-1.47082029g-6.47082029zSite 1691 aDalke, Isiah10aTest Publication 2013800281naaa 2200097zu 4500001000800000005001500008008004100023034007000064100002200134245002700156  2013920160513104939730000s1973    coAa          0  0  EL  d0 aad+33.61230501e+43.61230501f-4.12575355g-9.12575355zSite 3771 aBehringer, Anitra10aTest Publication 2013900281naaa 2200097zu 4500001000800000005001500008008004100023034007200064100002000136245002700156  2014020160513104939730000s1973    coAa          0  0  EL  d0 aad+75.10477259e+95.10477259f+73.86871739g+53.86871739zSite 2831 aWilhoite, Kathi10aTest Publication 2014000282naaa 2200097zu 4500001000800000005001500008008004100023034007400064100001900138245002700157  2014120160513104939730000s1973    coAa          0  0  EL  d0 aad+125.92523664e+135.92523664f-15.86550515g-25.86550515zSite 1841 aJasik, Micaela10aTest Publication 2014100283naaa 2200097zu 4500001000800000005001500008008004100023034007400064100002000138245002700158  2014220160513104939730000s1973    coAa          0  0  EL  d0 aad+112.65337661e+122.65337661f+78.04277975g+68.04277975zSite 5271 aStrine, Tabitha10aTest Publication 2014200276naaa 2200097zu 4500001000800000005001500008008004100023034006900064100001800133245002700151  2014320160513104939730000s1973    coAa          0  0  EL  d0 aad-10.83945484e-5.83945484f-30.6046605g-60.6046605zSite 1311 aOverall, Lula10aTest Publication 2014300279naaa 2200097zu 4500001000800000005001500008008004100023034007000064100002000134245002700154  2014420160513104939730000s1973    coAa          0  0  EL  d0 aad-15.53775937e-10.53775937f-46.3793589g-66.3793589zSite 2041 aMathisen, Dayle10aTest Publication 2014400281naaa 2200097zu 4500001000800000005001500008008004100023034007200064100002000136245002700156  2014520160513104939730000s1973    coAa          0  0  EL  d0 aad-147.1524264e-127.1524264f-70.97214091g-75.97214091zSite 4281 aWilhoite, Kathi10aTest Publication 2014500278naaa 2200097zu 4500001000800000005001500008008004100023034007200064100001700136245002700153  2014620160513104939730000s1973    coAa          0  0  EL  d0 aad+73.14760572e+93.14760572f-44.44305202g-64.44305202zSite 4881 aFines, Gregg10aTest Publication 2014600280naaa 2200097zu 4500001000800000005001500008008004100023034007400064100001700138245002700155  2014720160513104939730000s1973    coAa          0  0  EL  d0 aadE143.91680691eE153.91680691fN69.05928016gN59.05928016zSite 2301 aKinnan, Enda10aTest Publication 2014700281naaa 2200097zu 4500001000800000005001500008008004100023034007000064100002200134245002700156  2014820160513104939730000s1973    coAa          0  0  EL  d0 aadE109.2953057eE159.2953057fN75.6021786gN72.6021786zSite 2351 aHartfield, Shelba10aTest Publication 2014800282naaa 2200097zu 4500001000800000005001500008008004100023034007300064100002000137245002700157  2014920160513104939730000s1973    coAa          0  0  EL  d0 aadE144.81897837eE164.81897837fN18.62668817gN8.62668817zSite 2871 aSkeens, Cordell10aTest Publication 2014900278naaa 2200097zu 4500001000800000005001500008008004100023034007200064100001700136245002700153  2015020160513104939730000s1973    coAa          0  0  EL  d0 aadW115.49585203eW85.49585203fN19.56564384gN9.56564384zSite 4151 aHove, Armand10aTest Publication 2015000280naaa 2200097zu 4500001000800000005001500008008004100023034007200064100001900136245002700155  2015120160513104939730000s1973    coAa          0  0  EL  d0 aadW32.63289449eW22.63289449fS55.38513226gS75.38513226zSite 1201 aHaugh, Winford10aTest Publication 2015100279naaa 2200097zu 4500001000800000005001500008008004100023034007300064100001700137245002700154  2015220160513104939730000s1973    coAa          0  0  EL  d0 aadE87.77332672eE107.77332672fS54.25951534gS74.25951534zSite 3431 aValois, Arie10aTest Publication 2015200279naaa 2200097zu 4500001000800000005001500008008004100023034006800064100002200132245002700154  2015320160513104939730000s1973    coAa          0  0  EL  d0 aadW32.8377449eW22.8377449fS3.09135927gS8.09135927zSite 4141 aMcclaran, Kathern10aTest Publication 2015300277naaa 2200097zu 4500001000800000005001500008008004100023034007000064100001800134245002700152  2015420160513104939730000s1973    coAa          0  0  EL  d0 aadE34.4627201eE44.4627201fN23.51119899gN13.51119899zSite 3351 aHeinrich, See10aTest Publication 2015400282naaa 2200097zu 4500001000800000005001500008008004100023034007200064100002100136245002700157  2015520160513104939730000s1973    coAa          0  0  EL  d0 aadE11.25085415eE16.25085415fN62.44255328gN42.44255328zSite 3801 aSteenberg, Shila10aTest Publication 2015500278naaa 2200097zu 4500001000800000005001500008008004100023034007200064100001700136245002700153  2015620160513104939730000s1973    coAa          0  0  EL  d0 aadE35.02387108eE45.02387108fN51.72426854gN31.72426854zSite 1231 aNiccum, Alex10aTest Publication 2015600284naaa 2200097zu 4500001000800000005001500008008004100023034007400064100002100138245002700159  2015720160513104939730000s1973    coAa          0  0  EL  d0 aadE115.38134036eE145.38134036fS21.96462606gS41.96462606zSite 3801 aRussom, Clorinda10aTest Publication 2015700278naaa 2200097zu 4500001000800000005001500008008004100023034006600064100002300130245002700153  2015820160513104939730000s1973    coAa          0  0  EL  d0 aadW79.5685706eW59.5685706fS3.2186524gS8.2186524zSite 4461 aMontanye, Criselda10aTest Publication 2015800280naaa 2200097zu 4500001000800000005001500008008004100023034007200064100001900136245002700155  2015920160513104939730000s1973    coAa          0  0  EL  d0 aadE78.87843097eE98.87843097fS24.09348392gS44.09348392zSite 3721 aGalasso, Tatum10aTest Publication 2015900283naaa 2200097zu 4500001000800000005001500008008004100023034007400064100002000138245002700158  2016020160513104939730000s1973    coAa          0  0  EL  d0 aadW179.09659396eW119.09659396fS39.32213026gS79.32213026zSite 4631 aLiptak, Caitlin10aTest Publication 2016000282naaa 2200097zu 4500001000800000005001500008008004100023034007400064100001900138245002700157  2016120160513104939730000s1973    coAa          0  0  EL  d0 aadW163.27020238eW113.27020238fS36.75458726gS76.75458726zSite 1621 aGaetano, Dedra10aTest Publication 2016100261naaa 2200097zu 4500001000800000005001500008008004100023034005400064100001800118245002700136  2016220160513104939730000s1973    coAa          0  0  EL  d0 aadE1114626eE1214626fN752639gN452639zSite 4161 aTorian, Belva10aTest Publication 2016200262naaa 2200097zu 4500001000800000005001500008008004100023034005400064100001900118245002700137  2016320160513104939730000s1973    coAa          0  0  EL  d0 aadE0285018eE0335018fN271418gN171418zSite 2191 aMirabito, Shin10aTest Publication 2016300266naaa 2200097zu 4500001000800000005001500008008004100023034005400064100002300118245002700141  2016420160513104939730000s1973    coAa          0  0  EL  d0 aadE0330550eE0430550fN471910gN271910zSite 1651 aSpadaro, Geraldine10aTest Publication 2016400265naaa 2200097zu 4500001000800000005001500008008004100023034005400064100002200118245002700140  2016520160513104939730000s1973    coAa          0  0  EL  d0 aadW0501321eW0401321fN053851gN003851zSite 4651 aHartfield, Shelba10aTest Publication 2016500259naaa 2200097zu 4500001000800000005001500008008004100023034005400064100001600118245002700134  2016620160513104939730000s1973    coAa          0  0  EL  d0 aadE1541338eE1641338fS053823gS103823zSite 2621 aDaub, Lloyd10aTest Publication 2016600262naaa 2200097zu 4500001000800000005001500008008004100023034005400064100001900118245002700137  2016720160513104939730000s1973    coAa          0  0  EL  d0 aadW0722141eW0522141fS223403gS423403zSite 5141 aCutter, Annika10aTest Publication 2016700264naaa 2200097zu 4500001000800000005001500008008004100023034005400064100002100118245002700139  2016820160513104939730000s1973    coAa          0  0  EL  d0 aadW0053928eW0003928fS472308gS772308zSite 1971 aErickson, Joette10aTest Publication 2016800264naaa 2200097zu 4500001000800000005001500008008004100023034005400064100002100118245002700139  2016920160513104939730000s1973    coAa          0  0  EL  d0 aadW0675444eW0475444fN571945gN271945zSite 2791 aSharrow, Sherron10aTest Publication 2016900261naaa 2200097zu 4500001000800000005001500008008004100023034005400064100001800118245002700136  2017020160513104939730000s1973    coAa          0  0  EL  d0 aadE1064421eE1564421fN402522gN202522zSite 1701 aVidrio, Sofia10aTest Publication 2017000261naaa 2200097zu 4500001000800000005001500008008004100023034005400064100001800118245002700136  2017120160513104939730000s1973    coAa          0  0  EL  d0 aadW1254938eW0854938fN511735gN311735zSite 5101 aHeinrich, See10aTest Publication 2017100261naaa 2200097zu 4500001000800000005001500008008004100023034005400064100001800118245002700136  2017220160513104939730000s1973    coAa          0  0  EL  d0 aadW1344729eW0944729fN051424gN001424zSite 5111 aBoyland, Bebe10aTest Publication 2017200263naaa 2200097zu 4500001000800000005001500008008004100023034005400064100002000118245002700138  2017320160513104939730000s1973    coAa          0  0  EL  d0 aadE0932835eE1432835fS175621gS375621zSite 2151 aStrine, Tabitha10aTest Publication 2017300262naaa 2200097zu 4500001000800000005001500008008004100023034005400064100001900118245002700137  2017420160513104939730000s1973    coAa          0  0  EL  d0 aadE1701912eE1751912fS073104gS123104zSite 1931 aBornstein, Dia10aTest Publication 2017400266naaa 2200097zu 4500001000800000005001500008008004100023034005400064100002300118245002700141  2017520160513104939730000s1973    coAa          0  0  EL  d0 aadW1362047eW0962047fS250039gS550039zSite 4111 aGrizzell, Griselda10aTest Publication 2017500264naaa 2200097zu 4500001000800000005001500008008004100023034005400064100002100118245002700139  2017620160513104939730000s1973    coAa          0  0  EL  d0 aadW0545835eW0445835fS450010gS650010zSite 5091 aFalzone, Natasha10aTest Publication 2017600259naaa 2200097zu 4500001000800000005001500008008004100023034005400064100001600118245002700134  2017720160513104939730000s1973    coAa          0  0  EL  d0 aadE1455446eE1555446fS373045gS773045zSite 3521 aJaco, Angle10aTest Publication 20177
\ No newline at end of file
+00362naaa 2200109zu 4500001000800000005001500008008004100023034007400064034007000138100001700208245002700225  2000120160513104939730000s1973    coAa          0  0  EL  d0 aad+129.95348029e+129.95348029f-55.29356577g-55.29356577zSite 3740 aad+92.58856498e+92.58856498f+35.0285559g+35.0285559zSite 4511 aHurt, Millie10aTest Publication 2000100364naaa 2200109zu 4500001000800000005001500008008004100023034007000064034007200134100002100206245002700227  2000220160513104939730000s1973    coAa          0  0  EL  d0 aad+10.05908843e+10.05908843f-5.75031466g-5.75031466zSite 4400 aad+46.45283977e+46.45283977f+31.50720239g+31.50720239zSite 4471 aWinrow, Sanjuana10aTest Publication 2000200360naaa 2200109zu 4500001000800000005001500008008004100023034007200064034007200136100001500208245002700223  2000320160513104939730000s1973    coAa          0  0  EL  d0 aad-35.26826575e-35.26826575f+27.26620523g+27.26620523zSite 4000 aad-15.10285454e-15.10285454f+14.80524368g+14.80524368zSite 1631 aRudd, Jann10aTest Publication 2000300613naaa 2200145zu 4500001000800000005001500008008004100023034007200064034007200136034006600208034007400274034007200348100002000420245002700440  2000420160513104939730000s1973    coAa          0  0  EL  d0 aad-56.86690649e-56.86690649f+15.77554895g+15.77554895zSite 4790 aad+159.74574799e+159.74574799f-20.9661451g-20.9661451zSite 4340 aad+7.9676261e+7.9676261f+6.62658415g+6.62658415zSite 4480 aad+135.37478775e+135.37478775f+46.27024658g+46.27024658zSite 5530 aad-105.9279514e-105.9279514f+35.25445142g+35.25445142zSite 3061 aWalston, Verlie10aTest Publication 2000400526naaa 2200133zu 4500001000800000005001500008008004100023034007200064034007200136034006600208034007200274100001900346245002700365  2000520160513104939730000s1973    coAa          0  0  EL  d0 aad+83.63104693e+83.63104693f+21.46845472g+21.46845472zSite 3140 aad+156.17691966e+156.17691966f-9.22226407g-9.22226407zSite 1400 aad-7.6873641e-7.6873641f+49.3997425g+49.3997425zSite 1050 aad-85.11852582e-85.11852582f-32.54764684g-32.54764684zSite 2661 aPakele, Marina10aTest Publication 2000500365naaa 2200109zu 4500001000800000005001500008008004100023034007400064034007000138100002000208245002700228  2000620160513104939730000s1973    coAa          0  0  EL  d0 aadE119.53888243eE119.53888243fN62.91327942gN62.91327942zSite 2550 aadE67.8057745eE67.8057745fN36.44414008gN36.44414008zSite 5461 aMcglasson, Rich10aTest Publication 2000600627naaa 2200145zu 4500001000800000005001500008008004100023034007400064034007400138034007200212034007400284034007400358100002200432245002700454  2000720160513104939730000s1973    coAa          0  0  EL  d0 aadE121.59566053eE121.59566053fN23.86811097gN23.86811097zSite 3610 aadE151.51785078eE151.51785078fN13.91875447gN13.91875447zSite 1050 aadW86.72014286eW86.72014286fS10.73770388gS10.73770388zSite 4880 aadE134.89543887eE134.89543887fN25.94241103gN25.94241103zSite 2060 aadE161.78292166eE161.78292166fN10.15327259gN10.15327259zSite 3501 aRottman, Serafina10aTest Publication 2000700621naaa 2200145zu 4500001000800000005001500008008004100023034007400064034007400138034007200212034007200284034007200356100002000428245002700448  2000820160513104939730000s1973    coAa          0  0  EL  d0 aadW103.57340238eW103.57340238fS22.78804289gS22.78804289zSite 2170 aadW175.68166135eW175.68166135fS69.41361345gS69.41361345zSite 4970 aadE48.51599542eE48.51599542fS58.33629524gS58.33629524zSite 3550 aadE65.04196038eE65.04196038fN32.99243302gN32.99243302zSite 4860 aadW111.45384173eW111.45384173fS7.22546191gS7.22546191zSite 1131 aHaberle, Manuel10aTest Publication 2000800616naaa 2200145zu 4500001000800000005001500008008004100023034007000064034007000134034007400204034007200278034007000350100002300420245002700443  2000920160513104939730000s1973    coAa          0  0  EL  d0 aadE1.55144883eE1.55144883fS15.91268613gS15.91268613zSite 4710 aadE0.46771867eE0.46771867fS53.88776866gS53.88776866zSite 1390 aadE120.96526676eE120.96526676fN22.40092028gN22.40092028zSite 2390 aadW43.86881638eW43.86881638fS29.38831583gS29.38831583zSite 1970 aadW158.26944205eW158.26944205fS0.7378453gS0.7378453zSite 3941 aRuvalcaba, Letisha10aTest Publication 2000900326naaa 2200109zu 4500001000800000005001500008008004100023034005400064034005400118100001700172245002700189  2001020160513104939730000s1973    coAa          0  0  EL  d0 aadE0870709eE0870709fS065613gS065613zSite 1200 aadE1242258eE1242258fS110713gS110713zSite 2231 aBogard, Noma10aTest Publication 2001000525naaa 2200145zu 4500001000800000005001500008008004100023034005400064034005400118034005400172034005400226034005400280100001800334245002700352  2001120160513104939730000s1973    coAa          0  0  EL  d0 aadE0025331eE0025331fS493930gS493930zSite 3010 aadE0013038eE0013038fN444623gN444623zSite 1560 aadW0483141eW0483141fS452235gS452235zSite 4630 aadW0703406eW0703406fS373129gS373129zSite 3630 aadW1172630eW1172630fN661503gN661503zSite 3931 aPutman, Davis10aTest Publication 2001100526naaa 2200145zu 4500001000800000005001500008008004100023034005400064034005400118034005400172034005400226034005400280100001900334245002700353  2001220160513104939730000s1973    coAa          0  0  EL  d0 aadE1741450eE1741450fN154310gN154310zSite 5490 aadW0570821eW0570821fS415337gS415337zSite 2360 aadE1773647eE1773647fS330258gS330258zSite 4620 aadE0710915eE0710915fN400408gN400408zSite 3550 aadW0401638eW0401638fN093759gN093759zSite 5471 aBucher, Margit10aTest Publication 2001200528naaa 2200145zu 4500001000800000005001500008008004100023034005400064034005400118034005400172034005400226034005400280100002100334245002700355  2001320160513104939730000s1973    coAa          0  0  EL  d0 aadW1511513eW1511513fS055042gS055042zSite 1050 aadW1465931eW1465931fS261609gS261609zSite 4840 aadW0790538eW0790538fS512156gS512156zSite 5440 aadW1415343eW1415343fS185901gS185901zSite 4230 aadW1304431eW1304431fS502042gS502042zSite 1291 aDobyns, Wilfredo10aTest Publication 2001300463naaa 2200133zu 4500001000800000005001500008008004100023034005400064034005400118034005400172034005400226100002200280245002700302  2001420160513104939730000s1973    coAa          0  0  EL  d0 aadE1742335eE1742335fN191726gN191726zSite 2130 aadW1570705eW1570705fN435341gN435341zSite 5090 aadW1020233eW1020233fN203933gN203933zSite 2910 aadW1290413eW1290413fS691417gS691417zSite 2251 aMilbourne, Milton10aTest Publication 2001400328naaa 2200109zu 4500001000800000005001500008008004100023034005400064034005400118100001900172245002700191  2001520160513104939730000s1973    coAa          0  0  EL  d0 aadW0755517eW0755517fN151326gN151326zSite 3270 aadW0932259eW0932259fN020021gN020021zSite 1521 aMirsky, Dionna10aTest Publication 2001500536naaa 2200133zu 4500001000800000005001500008008004100023034007400064034007400138034007100212034007200283100002000355245002700375  2001620160513104939730000s1973    coAa          0  0  EL  d0 aad+100.64194149e+150.64194149f+76.29679349g+46.29679349zSite 3250 aad+140.41485857e+150.41485857f-59.57999928g-69.57999928zSite 1980 aad-14.23933962e-9.23933962f-27.72727724g-57.72727724zSite 3170 aad-175.1864435e-172.1864435f-10.03581345g-20.03581345zSite 1721 aInnocent, Leisa10aTest Publication 2001600615naaa 2200145zu 4500001000800000005001500008008004100023034006800064034007100132034007200203034007200275034007200347100002300419245002700442  2001720160513104939730000s1973    coAa          0  0  EL  d0 aad-165.6004414e-115.6004414f-14.509653g-24.509653zSite 2190 aad-172.2069375e-132.2069375f+10.76133978g+5.76133978zSite 2500 aad-162.8898108e-142.8898108f-15.07237354g-25.07237354zSite 5040 aad+71.03685744e+81.03685744f-66.09831516g-76.09831516zSite 1810 aad-160.1490595e-140.1490595f+68.15731704g+58.15731704zSite 4201 aCornforth, Desiree10aTest Publication 2001700613naaa 2200145zu 4500001000800000005001500008008004100023034007000064034007200134034007000206034007200276034007300348100001900421245002700440  2001820160513104939730000s1973    coAa          0  0  EL  d0 aad-91.5895638e-61.5895638f+74.14618546g+44.14618546zSite 1140 aad+64.41336345e+74.41336345f+79.74325176g+49.74325176zSite 1270 aad-7.44081494e-2.44081494f+68.18607023g+58.18607023zSite 1210 aad-170.1177443e-130.1177443f-63.43626229g-73.43626229zSite 4440 aad+95.39073945e+145.39073945f+42.45583955g+22.45583955zSite 2461 aKarter, Marvis10aTest Publication 2001800441naaa 2200121zu 4500001000800000005001500008008004100023034006800064034007000132034007200202100001800274245002700292  2001920160513104939730000s1973    coAa          0  0  EL  d0 aad+10.5670584e+15.5670584f-21.6083379g-41.6083379zSite 2070 aad+41.53787448e+51.53787448f+77.9847143g+57.9847143zSite 5480 aad+129.0839142e+139.0839142f+78.85096117g+68.85096117zSite 2721 aClaro, Bobbie10aTest Publication 2001900620naaa 2200145zu 4500001000800000005001500008008004100023034007400064034006900138034007200207034007400279034007400353100002000427245002700447  2002020160513104939730000s1973    coAa          0  0  EL  d0 aadW163.70412537eW143.70412537fN23.98046062gN13.98046062zSite 2460 aadW37.45857716eW27.45857716fN11.7990193gN6.7990193zSite 4110 aadW92.34562344eW62.34562344fS25.81496714gS55.81496714zSite 4880 aadE144.53537717eE174.53537717fS28.13599649gS58.13599649zSite 5160 aadW177.82278613eW117.82278613fS32.33211767gS62.33211767zSite 2831 aBeckett, Tamala10aTest Publication 2002000364naaa 2200109zu 4500001000800000005001500008008004100023034007400064034007200138100001700210245002700227  2002120160513104939730000s1973    coAa          0  0  EL  d0 aadE114.22094565eE144.22094565fS37.22983935gS77.22983935zSite 4160 aadW167.75647806eW147.75647806fN8.67140253gN3.67140253zSite 3961 aLam, Cristen10aTest Publication 2002100528naaa 2200133zu 4500001000800000005001500008008004100023034007200064034007200136034007200208034007000280100001700350245002700367  2002220160513104939730000s1973    coAa          0  0  EL  d0 aadW97.44010063eW67.44010063fN69.57202273gN39.57202273zSite 3650 aadW79.40943037eW59.40943037fN63.76345804gN43.76345804zSite 2300 aadW103.46816014eW73.46816014fS9.60188743gS14.60188743zSite 2350 aadW16.35276413eW11.35276413fS4.27200773gS9.27200773zSite 2451 aDalke, Isiah10aTest Publication 2002200618naaa 2200145zu 4500001000800000005001500008008004100023034007400064034007200138034007400210034007200284034007400356100001500430245002700445  2002320160513104939730000s1973    coAa          0  0  EL  d0 aadE127.23972147eE137.23972147fN63.12317768gN43.12317768zSite 2080 aadE129.15557267eE149.15557267fN45.7443194gN25.7443194zSite 1020 aadW151.73434552eW101.73434552fS55.73496457gS75.73496457zSite 1080 aadE54.94955124eE64.94955124fS34.71609174gS64.71609174zSite 5370 aadE106.81774118eE156.81774118fS29.05905321gS59.05905321zSite 4111 aOram, Donn10aTest Publication 2002300367naaa 2200109zu 4500001000800000005001500008008004100023034007400064034007100138100002100209245002700230  2002420160513104939730000s1973    coAa          0  0  EL  d0 aadE129.86022987eE149.86022987fN51.68020143gN31.68020143zSite 4760 aadE5.86815575eE15.86815575fN60.95617804gN40.95617804zSite 1761 aRupp, Georgeanna10aTest Publication 2002400450naaa 2200121zu 4500001000800000005001500008008004100023034007400064034007200138034007200210100001900282245002700301  2002520160513104939730000s1973    coAa          0  0  EL  d0 aadW156.11673622eW106.11673622fN78.32587133gN68.32587133zSite 3370 aadE47.92289733eE57.92289733fN77.17739015gN67.17739015zSite 1040 aadW32.89273609eW22.89273609fS40.70960814gS60.70960814zSite 4531 aWalter, Jasper10aTest Publication 2002500532naaa 2200133zu 4500001000800000005001500008008004100023034007300064034007400137034007300211034006800284100001900352245002700371  2002620160513104939730000s1973    coAa          0  0  EL  d0 aadE96.70798372eE146.70798372fN54.00011075gN34.00011075zSite 2710 aadE145.51684204eE165.51684204fN27.98976019gN17.98976019zSite 2660 aadW106.32772299eW76.32772299fN46.24201475gN26.24201475zSite 2860 aadE20.1511411eE25.1511411fN6.07910182gN1.07910182zSite 2421 aHultgren, Josh10aTest Publication 2002600328naaa 2200109zu 4500001000800000005001500008008004100023034005400064034005400118100001900172245002700191  2002720160513104939730000s1973    coAa          0  0  EL  d0 aadW0170403eW0120403fN755211gN455211zSite 4560 aadW1740209eW1340209fN794749gN694749zSite 3851 aGalasso, Tatum10aTest Publication 2002700333naaa 2200109zu 4500001000800000005001500008008004100023034005400064034005400118100002400172245002700196  2002820160513104939730000s1973    coAa          0  0  EL  d0 aadE0710106eE0810106fS111308gS211308zSite 5310 aadE0132703eE0182703fN541236gN341236zSite 3481 aCantrell, Cornelius10aTest Publication 2002800399naaa 2200121zu 4500001000800000005001500008008004100023034005400064034005400118034005400172100002400226245002700250  2002920160513104939730000s1973    coAa          0  0  EL  d0 aadW1693838eW1193838fN122531gN072531zSite 4150 aadE0844331eE1044331fS693723gS793723zSite 1320 aadE0062611eE0162611fN681512gN381512zSite 5031 aGreenblatt, Sherill10aTest Publication 2002900327naaa 2200109zu 4500001000800000005001500008008004100023034005400064034005400118100001800172245002700190  2003020160513104939730000s1973    coAa          0  0  EL  d0 aadE1053451eE1553451fS183256gS383256zSite 2870 aadE0830412eE1030412fS174644gS374644zSite 1801 aPerine, Alisa10aTest Publication 2003000393naaa 2200121zu 4500001000800000005001500008008004100023034005400064034005400118034005400172100001800226245002700244  2003120160513104939730000s1973    coAa          0  0  EL  d0 aadE0202657eE0252657fS470042gS770042zSite 2360 aadW1594422eW1094422fS562802gS762802zSite 4950 aadW0254325eW0204325fS591429gS691429zSite 3241 aSuen, Lanette10aTest Publication 2003100460naaa 2200133zu 4500001000800000005001500008008004100023034005400064034005400118034005400172034005400226100001900280245002700299  2003220160513104939730000s1973    coAa          0  0  EL  d0 aadW1331944eW0931944fN402114gN202114zSite 3060 aadW1780423eW1700423fN584511gN284511zSite 4340 aadW1600712eW1500712fN454326gN254326zSite 3810 aadW1752336eW1652336fN731737gN631737zSite 5211 aIverson, Beryl10aTest Publication 2003200459naaa 2200133zu 4500001000800000005001500008008004100023034005400064034005400118034005400172034005400226100001800280245002700298  2003320160513104939730000s1973    coAa          0  0  EL  d0 aadE1423151eE1523151fS521748gS721748zSite 2580 aadW1691508eW1391508fS131306gS231306zSite 5220 aadE1345235eE1745235fS630056gS730056zSite 3540 aadW1640324eW1140324fS330005gS630005zSite 1441 aBoyland, Bebe10aTest Publication 2003300394naaa 2200121zu 4500001000800000005001500008008004100023034005400064034005400118034005400172100001900226245002700245  2003420160513104939730000s1973    coAa          0  0  EL  d0 aadE1590126eE1690126fS341136gS641136zSite 3030 aadW1054117eW0754117fS354552gS754552zSite 3730 aadW0994125eW0694125fS434119gS634119zSite 3551 aArechiga, Moon10aTest Publication 2003400457naaa 2200133zu 4500001000800000005001500008008004100023034005400064034005400118034005400172034005400226100001600280245002700296  2003520160513104939730000s1973    coAa          0  0  EL  d0 aadW1405617eW1205617fS555856gS755856zSite 4800 aadE1073429eE1573429fS022601gS072601zSite 3730 aadE0913431eE1011343fS422933gS622933zSite 5360 aadE1131855eE1231855fS682514gS782514zSite 3241 aRozar, Josh10aTest Publication 2003500521naaa 2200133zu 4500001000800000005001500008008004100023034006800064034007200132034006800204034007000272100001800342245002700360  2003620160513104939730000s1973    coAa          0  0  EL  d0 aad-169.415256e-169.415256f+29.8815696g+29.8815696zSite 5600 aad-151.5560527e-151.5560527f-36.13307132g-36.13307132zSite 2020 aad-87.4479458e-87.4479458f+9.11816125g+9.11816125zSite 5400 aad-149.4183832e-149.4183832f+29.1541857g+29.1541857zSite 5571 aGuynn, Mayola10aTest Publication 2003600366naaa 2200109zu 4500001000800000005001500008008004100023034007200064034007200136100002100208245002700229  2003720160513104939730000s1973    coAa          0  0  EL  d0 aad+86.55263228e+86.55263228f-28.95862432g-28.95862432zSite 1680 aad-149.3464366e-129.3464366f+27.28202333g+17.28202333zSite 1341 aEngelhard, Marco10aTest Publication 2003700366naaa 2200109zu 4500001000800000005001500008008004100023034007400064034007200138100001900210245002700229  2003820160513104939730000s1973    coAa          0  0  EL  d0 aad+118.90296884e+118.90296884f+27.65389383g+27.65389383zSite 3970 aad-135.3498909e-95.34989087f+60.71524151g+40.71524151zSite 2231 aBornstein, Dia10aTest Publication 2003800363naaa 2200109zu 4500001000800000005001500008008004100023034007000064034007200134100002000206245002700226  2003920160513104939730000s1973    coAa          0  0  EL  d0 aad+15.7081159e+15.7081159f+10.51847859g+10.51847859zSite 1540 aad-65.34590317e-45.34590317f-16.22908424g-36.22908424zSite 4341 aMathisen, Dayle10aTest Publication 2003900356naaa 2200109zu 4500001000800000005001500008008004100023034007000064034007000134100001500204245002700219  2004020160513104939730000s1973    coAa          0  0  EL  d0 aad+120.07557262e+120.07557262f-7.8300017g-7.8300017zSite 4600 aad-78.33685724e-58.33685724f-20.7677353g-40.7677353zSite 3351 aOrtiz, Tia10aTest Publication 2004000370naaa 2200109zu 4500001000800000005001500008008004100023034007400064034007200138100002300210245002700233  2004120160513104939730000s1973    coAa          0  0  EL  d0 aad+179.11624407e+179.11624407f+49.45597061g+49.45597061zSite 1290 aad+18.65135762e+23.65135762f+75.67582839g+65.67582839zSite 3251 aSteffensen, Bianca10aTest Publication 2004100365naaa 2200109zu 4500001000800000005001500008008004100023034007200064034007200136100002000208245002700228  2004220160513104939730000s1973    coAa          0  0  EL  d0 aad-69.44473478e-69.44473478f+16.37800971g+16.37800971zSite 5180 aad-31.50294667e-21.50294667f-31.33882964g-61.33882964zSite 3511 aLaurich, Stuart10aTest Publication 2004200369naaa 2200109zu 4500001000800000005001500008008004100023034007400064034007200138100002200210245002700232  2004320160513104939730000s1973    coAa          0  0  EL  d0 aad+154.29238217e+154.29238217f-50.92756335g-50.92756335zSite 2970 aad-66.00381134e-46.00381134f-41.48033844g-61.48033844zSite 1781 aBeveridge, Albina10aTest Publication 2004300367naaa 2200109zu 4500001000800000005001500008008004100023034007000064034007400134100002200208245002700230  2004420160513104939730000s1973    coAa          0  0  EL  d0 aadE24.1857034eE24.1857034fS66.87278415gS66.87278415zSite 1290 aadW166.03284101eW156.03284101fN65.01324719gN35.01324719zSite 3991 aLetsinger, Tamiko10aTest Publication 2004400366naaa 2200109zu 4500001000800000005001500008008004100023034007000064034007400134100002100208245002700229  2004520160513104939730000s1973    coAa          0  0  EL  d0 aadE25.0293899eE25.0293899fS12.28047561gS12.28047561zSite 5060 aadW169.45170238eW119.45170238fN38.14274122gN18.14274122zSite 1251 aCounter, Modesto10aTest Publication 2004500531naaa 2200133zu 4500001000800000005001500008008004100023034007200064034007200136034007200208034007300280100001700353245002700370  2004620160513104939730000s1973    coAa          0  0  EL  d0 aadE86.99902059eE86.99902059fS41.27856855gS41.27856855zSite 3990 aadE133.71880822eE143.71880822fN8.13138602gN3.13138602zSite 4030 aadE171.49599516eE171.49599516fS56.3556026gS56.3556026zSite 1530 aadE119.63111094eE169.63111094fN11.62690851gN6.62690851zSite 1201 aValois, Arie10aTest Publication 2004600528naaa 2200133zu 4500001000800000005001500008008004100023034006800064034007200132034007200204034007400276100001700350245002700367  2004720160513104939730000s1973    coAa          0  0  EL  d0 aadW23.6918351eW23.6918351fN5.50055924gN5.50055924zSite 4950 aadW71.72678006eW51.72678006fN80.68048573gN72.68048573zSite 4190 aadW72.47081023eW72.47081023fS13.50689659gS13.50689659zSite 5050 aadW159.51582506eW109.51582506fS12.01041499gS22.01041499zSite 3211 aGiard, Dodie10aTest Publication 2004700364naaa 2200109zu 4500001000800000005001500008008004100023034007200064034007200136100001900208245002700227  2004820160513104939730000s1973    coAa          0  0  EL  d0 aadW98.39221287eW98.39221287fN20.00645186gN20.00645186zSite 1400 aadW35.22129012eW25.22129012fS11.27828226gS21.27828226zSite 1821 aDryer, Verlene10aTest Publication 2004800365naaa 2200109zu 4500001000800000005001500008008004100023034007400064034007400138100001600212245002700228  2004920160513104939730000s1973    coAa          0  0  EL  d0 aadW126.87139449eW126.87139449fS18.74530167gS18.74530167zSite 4470 aadW159.94018465eW109.94018465fS57.54337933gS67.54337933zSite 4601 aKohn, Clora10aTest Publication 2004900366naaa 2200109zu 4500001000800000005001500008008004100023034007200064034007200136100002100208245002700229  2005020160513104939730000s1973    coAa          0  0  EL  d0 aadW159.88627958eW109.88627958fS3.02307754gS8.02307754zSite 3560 aadE109.5707309eE119.5707309fS48.38262915gS78.38262915zSite 5401 aSutter, Katheryn10aTest Publication 2005000358naaa 2200109zu 4500001000800000005001500008008004100023034007000064034007000134100001700204245002700221  2005120160513104939730000s1973    coAa          0  0  EL  d0 aadE19.87166027eE24.87166027fS35.8561532gS75.8561532zSite 3760 aadE71.3886803eE81.3886803fS25.17975703gS55.17975703zSite 1071 aWalberg, Pia10aTest Publication 2005100590naaa 2200157zu 4500001000800000005001500008008004100023034005400064034005400118034005400172034005400226034005400280034005400334100001700388245002700405  2005220160513104939730000s1973    coAa          0  0  EL  d0 aadE0475840eE0475840fN315244gN315244zSite 3620 aadE0250120eE0250120fS051344gS051344zSite 4610 aadE0392838eE0392838fN123637gN123637zSite 3470 aadW0041819eW0041819fN670212gN670212zSite 3540 aadW0514641eW0514641fS325055gS325055zSite 5520 aadW0532607eW0432607fN401312gN201312zSite 2221 aHove, Armand10aTest Publication 2005200329naaa 2200109zu 4500001000800000005001500008008004100023034005400064034005400118100002000172245002700192  2005320160513104939730000s1973    coAa          0  0  EL  d0 aadW0670504eW0670504fS394806gS394806zSite 3640 aadW0380213eW0280213fN411500gN211500zSite 1091 aWestray, Shizue10aTest Publication 2005300326naaa 2200109zu 4500001000800000005001500008008004100023034005400064034005400118100001700172245002700189  2005420160513104939730000s1973    coAa          0  0  EL  d0 aadW0254536eW0254536fS244501gS244501zSite 2570 aadW0934339eW0634339fN451934gN251934zSite 5111 aOros, Cierra10aTest Publication 2005400330naaa 2200109zu 4500001000800000005001500008008004100023034005400064034005400118100002100172245002700193  2005520160513104939730000s1973    coAa          0  0  EL  d0 aadW1652138eW1652138fN004809gN004809zSite 3750 aadE0435513eE0535513fN510216gN310216zSite 2421 aBlacker, Minerva10aTest Publication 2005500329naaa 2200109zu 4500001000800000005001500008008004100023034005400064034005400118100002000172245002700192  2005620160513104939730000s1973    coAa          0  0  EL  d0 aadW1043920eW1043920fS011057gS011057zSite 2450 aadW0234238eW0184238fN682608gN382608zSite 4221 aLaurich, Stuart10aTest Publication 2005600328naaa 2200109zu 4500001000800000005001500008008004100023034005400064034005400118100001900172245002700191  2005720160513104939730000s1973    coAa          0  0  EL  d0 aadW1722040eW1722040fS352841gS352841zSite 2820 aadW1665858eW1565858fN683913gN383913zSite 1871 aKarter, Marvis10aTest Publication 2005700264naaa 2200097zu 4500001000800000005001500008008004100023034005400064100002100118245002700139  2005820160513104939730000s1973    coAa          0  0  EL  d0 aadW0981303eW0981303fN194221gN194221zSite 1021 aFavela, Lorretta10aTest Publication 2005800262naaa 2200097zu 4500001000800000005001500008008004100023034005400064100001900118245002700137  2005920160513104939730000s1973    coAa          0  0  EL  d0 aadW1612904eW1412904fS130045gS230045zSite 4881 aHultgren, Josh10aTest Publication 2005900327naaa 2200109zu 4500001000800000005001500008008004100023034005400064034005400118100001800172245002700190  2006020160513104939730000s1973    coAa          0  0  EL  d0 aadW0960543eW0960543fS052755gS052755zSite 5170 aadW1062423eW0762423fN181516gN081516zSite 1581 aMain, Neville10aTest Publication 2006000326naaa 2200109zu 4500001000800000005001500008008004100023034005400064034005400118100001700172245002700189  2006120160513104939730000s1973    coAa          0  0  EL  d0 aadW1681205eW1681205fN335749gN335749zSite 1440 aadW1684935eW1384935fS551611gS751611zSite 2101 aShaw, Denice10aTest Publication 2006100278naaa 2200097zu 4500001000800000005001500008008004100023034007000064100001900134245002700153  2006220160513104939730000s1973    coAa          0  0  EL  d0 aad+72.62860542e+72.62860542f-50.0640401g-50.0640401zSite 3861 aJasik, Micaela10aTest Publication 2006200280naaa 2200097zu 4500001000800000005001500008008004100023034007000064100002100134245002700155  2006320160513104939730000s1973    coAa          0  0  EL  d0 aad+79.53785174e+79.53785174f+6.56562911g+6.56562911zSite 1381 aRupp, Georgeanna10aTest Publication 2006300277naaa 2200097zu 4500001000800000005001500008008004100023034007200064100001600136245002700152  2006420160513104939730000s1973    coAa          0  0  EL  d0 aad+91.40655977e+91.40655977f-68.68188538g-68.68188538zSite 3761 aSears, Meri10aTest Publication 2006400280naaa 2200097zu 4500001000800000005001500008008004100023034007000064100002100134245002700155  2006520160513104939730000s1973    coAa          0  0  EL  d0 aad+90.5240303e+90.5240303f+16.31382075g+16.31382075zSite 2991 aWinrow, Sanjuana10aTest Publication 2006500279naaa 2200097zu 4500001000800000005001500008008004100023034007000064100002000134245002700154  2006620160513104939730000s1973    coAa          0  0  EL  d0 aad+51.37763177e+51.37763177f+0.65207263g+0.65207263zSite 4471 aSutter, Karolyn10aTest Publication 2006600280naaa 2200097zu 4500001000800000005001500008008004100023034007200064100001900136245002700155  2006720160513104939730000s1973    coAa          0  0  EL  d0 aad+173.34512334e+173.34512334f+28.0049181g+28.0049181zSite 1541 aArechiga, Moon10aTest Publication 2006700277naaa 2200097zu 4500001000800000005001500008008004100023034007200064100001600136245002700152  2006820160513104939730000s1973    coAa          0  0  EL  d0 aad-15.99213608e-15.99213608f+13.65438911g+13.65438911zSite 4251 aSaar, Danna10aTest Publication 2006800280naaa 2200097zu 4500001000800000005001500008008004100023034007200064100001900136245002700155  2006920160513104939730000s1973    coAa          0  0  EL  d0 aad+137.98717735e+137.98717735f-65.0442013g-65.0442013zSite 1001 aMirabito, Shin10aTest Publication 2006900278naaa 2200097zu 4500001000800000005001500008008004100023034007200064100001700136245002700153  2007020160513104939730000s1973    coAa          0  0  EL  d0 aad-117.4711533e-117.4711533f+38.23863124g+38.23863124zSite 3651 aWalberg, Pia10aTest Publication 2007000282naaa 2200097zu 4500001000800000005001500008008004100023034007200064100002100136245002700157  2007120160513104939730000s1973    coAa          0  0  EL  d0 aad+95.03142217e+95.03142217f-14.54137057g-14.54137057zSite 2361 aBalicki, Nicolas10aTest Publication 2007100276naaa 2200097zu 4500001000800000005001500008008004100023034007200064100001500136245002700151  2007220160513104939730000s1973    coAa          0  0  EL  d0 aad+34.55902657e+34.55902657f-27.96661882g-27.96661882zSite 5541 aOram, Donn10aTest Publication 2007200279naaa 2200097zu 4500001000800000005001500008008004100023034007200064100001800136245002700154  2007320160513104939730000s1973    coAa          0  0  EL  d0 aad+125.34051527e+125.34051527f+9.81883652g+9.81883652zSite 1211 aMurden, Claud10aTest Publication 2007300279naaa 2200097zu 4500001000800000005001500008008004100023034007400064100001600138245002700154  2007420160513104939730000s1973    coAa          0  0  EL  d0 aad+110.92377605e+110.92377605f+31.06593861g+31.06593861zSite 4421 aPerla, Jong10aTest Publication 2007400284naaa 2200097zu 4500001000800000005001500008008004100023034007400064100002100138245002700159  2007520160513104939730000s1973    coAa          0  0  EL  d0 aad+111.98924724e+111.98924724f+52.12174162g+52.12174162zSite 1501 aDobyns, Wilfredo10aTest Publication 2007500282naaa 2200097zu 4500001000800000005001500008008004100023034007000064100002300134245002700157  2007620160513104939730000s1973    coAa          0  0  EL  d0 aad+155.34616323e+155.34616323f-7.8061926g-7.8061926zSite 3231 aGrizzell, Griselda10aTest Publication 2007600282naaa 2200097zu 4500001000800000005001500008008004100023034007200064100002100136245002700157  2007720160513104939730000s1973    coAa          0  0  EL  d0 aad-45.37116744e-45.37116744f-45.10756474g-45.10756474zSite 1551 aSharrow, Sherron10aTest Publication 2007700279naaa 2200097zu 4500001000800000005001500008008004100023034007200064100001800136245002700154  2007820160513104939730000s1973    coAa          0  0  EL  d0 aad-125.8758505e-125.8758505f+37.66553345g+37.66553345zSite 4951 aOverall, Lula10aTest Publication 2007800280naaa 2200097zu 4500001000800000005001500008008004100023034007200064100001900136245002700155  2007920160513104939730000s1973    coAa          0  0  EL  d0 aad-125.7131481e-125.7131481f-65.01937325g-65.01937325zSite 2721 aHersh, Sheldon10aTest Publication 2007900278naaa 2200097zu 4500001000800000005001500008008004100023034007200064100001700136245002700153  2008020160513104939730000s1973    coAa          0  0  EL  d0 aad-167.5160645e-167.5160645f+48.54645955g+48.54645955zSite 4591 aFouche, Hsiu10aTest Publication 2008000281naaa 2200097zu 4500001000800000005001500008008004100023034007400064100001800138245002700156  2008120160513104939730000s1973    coAa          0  0  EL  d0 aadE118.55522501eE118.55522501fS59.40043873gS59.40043873zSite 4161 aPerine, Alisa10aTest Publication 2008100280naaa 2200097zu 4500001000800000005001500008008004100023034007200064100001900136245002700155  2008220160513104939730000s1973    coAa          0  0  EL  d0 aadE19.95358751eE19.95358751fN66.64677012gN66.64677012zSite 4031 aWalter, Jasper10aTest Publication 2008200285naaa 2200097zu 4500001000800000005001500008008004100023034007200064100002400136245002700160  2008320160513104939730000s1973    coAa          0  0  EL  d0 aadW61.22077604eW61.22077604fS26.01320081gS26.01320081zSite 3771 aGreenblatt, Sherill10aTest Publication 2008300283naaa 2200097zu 4500001000800000005001500008008004100023034007200064100002200136245002700158  2008420160513104939730000s1973    coAa          0  0  EL  d0 aadW38.52101948eW38.52101948fN42.22226461gN42.22226461zSite 5481 aCrafts, Claudette10aTest Publication 2008400284naaa 2200097zu 4500001000800000005001500008008004100023034007400064100002100138245002700159  2008520160513104939730000s1973    coAa          0  0  EL  d0 aadE132.70789703eE132.70789703fN38.04866994gN38.04866994zSite 1881 aCounter, Modesto10aTest Publication 2008500281naaa 2200097zu 4500001000800000005001500008008004100023034007200064100002000136245002700156  2008620160513104939730000s1973    coAa          0  0  EL  d0 aadW89.35020317eW89.35020317fN47.93266336gN47.93266336zSite 3091 aCrowder, Carlee10aTest Publication 2008600280naaa 2200097zu 4500001000800000005001500008008004100023034007200064100001900136245002700155  2008720160513104939730000s1973    coAa          0  0  EL  d0 aadW125.32764205eW125.32764205fS4.19255958gS4.19255958zSite 3411 aJone, Federico10aTest Publication 2008700282naaa 2200097zu 4500001000800000005001500008008004100023034007200064100002100136245002700157  2008820160513104939730000s1973    coAa          0  0  EL  d0 aadW168.93025338eW168.93025338fS6.02872258gS6.02872258zSite 2641 aSchock, Lisandra10aTest Publication 2008800282naaa 2200097zu 4500001000800000005001500008008004100023034007000064100002300134245002700157  2008920160513104939730000s1973    coAa          0  0  EL  d0 aadW98.77347908eW98.77347908fS42.6798184gS42.6798184zSite 1191 aSpadaro, Geraldine10aTest Publication 2008900278naaa 2200097zu 4500001000800000005001500008008004100023034007000064100001900134245002700153  2009020160513104939730000s1973    coAa          0  0  EL  d0 aadE85.8591623eE85.8591623fN66.00524174gN66.00524174zSite 3251 aSwanson, Mario10aTest Publication 2009000286naaa 2200097zu 4500001000800000005001500008008004100023034007400064100002300138245002700161  2009120160513104939730000s1973    coAa          0  0  EL  d0 aadE137.11729029eE137.11729029fN39.84518323gN39.84518323zSite 1601 aCornforth, Desiree10aTest Publication 2009100276naaa 2200097zu 4500001000800000005001500008008004100023034007000064100001700134245002700151  2009220160513104939730000s1973    coAa          0  0  EL  d0 aadW65.3799254eW65.3799254fS46.40296668gS46.40296668zSite 3221 aLam, Cristen10aTest Publication 2009200283naaa 2200097zu 4500001000800000005001500008008004100023034007400064100002000138245002700158  2009320160513104939730000s1973    coAa          0  0  EL  d0 aadE176.53377147eE176.53377147fN22.77971971gN22.77971971zSite 3131 aFrankum, Thomas10aTest Publication 2009300284naaa 2200097zu 4500001000800000005001500008008004100023034007200064100002300136245002700159  2009420160513104939730000s1973    coAa          0  0  EL  d0 aadW27.45737117eW27.45737117fS55.67694086gS55.67694086zSite 3631 aMagallon, Christia10aTest Publication 2009400282naaa 2200097zu 4500001000800000005001500008008004100023034007400064100001900138245002700157  2009520160513104939730000s1973    coAa          0  0  EL  d0 aadE175.12324693eE175.12324693fS38.39888377gS38.39888377zSite 4401 aIverson, Beryl10aTest Publication 2009500274naaa 2200097zu 4500001000800000005001500008008004100023034007000064100001500134245002700149  2009620160513104939730000s1973    coAa          0  0  EL  d0 aadW23.4142272eW23.4142272fN29.80880028gN29.80880028zSite 3131 aOrtiz, Tia10aTest Publication 2009600276naaa 2200097zu 4500001000800000005001500008008004100023034007000064100001700134245002700151  2009720160513104939730000s1973    coAa          0  0  EL  d0 aadW18.33091801eW18.33091801fS6.31305738gS6.31305738zSite 3991 aBogard, Noma10aTest Publication 2009700281naaa 2200097zu 4500001000800000005001500008008004100023034007200064100002000136245002700156  2009820160513104939730000s1973    coAa          0  0  EL  d0 aadW72.31173246eW72.31173246fS46.75721273gS46.75721273zSite 3311 aWalston, Verlie10aTest Publication 2009800281naaa 2200097zu 4500001000800000005001500008008004100023034007200064100002000136245002700156  2009920160513104939730000s1973    coAa          0  0  EL  d0 aadW48.97356546eW48.97356546fN36.74731237gN36.74731237zSite 3291 aInnocent, Leisa10aTest Publication 2009900277naaa 2200097zu 4500001000800000005001500008008004100023034007200064100001600136245002700152  2010020160513104939730000s1973    coAa          0  0  EL  d0 aadW91.61595667eW91.61595667fN11.85462394gN11.85462394zSite 2661 aKohn, Clora10aTest Publication 2010000280naaa 2200097zu 4500001000800000005001500008008004100023034007200064100001900136245002700155  2010120160513104939730000s1973    coAa          0  0  EL  d0 aadW99.81880793eW99.81880793fN56.31339558gN56.31339558zSite 1271 aLinney, Samual10aTest Publication 2010100283naaa 2200097zu 4500001000800000005001500008008004100023034007400064100002000138245002700158  2010220160513104939730000s1973    coAa          0  0  EL  d0 aadW125.07883932eW125.07883932fS45.00178881gS45.00178881zSite 2591 aMerrifield, Kym10aTest Publication 2010200262naaa 2200097zu 4500001000800000005001500008008004100023034005400064100001900118245002700137  2010320160513104939730000s1973    coAa          0  0  EL  d0 aadE0362614eE0362614fS011543gS011543zSite 1811 aBucher, Margit10aTest Publication 2010300264naaa 2200097zu 4500001000800000005001500008008004100023034005400064100002100118245002700139  2010420160513104939730000s1973    coAa          0  0  EL  d0 aadE0181242eE0181242fS291354gS291354zSite 2271 aSteenberg, Shila10aTest Publication 2010400264naaa 2200097zu 4500001000800000005001500008008004100023034005400064100002100118245002700139  2010520160513104939730000s1973    coAa          0  0  EL  d0 aadE0983727eE0983727fN682744gN682744zSite 5311 aBlacker, Minerva10aTest Publication 2010500261naaa 2200097zu 4500001000800000005001500008008004100023034005400064100001800118245002700136  2010620160513104939730000s1973    coAa          0  0  EL  d0 aadE0963319eE0963319fN151338gN151338zSite 1301 aHanley, Karla10aTest Publication 2010600264naaa 2200097zu 4500001000800000005001500008008004100023034005400064100002100118245002700139  2010720160513104939730000s1973    coAa          0  0  EL  d0 aadW0753627eW0753627fN265359gN265359zSite 3661 aMackson, Yolanda10aTest Publication 2010700263naaa 2200097zu 4500001000800000005001500008008004100023034005400064100002000118245002700138  2010820160513104939730000s1973    coAa          0  0  EL  d0 aadE1792143eE1792143fS752257gS752257zSite 5231 aHarrill, Mariko10aTest Publication 2010800265naaa 2200097zu 4500001000800000005001500008008004100023034005400064100002200118245002700140  2010920160513104939730000s1973    coAa          0  0  EL  d0 aadW0953048eW0953048fS170735gS170735zSite 4021 aBehringer, Anitra10aTest Publication 2010900258naaa 2200097zu 4500001000800000005001500008008004100023034005400064100001500118245002700133  2011020160513104939730000s1973    coAa          0  0  EL  d0 aadW1184933eW1184933fN152720gN152720zSite 3511 aRowse, Ida10aTest Publication 2011000264naaa 2200097zu 4500001000800000005001500008008004100023034005400064100002100118245002700139  2011120160513104939730000s1973    coAa          0  0  EL  d0 aadW1374144eW1374144fS081546gS081546zSite 1531 aSutter, Katheryn10aTest Publication 2011100263naaa 2200097zu 4500001000800000005001500008008004100023034005400064100002000118245002700138  2011220160513104939730000s1973    coAa          0  0  EL  d0 aadW1705954eW1705954fS082612gS082612zSite 3541 aBeckett, Tamala10aTest Publication 2011200259naaa 2200097zu 4500001000800000005001500008008004100023034005400064100001600118245002700134  2011320160513104939730000s1973    coAa          0  0  EL  d0 aadE0783553eE0783553fS255532gS255532zSite 4171 aBetty, Eryn10aTest Publication 2011300265naaa 2200097zu 4500001000800000005001500008008004100023034005400064100002200118245002700140  2011420160513104939730000s1973    coAa          0  0  EL  d0 aadE1284246eE1284246fS020216gS020216zSite 2121 aLetsinger, Tamiko10aTest Publication 2011400267naaa 2200097zu 4500001000800000005001500008008004100023034005400064100002400118245002700142  2011520160513104939730000s1973    coAa          0  0  EL  d0 aadE0521421eE0521421fS022222gS022222zSite 4701 aCantrell, Cornelius10aTest Publication 2011500260naaa 2200097zu 4500001000800000005001500008008004100023034005400064100001700118245002700135  2011620160513104939730000s1973    coAa          0  0  EL  d0 aadE0331639eE0331639fS283049gS283049zSite 4771 aLeyva, Marie10aTest Publication 2011600265naaa 2200097zu 4500001000800000005001500008008004100023034005400064100002200118245002700140  2011720160513104939730000s1973    coAa          0  0  EL  d0 aadE0760744eE0760744fN480042gN480042zSite 4401 aBeveridge, Albina10aTest Publication 2011700261naaa 2200097zu 4500001000800000005001500008008004100023034005400064100001800118245002700136  2011820160513104939730000s1973    coAa          0  0  EL  d0 aadW0712539eW0712539fN295730gN295730zSite 5271 aBramhall, Ria10aTest Publication 2011800260naaa 2200097zu 4500001000800000005001500008008004100023034005400064100001700118245002700135  2011920160513104939730000s1973    coAa          0  0  EL  d0 aadE1681553eE1681553fN524510gN524510zSite 1391 aHurt, Millie10aTest Publication 2011900260naaa 2200097zu 4500001000800000005001500008008004100023034005400064100001700118245002700135  2012020160513104939730000s1973    coAa          0  0  EL  d0 aadW0140130eW0140130fS010120gS010120zSite 4641 aWulff, Nilsa10aTest Publication 2012000263naaa 2200097zu 4500001000800000005001500008008004100023034005400064100002000118245002700138  2012120160513104939730000s1973    coAa          0  0  EL  d0 aadW0782218eW0782218fS753724gS753724zSite 5041 aFirth, Theressa10aTest Publication 2012100263naaa 2200097zu 4500001000800000005001500008008004100023034005400064100002000118245002700138  2012220160513104939730000s1973    coAa          0  0  EL  d0 aadW1330422eW1330422fN034324gN034324zSite 4511 aWorster, Marita10aTest Publication 2012200265naaa 2200097zu 4500001000800000005001500008008004100023034005400064100002200118245002700140  2012320160513104939730000s1973    coAa          0  0  EL  d0 aadW0843206eW0843206fS553424gS553424zSite 2961 aOlveda, Jenniffer10aTest Publication 2012300263naaa 2200097zu 4500001000800000005001500008008004100023034005400064100002000118245002700138  2012420160513104939730000s1973    coAa          0  0  EL  d0 aadW1582630eW1582630fS142429gS142429zSite 2791 aMessner, Leanna10aTest Publication 2012400275naaa 2200097zu 4500001000800000005001500008008004100023034006900064100001700133245002700150  2012520160513104939730000s1973    coAa          0  0  EL  d0 aad-12.49085466e-7.49085466f+9.71187917g+4.71187917zSite 1731 aBevill, Sook10aTest Publication 2012500282naaa 2200097zu 4500001000800000005001500008008004100023034007200064100002100136245002700157  2012620160513104939730000s1973    coAa          0  0  EL  d0 aad+71.12605143e+81.12605143f+20.40214021g+10.40214021zSite 1211 aSchock, Lisandra10aTest Publication 2012600281naaa 2200097zu 4500001000800000005001500008008004100023034007400064100001800138245002700156  2012720160513104939730000s1973    coAa          0  0  EL  d0 aad+104.20929332e+154.20929332f+23.15670674g+13.15670674zSite 2831 aAbner, Shelli10aTest Publication 2012700282naaa 2200097zu 4500001000800000005001500008008004100023034007200064100002100136245002700157  2012820160513104939730000s1973    coAa          0  0  EL  d0 aad-130.3358613e-90.33586126f+54.37067475g+34.37067475zSite 3061 aNecessary, Dante10aTest Publication 2012800277naaa 2200097zu 4500001000800000005001500008008004100023034007300064100001500137245002700152  2012920160513104939730000s1973    coAa          0  0  EL  d0 aad+89.51162859e+109.51162859f-22.88853952g-42.88853952zSite 1271 aAmyx, Lyle10aTest Publication 2012900281naaa 2200097zu 4500001000800000005001500008008004100023034007400064100001800138245002700156  2013020160513104939730000s1973    coAa          0  0  EL  d0 aad+120.94552421e+130.94552421f+80.21089126g+77.21089126zSite 5191 aGranda, Isiah10aTest Publication 2013000280naaa 2200097zu 4500001000800000005001500008008004100023034007000064100002100134245002700155  2013120160513104939730000s1973    coAa          0  0  EL  d0 aad+166.31983556e+176.31983556f-64.114475g-74.114475zSite 1291 aFavela, Lorretta10aTest Publication 2013100277naaa 2200097zu 4500001000800000005001500008008004100023034007200064100001600136245002700152  2013220160513104939730000s1973    coAa          0  0  EL  d0 aad-33.35817709e-23.35817709f-26.04958019g-56.04958019zSite 3441 aDaub, Lloyd10aTest Publication 2013200278naaa 2200097zu 4500001000800000005001500008008004100023034007200064100001700136245002700153  2013320160513104939730000s1973    coAa          0  0  EL  d0 aad+100.28119821e+150.28119821f-39.5929073g-79.5929073zSite 2811 aFines, Gregg10aTest Publication 2013300279naaa 2200097zu 4500001000800000005001500008008004100023034006800064100002200132245002700154  2013420160513104939730000s1973    coAa          0  0  EL  d0 aad-98.724204e-38.72420401f+40.4924143g+20.4924143zSite 4941 aWalcott, Porfirio10aTest Publication 2013400280naaa 2200097zu 4500001000800000005001500008008004100023034007300064100001800137245002700155  2013520160513104939730000s1973    coAa          0  0  EL  d0 aad-170.45022257e-156.4502226f+25.08138959g+15.08138959zSite 4151 aGranda, Isiah10aTest Publication 2013500281naaa 2200097zu 4500001000800000005001500008008004100023034007300064100001900137245002700156  2013620160513104939730000s1973    coAa          0  0  EL  d0 aad+93.74890612e+143.74890612f-13.32263614g-23.32263614zSite 2561 aCutter, Annika10aTest Publication 2013600279naaa 2200097zu 4500001000800000005001500008008004100023034007200064100001800136245002700154  2013720160513104939730000s1973    coAa          0  0  EL  d0 aad-66.87358455e-46.87358455f+70.98897026g+50.98897026zSite 5431 aHanley, Karla10aTest Publication 2013700276naaa 2200097zu 4500001000800000005001500008008004100023034007000064100001700134245002700151  2013820160513104939730000s1973    coAa          0  0  EL  d0 aad-172.9265117e-162.9265117f-1.47082029g-6.47082029zSite 1691 aDalke, Isiah10aTest Publication 2013800281naaa 2200097zu 4500001000800000005001500008008004100023034007000064100002200134245002700156  2013920160513104939730000s1973    coAa          0  0  EL  d0 aad+33.61230501e+43.61230501f-4.12575355g-9.12575355zSite 3771 aBehringer, Anitra10aTest Publication 2013900281naaa 2200097zu 4500001000800000005001500008008004100023034007200064100002000136245002700156  2014020160513104939730000s1973    coAa          0  0  EL  d0 aad+75.10477259e+95.10477259f+73.86871739g+53.86871739zSite 2831 aWilhoite, Kathi10aTest Publication 2014000282naaa 2200097zu 4500001000800000005001500008008004100023034007400064100001900138245002700157  2014120160513104939730000s1973    coAa          0  0  EL  d0 aad+125.92523664e+135.92523664f-15.86550515g-25.86550515zSite 1841 aJasik, Micaela10aTest Publication 2014100283naaa 2200097zu 4500001000800000005001500008008004100023034007400064100002000138245002700158  2014220160513104939730000s1973    coAa          0  0  EL  d0 aad+112.65337661e+122.65337661f+78.04277975g+68.04277975zSite 5271 aStrine, Tabitha10aTest Publication 2014200276naaa 2200097zu 4500001000800000005001500008008004100023034006900064100001800133245002700151  2014320160513104939730000s1973    coAa          0  0  EL  d0 aad-10.83945484e-5.83945484f-30.6046605g-60.6046605zSite 1311 aOverall, Lula10aTest Publication 2014300279naaa 2200097zu 4500001000800000005001500008008004100023034007000064100002000134245002700154  2014420160513104939730000s1973    coAa          0  0  EL  d0 aad-15.53775937e-10.53775937f-46.3793589g-66.3793589zSite 2041 aMathisen, Dayle10aTest Publication 2014400281naaa 2200097zu 4500001000800000005001500008008004100023034007200064100002000136245002700156  2014520160513104939730000s1973    coAa          0  0  EL  d0 aad-147.1524264e-127.1524264f-70.97214091g-75.97214091zSite 4281 aWilhoite, Kathi10aTest Publication 2014500278naaa 2200097zu 4500001000800000005001500008008004100023034007200064100001700136245002700153  2014620160513104939730000s1973    coAa          0  0  EL  d0 aad+73.14760572e+93.14760572f-44.44305202g-64.44305202zSite 4881 aFines, Gregg10aTest Publication 2014600280naaa 2200097zu 4500001000800000005001500008008004100023034007400064100001700138245002700155  2014720160513104939730000s1973    coAa          0  0  EL  d0 aadE143.91680691eE153.91680691fN69.05928016gN59.05928016zSite 2301 aKinnan, Enda10aTest Publication 2014700281naaa 2200097zu 4500001000800000005001500008008004100023034007000064100002200134245002700156  2014820160513104939730000s1973    coAa          0  0  EL  d0 aadE109.2953057eE159.2953057fN75.6021786gN72.6021786zSite 2351 aHartfield, Shelba10aTest Publication 2014800282naaa 2200097zu 4500001000800000005001500008008004100023034007300064100002000137245002700157  2014920160513104939730000s1973    coAa          0  0  EL  d0 aadE144.81897837eE164.81897837fN18.62668817gN8.62668817zSite 2871 aSkeens, Cordell10aTest Publication 2014900278naaa 2200097zu 4500001000800000005001500008008004100023034007200064100001700136245002700153  2015020160513104939730000s1973    coAa          0  0  EL  d0 aadW115.49585203eW85.49585203fN19.56564384gN9.56564384zSite 4151 aHove, Armand10aTest Publication 2015000280naaa 2200097zu 4500001000800000005001500008008004100023034007200064100001900136245002700155  2015120160513104939730000s1973    coAa          0  0  EL  d0 aadW32.63289449eW22.63289449fS55.38513226gS75.38513226zSite 1201 aHaugh, Winford10aTest Publication 2015100279naaa 2200097zu 4500001000800000005001500008008004100023034007300064100001700137245002700154  2015220160513104939730000s1973    coAa          0  0  EL  d0 aadE87.77332672eE107.77332672fS54.25951534gS74.25951534zSite 3431 aValois, Arie10aTest Publication 2015200279naaa 2200097zu 4500001000800000005001500008008004100023034006800064100002200132245002700154  2015320160513104939730000s1973    coAa          0  0  EL  d0 aadW32.8377449eW22.8377449fS3.09135927gS8.09135927zSite 4141 aMcclaran, Kathern10aTest Publication 2015300277naaa 2200097zu 4500001000800000005001500008008004100023034007000064100001800134245002700152  2015420160513104939730000s1973    coAa          0  0  EL  d0 aadE34.4627201eE44.4627201fN23.51119899gN13.51119899zSite 3351 aHeinrich, See10aTest Publication 2015400282naaa 2200097zu 4500001000800000005001500008008004100023034007200064100002100136245002700157  2015520160513104939730000s1973    coAa          0  0  EL  d0 aadE11.25085415eE16.25085415fN62.44255328gN42.44255328zSite 3801 aSteenberg, Shila10aTest Publication 2015500278naaa 2200097zu 4500001000800000005001500008008004100023034007200064100001700136245002700153  2015620160513104939730000s1973    coAa          0  0  EL  d0 aadE35.02387108eE45.02387108fN51.72426854gN31.72426854zSite 1231 aNiccum, Alex10aTest Publication 2015600284naaa 2200097zu 4500001000800000005001500008008004100023034007400064100002100138245002700159  2015720160513104939730000s1973    coAa          0  0  EL  d0 aadE115.38134036eE145.38134036fS21.96462606gS41.96462606zSite 3801 aRussom, Clorinda10aTest Publication 2015700278naaa 2200097zu 4500001000800000005001500008008004100023034006600064100002300130245002700153  2015820160513104939730000s1973    coAa          0  0  EL  d0 aadW79.5685706eW59.5685706fS3.2186524gS8.2186524zSite 4461 aMontanye, Criselda10aTest Publication 2015800280naaa 2200097zu 4500001000800000005001500008008004100023034007200064100001900136245002700155  2015920160513104939730000s1973    coAa          0  0  EL  d0 aadE78.87843097eE98.87843097fS24.09348392gS44.09348392zSite 3721 aGalasso, Tatum10aTest Publication 2015900283naaa 2200097zu 4500001000800000005001500008008004100023034007400064100002000138245002700158  2016020160513104939730000s1973    coAa          0  0  EL  d0 aadW179.09659396eW119.09659396fS39.32213026gS79.32213026zSite 4631 aLiptak, Caitlin10aTest Publication 2016000282naaa 2200097zu 4500001000800000005001500008008004100023034007400064100001900138245002700157  2016120160513104939730000s1973    coAa          0  0  EL  d0 aadW163.27020238eW113.27020238fS36.75458726gS76.75458726zSite 1621 aGaetano, Dedra10aTest Publication 2016100261naaa 2200097zu 4500001000800000005001500008008004100023034005400064100001800118245002700136  2016220160513104939730000s1973    coAa          0  0  EL  d0 aadE1114626eE1214626fN752639gN452639zSite 4161 aTorian, Belva10aTest Publication 2016200262naaa 2200097zu 4500001000800000005001500008008004100023034005400064100001900118245002700137  2016320160513104939730000s1973    coAa          0  0  EL  d0 aadE0285018eE0335018fN271418gN171418zSite 2191 aMirabito, Shin10aTest Publication 2016300266naaa 2200097zu 4500001000800000005001500008008004100023034005400064100002300118245002700141  2016420160513104939730000s1973    coAa          0  0  EL  d0 aadE0330550eE0430550fN471910gN271910zSite 1651 aSpadaro, Geraldine10aTest Publication 2016400265naaa 2200097zu 4500001000800000005001500008008004100023034005400064100002200118245002700140  2016520160513104939730000s1973    coAa          0  0  EL  d0 aadW0501321eW0401321fN053851gN003851zSite 4651 aHartfield, Shelba10aTest Publication 2016500259naaa 2200097zu 4500001000800000005001500008008004100023034005400064100001600118245002700134  2016620160513104939730000s1973    coAa          0  0  EL  d0 aadE1541338eE1641338fS053823gS103823zSite 2621 aDaub, Lloyd10aTest Publication 2016600262naaa 2200097zu 4500001000800000005001500008008004100023034005400064100001900118245002700137  2016720160513104939730000s1973    coAa          0  0  EL  d0 aadW0722141eW0522141fS223403gS423403zSite 5141 aCutter, Annika10aTest Publication 2016700264naaa 2200097zu 4500001000800000005001500008008004100023034005400064100002100118245002700139  2016820160513104939730000s1973    coAa          0  0  EL  d0 aadW0053928eW0003928fS472308gS772308zSite 1971 aErickson, Joette10aTest Publication 2016800264naaa 2200097zu 4500001000800000005001500008008004100023034005400064100002100118245002700139  2016920160513104939730000s1973    coAa          0  0  EL  d0 aadW0675444eW0475444fN571945gN271945zSite 2791 aSharrow, Sherron10aTest Publication 2016900261naaa 2200097zu 4500001000800000005001500008008004100023034005400064100001800118245002700136  2017020160513104939730000s1973    coAa          0  0  EL  d0 aadE1064421eE1564421fN402522gN202522zSite 1701 aVidrio, Sofia10aTest Publication 2017000261naaa 2200097zu 4500001000800000005001500008008004100023034005400064100001800118245002700136  2017120160513104939730000s1973    coAa          0  0  EL  d0 aadW1254938eW0854938fN511735gN311735zSite 5101 aHeinrich, See10aTest Publication 2017100261naaa 2200097zu 4500001000800000005001500008008004100023034005400064100001800118245002700136  2017220160513104939730000s1973    coAa          0  0  EL  d0 aadW1344729eW0944729fN051424gN001424zSite 5111 aBoyland, Bebe10aTest Publication 2017200263naaa 2200097zu 4500001000800000005001500008008004100023034005400064100002000118245002700138  2017320160513104939730000s1973    coAa          0  0  EL  d0 aadE0932835eE1432835fS175621gS375621zSite 2151 aStrine, Tabitha10aTest Publication 2017300262naaa 2200097zu 4500001000800000005001500008008004100023034005400064100001900118245002700137  2017420160513104939730000s1973    coAa          0  0  EL  d0 aadE1701912eE1751912fS073104gS123104zSite 1931 aBornstein, Dia10aTest Publication 2017400266naaa 2200097zu 4500001000800000005001500008008004100023034005400064100002300118245002700141  2017520160513104939730000s1973    coAa          0  0  EL  d0 aadW1362047eW0962047fS250039gS550039zSite 4111 aGrizzell, Griselda10aTest Publication 2017500264naaa 2200097zu 4500001000800000005001500008008004100023034005400064100002100118245002700139  2017620160513104939730000s1973    coAa          0  0  EL  d0 aadW0545835eW0445835fS450010gS650010zSite 5091 aFalzone, Natasha10aTest Publication 2017600259naaa 2200097zu 4500001000800000005001500008008004100023034005400064100001600118245002700134  2017720160513104939730000s1973    coAa          0  0  EL  d0 aadE1455446eE1555446fS373045gS773045zSite 3521 aJaco, Angle10aTest Publication 2017700303nam  2200109   45e0001000900000005001500009008004100024034004700065100001800112245002800130500003500158  20170020170517104939730000s1973    coAa          0  0  EL  d0 aadW1362047eW0962047fS250039gzSite 4111 aOverall, Lula10aTest Publication 201700  aForms a line at the North Pole00311nam  2200109   45e0001000900000005001500009008004100024034005500065100001800120245002800138500003500166  20170120170517104939730000s1973    coAa          0  0  EL  d0 aadeW59.5685706fS3.2186524gS8.2186524zSite 4461 aGranda, Isiah10aTest Publication 201701  aForms a line at the North Pole00316nam  2200109   45e0001000900000005001500009008004100024034006100065100001700126245002800143500003500171  20170220170517104939730000s1973    coAa          0  0  EL  d0 aadW103.57340238efS22.78804289gS22.78804289zSite 2171 aOros, Cierra10aTest Publication 201702  aForms a line at the North Pole00316nam  2200109   45e0001000900000005001500009008004100024034006200065100001600127245002800143500003500171  20170320170517104939730000s1973    coAa          0  0  EL  d0 aadE120.96526676eE120.96526676fgN22.40092028zSite 2391 aSaar, Danna10aTest Publication 201703  aForms a line at the South Pole00321nam  2200109   45e0001000900000005001500009008004100024034006200065100002100127245002800148500003500176  20170420170517104939730000s1973    coAa          0  0  EL  d0 aadE151.51785078eE151.51785078fN13.91875447gzSite 1051 aMackson, Yolanda10aTest Publication 201704  aForms a line at the South Pole00320nam  2200109   45e0001000900000005001500009008004100024034006000065100002200125245002800147500003500175  20170520170517104939730000s1973    coAa          0  0  EL  d0 aade+86.55263228f-28.95862432g-28.95862432zSite 1681 aHartfield, Shelba10aTest Publication 201705  aForms a line at the South Pole00308nam  2200109   45e0001000900000005001500009008004100024034006100065100002100126245002800147500002300175  20170620170517104939730000s1973    coAa          0  0  EL  d0 aad+104.20929332ef+23.15670674g+13.15670674zSite 2461 aWinrow, Sanjuana10aTest Publication 201706  aWest value is null00303nam  2200109   45e0001000900000005001500009008004100024034005900065100001800124245002800142500002300170  20170720170517104939730000s1973    coAa          0  0  EL  d0 aad-172.9265117e-162.9265117fg-6.47082029zSite 1691 aAbner, Shelli10aTest Publication 201707  aEast value is null00306nam  2200109   45e0001000900000005001500009008004100024034006000065100001900125245002800144500002400172  20170820170517104939730000s1973    coAa          0  0  EL  d0 aad-149.3464366e-129.3464366f+27.28202333gzSite 1341 aNelms, Lanelle10aTest Publication 201708  aNorth value is null00300nam  2200109   45e0001000900000005001500009008004100024034005400065100001900119245002800138500002400166  20170920170517104939730000s1973    coAa          0  0  EL  d0 aadE1865330eE1765330fN221220gN122012zSite 3131 aPakele, Marina10aTest Publication 201709  aSouth value is null00295nam  2200109   45e0001000900000005001500009008004100024034005400065100001500119245002800134500002300162  20171020170517104939730000s1973    coAa          0  0  EL  d0 aadW1899190eW999180fN663133gN563133zSite 12771 aOram, Donn10aTest Publication 201710  aWest value is null00300nam  2200109   45e0001000900000005001500009008004100024034005400065100002000119245002800139500002300167  20171120170517104939730000s1973    coAa          0  0  EL  d0 aadE1792143eE1892143fS702257gS752257zSite 5231 aHarrill, Mariko10aTest Publication 201711  aEast value is null00298nam  2200109   45e0001000900000005001500009008004100024034005400065100001700119245002800136500002400164  20171220170517104939730000s1973    coAa          0  0  EL  d0 aadW1792143eW1892143fS702257gS752257zSite 5231 aLeyva, Marie10aTest Publication 201712  aNorth value is null00303nam  2200109   45e0001000900000005001500009008004100024034005400065100002200119245002800141500002400169  20171320170517104939730000s1973    coAa          0  0  EL  d0 aadE1202300eE1301512fN982100gN772108zSite 5191 aWalcott, Porfirio10aTest Publication 201713  aSouth value is null00301nam  2200109   45e0001000900000005001500009008004100024034005400065100002100119245002800140500002300168  20171420170517104939730000s1973    coAa          0  0  EL  d0 aadE1202300eE1301512fS982100gS772108zSite 6191 aErickson, Joette10aTest Publication 201714  aWest value is null00302nam  2200109   45e0001000900000005001500009008004100024034005400065100002200119245002800141500002300169  20171520170517104939730000s1973    coAa          0  0  EL  d0 aadW1790910eW1190915fN393212gN913213zSite 4631 aCrafts, Claudette10aTest Publication 201715  aEast value is null00300nam  2200109   45e0001000900000005001500009008004100024034005400065100001900119245002800138500002400166  20171620170517104939730000s1973    coAa          0  0  EL  d0 aadW1790910eW1190915fS393212gS913213zSite 4631 aAlcina, Rashad10aTest Publication 201716  aNorth value is null00322nam  2200109   45e0001000900000005001500009008004100024034007400065100002100139245002800160500002400188  20171720170517104939730000s1973    coAa          0  0  EL  d0 aadE186.53377147eE176.53377147fN22.77971971gN12.77971971zSite 3131 aSchlosser, Karan10aTest Publication 201717  aSouth value is null00316nam  2200109   45e0001000900000005001500009008004100024034007400065100001800139245002800157500002100185  20171820170517104939730000s1973    coAa          0  0  EL  d0 aadW189.81880793eW99.81880793fN66.31339558gN56.31339558zSite 12771 aMurden, Claud10aTest Publication 201718  aWest exceeds 18000317nam  2200109   45e0001000900000005001500009008004100024034007400065100001800139245002800157500002200185  20171920170517104939730000s1973    coAa          0  0  EL  d0 aadE176.53377147eE186.53377147fN22.77971971gN12.77971971zSite 3131 aOverall, Lula10aTest Publication 201719  aWest exceeds -18000316nam  2200109   45e0001000900000005001500009008004100024034007400065100001800139245002800157500002100185  20172020170517104939730000s1973    coAa          0  0  EL  d0 aadW175.68166135eW185.68166135fS60.41361345gS69.41361345zSite 4971 aGranda, Isiah10aTest Publication 201720  aEast exceeds 18000316nam  2200109   45e0001000900000005001500009008004100024034007400065100001700139245002800156500002200184  20172120170517104939730000s1973    coAa          0  0  EL  d0 aadE120.94552421eE130.94552421fN98.21089126gN77.21089126zSite 5191 aOros, Cierra10aTest Publication 201721  aEast exceeds -18000314nam  2200109   45e0001000900000005001500009008004100024034007400065100001600139245002800155500002100183  20172220170517104939730000s1973    coAa          0  0  EL  d0 aadE120.94552421eE130.94552421fS98.21089126gS77.21089126zSite 6191 aSaar, Danna10aTest Publication 201722  aNorth exceeds 9000320nam  2200109   45e0001000900000005001500009008004100024034007400065100002100139245002800160500002200188  20172320170517104939730000s1973    coAa          0  0  EL  d0 aadW179.09659396eW119.09659396fN39.32213026gN91.32213026zSite 4631 aMackson, Yolanda10aTest Publication 201723  aNorth exceeds -9000320nam  2200109   45e0001000900000005001500009008004100024034007400065100002200139245002800161500002100189  20172420170517104939730000s1973    coAa          0  0  EL  d0 aadW179.09659396eW119.09659396fS39.32213026gS91.32213026zSite 4631 aHartfield, Shelba10aTest Publication 201724  aSouth exceeds 9000320nam  2200109   45e0001000900000005001500009008004100024034007400065100002100139245002800160500002200188  20172520170517104939730000s1973    coAa          0  0  EL  d0 aad+186.53377147e+176.53377147f+22.77971971g+12.77971971zSite 3131 aWinrow, Sanjuana10aTest Publication 201725  aSouth exceeds -9000316nam  2200109   45e0001000900000005001500009008004100024034007400065100001800139245002800157500002100185  20172620170517104939730000s1973    coAa          0  0  EL  d0 aad-189.81880793e-99.81880793f+66.31339558g+56.31339558zSite 12771 aAbner, Shelli10aTest Publication 201726  aWest exceeds 18000318nam  2200109   45e0001000900000005001500009008004100024034007400065100001900139245002800158500002200186  20172720170517104939730000s1973    coAa          0  0  EL  d0 aad+175.1864435e+182.18644345f-10.03581345g-20.03581345zSite 11721 aNelms, Lanelle10aTest Publication 201727  aWest exceeds -18000315nam  2200109   45e0001000900000005001500009008004100024034007200065100001900137245002800156500002100184  20172820170517104939730000s1973    coAa          0  0  EL  d0 aad-175.1864435e-182.1864435f-10.03581345g-20.03581345zSite 1721 aPakele, Marina10aTest Publication 201728  aEast exceeds 18000315nam  2200109   45e0001000900000005001500009008004100024034007500065100001500140245002800155500002200183  20172920170517104939730000s1973    coAa          0  0  EL  d0 aad+120.94552421e'+130.94552421f+98.21089126g+77.21089126zSite 5191 aOram, Donn10aTest Publication 201729  aEast exceeds -18000319nam  2200109   45e0001000900000005001500009008004100024034007500065100002000140245002800160500002100188  20173020170517104939730000s1973    coAa          0  0  EL  d0 aad+120.94552421e'+130.94552421f-98.21089126g-77.21089126zSite 6191 aHarrill, Mariko10aTest Publication 201730  aNorth exceeds 9000316nam  2200109   45e0001000900000005001500009008004100024034007400065100001700139245002800156500002200184  20173120170517104939730000s1973    coAa          0  0  EL  d0 aad-179.09659396e-119.09659396f+39.32213026g+91.32213026zSite 4631 aLeyva, Marie10aTest Publication 201731  aNorth exceeds -9000320nam  2200109   45e0001000900000005001500009008004100024034007400065100002200139245002800161500002100189  20173220170517104939730000s1973    coAa          0  0  EL  d0 aad-179.09659396e-119.09659396f-39.32213026g-91.32213026zSite 4631 aWalcott, Porfirio10aTest Publication 201732  aSouth exceeds 9000318nam  2200109   45e0001000900000005001500009008004100024034007200065100002100137245002800158500002200186  20173320170517104939730000s1973    coAa          0  0  EL  d0 aad+75.10477259e'+95.10477259f43.86871739g+53.86871739zSite 2831 aErickson, Joette10aTest Publication 201733  aSouth exceeds -9000301nam  2200109   45e0001000900000005001500009008004100024034005500065100002200120245002800142500002100170  20173420170517104939730000s1973    coAa          0  0  EL  d0 aadE1455446eE1555446fS793045gS773045zSite 35201 aCrafts, Claudette10aTest Publication 201734  aWest exceeds 18000317nam  2200109   45e0001000900000005001500009008004100024034007300065100001900138245002800157500002200185  20173520170517104939730000s1973    coAa          0  0  EL  d0 aadW106.32772299eW76.32772299fN46.24201475gN56.24201475zSite 2861 aAlcina, Rashad10aTest Publication 201735  aWest exceeds -18000319nam  2200109   45e0001000900000005001500009008004100024034007400065100002100139245002800160500002100188  20173620170517104939730000s1973    coAa          0  0  EL  d0 aad-180.0 e+179.98333333333332f-89.98333333333333g-90.0zSite 25831 aSchlosser, Karan10aTest Publication 201736  aEast exceeds 18000298nam  2200109   45e0001000900000005001500009008004100024034005500065100001800120245002800138500002200166  20173720170517104939730000s1973    coAa          0  0  EL  d0 aadW1800000eE1795900fS895900gS900000zSite 25831 aMurden, Claud10aTest Publication 201737  aEast exceeds -18000316nam  2200109   45e0001000900000005001500009008004100024034007400065100001800139245002800157500002100185  20173820170517104939730000s1973    coAa          0  0  EL  d0 aadW180.0 eE179.98333333333332fS89.98333333333333gS90.0zSite 25831 aOverall, Lula10aTest Publication 201738  aNorth exceeds 9000315nam  2200109   45e0001000900000005001500009008004100024034007200065100001800137245002800155500002200183  20173920170517104939730000s1973    coAa          0  0  EL  d0 aad-180.0 e+179.98333333333332f-85g-89.98333333333333zSite 25841 aGranda, Isiah10aTest Publication 201739  aNorth exceeds -9000296nam  2200109   45e0001000900000005001500009008004100024034005500065100001700120245002800137500002100165  20174020170517104939730000s1973    coAa          0  0  EL  d0 aadW1800000eE1795900fS850000gS895900zSite 25841 aOros, Cierra10aTest Publication 201740  aSouth exceeds 9000313nam  2200109   45e0001000900000005001500009008004100024034007200065100001600137245002800153500002200181  20174120170517104939730000s1973    coAa          0  0  EL  d0 aadW180.0 eE179.98333333333332fS85gS89.98333333333333zSite 25841 aSaar, Danna10aTest Publication 201741  aSouth exceeds -9000291nam  2200109   45e0001000900000005001500009008004100024034004100065100002100106245002800127500002600155  20174220170517104939730000s1973    coAa          0  0  EL  d0 aad+1.0e-0.0f90.0g70.0zSite 22331 aMackson, Yolanda10aTest Publication 201742  aNorth less than South00306nam  2200109   45e0001000900000005001500009008004100024034005500065100002200120245002800142500002600170  20174320170517104939730000s1973    coAa          0  0  EL  d0 aadE0000001eW0000000fN900000gN700000zSite 22331 aHartfield, Shelba10aTest Publication 201743  aNorth less than South00293nam  2200109   45e0001000900000005001500009008004100024034004300065100002100108245002800129500002600157  20174420170517104939730000s1973    coAa          0  0  EL  d0 aadE1.0eW0.0fN90.0gN70.0zSite 22331 aWinrow, Sanjuana10aTest Publication 201744  aNorth less than South00337nam  2200109   45e0001000900000005001500009008004100024034007400065100001800139245002800157500004200185  20174520170517104939730000s1973    coAa          0  0  EL  d0 aad-180.0 e+179.98333333333332f-89.98333333333333g-90.0zSite 25831 aAbner, Shelli10aTest Publication 201745  aNorth less than 0.167 from South Pole00319nam  2200109   45e0001000900000005001500009008004100024034005500065100001900120245002800139500004200167  20174620170517104939730000s1973    coAa          0  0  EL  d0 aadW1800000eE1795900fS895900gS900000zSite 25831 aNelms, Lanelle10aTest Publication 201746  aNorth less than 0.167 from South Pole00338nam  2200109   45e0001000900000005001500009008004100024034007400065100001900139245002800158500004200186  20174720170517104939730000s1973    coAa          0  0  EL  d0 aadW180.0 eE179.98333333333332fS89.98333333333333gS90.0zSite 25831 aPakele, Marina10aTest Publication 201747  aNorth less than 0.167 from South Pole00332nam  2200109   45e0001000900000005001500009008004100024034007200065100001500137245002800152500004200180  20174820170517104939730000s1973    coAa          0  0  EL  d0 aad-180.0 e+179.98333333333332f-85g-89.98333333333333zSite 25841 aOram, Donn10aTest Publication 201748  aSouth less than 0.167 from South Pole00320nam  2200109   45e0001000900000005001500009008004100024034005500065100002000120245002800140500004200168  20174920170517104939730000s1973    coAa          0  0  EL  d0 aadW1800000eE1795900fS850000gS895900zSite 25841 aHarrill, Mariko10aTest Publication 201749  aSouth less than 0.167 from South Pole00334nam  2200109   45e0001000900000005001500009008004100024034007200065100001700137245002800154500004200182  20175020170517104939730000s1973    coAa          0  0  EL  d0 aadW180.0 eE179.98333333333332fS85gS89.98333333333333zSite 25841 aLeyva, Marie10aTest Publication 201750  aSouth less than 0.167 from South Pole00317nam  2200109   45e0001000900000005001500009008004100024034004100065100002200106245002800128500005100156  20175120170517104939730000s1973    coAa          0  0  EL  d0 aad+1.0e-0.0f90.0g70.0zSite 22331 aWalcott, Porfirio10aTest Publication 201751  aEW distance is greater than -2 and less than 000330nam  2200109   45e0001000900000005001500009008004100024034005500065100002100120245002800141500005100169  20175220170517104939730000s1973    coAa          0  0  EL  d0 aadE0000001eW0000000fN900000gN700000zSite 22331 aErickson, Joette10aTest Publication 201752  aEW distance is greater than -2 and less than 000319nam  2200109   45e0001000900000005001500009008004100024034004300065100002200108245002800130500005100158  20175320170517104939730000s1973    coAa          0  0  EL  d0 aadE1.0eW0.0fN90.0gN70.0zSite 22331 aCrafts, Claudette10aTest Publication 201753  aEW distance is greater than -2 and less than 0
\ No newline at end of file
diff --git a/tests/data/geo.mrc.properties b/tests/data/geo.mrc.properties
index e5d632f91c36bb66fbc9c31a820dfe56632ad1df..6ef41c73276627678b3ce61e9e9fc4a7bf176ff7 100644
--- a/tests/data/geo.mrc.properties
+++ b/tests/data/geo.mrc.properties
@@ -1,6 +1,5 @@
 id = 001, (pattern_map.id_prefix), first
 pattern_map.id_prefix.pattern_0 = (.+)=>geo$1
-location_geo = custom, getAllCoordinates
-long_lat = custom, getPointCoordinates
+long_lat = custom, getAllCoordinates
 long_lat_display = custom, getDisplayCoordinates
 long_lat_label = 034z
diff --git a/themes/bootprint3/less/bootprint.less b/themes/bootprint3/less/bootprint.less
index cbf1d366e54db64a000275104c790a33a3aa633c..bef476850a056c186571f020fccd6ca97102ee29 100644
--- a/themes/bootprint3/less/bootprint.less
+++ b/themes/bootprint3/less/bootprint.less
@@ -2,112 +2,28 @@
 @import "variables";
 @import "icons";
 @import "search";
+@import "forms";
 
-@brand-primary: #619144; // a11y overrides @brand-primary in sass
+@brand-primary: #619144; /* a11y overrides @brand-primary in sass */
 @active-orange: #E70;
 
 /* --- Bootstrap MODS ---*/
+@import "common";
+
 body {
   background: @brand-primary;
   font-size: 13px
 }
-.container {
-  background: #FFF;
-  padding: 0;
-}
-.main .container { padding: 0 4px 18px; }
-
-a,
-.btn-link {
-  color: #06C;
-  &:hover { color: #09F; }
-}
-.alert { padding: 8px; }
-.btn { padding: 3px 5px 2px; }
-.btn.btn-default {
-  background: @gray-lighter;
-  background-image: linear-gradient(#FFF, @nav-tabs-border-color);
-  border: 1px solid @gray;
-  color: @gray-darker;
-  text-shadow: 0 1px 0 #FFF;
-}
-.btn:not(.btn-default) { font-weight:bold; }
-.btn-danger,
-.btn-danger:hover  { border-color:darken(@brand-danger,  12%); }
-.btn-info,
-.btn-info:hover    { border-color:darken(@brand-info,    12%); }
-.btn-primary,
-.btn-primary:hover { border-color:darken(@brand-primary, 12%); }
-.btn-success,
-.btn-success:hover { border-color:darken(@brand-success, 12%); }
-.btn-warning,
-.btn-warning:hover { border-color:darken(@brand-warning, 12%); }
 
 #commentList .comment:nth-child(even) { background: @gray-lighter; }
 #dateVisColorSettings { stroke: @brand-primary; }
-#hierarchyRecord { background: #FFF; }
-h2 { margin: 0 8px 8px; }
-input[type=radio],
-input[type=checkbox] {
-  margin: 2px auto 0;
-  padding: 0 2px;
-}
-.nav > li > a { padding: 5px 10px; }
-.nav-pills {
-  display: table;
-  margin: 0 auto;
-}
-.navbar { min-height: 1px; }
-.navbar-form {
-  margin-top: 5px;
-  margin-bottom: 5px;
-}
-.pagination {
-  display: table;
-  margin: 18px auto;
-}
-.pagination > li > a,
-.pagination > li > span { padding: 4px 12px 3px; }
-.pagination > .active > a,
-.pagination > .active > a:focus,
-.pagination > .active > a:hover,
-.pagination > .active > span,
-.pagination > .active > span:focus,
-.pagination > .active > span:hover {
-  background: @brand-primary;
-  border-color: @brand-primary;
-}
-.panel-heading { padding: 0; }
-.panel-heading a {
-  cursor: pointer;
-  display: inline-block;
-  padding: 6px;
-  width: 100%;
-}
-.row:not(.top-row) {
-  padding: 6px 4px;
-  margin: 0 -4px;
-}
-.row > p { padding: 0 1em; }
-.sub-breadcrumb { padding: 0 5px; }
-.tab-content {
-  padding: 6px 8px;
-  border: 1px solid @gray-lighter;
-  border-top: 0;
-}
+#hierarchyRecord { background: #fff; }
+.cart-controls .checkbox { line-height: 2rem; }
 
-@media (max-width: 767px) {
-  body { padding: 6px; }
-  header { margin-top: 0; }
-  .label { font-size: 85%; }
-}
+/* --- Layout --- */
+.main .container { padding-top: 1rem; }
 @media (min-width: 768px) {
-  .badge {
-    font-size: 85%;
-    margin-top: 1px;
-  }
-  .label { padding-top: .3em; }
-  .modal-dialog { width: 650px; }
+  .main .sidebar { padding: 0; }
 }
 
 /* --- Header --- */
@@ -116,7 +32,7 @@ header .fa.fa-bars { font-size: 21px; }
 header .navbar {
   border-radius: 5px 5px 0 0;
   padding: 0 10px;
-  .searchForm { display: none !important; }
+  &.search { border-radius: 0; }
   .navbar-brand {
     height: 65px;
     width: 170px;
@@ -138,10 +54,6 @@ header .navbar {
     .navbar-right { margin: 0; }
   }
 }
-header .searchbox {
-  background: linear-gradient(to bottom, #FFF, #EEE);
-  display: block !important;
-}
 header .searchbox .tab-content { border: 0; }
 header .searchbox .tab-content .navbar-text { margin: 5px 10px 5px 0; }
 @media (max-width: 767px) {
@@ -151,21 +63,12 @@ header .searchbox .tab-content .navbar-text { margin: 5px 10px 5px 0; }
     margin-bottom: 2px
   }
 }
-header .breadcrumb {
-  border: 1px solid @gray-lighter;
-  border-radius: 0;
-  border-width: 1px 0;
-  font-size: 12px;
-  margin-bottom: 2px;
-  padding: 7px 20px 5px
-}
 
 /* --- Footer --- */
-footer { margin-bottom: 36px; }
-footer .container {
+footer {
+  margin-bottom: 2rem;
   border-radius: 0 0 5px 5px;
   border-top: 1px solid @nav-tabs-border-color;
-  padding-top: 18px;
 }
 footer hr { display: none; }
 footer p { margin: 0; }
@@ -174,6 +77,12 @@ footer ul { padding-left: 30px; }
 /* --- Browse --- */
 [id^=list].list-group .col-sm-9 { margin: 0; }
 
+/* --- Channels --- */
+.channel,
+.channel-title.no-results { margin-bottom: 2rem; }
+.channel-title { margin-top: 1rem; }
+.channel-title .fa { margin-top: 4px; }
+
 /* --- Offcanvas --- */
 body.offcanvas {
   .offcanvas-toggle {
@@ -216,65 +125,27 @@ ul.random.image li img { margin: 0 auto; }
   margin: 5px 10px 5px 0;
 }
 
-/* --- Record --- */
-.tagList button {
-  margin-top: 0;
-  padding-top: 0;
-  padding-bottom: 4px;
-  font-size: 95%;
-  vertical-align: initial;
-}
-.tagList button .fa-close { margin-top: 3px; }
-
-/* --- Search --- */
-.bulkActionButtons { margin-bottom: 6px; }
-.result {
-  padding: 1rem;
-  margin-left: -1.1rem;
-  &:nth-child(even) { background-color: @gray-lighter; }
-  &.embedded .getFull.expanded {
-    margin-top: -6px;
-    padding-top: .5rem;
-    padding-bottom: .5rem;
-  }
-}
-.result > p {padding:0 1em;}
-.result .label {
-  display: inline-block;
-  margin-bottom: 4px;
-}
-.result .long-view .tab-content {background: #FFF;}
-.result .media { margin: 0; }
-.result .row { padding: 0; }
-.result .savedLists {
-  margin: 0 0 4px;
-  padding: 4px 0 4px 6px;
-}
-.result .savedLists ul { padding-left: 18px; }
-.search-controls label { text-align: left; }
-@media (max-width: 767px) {
-  .result .search-controls .form-inline { text-align: left; }
-  .search-controls {
-    margin: 4px -4px;
-    padding: 4px 0;
-  }
-}
-
 /* --- Sidebar --- */
 .sidebar {
-  .list-group { margin-bottom: 5px; }
-  .list-group label.list-group-item { padding-left: 26px; }
-  .list-group label.list-group-item input[type=checkbox] { margin-top: 2px; }
+  .facet-group { margin-bottom: 5px; }
+  .facet-group label.list-group-item { padding-left: 26px; }
+  .facet-group label.list-group-item input[type=checkbox] { margin-top: 2px; }
 
-  .list-group-item { padding: 7px 10px 6px; }
-  .list-group-item.active { color: #fff; }
-  .list-group-item.active .badge { color: @active-orange; }
-  .list-group-item.active,
-  .list-group-item.active:hover {
-    background: @active-orange;
+  .facet { padding: 7px 10px 6px; }
+  .facet.active,
+  .facet.active:hover,
+  .active-filters .facet {
+    color: #fff;
+    background-color: @active-orange;
     border-color: @active-orange;
   }
-  .list-group-item .badge a { color: #fff; }
+  .facet.active .badge,
+  .jstree-node.active .badge,
+  .jstree-node.active .badge .fa { color: @active-orange; }
+  .facet .badge a { color: #fff; }
+
+  .facet.facetOR { padding-left: 1rem; }
+  .facet.excludable { padding-right: 0; }
 }
 .slider-container .slider-handle {
   background: @brand-primary;
@@ -289,3 +160,5 @@ ul.random.image li img { margin: 0 auto; }
   color: #fff;
   &:hover { color: @brand-danger; }
 }
+.jstree-facet .jstree-ocl::before { margin-left: -5px; }
+.jstree-node.active { background-color: @active-orange; }
diff --git a/themes/bootprint3/less/common.less b/themes/bootprint3/less/common.less
new file mode 100644
index 0000000000000000000000000000000000000000..b4f6dfded9ab4fcac27ab2a9216ae43226370883
--- /dev/null
+++ b/themes/bootprint3/less/common.less
@@ -0,0 +1,109 @@
+a,
+.btn-link {
+  color: #06C;
+  &:hover { color: #09F; }
+}
+.alert { padding: 8px; }
+.breadcrumbs .container {
+  border-top: 1px solid #ddd;
+  border-bottom: 1px solid #ddd;
+}
+.breadcrumb {
+  margin-top: .25rem;
+  margin-bottom: .25rem;
+  padding-left: 0;
+  font-size: 12px;
+}
+.btn { padding: 3px 5px 2px; }
+.btn.btn-default {
+  background: @gray-lighter;
+  background-image: linear-gradient(#fff, @nav-tabs-border-color);
+  border: 1px solid @gray;
+  color: @gray-darker;
+  text-shadow: 0 1px 0 #fff;
+}
+.btn:not(.btn-default) { font-weight:bold; }
+.btn-danger,
+.btn-danger:hover  { border-color:darken(@brand-danger,  12%); }
+.btn-info,
+.btn-info:hover    { border-color:darken(@brand-info,    12%); }
+.btn-primary,
+.btn-primary:hover { border-color:darken(@brand-primary, 12%); }
+.btn-success,
+.btn-success:hover { border-color:darken(@brand-success, 12%); }
+.btn-warning,
+.btn-warning:hover { border-color:darken(@brand-warning, 12%); }
+.container {
+  padding: 0;
+  background: #fff;
+}
+
+h2 { margin: 8px 0; }
+
+.container {
+  padding-left: 1rem;
+  padding-right: 1rem;
+  background: #fff;
+}
+
+input[type=radio],
+input[type=checkbox] {
+  margin: 2px auto 0;
+  padding: 0 2px;
+}
+.nav > li > a { padding: 5px 10px; }
+.nav-pills {
+  display: table;
+  margin: 0 auto;
+}
+.navbar { min-height: 1px; }
+.navbar-form {
+  margin-top: .5rem;
+  margin-bottom: .5rem;
+}
+.pagination {
+  display: table;
+  margin: 18px auto;
+}
+.pagination > li > a,
+.pagination > li > span { padding: 4px 12px 3px; }
+.pagination > .active > a,
+.pagination > .active > a:focus,
+.pagination > .active > a:hover,
+.pagination > .active > span,
+.pagination > .active > span:focus,
+.pagination > .active > span:hover {
+  background: @brand-primary;
+  border-color: @brand-primary;
+}
+.panel-heading { padding: 0; }
+.panel-heading a {
+  cursor: pointer;
+  display: inline-block;
+  padding: 6px;
+  width: 100%;
+}
+.row:not(.top-row) {
+  padding: 6px 4px;
+  margin: 0 -4px;
+}
+.row > p { padding: 0 1em; }
+.sub-breadcrumb { padding: 0 5px; }
+.tab-content {
+  padding: 6px 8px;
+  border: 1px solid @gray-lighter;
+  border-top: 0;
+  margin-bottom: 5px;
+}
+
+@media (max-width: 767px) {
+  .label { font-size: 85%; }
+}
+@media (min-width: 768px) {
+  .badge {
+    font-size: 85%;
+    margin-top: 1px;
+  }
+  .label { padding-top: .3em; }
+  .modal-dialog { width: 650px; }
+}
diff --git a/themes/bootprint3/less/forms.less b/themes/bootprint3/less/forms.less
new file mode 100644
index 0000000000000000000000000000000000000000..6d26bd5465987004d50b1a75f73ae66f3b2ef487
--- /dev/null
+++ b/themes/bootprint3/less/forms.less
@@ -0,0 +1,19 @@
+legend { margin: 0; }
+
+@media (min-width: 768px) {
+  .form-fix-database,
+  .form-oai-home,
+  .form-search-reserves {
+    .control-label {
+      width: 200px;
+      padding-left: 1rem;
+      padding-right: 1rem;
+      text-align: right;
+    }
+    .form-control {
+      display: inline-table;
+      width: 300px;
+    }
+    .form-group > .btn:first-child { margin-left: 200px; }
+  }
+}
diff --git a/themes/bootprint3/less/icons.less b/themes/bootprint3/less/icons.less
index 6ab6c37e0afffa613bea4688f4ff7b97c873027c..7bd591defba94734236577b7a548bfd27e3def19 100644
--- a/themes/bootprint3/less/icons.less
+++ b/themes/bootprint3/less/icons.less
@@ -2,7 +2,7 @@
 .bp-icon {
   background-position: center center;
   background-repeat: no-repeat;
-  color: transparent;
+  color: transparent !important;
   content: '';
   display: inline-block;
   height: 16px;
@@ -12,112 +12,113 @@
   vertical-align: text-bottom;
   width: 16px;
 }
-.fa-x { background-image: ~"url('@{bp3-icon-path}/page_white.png')"; &:extend(.bp-icon); }
-i.fa-archive { background-image: ~"url('@{bp3-icon-path}/package.png')"; &:extend(.bp-icon); }
-i.fa-asterisk { background-image: ~"url('@{bp3-icon-path}/list.png')"; &:extend(.bp-icon); }
-i.fa-atlas { background-image: ~"url('@{bp3-icon-path}/map.png')"; &:extend(.bp-icon); }
-i.fa-bell { background-image: ~"url('@{bp3-icon-path}/bell.png')"; &:extend(.bp-icon); }
-i.fa-book { background-image: ~"url('@{bp3-icon-path}/book.png')"; &:extend(.bp-icon); }
-i.fa-bookbag-add { background-image: ~"url('@{bp3-icon-path}/bookbag_add.png')"; &:extend(.bp-icon); }
-i.fa-bookbag-delete { background-image: ~"url('@{bp3-icon-path}/bookbag_delete.png')"; &:extend(.bp-icon); }
-i.fa-bookbag-empty { background-image: ~"url('@{bp3-icon-path}/bookbag_empty.png')"; &:extend(.bp-icon); }
-i.fa-bookmark { background-image: ~"url('@{bp3-icon-path}/bookmark_add.png')"; &:extend(.bp-icon); }
-i.fa-braille { background-image: ~"url('@{bp3-icon-path}/page_red.png')"; &:extend(.bp-icon); }
-i.fa-cancel-all-holds { background-image: ~"url('@{bp3-icon-path}/holdCancelAll.png')"; &:extend(.bp-icon); }
-i.fa-cancel-all-storage-retrieval-requests { background-image: ~"url('@{bp3-icon-path}/holdCancelAll.png')"; &:extend(.bp-icon); }
-i.fa-cancel-holds { background-image: ~"url('@{bp3-icon-path}/holdCancel.png')"; &:extend(.bp-icon); }
-i.fa-cancel-storage-retrieval-requests { background-image: ~"url('@{bp3-icon-path}/holdCancel.png')"; &:extend(.bp-icon); }
-i.fa-cdrom { background-image: ~"url('@{bp3-icon-path}/cd.png')"; &:extend(.bp-icon); }
-i.fa-chart { background-image: ~"url('@{bp3-icon-path}/chart_bar.png')"; &:extend(.bp-icon); }
-i.fa-chipcartridge { background-image: ~"url('@{bp3-icon-path}/server.png')"; &:extend(.bp-icon); }
-i.fa-collage { background-image: ~"url('@{bp3-icon-path}/pictures.png')"; &:extend(.bp-icon); }
-i.fa-close { background-image: ~"url('@{bp3-icon-path}/cross.png')"; &:extend(.bp-icon); }
-i.fa-disccartridge { background-image: ~"url('@{bp3-icon-path}/cd.png')"; &:extend(.bp-icon); }
-i.fa-drawing { background-image: ~"url('@{bp3-icon-path}/photo.png')"; &:extend(.bp-icon); }
-i.fa-ebook { background-image: ~"url('@{bp3-icon-path}/book_addresses.png')"; &:extend(.bp-icon); }
-i.fa-edit { background-image: ~"url('@{bp3-icon-path}/edit.png')"; &:extend(.bp-icon); }
-i.fa-electronic { background-image: ~"url('@{bp3-icon-path}/mouse.png')"; &:extend(.bp-icon); }
+.fa-x { background-image: url("@{bp3-icon-path}/page_white.png"); &:extend(.bp-icon); }
+i.fa-archive { background-image: url("@{bp3-icon-path}/package.png"); &:extend(.bp-icon); }
+i.fa-asterisk { background-image: url("@{bp3-icon-path}/list.png"); &:extend(.bp-icon); }
+i.fa-atlas { background-image: url("@{bp3-icon-path}/map.png"); &:extend(.bp-icon); }
+i.fa-bell { background-image: url("@{bp3-icon-path}/bell.png"); &:extend(.bp-icon); }
+i.fa-book { background-image: url("@{bp3-icon-path}/book.png"); &:extend(.bp-icon); }
+i.fa-bookbag-add { background-image: url("@{bp3-icon-path}/bookbag_add.png"); &:extend(.bp-icon); }
+i.fa-bookbag-delete { background-image: url("@{bp3-icon-path}/bookbag_delete.png"); &:extend(.bp-icon); }
+i.fa-bookbag-empty { background-image: url("@{bp3-icon-path}/bookbag_empty.png"); &:extend(.bp-icon); }
+i.fa-bookmark { background-image: url("@{bp3-icon-path}/bookmark_add.png"); &:extend(.bp-icon); }
+i.fa-braille { background-image: url("@{bp3-icon-path}/page_red.png"); &:extend(.bp-icon); }
+i.fa-cancel-all-holds { background-image: url("@{bp3-icon-path}/holdCancelAll.png"); &:extend(.bp-icon); }
+i.fa-cancel-all-storage-retrieval-requests { background-image: url("@{bp3-icon-path}/holdCancelAll.png"); &:extend(.bp-icon); }
+i.fa-cancel-holds { background-image: url("@{bp3-icon-path}/holdCancel.png"); &:extend(.bp-icon); }
+i.fa-cancel-storage-retrieval-requests { background-image: url("@{bp3-icon-path}/holdCancel.png"); &:extend(.bp-icon); }
+i.fa-cdrom { background-image: url("@{bp3-icon-path}/cd.png"); &:extend(.bp-icon); }
+i.fa-chart { background-image: url("@{bp3-icon-path}/chart_bar.png"); &:extend(.bp-icon); }
+i.fa-chipcartridge { background-image: url("@{bp3-icon-path}/server.png"); &:extend(.bp-icon); }
+i.fa-collage { background-image: url("@{bp3-icon-path}/pictures.png"); &:extend(.bp-icon); }
+i.fa-close { background-image: url("@{bp3-icon-path}/cross.png"); &:extend(.bp-icon); }
+i.fa-disccartridge { background-image: url("@{bp3-icon-path}/cd.png"); &:extend(.bp-icon); }
+i.fa-drawing { background-image: url("@{bp3-icon-path}/photo.png"); &:extend(.bp-icon); }
+i.fa-ebook { background-image: url("@{bp3-icon-path}/book_addresses.png"); &:extend(.bp-icon); }
+i.fa-edit { background-image: url("@{bp3-icon-path}/edit.png"); &:extend(.bp-icon); }
+i.fa-electronic { background-image: url("@{bp3-icon-path}/mouse.png"); &:extend(.bp-icon); }
 i.fa-email,
 i.fa-envelope,
-i.fa-envelope-o { background-image: ~"url('@{bp3-icon-path}/email.png')"; &:extend(.bp-icon); }
-i.fa-exchange { background-image: ~"url('@{bp3-icon-path}/arrow_refresh.png')"; &:extend(.bp-icon); }
-i.fa-external-link { background-image: ~"url('@{bp3-icon-path}/link_go.png')"; &:extend(.bp-icon); }
-i.fa-filmstrip { background-image: ~"url('@{bp3-icon-path}/film.png')"; &:extend(.bp-icon); }
-i.fa-flag { background-image: ~"url('@{bp3-icon-path}/flag_red.png')"; &:extend(.bp-icon); }
-i.fa-flashcard { background-image: ~"url('@{bp3-icon-path}/table_lightening.png')"; &:extend(.bp-icon); }
-i.fa-floppydisk { background-image: ~"url('@{bp3-icon-path}/disk.png')"; &:extend(.bp-icon); }
-i.fa-globe { background-image: ~"url('@{bp3-icon-path}/world.png')"; &:extend(.bp-icon); }
-i.fa-grid { background-image: ~"url('@{bp3-icon-path}/view_grid.png')"; &:extend(.bp-icon); }
-i.fa-heart { background-image: ~"url('@{bp3-icon-path}/heart.png')"; &:extend(.bp-icon); }
-i.fa-home { background-image: ~"url('@{bp3-icon-path}/house.png')"; &:extend(.bp-icon); }
-i.fa-inbox { background-image: ~"url('@{bp3-icon-path}/box.png')"; &:extend(.bp-icon); }
-i.fa-journal { background-image: ~"url('@{bp3-icon-path}/book.png')"; &:extend(.bp-icon); }
-i.fa-kit { background-image: ~"url('@{bp3-icon-path}/briefcase.png')"; &:extend(.bp-icon); }
-i.fa-leaf,.fa-sitemap { background-image: ~"url('@{bp3-icon-path}/treeCurrent.png')"; &:extend(.bp-icon); }
-i.fa-list { background-image: ~"url('@{bp3-icon-path}/view_list.png')"; &:extend(.bp-icon); }
-i.fa-list-alt,i.fa-export { background-image: ~"url('@{bp3-icon-path}/application_add.png')"; &:extend(.bp-icon); }
-i.fa-lock { background-image: ~"url('@{bp3-icon-path}/lock.png')"; &:extend(.bp-icon); }
-i.fa-manuscript { background-image: ~"url('@{bp3-icon-path}/script.png')"; &:extend(.bp-icon); }
-i.fa-map { background-image: ~"url('@{bp3-icon-path}/map.png')"; &:extend(.bp-icon); }
-i.fa-microfilm { background-image: ~"url('@{bp3-icon-path}/film.png')"; &:extend(.bp-icon); }
-i.fa-minus-circle,i.fa-minus-sign { background-image: ~"url('@{bp3-icon-path}/delete.png')"; &:extend(.bp-icon); }
-i.fa-mobile { background-image: ~"url('@{bp3-icon-path}/phone.png')"; &:extend(.bp-icon); }
-i.fa-motionpicture { background-image: ~"url('@{bp3-icon-path}/television.png')"; &:extend(.bp-icon); }
-i.fa-musicalscore { background-image: ~"url('@{bp3-icon-path}/music.png')"; &:extend(.bp-icon); }
-i.fa-musicrecording { background-image: ~"url('@{bp3-icon-path}/music.png')"; &:extend(.bp-icon); }
-i.fa-newspaper { background-image: ~"url('@{bp3-icon-path}/newspaper.png')"; &:extend(.bp-icon); }
-i.fa-ok { background-image: ~"url('@{bp3-icon-path}/tick.png')"; &:extend(.bp-icon); }
-i.fa-online { background-image: ~"url('@{bp3-icon-path}/computer.png')"; &:extend(.bp-icon); }
-i.fa-painting { background-image: ~"url('@{bp3-icon-path}/paintbrush.png')"; &:extend(.bp-icon); }
-i.fa-photo { background-image: ~"url('@{bp3-icon-path}/photo.png')"; &:extend(.bp-icon); }
-i.fa-photonegative { background-image: ~"url('@{bp3-icon-path}/film.png')"; &:extend(.bp-icon); }
-i.fa-physicalobject { background-image: ~"url('@{bp3-icon-path}/box.png')"; &:extend(.bp-icon); }
-i.fa-plus { background-image: ~"url('@{bp3-icon-path}/add.png')"; &:extend(.bp-icon); }
-i.fa-plus-circle { background-image: ~"url('@{bp3-icon-path}/add.png')"; &:extend(.bp-icon); }
-i.fa-print { background-image: ~"url('@{bp3-icon-path}/printer.png')"; &:extend(.bp-icon); }
-i.fa-qrcode { background-image: ~"url('@{bp3-icon-path}/qrcode.png')"; &:extend(.bp-icon); }
-i.fa-remove { background-image: ~"url('@{bp3-icon-path}/delete.png')"; &:extend(.bp-icon); }
-i.fa-renew { background-image: ~"url('@{bp3-icon-path}/renew.png')"; &:extend(.bp-icon); }
-i.fa-renew-all { background-image: ~"url('@{bp3-icon-path}/renewAll.png')"; &:extend(.bp-icon); }
-i.fa-report { background-image: ~"url('@{bp3-icon-path}/report.png')"; &:extend(.bp-icon); }
-i.fa-rss { background-image: ~"url('@{bp3-icon-path}/feed.png')"; &:extend(.bp-icon); }
-i.fa-save { background-image: ~"url('@{bp3-icon-path}/disk.png')"; &:extend(.bp-icon); }
-i.fa-search { background-image: ~"url('@{bp3-icon-path}/magnifier.png')"; &:extend(.bp-icon); }
-i.fa-sensorimage { background-image: ~"url('@{bp3-icon-path}/photo.png')"; &:extend(.bp-icon); }
-i.fa-serial { background-image: ~"url('@{bp3-icon-path}/page_white_stack.png')"; &:extend(.bp-icon); }
-i.fa-shopping-cart { background-image: ~"url('@{bp3-icon-path}/cart.png')"; &:extend(.bp-icon); }
-i.fa-sign-in { background-image: ~"url('@{bp3-icon-path}/door_in.png')"; &:extend(.bp-icon); }
-i.fa-sign-out { background-image: ~"url('@{bp3-icon-path}/door_out.png')"; &:extend(.bp-icon); }
-i.fa-slide { background-image: ~"url('@{bp3-icon-path}/film.png')"; &:extend(.bp-icon); }
-i.fa-software { background-image: ~"url('@{bp3-icon-path}/drive_cd.png')"; &:extend(.bp-icon); }
-i.fa-soundcassette { background-image: ~"url('@{bp3-icon-path}/sound.png')"; &:extend(.bp-icon); }
-i.fa-sounddisc { background-image: ~"url('@{bp3-icon-path}/cd.png')"; &:extend(.bp-icon); }
-i.fa-soundrecording { background-image: ~"url('@{bp3-icon-path}/sound.png')"; &:extend(.bp-icon); }
-i.fa-spinner { background-image: ~"url('@{bp3-icon-path}/ajax_loading.gif')"; &:extend(.bp-icon); }
-i.fa-star { background-image: ~"url('@{bp3-icon-path}/star.png')"; &:extend(.bp-icon); }
-i.fa-status-unknown { background-image: ~"url('@{bp3-icon-path}/bullet_orange.png')"; &:extend(.bp-icon); }
-i.fa-suitcase { background-image: ~"url('@{bp3-icon-path}/bookbag.png')"; &:extend(.bp-icon); }
-i.fa-tapecartridge { background-image: ~"url('@{bp3-icon-path}/drive.png')"; &:extend(.bp-icon); }
-i.fa-tapecassette { background-image: ~"url('@{bp3-icon-path}/drive.png')"; &:extend(.bp-icon); }
-i.fa-tapereel { background-image: ~"url('@{bp3-icon-path}/film.png')"; &:extend(.bp-icon); }
-i.fa-transparency { background-image: ~"url('@{bp3-icon-path}/film.png')"; &:extend(.bp-icon); }
+i.fa-envelope-o { background-image: url("@{bp3-icon-path}/email.png"); &:extend(.bp-icon); }
+i.fa-exchange { background-image: url("@{bp3-icon-path}/arrow_refresh.png"); &:extend(.bp-icon); }
+i.fa-external-link { background-image: url("@{bp3-icon-path}/link_go.png"); &:extend(.bp-icon); }
+i.fa-filmstrip { background-image: url("@{bp3-icon-path}/film.png"); &:extend(.bp-icon); }
+i.fa-flag { background-image: url("@{bp3-icon-path}/flag_red.png"); &:extend(.bp-icon); }
+i.fa-flashcard { background-image: url("@{bp3-icon-path}/table_lightening.png"); &:extend(.bp-icon); }
+i.fa-floppydisk { background-image: url("@{bp3-icon-path}/disk.png"); &:extend(.bp-icon); }
+i.fa-globe { background-image: url("@{bp3-icon-path}/world.png"); &:extend(.bp-icon); }
+i.fa-grid { background-image: url("@{bp3-icon-path}/view_grid.png"); &:extend(.bp-icon); }
+i.fa-heart { background-image: url("@{bp3-icon-path}/heart.png"); &:extend(.bp-icon); }
+i.fa-home { background-image: url("@{bp3-icon-path}/house.png"); &:extend(.bp-icon); }
+i.fa-inbox { background-image: url("@{bp3-icon-path}/box.png"); &:extend(.bp-icon); }
+i.fa-journal { background-image: url("@{bp3-icon-path}/book.png"); &:extend(.bp-icon); }
+i.fa-kit { background-image: url("@{bp3-icon-path}/briefcase.png"); &:extend(.bp-icon); }
+i.fa-leaf,.fa-sitemap { background-image: url("@{bp3-icon-path}/treeCurrent.png"); &:extend(.bp-icon); }
+i.fa-list { background-image: url("@{bp3-icon-path}/view_list.png"); &:extend(.bp-icon); }
+i.fa-list-alt,i.fa-export { background-image: url("@{bp3-icon-path}/application_add.png"); &:extend(.bp-icon); }
+i.fa-lock { background-image: url("@{bp3-icon-path}/lock.png"); &:extend(.bp-icon); }
+i.fa-manuscript { background-image: url("@{bp3-icon-path}/script.png"); &:extend(.bp-icon); }
+i.fa-map { background-image: url("@{bp3-icon-path}/map.png"); &:extend(.bp-icon); }
+i.fa-microfilm { background-image: url("@{bp3-icon-path}/film.png"); &:extend(.bp-icon); }
+i.fa-minus-circle,i.fa-minus-sign { background-image: url("@{bp3-icon-path}/delete.png"); &:extend(.bp-icon); }
+i.fa-mobile { background-image: url("@{bp3-icon-path}/phone.png"); &:extend(.bp-icon); }
+i.fa-motionpicture { background-image: url("@{bp3-icon-path}/television.png"); &:extend(.bp-icon); }
+i.fa-musicalscore { background-image: url("@{bp3-icon-path}/music.png"); &:extend(.bp-icon); }
+i.fa-musicrecording { background-image: url("@{bp3-icon-path}/music.png"); &:extend(.bp-icon); }
+i.fa-newspaper { background-image: url("@{bp3-icon-path}/newspaper.png"); &:extend(.bp-icon); }
+i.fa-ok { background-image: url("@{bp3-icon-path}/tick.png"); &:extend(.bp-icon); }
+i.fa-online { background-image: url("@{bp3-icon-path}/computer.png"); &:extend(.bp-icon); }
+i.fa-painting { background-image: url("@{bp3-icon-path}/paintbrush.png"); &:extend(.bp-icon); }
+i.fa-photo { background-image: url("@{bp3-icon-path}/photo.png"); &:extend(.bp-icon); }
+i.fa-photonegative { background-image: url("@{bp3-icon-path}/film.png"); &:extend(.bp-icon); }
+i.fa-physicalobject { background-image: url("@{bp3-icon-path}/box.png"); &:extend(.bp-icon); }
+i.fa-plus { background-image: url("@{bp3-icon-path}/add.png"); &:extend(.bp-icon); }
+i.fa-plus-circle { background-image: url("@{bp3-icon-path}/add.png"); &:extend(.bp-icon); }
+i.fa-print { background-image: url("@{bp3-icon-path}/printer.png"); &:extend(.bp-icon); }
+i.fa-qrcode { background-image: url("@{bp3-icon-path}/qrcode.png"); &:extend(.bp-icon); }
+i.fa-remove { background-image: url("@{bp3-icon-path}/delete.png"); &:extend(.bp-icon); }
+i.fa-renew { background-image: url("@{bp3-icon-path}/renew.png"); &:extend(.bp-icon); }
+i.fa-renew-all { background-image: url("@{bp3-icon-path}/renewAll.png"); &:extend(.bp-icon); }
+i.fa-report { background-image: url("@{bp3-icon-path}/report.png"); &:extend(.bp-icon); }
+i.fa-rss { background-image: url("@{bp3-icon-path}/feed.png"); &:extend(.bp-icon); }
+i.fa-save { background-image: url("@{bp3-icon-path}/disk.png"); &:extend(.bp-icon); }
+i.fa-search { background-image: url("@{bp3-icon-path}/magnifier.png"); &:extend(.bp-icon); }
+i.fa-search-plus { background-image: url("@{bp3-icon-path}/magnifier_zoom_in.png"); &:extend(.bp-icon); }
+i.fa-sensorimage { background-image: url("@{bp3-icon-path}/photo.png"); &:extend(.bp-icon); }
+i.fa-serial { background-image: url("@{bp3-icon-path}/page_white_stack.png"); &:extend(.bp-icon); }
+i.fa-shopping-cart { background-image: url("@{bp3-icon-path}/cart.png"); &:extend(.bp-icon); }
+i.fa-sign-in { background-image: url("@{bp3-icon-path}/door_in.png"); &:extend(.bp-icon); }
+i.fa-sign-out { background-image: url("@{bp3-icon-path}/door_out.png"); &:extend(.bp-icon); }
+i.fa-slide { background-image: url("@{bp3-icon-path}/film.png"); &:extend(.bp-icon); }
+i.fa-software { background-image: url("@{bp3-icon-path}/drive_cd.png"); &:extend(.bp-icon); }
+i.fa-soundcassette { background-image: url("@{bp3-icon-path}/sound.png"); &:extend(.bp-icon); }
+i.fa-sounddisc { background-image: url("@{bp3-icon-path}/cd.png"); &:extend(.bp-icon); }
+i.fa-soundrecording { background-image: url("@{bp3-icon-path}/sound.png"); &:extend(.bp-icon); }
+i.fa-spinner { background-image: url("@{bp3-icon-path}/ajax_loading.gif"); &:extend(.bp-icon); }
+i.fa-star { background-image: url("@{bp3-icon-path}/star.png"); &:extend(.bp-icon); }
+i.fa-status-unknown { background-image: url("@{bp3-icon-path}/bullet_orange.png"); &:extend(.bp-icon); }
+i.fa-suitcase { background-image: url("@{bp3-icon-path}/bookbag.png"); &:extend(.bp-icon); }
+i.fa-tapecartridge { background-image: url("@{bp3-icon-path}/drive.png"); &:extend(.bp-icon); }
+i.fa-tapecassette { background-image: url("@{bp3-icon-path}/drive.png"); &:extend(.bp-icon); }
+i.fa-tapereel { background-image: url("@{bp3-icon-path}/film.png"); &:extend(.bp-icon); }
+i.fa-transparency { background-image: url("@{bp3-icon-path}/film.png"); &:extend(.bp-icon); }
 i.fa-trash,
-i.fa-trash-o { background-image: ~"url('@{bp3-icon-path}/bin.png')"; &:extend(.bp-icon); }
-i.fa-tree { background-image: ~"url('@{bp3-icon-path}/treeCurrent.png')"; &:extend(.bp-icon); }
-i.fa-tree-muted { background-image: ~"url('@{bp3-icon-path}/treeMuted.png')"; &:extend(.bp-icon); }
-i.fa-unknown { background-image: ~"url('@{bp3-icon-path}/page_white.png')"; &:extend(.bp-icon); }
-i.fa-usd { background-image: ~"url('@{bp3-icon-path}/money_dollar.png')"; &:extend(.bp-icon); }
-i.fa-user { background-image: ~"url('@{bp3-icon-path}/user.png')"; &:extend(.bp-icon); }
-i.fa-video{background-image: ~"url('@{bp3-icon-path}/television.png')"; &:extend(.bp-icon); }
-i.fa-videocartridge { background-image: ~"url('@{bp3-icon-path}/television.png')"; &:extend(.bp-icon); }
-i.fa-videocassette{background-image: ~"url('@{bp3-icon-path}/television.png')"; &:extend(.bp-icon); }
-i.fa-videodisc{background-image: ~"url('@{bp3-icon-path}/cd.png')"; &:extend(.bp-icon); }
-i.fa-videoreel{background-image: ~"url('@{bp3-icon-path}/film.png')"; &:extend(.bp-icon); }
-i.fa-visual { background-image: ~"url('@{bp3-icon-path}/view_visual.png')"; &:extend(.bp-icon); }
+i.fa-trash-o { background-image: url("@{bp3-icon-path}/bin.png"); &:extend(.bp-icon); }
+i.fa-tree { background-image: url("@{bp3-icon-path}/treeCurrent.png"); &:extend(.bp-icon); }
+i.fa-tree-muted { background-image: url("@{bp3-icon-path}/treeMuted.png"); &:extend(.bp-icon); }
+i.fa-unknown { background-image: url("@{bp3-icon-path}/page_white.png"); &:extend(.bp-icon); }
+i.fa-usd { background-image: url("@{bp3-icon-path}/money_dollar.png"); &:extend(.bp-icon); }
+i.fa-user { background-image: url("@{bp3-icon-path}/user.png"); &:extend(.bp-icon); }
+i.fa-video{background-image: url("@{bp3-icon-path}/television.png"); &:extend(.bp-icon); }
+i.fa-videocartridge { background-image: url("@{bp3-icon-path}/television.png"); &:extend(.bp-icon); }
+i.fa-videocassette{background-image: url("@{bp3-icon-path}/television.png"); &:extend(.bp-icon); }
+i.fa-videodisc{background-image: url("@{bp3-icon-path}/cd.png"); &:extend(.bp-icon); }
+i.fa-videoreel{background-image: url("@{bp3-icon-path}/film.png"); &:extend(.bp-icon); }
+i.fa-visual { background-image: url("@{bp3-icon-path}/view_visual.png"); &:extend(.bp-icon); }
 
 body.rtl {
-  i.fa-external-link { background-image: ~"url('@{bp3-icon-path}/link_go_rtl.png')"; }
-  i.fa-flag { background-image: ~"url('@{bp3-icon-path}/flag_red_rtl.png')"; }
+  i.fa-external-link { background-image: url("@{bp3-icon-path}/link_go_rtl.png"); }
+  i.fa-flag { background-image: url("@{bp3-icon-path}/flag_red_rtl.png"); }
 }
 
-#cart-empty-label i.fa-close { background-image: ~"url('@{bp3-icon-path}/briefcase.png')"; &:extend(.bp-icon); }
+#cart-empty-label i.fa-close { background-image: url("@{bp3-icon-path}/briefcase.png"); &:extend(.bp-icon); }
diff --git a/themes/bootprint3/less/search.less b/themes/bootprint3/less/search.less
index 90ee8ce35b44caf2364a22449beaddf605f4b753..772c18080713332fda656b357cd640f1302bad10 100644
--- a/themes/bootprint3/less/search.less
+++ b/themes/bootprint3/less/search.less
@@ -3,14 +3,12 @@
   margin: 1em auto;
   width: 90%;
 }
-#advSearchForm .search { margin: 0; }
 .group .match { margin-top: .5em; }
 
 /* --- Search form --- */
 .searchForm_lookfor,
 .searchForm_type { border-color: @brand-primary; }
-[name=searchForm] {
-  margin: 6px 8px 8px;
+.searchForm {
   padding: 0;
 
   .clear-btn,
@@ -49,3 +47,108 @@
     z-index: 5;
   }
 }
+
+.bulkActionButtons { padding-bottom: 1rem; }
+.top-facets .facet a { vertical-align: middle; }
+.result {
+  padding: 1rem;
+  margin-left: -1rem; // Bring result to the edge of the container
+  &:nth-child(even) { background-color: @gray-lighter; }
+  &.embedded .getFull.expanded {
+    margin-top: -6px;
+    padding-top: .5rem;
+    padding-bottom: .5rem;
+  }
+}
+.result > p { padding:0 1em; }
+.result .long-view .tab-content { background: #fff; }
+.result .media { margin: 0; }
+.result .row { padding: 0; }
+.result .savedLists {
+  margin: 0 0 4px;
+  padding: 4px 0 4px 6px;
+}
+.result .savedLists ul { padding-left: 18px; }
+.search-controls label {
+  margin: 0;
+  vertical-align: middle;
+}
+.search-stats { color: @gray; }
+
+/* --- Advanced --- */
+legend {
+  margin-top: 2rem;
+  margin-bottom: 0;
+}
+
+.grid-result { padding-top: 1rem; }
+.grid-checkbox {
+  text-align: right;
+  cursor: pointer;
+}
+.grid-body {
+  text-align: center;
+
+  .status {
+    margin-top: .5rem;
+    margin-bottom: .5rem;
+  }
+}
+
+.template-dir-eds.template-name-advanced h2,
+.template-dir-search.template-name-advanced h2 { margin-top: 3px; }
+
+/* --- Combined --- */
+.combined-column {
+  padding-left: 1rem;
+  padding-right: 1rem;
+
+  .result {
+    margin-right: -1rem;
+    padding-right: .5rem;
+  }
+}
+.template-dir-combined.template-name-results {
+  &.offcanvas {
+    margin-left: .5rem;
+    margin-right: .5rem;
+  }
+  .main .container {
+    width: 100%;
+    padding-left: 0;
+    padding-right: 0;
+  }
+
+  header,
+  .breadcrumbs,
+  .main,
+  footer { background-color: #fff; }
+
+  header { border-radius: 5px 5px 0 0; }
+  footer {
+    width: 100%;
+    padding: 1rem;
+    border-radius: 0 0 5px 5px;
+
+    .footer-container,
+    .poweredby { &:extend(.container); }
+  }
+
+  .breadcrumbs {
+    border-top: 1px solid #ddd;
+    border-bottom: 1px solid #ddd;
+  }
+  .breadcrumbs .container { border: 0; }
+
+  .bulkActionButtons { padding-left: 1rem; }
+
+}
+@media (min-width: 768px) {
+  .template-dir-combined.template-name-results {
+    &,
+    &.offcanvas { // overcoming specificity
+      margin-left: 1rem;
+      margin-right: 1rem;
+    }
+  }
+}
diff --git a/themes/bootprint3/scss/bootprint.scss b/themes/bootprint3/scss/bootprint.scss
index 36d2efa7102a0c58b996244dc59090868d2207ee..08ca65316888188e37eff5a03f980f13dc29141c 100644
--- a/themes/bootprint3/scss/bootprint.scss
+++ b/themes/bootprint3/scss/bootprint.scss
@@ -1,112 +1,28 @@
 @import "variables", "bootstrap";
 @import "icons";
 @import "search";
+@import "forms";
 
-$brand-primary: #619144; // a11y overrides $brand-primary in sass
+$brand-primary: #619144; /* a11y overrides $brand-primary in sass */
 $active-orange: #E70 !default;
 
 /* --- Bootstrap MODS ---*/
+@import "common";
+
 body {
   background: $brand-primary;
   font-size: 13px
 }
-.container {
-  background: #FFF;
-  padding: 0;
-}
-.main .container { padding: 0 4px 18px; }
-
-a,
-.btn-link {
-  color: #06C;
-  &:hover { color: #09F; }
-}
-.alert { padding: 8px; }
-.btn { padding: 3px 5px 2px; }
-.btn.btn-default {
-  background: $gray-lighter;
-  background-image: linear-gradient(#FFF, $nav-tabs-border-color);
-  border: 1px solid $gray;
-  color: $gray-darker;
-  text-shadow: 0 1px 0 #FFF;
-}
-.btn:not(.btn-default) { font-weight:bold; }
-.btn-danger,
-.btn-danger:hover  { border-color:darken($brand-danger,  12%); }
-.btn-info,
-.btn-info:hover    { border-color:darken($brand-info,    12%); }
-.btn-primary,
-.btn-primary:hover { border-color:darken($brand-primary, 12%); }
-.btn-success,
-.btn-success:hover { border-color:darken($brand-success, 12%); }
-.btn-warning,
-.btn-warning:hover { border-color:darken($brand-warning, 12%); }
 
 #commentList .comment:nth-child(even) { background: $gray-lighter; }
 #dateVisColorSettings { stroke: $brand-primary; }
-#hierarchyRecord { background: #FFF; }
-h2 { margin: 0 8px 8px; }
-input[type=radio],
-input[type=checkbox] {
-  margin: 2px auto 0;
-  padding: 0 2px;
-}
-.nav > li > a { padding: 5px 10px; }
-.nav-pills {
-  display: table;
-  margin: 0 auto;
-}
-.navbar { min-height: 1px; }
-.navbar-form {
-  margin-top: 5px;
-  margin-bottom: 5px;
-}
-.pagination {
-  display: table;
-  margin: 18px auto;
-}
-.pagination > li > a,
-.pagination > li > span { padding: 4px 12px 3px; }
-.pagination > .active > a,
-.pagination > .active > a:focus,
-.pagination > .active > a:hover,
-.pagination > .active > span,
-.pagination > .active > span:focus,
-.pagination > .active > span:hover {
-  background: $brand-primary;
-  border-color: $brand-primary;
-}
-.panel-heading { padding: 0; }
-.panel-heading a {
-  cursor: pointer;
-  display: inline-block;
-  padding: 6px;
-  width: 100%;
-}
-.row:not(.top-row) {
-  padding: 6px 4px;
-  margin: 0 -4px;
-}
-.row > p { padding: 0 1em; }
-.sub-breadcrumb { padding: 0 5px; }
-.tab-content {
-  padding: 6px 8px;
-  border: 1px solid $gray-lighter;
-  border-top: 0;
-}
+#hierarchyRecord { background: #fff; }
+.cart-controls .checkbox { line-height: 2rem; }
 
-@media (max-width: 767px) {
-  body { padding: 6px; }
-  header { margin-top: 0; }
-  .label { font-size: 85%; }
-}
+/* --- Layout --- */
+.main .container { padding-top: 1rem; }
 @media (min-width: 768px) {
-  .badge {
-    font-size: 85%;
-    margin-top: 1px;
-  }
-  .label { padding-top: .3em; }
-  .modal-dialog { width: 650px; }
+  .main .sidebar { padding: 0; }
 }
 
 /* --- Header --- */
@@ -115,20 +31,20 @@ header .fa.fa-bars { font-size: 21px; }
 header .navbar {
   border-radius: 5px 5px 0 0;
   padding: 0 10px;
-  .searchForm { display: none !important; }
+  &.search { border-radius: 0; }
   .navbar-brand {
     height: 65px;
     width: 170px;
     margin-top: 5px;
     color: transparent;
-    background-image: unquote("url('../../bootprint3/images/vufind_logo.png')");
+    background-image: url('../../bootprint3/images/vufind_logo.png');
     background-position: center center;
     background-repeat: no-repeat;
     background-size: contain;
     &:active,
     &:focus,
     &:hover { color: transparent; }
-    &.lang-ar { background-image: unquote("url('../../bootprint3/images/vufind_logo_ar.png')"); }
+    &.lang-ar { background-image: url('../../bootprint3/images/vufind_logo_ar.png'); }
   }
   .navbar-nav > li > a { padding: 12px 6px; }
   .navbar-right { margin-top: 12px; }
@@ -137,10 +53,6 @@ header .navbar {
     .navbar-right { margin: 0; }
   }
 }
-header .searchbox {
-  background: linear-gradient(to bottom, #FFF, #EEE);
-  display: block !important;
-}
 header .searchbox .tab-content { border: 0; }
 header .searchbox .tab-content .navbar-text { margin: 5px 10px 5px 0; }
 @media (max-width: 767px) {
@@ -150,21 +62,12 @@ header .searchbox .tab-content .navbar-text { margin: 5px 10px 5px 0; }
     margin-bottom: 2px
   }
 }
-header .breadcrumb {
-  border: 1px solid $gray-lighter;
-  border-radius: 0;
-  border-width: 1px 0;
-  font-size: 12px;
-  margin-bottom: 2px;
-  padding: 7px 20px 5px
-}
 
 /* --- Footer --- */
-footer { margin-bottom: 36px; }
-footer .container {
+footer {
+  margin-bottom: 2rem;
   border-radius: 0 0 5px 5px;
   border-top: 1px solid $nav-tabs-border-color;
-  padding-top: 18px;
 }
 footer hr { display: none; }
 footer p { margin: 0; }
@@ -173,6 +76,15 @@ footer ul { padding-left: 30px; }
 /* --- Browse --- */
 [id^=list].list-group .col-sm-9 { margin: 0; }
 
+/* --- Channels --- */
+.channel { margin-bottom: 2rem; }
+.channel-title {
+  margin-top: 1rem;
+  margin-left: -56px;
+}
+.channel-title .fa { margin-top: 4px; }
+.channel-title h2 { padding-left: 50px; }
+
 /* --- Offcanvas --- */
 body.offcanvas {
   .offcanvas-toggle {
@@ -215,65 +127,27 @@ ul.random.image li img { margin: 0 auto; }
   margin: 5px 10px 5px 0;
 }
 
-/* --- Record --- */
-.tagList button {
-  margin-top: 0;
-  padding-top: 0;
-  padding-bottom: 4px;
-  font-size: 95%;
-  vertical-align: initial;
-}
-.tagList button .fa-close { margin-top: 3px; }
-
-/* --- Search --- */
-.bulkActionButtons { margin-bottom: 6px; }
-.result {
-  padding: 1rem;
-  margin-left: -1.1rem;
-  &:nth-child(even) { background-color: $gray-lighter; }
-  &.embedded .getFull.expanded {
-    margin-top: -6px;
-    padding-top: .5rem;
-    padding-bottom: .5rem;
-  }
-}
-.result > p {padding:0 1em;}
-.result .label {
-  display: inline-block;
-  margin-bottom: 4px;
-}
-.result .long-view .tab-content {background: #FFF;}
-.result .media { margin: 0; }
-.result .row { padding: 0; }
-.result .savedLists {
-  margin: 0 0 4px;
-  padding: 4px 0 4px 6px;
-}
-.result .savedLists ul { padding-left: 18px; }
-.search-controls label { text-align: left; }
-@media (max-width: 767px) {
-  .result .search-controls .form-inline { text-align: left; }
-  .search-controls {
-    margin: 4px -4px;
-    padding: 4px 0;
-  }
-}
-
 /* --- Sidebar --- */
 .sidebar {
-  .list-group { margin-bottom: 5px; }
-  .list-group label.list-group-item { padding-left: 26px; }
-  .list-group label.list-group-item input[type=checkbox] { margin-top: 2px; }
+  .facet-group { margin-bottom: 5px; }
+  .facet-group label.list-group-item { padding-left: 26px; }
+  .facet-group label.list-group-item input[type=checkbox] { margin-top: 2px; }
 
-  .list-group-item { padding: 7px 10px 6px; }
-  .list-group-item.active { color: #fff; }
-  .list-group-item.active .badge { color: $active-orange; }
-  .list-group-item.active,
-  .list-group-item.active:hover {
-    background: $active-orange;
+  .facet { padding: 7px 10px 6px; }
+  .facet.active,
+  .facet.active:hover,
+  .active-filters .facet {
+    color: #fff;
+    background-color: $active-orange;
     border-color: $active-orange;
   }
-  .list-group-item .badge a { color: #fff; }
+  .facet.active .badge,
+  .jstree-node.active .badge,
+  .jstree-node.active .badge .fa { color: $active-orange; }
+  .facet .badge a { color: #fff; }
+
+  .facet.facetOR { padding-left: 1rem; }
+  .facet.excludable { padding-right: 0; }
 }
 .slider-container .slider-handle {
   background: $brand-primary;
@@ -288,3 +162,5 @@ ul.random.image li img { margin: 0 auto; }
   color: #fff;
   &:hover { color: $brand-danger; }
 }
+.jstree-facet .jstree-ocl::before { margin-left: -5px; }
+.jstree-node.active { background-color: $active-orange; }
diff --git a/themes/bootprint3/scss/common.scss b/themes/bootprint3/scss/common.scss
new file mode 100644
index 0000000000000000000000000000000000000000..87806fd6954b7e7c32fb6bbbc0e8232eb852ea62
--- /dev/null
+++ b/themes/bootprint3/scss/common.scss
@@ -0,0 +1,109 @@
+a,
+.btn-link {
+  color: #06C;
+  &:hover { color: #09F; }
+}
+.alert { padding: 8px; }
+.breadcrumbs .container {
+  border-top: 1px solid #ddd;
+  border-bottom: 1px solid #ddd;
+}
+.breadcrumb {
+  margin-top: .25rem;
+  margin-bottom: .25rem;
+  padding-left: 0;
+  font-size: 12px;
+}
+.btn { padding: 3px 5px 2px; }
+.btn.btn-default {
+  background: $gray-lighter;
+  background-image: linear-gradient(#fff, $nav-tabs-border-color);
+  border: 1px solid $gray;
+  color: $gray-darker;
+  text-shadow: 0 1px 0 #fff;
+}
+.btn:not(.btn-default) { font-weight:bold; }
+.btn-danger,
+.btn-danger:hover  { border-color:darken($brand-danger,  12%); }
+.btn-info,
+.btn-info:hover    { border-color:darken($brand-info,    12%); }
+.btn-primary,
+.btn-primary:hover { border-color:darken($brand-primary, 12%); }
+.btn-success,
+.btn-success:hover { border-color:darken($brand-success, 12%); }
+.btn-warning,
+.btn-warning:hover { border-color:darken($brand-warning, 12%); }
+.container {
+  padding: 0;
+  background: #fff;
+}
+
+h2 { margin: 8px 0; }
+
+.container {
+  padding-left: 1rem;
+  padding-right: 1rem;
+  background: #fff;
+}
+
+input[type=radio],
+input[type=checkbox] {
+  margin: 2px auto 0;
+  padding: 0 2px;
+}
+.nav > li > a { padding: 5px 10px; }
+.nav-pills {
+  display: table;
+  margin: 0 auto;
+}
+.navbar { min-height: 1px; }
+.navbar-form {
+  margin-top: .5rem;
+  margin-bottom: .5rem;
+}
+.pagination {
+  display: table;
+  margin: 18px auto;
+}
+.pagination > li > a,
+.pagination > li > span { padding: 4px 12px 3px; }
+.pagination > .active > a,
+.pagination > .active > a:focus,
+.pagination > .active > a:hover,
+.pagination > .active > span,
+.pagination > .active > span:focus,
+.pagination > .active > span:hover {
+  background: $brand-primary;
+  border-color: $brand-primary;
+}
+.panel-heading { padding: 0; }
+.panel-heading a {
+  cursor: pointer;
+  display: inline-block;
+  padding: 6px;
+  width: 100%;
+}
+.row:not(.top-row) {
+  padding: 6px 4px;
+  margin: 0 -4px;
+}
+.row > p { padding: 0 1em; }
+.sub-breadcrumb { padding: 0 5px; }
+.tab-content {
+  padding: 6px 8px;
+  border: 1px solid $gray-lighter;
+  border-top: 0;
+  margin-bottom: 5px;
+}
+
+@media (max-width: 767px) {
+  .label { font-size: 85%; }
+}
+@media (min-width: 768px) {
+  .badge {
+    font-size: 85%;
+    margin-top: 1px;
+  }
+  .label { padding-top: .3em; }
+  .modal-dialog { width: 650px; }
+}
diff --git a/themes/bootprint3/scss/forms.scss b/themes/bootprint3/scss/forms.scss
new file mode 100644
index 0000000000000000000000000000000000000000..6d26bd5465987004d50b1a75f73ae66f3b2ef487
--- /dev/null
+++ b/themes/bootprint3/scss/forms.scss
@@ -0,0 +1,19 @@
+legend { margin: 0; }
+
+@media (min-width: 768px) {
+  .form-fix-database,
+  .form-oai-home,
+  .form-search-reserves {
+    .control-label {
+      width: 200px;
+      padding-left: 1rem;
+      padding-right: 1rem;
+      text-align: right;
+    }
+    .form-control {
+      display: inline-table;
+      width: 300px;
+    }
+    .form-group > .btn:first-child { margin-left: 200px; }
+  }
+}
diff --git a/themes/bootprint3/scss/icons.scss b/themes/bootprint3/scss/icons.scss
index 10dbd116a5aa27fc2c4f221bf91365b73c575960..ff55c65d9f5fe1ead08fedc38ed543512a0b6047 100644
--- a/themes/bootprint3/scss/icons.scss
+++ b/themes/bootprint3/scss/icons.scss
@@ -2,7 +2,7 @@ $bp3-icon-path: '../../bootprint3/images/icons' !default;
 .bp-icon {
   background-position: center center;
   background-repeat: no-repeat;
-  color: transparent;
+  color: transparent !important;
   content: '';
   display: inline-block;
   height: 16px;
@@ -12,112 +12,113 @@ $bp3-icon-path: '../../bootprint3/images/icons' !default;
   vertical-align: text-bottom;
   width: 16px;
 }
-.fa-x { background-image: unquote("url('#{$bp3-icon-path}/page_white.png')"); @extend .bp-icon; }
-i.fa-archive { background-image: unquote("url('#{$bp3-icon-path}/package.png')"); @extend .bp-icon; }
-i.fa-asterisk { background-image: unquote("url('#{$bp3-icon-path}/list.png')"); @extend .bp-icon; }
-i.fa-atlas { background-image: unquote("url('#{$bp3-icon-path}/map.png')"); @extend .bp-icon; }
-i.fa-bell { background-image: unquote("url('#{$bp3-icon-path}/bell.png')"); @extend .bp-icon; }
-i.fa-book { background-image: unquote("url('#{$bp3-icon-path}/book.png')"); @extend .bp-icon; }
-i.fa-bookbag-add { background-image: unquote("url('#{$bp3-icon-path}/bookbag_add.png')"); @extend .bp-icon; }
-i.fa-bookbag-delete { background-image: unquote("url('#{$bp3-icon-path}/bookbag_delete.png')"); @extend .bp-icon; }
-i.fa-bookbag-empty { background-image: unquote("url('#{$bp3-icon-path}/bookbag_empty.png')"); @extend .bp-icon; }
-i.fa-bookmark { background-image: unquote("url('#{$bp3-icon-path}/bookmark_add.png')"); @extend .bp-icon; }
-i.fa-braille { background-image: unquote("url('#{$bp3-icon-path}/page_red.png')"); @extend .bp-icon; }
-i.fa-cancel-all-holds { background-image: unquote("url('#{$bp3-icon-path}/holdCancelAll.png')"); @extend .bp-icon; }
-i.fa-cancel-all-storage-retrieval-requests { background-image: unquote("url('#{$bp3-icon-path}/holdCancelAll.png')"); @extend .bp-icon; }
-i.fa-cancel-holds { background-image: unquote("url('#{$bp3-icon-path}/holdCancel.png')"); @extend .bp-icon; }
-i.fa-cancel-storage-retrieval-requests { background-image: unquote("url('#{$bp3-icon-path}/holdCancel.png')"); @extend .bp-icon; }
-i.fa-cdrom { background-image: unquote("url('#{$bp3-icon-path}/cd.png')"); @extend .bp-icon; }
-i.fa-chart { background-image: unquote("url('#{$bp3-icon-path}/chart_bar.png')"); @extend .bp-icon; }
-i.fa-chipcartridge { background-image: unquote("url('#{$bp3-icon-path}/server.png')"); @extend .bp-icon; }
-i.fa-collage { background-image: unquote("url('#{$bp3-icon-path}/pictures.png')"); @extend .bp-icon; }
-i.fa-close { background-image: unquote("url('#{$bp3-icon-path}/cross.png')"); @extend .bp-icon; }
-i.fa-disccartridge { background-image: unquote("url('#{$bp3-icon-path}/cd.png')"); @extend .bp-icon; }
-i.fa-drawing { background-image: unquote("url('#{$bp3-icon-path}/photo.png')"); @extend .bp-icon; }
-i.fa-ebook { background-image: unquote("url('#{$bp3-icon-path}/book_addresses.png')"); @extend .bp-icon; }
-i.fa-edit { background-image: unquote("url('#{$bp3-icon-path}/edit.png')"); @extend .bp-icon; }
-i.fa-electronic { background-image: unquote("url('#{$bp3-icon-path}/mouse.png')"); @extend .bp-icon; }
+.fa-x { background-image: url("#{$bp3-icon-path}/page_white.png"); @extend .bp-icon; }
+i.fa-archive { background-image: url("#{$bp3-icon-path}/package.png"); @extend .bp-icon; }
+i.fa-asterisk { background-image: url("#{$bp3-icon-path}/list.png"); @extend .bp-icon; }
+i.fa-atlas { background-image: url("#{$bp3-icon-path}/map.png"); @extend .bp-icon; }
+i.fa-bell { background-image: url("#{$bp3-icon-path}/bell.png"); @extend .bp-icon; }
+i.fa-book { background-image: url("#{$bp3-icon-path}/book.png"); @extend .bp-icon; }
+i.fa-bookbag-add { background-image: url("#{$bp3-icon-path}/bookbag_add.png"); @extend .bp-icon; }
+i.fa-bookbag-delete { background-image: url("#{$bp3-icon-path}/bookbag_delete.png"); @extend .bp-icon; }
+i.fa-bookbag-empty { background-image: url("#{$bp3-icon-path}/bookbag_empty.png"); @extend .bp-icon; }
+i.fa-bookmark { background-image: url("#{$bp3-icon-path}/bookmark_add.png"); @extend .bp-icon; }
+i.fa-braille { background-image: url("#{$bp3-icon-path}/page_red.png"); @extend .bp-icon; }
+i.fa-cancel-all-holds { background-image: url("#{$bp3-icon-path}/holdCancelAll.png"); @extend .bp-icon; }
+i.fa-cancel-all-storage-retrieval-requests { background-image: url("#{$bp3-icon-path}/holdCancelAll.png"); @extend .bp-icon; }
+i.fa-cancel-holds { background-image: url("#{$bp3-icon-path}/holdCancel.png"); @extend .bp-icon; }
+i.fa-cancel-storage-retrieval-requests { background-image: url("#{$bp3-icon-path}/holdCancel.png"); @extend .bp-icon; }
+i.fa-cdrom { background-image: url("#{$bp3-icon-path}/cd.png"); @extend .bp-icon; }
+i.fa-chart { background-image: url("#{$bp3-icon-path}/chart_bar.png"); @extend .bp-icon; }
+i.fa-chipcartridge { background-image: url("#{$bp3-icon-path}/server.png"); @extend .bp-icon; }
+i.fa-collage { background-image: url("#{$bp3-icon-path}/pictures.png"); @extend .bp-icon; }
+i.fa-close { background-image: url("#{$bp3-icon-path}/cross.png"); @extend .bp-icon; }
+i.fa-disccartridge { background-image: url("#{$bp3-icon-path}/cd.png"); @extend .bp-icon; }
+i.fa-drawing { background-image: url("#{$bp3-icon-path}/photo.png"); @extend .bp-icon; }
+i.fa-ebook { background-image: url("#{$bp3-icon-path}/book_addresses.png"); @extend .bp-icon; }
+i.fa-edit { background-image: url("#{$bp3-icon-path}/edit.png"); @extend .bp-icon; }
+i.fa-electronic { background-image: url("#{$bp3-icon-path}/mouse.png"); @extend .bp-icon; }
 i.fa-email,
 i.fa-envelope,
-i.fa-envelope-o { background-image: unquote("url('#{$bp3-icon-path}/email.png')"); @extend .bp-icon; }
-i.fa-exchange { background-image: unquote("url('#{$bp3-icon-path}/arrow_refresh.png')"); @extend .bp-icon; }
-i.fa-external-link { background-image: unquote("url('#{$bp3-icon-path}/link_go.png')"); @extend .bp-icon; }
-i.fa-filmstrip { background-image: unquote("url('#{$bp3-icon-path}/film.png')"); @extend .bp-icon; }
-i.fa-flag { background-image: unquote("url('#{$bp3-icon-path}/flag_red.png')"); @extend .bp-icon; }
-i.fa-flashcard { background-image: unquote("url('#{$bp3-icon-path}/table_lightening.png')"); @extend .bp-icon; }
-i.fa-floppydisk { background-image: unquote("url('#{$bp3-icon-path}/disk.png')"); @extend .bp-icon; }
-i.fa-globe { background-image: unquote("url('#{$bp3-icon-path}/world.png')"); @extend .bp-icon; }
-i.fa-grid { background-image: unquote("url('#{$bp3-icon-path}/view_grid.png')"); @extend .bp-icon; }
-i.fa-heart { background-image: unquote("url('#{$bp3-icon-path}/heart.png')"); @extend .bp-icon; }
-i.fa-home { background-image: unquote("url('#{$bp3-icon-path}/house.png')"); @extend .bp-icon; }
-i.fa-inbox { background-image: unquote("url('#{$bp3-icon-path}/box.png')"); @extend .bp-icon; }
-i.fa-journal { background-image: unquote("url('#{$bp3-icon-path}/book.png')"); @extend .bp-icon; }
-i.fa-kit { background-image: unquote("url('#{$bp3-icon-path}/briefcase.png')"); @extend .bp-icon; }
-i.fa-leaf,.fa-sitemap { background-image: unquote("url('#{$bp3-icon-path}/treeCurrent.png')"); @extend .bp-icon; }
-i.fa-list { background-image: unquote("url('#{$bp3-icon-path}/view_list.png')"); @extend .bp-icon; }
-i.fa-list-alt,i.fa-export { background-image: unquote("url('#{$bp3-icon-path}/application_add.png')"); @extend .bp-icon; }
-i.fa-lock { background-image: unquote("url('#{$bp3-icon-path}/lock.png')"); @extend .bp-icon; }
-i.fa-manuscript { background-image: unquote("url('#{$bp3-icon-path}/script.png')"); @extend .bp-icon; }
-i.fa-map { background-image: unquote("url('#{$bp3-icon-path}/map.png')"); @extend .bp-icon; }
-i.fa-microfilm { background-image: unquote("url('#{$bp3-icon-path}/film.png')"); @extend .bp-icon; }
-i.fa-minus-circle,i.fa-minus-sign { background-image: unquote("url('#{$bp3-icon-path}/delete.png')"); @extend .bp-icon; }
-i.fa-mobile { background-image: unquote("url('#{$bp3-icon-path}/phone.png')"); @extend .bp-icon; }
-i.fa-motionpicture { background-image: unquote("url('#{$bp3-icon-path}/television.png')"); @extend .bp-icon; }
-i.fa-musicalscore { background-image: unquote("url('#{$bp3-icon-path}/music.png')"); @extend .bp-icon; }
-i.fa-musicrecording { background-image: unquote("url('#{$bp3-icon-path}/music.png')"); @extend .bp-icon; }
-i.fa-newspaper { background-image: unquote("url('#{$bp3-icon-path}/newspaper.png')"); @extend .bp-icon; }
-i.fa-ok { background-image: unquote("url('#{$bp3-icon-path}/tick.png')"); @extend .bp-icon; }
-i.fa-online { background-image: unquote("url('#{$bp3-icon-path}/computer.png')"); @extend .bp-icon; }
-i.fa-painting { background-image: unquote("url('#{$bp3-icon-path}/paintbrush.png')"); @extend .bp-icon; }
-i.fa-photo { background-image: unquote("url('#{$bp3-icon-path}/photo.png')"); @extend .bp-icon; }
-i.fa-photonegative { background-image: unquote("url('#{$bp3-icon-path}/film.png')"); @extend .bp-icon; }
-i.fa-physicalobject { background-image: unquote("url('#{$bp3-icon-path}/box.png')"); @extend .bp-icon; }
-i.fa-plus { background-image: unquote("url('#{$bp3-icon-path}/add.png')"); @extend .bp-icon; }
-i.fa-plus-circle { background-image: unquote("url('#{$bp3-icon-path}/add.png')"); @extend .bp-icon; }
-i.fa-print { background-image: unquote("url('#{$bp3-icon-path}/printer.png')"); @extend .bp-icon; }
-i.fa-qrcode { background-image: unquote("url('#{$bp3-icon-path}/qrcode.png')"); @extend .bp-icon; }
-i.fa-remove { background-image: unquote("url('#{$bp3-icon-path}/delete.png')"); @extend .bp-icon; }
-i.fa-renew { background-image: unquote("url('#{$bp3-icon-path}/renew.png')"); @extend .bp-icon; }
-i.fa-renew-all { background-image: unquote("url('#{$bp3-icon-path}/renewAll.png')"); @extend .bp-icon; }
-i.fa-report { background-image: unquote("url('#{$bp3-icon-path}/report.png')"); @extend .bp-icon; }
-i.fa-rss { background-image: unquote("url('#{$bp3-icon-path}/feed.png')"); @extend .bp-icon; }
-i.fa-save { background-image: unquote("url('#{$bp3-icon-path}/disk.png')"); @extend .bp-icon; }
-i.fa-search { background-image: unquote("url('#{$bp3-icon-path}/magnifier.png')"); @extend .bp-icon; }
-i.fa-sensorimage { background-image: unquote("url('#{$bp3-icon-path}/photo.png')"); @extend .bp-icon; }
-i.fa-serial { background-image: unquote("url('#{$bp3-icon-path}/page_white_stack.png')"); @extend .bp-icon; }
-i.fa-shopping-cart { background-image: unquote("url('#{$bp3-icon-path}/cart.png')"); @extend .bp-icon; }
-i.fa-sign-in { background-image: unquote("url('#{$bp3-icon-path}/door_in.png')"); @extend .bp-icon; }
-i.fa-sign-out { background-image: unquote("url('#{$bp3-icon-path}/door_out.png')"); @extend .bp-icon; }
-i.fa-slide { background-image: unquote("url('#{$bp3-icon-path}/film.png')"); @extend .bp-icon; }
-i.fa-software { background-image: unquote("url('#{$bp3-icon-path}/drive_cd.png')"); @extend .bp-icon; }
-i.fa-soundcassette { background-image: unquote("url('#{$bp3-icon-path}/sound.png')"); @extend .bp-icon; }
-i.fa-sounddisc { background-image: unquote("url('#{$bp3-icon-path}/cd.png')"); @extend .bp-icon; }
-i.fa-soundrecording { background-image: unquote("url('#{$bp3-icon-path}/sound.png')"); @extend .bp-icon; }
-i.fa-spinner { background-image: unquote("url('#{$bp3-icon-path}/ajax_loading.gif')"); @extend .bp-icon; }
-i.fa-star { background-image: unquote("url('#{$bp3-icon-path}/star.png')"); @extend .bp-icon; }
-i.fa-status-unknown { background-image: unquote("url('#{$bp3-icon-path}/bullet_orange.png')"); @extend .bp-icon; }
-i.fa-suitcase { background-image: unquote("url('#{$bp3-icon-path}/bookbag.png')"); @extend .bp-icon; }
-i.fa-tapecartridge { background-image: unquote("url('#{$bp3-icon-path}/drive.png')"); @extend .bp-icon; }
-i.fa-tapecassette { background-image: unquote("url('#{$bp3-icon-path}/drive.png')"); @extend .bp-icon; }
-i.fa-tapereel { background-image: unquote("url('#{$bp3-icon-path}/film.png')"); @extend .bp-icon; }
-i.fa-transparency { background-image: unquote("url('#{$bp3-icon-path}/film.png')"); @extend .bp-icon; }
+i.fa-envelope-o { background-image: url("#{$bp3-icon-path}/email.png"); @extend .bp-icon; }
+i.fa-exchange { background-image: url("#{$bp3-icon-path}/arrow_refresh.png"); @extend .bp-icon; }
+i.fa-external-link { background-image: url("#{$bp3-icon-path}/link_go.png"); @extend .bp-icon; }
+i.fa-filmstrip { background-image: url("#{$bp3-icon-path}/film.png"); @extend .bp-icon; }
+i.fa-flag { background-image: url("#{$bp3-icon-path}/flag_red.png"); @extend .bp-icon; }
+i.fa-flashcard { background-image: url("#{$bp3-icon-path}/table_lightening.png"); @extend .bp-icon; }
+i.fa-floppydisk { background-image: url("#{$bp3-icon-path}/disk.png"); @extend .bp-icon; }
+i.fa-globe { background-image: url("#{$bp3-icon-path}/world.png"); @extend .bp-icon; }
+i.fa-grid { background-image: url("#{$bp3-icon-path}/view_grid.png"); @extend .bp-icon; }
+i.fa-heart { background-image: url("#{$bp3-icon-path}/heart.png"); @extend .bp-icon; }
+i.fa-home { background-image: url("#{$bp3-icon-path}/house.png"); @extend .bp-icon; }
+i.fa-inbox { background-image: url("#{$bp3-icon-path}/box.png"); @extend .bp-icon; }
+i.fa-journal { background-image: url("#{$bp3-icon-path}/book.png"); @extend .bp-icon; }
+i.fa-kit { background-image: url("#{$bp3-icon-path}/briefcase.png"); @extend .bp-icon; }
+i.fa-leaf,.fa-sitemap { background-image: url("#{$bp3-icon-path}/treeCurrent.png"); @extend .bp-icon; }
+i.fa-list { background-image: url("#{$bp3-icon-path}/view_list.png"); @extend .bp-icon; }
+i.fa-list-alt,i.fa-export { background-image: url("#{$bp3-icon-path}/application_add.png"); @extend .bp-icon; }
+i.fa-lock { background-image: url("#{$bp3-icon-path}/lock.png"); @extend .bp-icon; }
+i.fa-manuscript { background-image: url("#{$bp3-icon-path}/script.png"); @extend .bp-icon; }
+i.fa-map { background-image: url("#{$bp3-icon-path}/map.png"); @extend .bp-icon; }
+i.fa-microfilm { background-image: url("#{$bp3-icon-path}/film.png"); @extend .bp-icon; }
+i.fa-minus-circle,i.fa-minus-sign { background-image: url("#{$bp3-icon-path}/delete.png"); @extend .bp-icon; }
+i.fa-mobile { background-image: url("#{$bp3-icon-path}/phone.png"); @extend .bp-icon; }
+i.fa-motionpicture { background-image: url("#{$bp3-icon-path}/television.png"); @extend .bp-icon; }
+i.fa-musicalscore { background-image: url("#{$bp3-icon-path}/music.png"); @extend .bp-icon; }
+i.fa-musicrecording { background-image: url("#{$bp3-icon-path}/music.png"); @extend .bp-icon; }
+i.fa-newspaper { background-image: url("#{$bp3-icon-path}/newspaper.png"); @extend .bp-icon; }
+i.fa-ok { background-image: url("#{$bp3-icon-path}/tick.png"); @extend .bp-icon; }
+i.fa-online { background-image: url("#{$bp3-icon-path}/computer.png"); @extend .bp-icon; }
+i.fa-painting { background-image: url("#{$bp3-icon-path}/paintbrush.png"); @extend .bp-icon; }
+i.fa-photo { background-image: url("#{$bp3-icon-path}/photo.png"); @extend .bp-icon; }
+i.fa-photonegative { background-image: url("#{$bp3-icon-path}/film.png"); @extend .bp-icon; }
+i.fa-physicalobject { background-image: url("#{$bp3-icon-path}/box.png"); @extend .bp-icon; }
+i.fa-plus { background-image: url("#{$bp3-icon-path}/add.png"); @extend .bp-icon; }
+i.fa-plus-circle { background-image: url("#{$bp3-icon-path}/add.png"); @extend .bp-icon; }
+i.fa-print { background-image: url("#{$bp3-icon-path}/printer.png"); @extend .bp-icon; }
+i.fa-qrcode { background-image: url("#{$bp3-icon-path}/qrcode.png"); @extend .bp-icon; }
+i.fa-remove { background-image: url("#{$bp3-icon-path}/delete.png"); @extend .bp-icon; }
+i.fa-renew { background-image: url("#{$bp3-icon-path}/renew.png"); @extend .bp-icon; }
+i.fa-renew-all { background-image: url("#{$bp3-icon-path}/renewAll.png"); @extend .bp-icon; }
+i.fa-report { background-image: url("#{$bp3-icon-path}/report.png"); @extend .bp-icon; }
+i.fa-rss { background-image: url("#{$bp3-icon-path}/feed.png"); @extend .bp-icon; }
+i.fa-save { background-image: url("#{$bp3-icon-path}/disk.png"); @extend .bp-icon; }
+i.fa-search { background-image: url("#{$bp3-icon-path}/magnifier.png"); @extend .bp-icon; }
+i.fa-search-plus { background-image: url("#{$bp3-icon-path}/magnifier_zoom_in.png"); @extend .bp-icon; }
+i.fa-sensorimage { background-image: url("#{$bp3-icon-path}/photo.png"); @extend .bp-icon; }
+i.fa-serial { background-image: url("#{$bp3-icon-path}/page_white_stack.png"); @extend .bp-icon; }
+i.fa-shopping-cart { background-image: url("#{$bp3-icon-path}/cart.png"); @extend .bp-icon; }
+i.fa-sign-in { background-image: url("#{$bp3-icon-path}/door_in.png"); @extend .bp-icon; }
+i.fa-sign-out { background-image: url("#{$bp3-icon-path}/door_out.png"); @extend .bp-icon; }
+i.fa-slide { background-image: url("#{$bp3-icon-path}/film.png"); @extend .bp-icon; }
+i.fa-software { background-image: url("#{$bp3-icon-path}/drive_cd.png"); @extend .bp-icon; }
+i.fa-soundcassette { background-image: url("#{$bp3-icon-path}/sound.png"); @extend .bp-icon; }
+i.fa-sounddisc { background-image: url("#{$bp3-icon-path}/cd.png"); @extend .bp-icon; }
+i.fa-soundrecording { background-image: url("#{$bp3-icon-path}/sound.png"); @extend .bp-icon; }
+i.fa-spinner { background-image: url("#{$bp3-icon-path}/ajax_loading.gif"); @extend .bp-icon; }
+i.fa-star { background-image: url("#{$bp3-icon-path}/star.png"); @extend .bp-icon; }
+i.fa-status-unknown { background-image: url("#{$bp3-icon-path}/bullet_orange.png"); @extend .bp-icon; }
+i.fa-suitcase { background-image: url("#{$bp3-icon-path}/bookbag.png"); @extend .bp-icon; }
+i.fa-tapecartridge { background-image: url("#{$bp3-icon-path}/drive.png"); @extend .bp-icon; }
+i.fa-tapecassette { background-image: url("#{$bp3-icon-path}/drive.png"); @extend .bp-icon; }
+i.fa-tapereel { background-image: url("#{$bp3-icon-path}/film.png"); @extend .bp-icon; }
+i.fa-transparency { background-image: url("#{$bp3-icon-path}/film.png"); @extend .bp-icon; }
 i.fa-trash,
-i.fa-trash-o { background-image: unquote("url('#{$bp3-icon-path}/bin.png')"); @extend .bp-icon; }
-i.fa-tree { background-image: unquote("url('#{$bp3-icon-path}/treeCurrent.png')"); @extend .bp-icon; }
-i.fa-tree-muted { background-image: unquote("url('#{$bp3-icon-path}/treeMuted.png')"); @extend .bp-icon; }
-i.fa-unknown { background-image: unquote("url('#{$bp3-icon-path}/page_white.png')"); @extend .bp-icon; }
-i.fa-usd { background-image: unquote("url('#{$bp3-icon-path}/money_dollar.png')"); @extend .bp-icon; }
-i.fa-user { background-image: unquote("url('#{$bp3-icon-path}/user.png')"); @extend .bp-icon; }
-i.fa-video{background-image: unquote("url('#{$bp3-icon-path}/television.png')"); @extend .bp-icon; }
-i.fa-videocartridge { background-image: unquote("url('#{$bp3-icon-path}/television.png')"); @extend .bp-icon; }
-i.fa-videocassette{background-image: unquote("url('#{$bp3-icon-path}/television.png')"); @extend .bp-icon; }
-i.fa-videodisc{background-image: unquote("url('#{$bp3-icon-path}/cd.png')"); @extend .bp-icon; }
-i.fa-videoreel{background-image: unquote("url('#{$bp3-icon-path}/film.png')"); @extend .bp-icon; }
-i.fa-visual { background-image: unquote("url('#{$bp3-icon-path}/view_visual.png')"); @extend .bp-icon; }
+i.fa-trash-o { background-image: url("#{$bp3-icon-path}/bin.png"); @extend .bp-icon; }
+i.fa-tree { background-image: url("#{$bp3-icon-path}/treeCurrent.png"); @extend .bp-icon; }
+i.fa-tree-muted { background-image: url("#{$bp3-icon-path}/treeMuted.png"); @extend .bp-icon; }
+i.fa-unknown { background-image: url("#{$bp3-icon-path}/page_white.png"); @extend .bp-icon; }
+i.fa-usd { background-image: url("#{$bp3-icon-path}/money_dollar.png"); @extend .bp-icon; }
+i.fa-user { background-image: url("#{$bp3-icon-path}/user.png"); @extend .bp-icon; }
+i.fa-video{background-image: url("#{$bp3-icon-path}/television.png"); @extend .bp-icon; }
+i.fa-videocartridge { background-image: url("#{$bp3-icon-path}/television.png"); @extend .bp-icon; }
+i.fa-videocassette{background-image: url("#{$bp3-icon-path}/television.png"); @extend .bp-icon; }
+i.fa-videodisc{background-image: url("#{$bp3-icon-path}/cd.png"); @extend .bp-icon; }
+i.fa-videoreel{background-image: url("#{$bp3-icon-path}/film.png"); @extend .bp-icon; }
+i.fa-visual { background-image: url("#{$bp3-icon-path}/view_visual.png"); @extend .bp-icon; }
 
 body.rtl {
-  i.fa-external-link { background-image: unquote("url('#{$bp3-icon-path}/link_go_rtl.png')"); }
-  i.fa-flag { background-image: unquote("url('#{$bp3-icon-path}/flag_red_rtl.png')"); }
+  i.fa-external-link { background-image: url("#{$bp3-icon-path}/link_go_rtl.png"); }
+  i.fa-flag { background-image: url("#{$bp3-icon-path}/flag_red_rtl.png"); }
 }
 
-#cart-empty-label i.fa-close { background-image: unquote("url('#{$bp3-icon-path}/briefcase.png')"); @extend .bp-icon; }
+#cart-empty-label i.fa-close { background-image: url("#{$bp3-icon-path}/briefcase.png"); @extend .bp-icon; }
diff --git a/themes/bootprint3/scss/search.scss b/themes/bootprint3/scss/search.scss
index 77f9d4d663da63e1df4fc89369e2f94545fdac70..6b11e7e684ea141a4c8c3760750cdf77cd31fb5b 100644
--- a/themes/bootprint3/scss/search.scss
+++ b/themes/bootprint3/scss/search.scss
@@ -3,14 +3,12 @@
   margin: 1em auto;
   width: 90%;
 }
-#advSearchForm .search { margin: 0; }
 .group .match { margin-top: .5em; }
 
 /* --- Search form --- */
 .searchForm_lookfor,
 .searchForm_type { border-color: $brand-primary; }
-[name=searchForm] {
-  margin: 6px 8px 8px;
+.searchForm {
   padding: 0;
 
   .clear-btn,
@@ -49,3 +47,108 @@
     z-index: 5;
   }
 }
+
+.bulkActionButtons { padding-bottom: 1rem; }
+.top-facets .facet a { vertical-align: middle; }
+.result {
+  padding: 1rem;
+  margin-left: -1rem; // Bring result to the edge of the container
+  &:nth-child(even) { background-color: $gray-lighter; }
+  &.embedded .getFull.expanded {
+    margin-top: -6px;
+    padding-top: .5rem;
+    padding-bottom: .5rem;
+  }
+}
+.result > p { padding:0 1em; }
+.result .long-view .tab-content { background: #fff; }
+.result .media { margin: 0; }
+.result .row { padding: 0; }
+.result .savedLists {
+  margin: 0 0 4px;
+  padding: 4px 0 4px 6px;
+}
+.result .savedLists ul { padding-left: 18px; }
+.search-controls label {
+  margin: 0;
+  vertical-align: middle;
+}
+.search-stats { color: $gray; }
+
+/* --- Advanced --- */
+legend {
+  margin-top: 2rem;
+  margin-bottom: 0;
+}
+
+.grid-result { padding-top: 1rem; }
+.grid-checkbox {
+  text-align: right;
+  cursor: pointer;
+}
+.grid-body {
+  text-align: center;
+
+  .status {
+    margin-top: .5rem;
+    margin-bottom: .5rem;
+  }
+}
+
+.template-dir-eds.template-name-advanced h2,
+.template-dir-search.template-name-advanced h2 { margin-top: 3px; }
+
+/* --- Combined --- */
+.combined-column {
+  padding-left: 1rem;
+  padding-right: 1rem;
+
+  .result {
+    margin-right: -1rem;
+    padding-right: .5rem;
+  }
+}
+.template-dir-combined.template-name-results {
+  &.offcanvas {
+    margin-left: .5rem;
+    margin-right: .5rem;
+  }
+  .main .container {
+    width: 100%;
+    padding-left: 0;
+    padding-right: 0;
+  }
+
+  header,
+  .breadcrumbs,
+  .main,
+  footer { background-color: #fff; }
+
+  header { border-radius: 5px 5px 0 0; }
+  footer {
+    width: 100%;
+    padding: 1rem;
+    border-radius: 0 0 5px 5px;
+
+    .footer-container,
+    .poweredby { @extend .container; }
+  }
+
+  .breadcrumbs {
+    border-top: 1px solid #ddd;
+    border-bottom: 1px solid #ddd;
+  }
+  .breadcrumbs .container { border: 0; }
+
+  .bulkActionButtons { padding-left: 1rem; }
+
+}
+@media (min-width: 768px) {
+  .template-dir-combined.template-name-results {
+    &,
+    &.offcanvas { // overcoming specificity
+      margin-left: 1rem;
+      margin-right: 1rem;
+    }
+  }
+}
diff --git a/themes/bootstrap3/css/EDS.css b/themes/bootstrap3/css/EDS.css
index 6493ed26d546df2f040af22e77804164094af266..de50a492957d65e9906d684626868802511bfa8c 100644
--- a/themes/bootstrap3/css/EDS.css
+++ b/themes/bootstrap3/css/EDS.css
@@ -1,6 +1,6 @@
 /* publication type css */
 
-.pt-icon { width: 70px; float: left; display: inline-block; background-image: url('../images/EDS/PT_Sprite.png'); background-repeat: no-repeat; }
+.pt-icon { width: 70px; display: block; background-image: url('../images/EDS/PT_Sprite.png'); background-repeat: no-repeat; }
 .pt-serialPeriodical { background-position: -30px -30px; height: 59px; }
 .pt-newspaperArticle { background-position: -140px -30px; height: 51px; }
 .pt-image { background-position: -245px -30px; height: 47px; }
@@ -75,4 +75,4 @@
 
 .icon13.expanded {
     background-position: 0 -149px;
-}
\ No newline at end of file
+}
diff --git a/themes/bootstrap3/css/flex-fallback.css b/themes/bootstrap3/css/flex-fallback.css
new file mode 100644
index 0000000000000000000000000000000000000000..20fb27d57cee02efc2f2733ba24810924f467a37
--- /dev/null
+++ b/themes/bootstrap3/css/flex-fallback.css
@@ -0,0 +1,26 @@
+/* Broken up due to IE selector length limits */
+@media (min-width: 768px) {
+  /* Search */
+  .author-facets .author-list,
+  .result .media,
+  .result .record-checkbox,
+  .result .record-number,
+  .grid-result .grid-body,
+  .grid-result .grid-checkbox {
+    display: table-cell;
+    min-width: 20px;
+    vertical-align: top;
+  }
+  /* Layout */
+  .combined-search-container .combined-column,
+  .date-fields .date-from,
+  .date-fields .date-top,
+  .footer-container .footer-column,
+  .home-facet-container .home-facet,
+  .home-facet-container .home-facet-list,
+  .solr-facet-container .solr-adv-facet {
+    display: table-cell;
+    min-width: 20px;
+    vertical-align: top;
+  }
+}
diff --git a/themes/bootstrap3/css/fonts/FontAwesome.otf b/themes/bootstrap3/css/fonts/FontAwesome.otf
index d4de13e832d567ff29c5b4e9561b8c370348cc9c..401ec0f36e4f73b8efa40bd6f604fe80d286db70 100644
Binary files a/themes/bootstrap3/css/fonts/FontAwesome.otf and b/themes/bootstrap3/css/fonts/FontAwesome.otf differ
diff --git a/themes/bootstrap3/css/fonts/fontawesome-webfont.eot b/themes/bootstrap3/css/fonts/fontawesome-webfont.eot
index c7b00d2ba8896fd29de846b19f89fcf0d56ad152..e9f60ca953f93e35eab4108bd414bc02ddcf3928 100644
Binary files a/themes/bootstrap3/css/fonts/fontawesome-webfont.eot and b/themes/bootstrap3/css/fonts/fontawesome-webfont.eot differ
diff --git a/themes/bootstrap3/css/fonts/fontawesome-webfont.svg b/themes/bootstrap3/css/fonts/fontawesome-webfont.svg
index 8b66187fe067c3aa389ce8c98108f349ceae159c..855c845e538b65548118279537a04eab2ec6ef0d 100644
--- a/themes/bootstrap3/css/fonts/fontawesome-webfont.svg
+++ b/themes/bootstrap3/css/fonts/fontawesome-webfont.svg
@@ -1,685 +1,2671 @@
 <?xml version="1.0" standalone="no"?>
 <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
-<svg xmlns="http://www.w3.org/2000/svg">
-<metadata></metadata>
+<svg>
+<metadata>
+Created by FontForge 20120731 at Mon Oct 24 17:37:40 2016
+ By ,,,
+Copyright Dave Gandy 2016. All rights reserved.
+</metadata>
 <defs>
-<font id="fontawesomeregular" horiz-adv-x="1536" >
-<font-face units-per-em="1792" ascent="1536" descent="-256" />
-<missing-glyph horiz-adv-x="448" />
-<glyph unicode=" "  horiz-adv-x="448" />
-<glyph unicode="&#x09;" horiz-adv-x="448" />
-<glyph unicode="&#xa0;" horiz-adv-x="448" />
-<glyph unicode="&#xa8;" horiz-adv-x="1792" />
-<glyph unicode="&#xa9;" horiz-adv-x="1792" />
-<glyph unicode="&#xae;" horiz-adv-x="1792" />
-<glyph unicode="&#xb4;" horiz-adv-x="1792" />
-<glyph unicode="&#xc6;" horiz-adv-x="1792" />
-<glyph unicode="&#xd8;" horiz-adv-x="1792" />
-<glyph unicode="&#x2000;" horiz-adv-x="768" />
-<glyph unicode="&#x2001;" horiz-adv-x="1537" />
-<glyph unicode="&#x2002;" horiz-adv-x="768" />
-<glyph unicode="&#x2003;" horiz-adv-x="1537" />
-<glyph unicode="&#x2004;" horiz-adv-x="512" />
-<glyph unicode="&#x2005;" horiz-adv-x="384" />
-<glyph unicode="&#x2006;" horiz-adv-x="256" />
-<glyph unicode="&#x2007;" horiz-adv-x="256" />
-<glyph unicode="&#x2008;" horiz-adv-x="192" />
-<glyph unicode="&#x2009;" horiz-adv-x="307" />
-<glyph unicode="&#x200a;" horiz-adv-x="85" />
-<glyph unicode="&#x202f;" horiz-adv-x="307" />
-<glyph unicode="&#x205f;" horiz-adv-x="384" />
-<glyph unicode="&#x2122;" horiz-adv-x="1792" />
-<glyph unicode="&#x221e;" horiz-adv-x="1792" />
-<glyph unicode="&#x2260;" horiz-adv-x="1792" />
-<glyph unicode="&#x25fc;" horiz-adv-x="500" d="M0 0z" />
-<glyph unicode="&#xf000;" horiz-adv-x="1792" d="M1699 1350q0 -35 -43 -78l-632 -632v-768h320q26 0 45 -19t19 -45t-19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45t45 19h320v768l-632 632q-43 43 -43 78q0 23 18 36.5t38 17.5t43 4h1408q23 0 43 -4t38 -17.5t18 -36.5z" />
-<glyph unicode="&#xf001;" d="M1536 1312v-1120q0 -50 -34 -89t-86 -60.5t-103.5 -32t-96.5 -10.5t-96.5 10.5t-103.5 32t-86 60.5t-34 89t34 89t86 60.5t103.5 32t96.5 10.5q105 0 192 -39v537l-768 -237v-709q0 -50 -34 -89t-86 -60.5t-103.5 -32t-96.5 -10.5t-96.5 10.5t-103.5 32t-86 60.5t-34 89 t34 89t86 60.5t103.5 32t96.5 10.5q105 0 192 -39v967q0 31 19 56.5t49 35.5l832 256q12 4 28 4q40 0 68 -28t28 -68z" />
-<glyph unicode="&#xf002;" horiz-adv-x="1664" d="M1152 704q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5zM1664 -128q0 -52 -38 -90t-90 -38q-54 0 -90 38l-343 342q-179 -124 -399 -124q-143 0 -273.5 55.5t-225 150t-150 225t-55.5 273.5 t55.5 273.5t150 225t225 150t273.5 55.5t273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -220 -124 -399l343 -343q37 -37 37 -90z" />
-<glyph unicode="&#xf003;" horiz-adv-x="1792" d="M1664 32v768q-32 -36 -69 -66q-268 -206 -426 -338q-51 -43 -83 -67t-86.5 -48.5t-102.5 -24.5h-1h-1q-48 0 -102.5 24.5t-86.5 48.5t-83 67q-158 132 -426 338q-37 30 -69 66v-768q0 -13 9.5 -22.5t22.5 -9.5h1472q13 0 22.5 9.5t9.5 22.5zM1664 1083v11v13.5t-0.5 13 t-3 12.5t-5.5 9t-9 7.5t-14 2.5h-1472q-13 0 -22.5 -9.5t-9.5 -22.5q0 -168 147 -284q193 -152 401 -317q6 -5 35 -29.5t46 -37.5t44.5 -31.5t50.5 -27.5t43 -9h1h1q20 0 43 9t50.5 27.5t44.5 31.5t46 37.5t35 29.5q208 165 401 317q54 43 100.5 115.5t46.5 131.5z M1792 1120v-1088q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1472q66 0 113 -47t47 -113z" />
-<glyph unicode="&#xf004;" horiz-adv-x="1792" d="M896 -128q-26 0 -44 18l-624 602q-10 8 -27.5 26t-55.5 65.5t-68 97.5t-53.5 121t-23.5 138q0 220 127 344t351 124q62 0 126.5 -21.5t120 -58t95.5 -68.5t76 -68q36 36 76 68t95.5 68.5t120 58t126.5 21.5q224 0 351 -124t127 -344q0 -221 -229 -450l-623 -600 q-18 -18 -44 -18z" />
-<glyph unicode="&#xf005;" horiz-adv-x="1664" d="M1664 889q0 -22 -26 -48l-363 -354l86 -500q1 -7 1 -20q0 -21 -10.5 -35.5t-30.5 -14.5q-19 0 -40 12l-449 236l-449 -236q-22 -12 -40 -12q-21 0 -31.5 14.5t-10.5 35.5q0 6 2 20l86 500l-364 354q-25 27 -25 48q0 37 56 46l502 73l225 455q19 41 49 41t49 -41l225 -455 l502 -73q56 -9 56 -46z" />
-<glyph unicode="&#xf006;" horiz-adv-x="1664" d="M1137 532l306 297l-422 62l-189 382l-189 -382l-422 -62l306 -297l-73 -421l378 199l377 -199zM1664 889q0 -22 -26 -48l-363 -354l86 -500q1 -7 1 -20q0 -50 -41 -50q-19 0 -40 12l-449 236l-449 -236q-22 -12 -40 -12q-21 0 -31.5 14.5t-10.5 35.5q0 6 2 20l86 500 l-364 354q-25 27 -25 48q0 37 56 46l502 73l225 455q19 41 49 41t49 -41l225 -455l502 -73q56 -9 56 -46z" />
-<glyph unicode="&#xf007;" horiz-adv-x="1408" d="M1408 131q0 -120 -73 -189.5t-194 -69.5h-874q-121 0 -194 69.5t-73 189.5q0 53 3.5 103.5t14 109t26.5 108.5t43 97.5t62 81t85.5 53.5t111.5 20q9 0 42 -21.5t74.5 -48t108 -48t133.5 -21.5t133.5 21.5t108 48t74.5 48t42 21.5q61 0 111.5 -20t85.5 -53.5t62 -81 t43 -97.5t26.5 -108.5t14 -109t3.5 -103.5zM1088 1024q0 -159 -112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5z" />
-<glyph unicode="&#xf008;" horiz-adv-x="1920" d="M384 -64v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM384 320v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM384 704v128q0 26 -19 45t-45 19h-128 q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1408 -64v512q0 26 -19 45t-45 19h-768q-26 0 -45 -19t-19 -45v-512q0 -26 19 -45t45 -19h768q26 0 45 19t19 45zM384 1088v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45 t45 -19h128q26 0 45 19t19 45zM1792 -64v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1408 704v512q0 26 -19 45t-45 19h-768q-26 0 -45 -19t-19 -45v-512q0 -26 19 -45t45 -19h768q26 0 45 19t19 45zM1792 320v128 q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1792 704v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1792 1088v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19 t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1920 1248v-1344q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113v1344q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" />
-<glyph unicode="&#xf009;" horiz-adv-x="1664" d="M768 512v-384q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90zM768 1280v-384q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90zM1664 512v-384q0 -52 -38 -90t-90 -38 h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90zM1664 1280v-384q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90z" />
-<glyph unicode="&#xf00a;" horiz-adv-x="1792" d="M512 288v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM512 800v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1152 288v-192q0 -40 -28 -68t-68 -28h-320 q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM512 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1152 800v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28 h320q40 0 68 -28t28 -68zM1792 288v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1152 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 800v-192 q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68z" />
-<glyph unicode="&#xf00b;" horiz-adv-x="1792" d="M512 288v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM512 800v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 288v-192q0 -40 -28 -68t-68 -28h-960 q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h960q40 0 68 -28t28 -68zM512 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 800v-192q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v192q0 40 28 68t68 28 h960q40 0 68 -28t28 -68zM1792 1312v-192q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h960q40 0 68 -28t28 -68z" />
-<glyph unicode="&#xf00c;" horiz-adv-x="1792" d="M1671 970q0 -40 -28 -68l-724 -724l-136 -136q-28 -28 -68 -28t-68 28l-136 136l-362 362q-28 28 -28 68t28 68l136 136q28 28 68 28t68 -28l294 -295l656 657q28 28 68 28t68 -28l136 -136q28 -28 28 -68z" />
-<glyph unicode="&#xf00d;" horiz-adv-x="1408" d="M1298 214q0 -40 -28 -68l-136 -136q-28 -28 -68 -28t-68 28l-294 294l-294 -294q-28 -28 -68 -28t-68 28l-136 136q-28 28 -28 68t28 68l294 294l-294 294q-28 28 -28 68t28 68l136 136q28 28 68 28t68 -28l294 -294l294 294q28 28 68 28t68 -28l136 -136q28 -28 28 -68 t-28 -68l-294 -294l294 -294q28 -28 28 -68z" />
-<glyph unicode="&#xf00e;" horiz-adv-x="1664" d="M1024 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-224v-224q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v224h-224q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h224v224q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5v-224h224 q13 0 22.5 -9.5t9.5 -22.5zM1152 704q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5zM1664 -128q0 -53 -37.5 -90.5t-90.5 -37.5q-54 0 -90 38l-343 342q-179 -124 -399 -124q-143 0 -273.5 55.5 t-225 150t-150 225t-55.5 273.5t55.5 273.5t150 225t225 150t273.5 55.5t273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -220 -124 -399l343 -343q37 -37 37 -90z" />
-<glyph unicode="&#xf010;" horiz-adv-x="1664" d="M1024 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-576q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h576q13 0 22.5 -9.5t9.5 -22.5zM1152 704q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5z M1664 -128q0 -53 -37.5 -90.5t-90.5 -37.5q-54 0 -90 38l-343 342q-179 -124 -399 -124q-143 0 -273.5 55.5t-225 150t-150 225t-55.5 273.5t55.5 273.5t150 225t225 150t273.5 55.5t273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -220 -124 -399l343 -343q37 -37 37 -90z " />
-<glyph unicode="&#xf011;" d="M1536 640q0 -156 -61 -298t-164 -245t-245 -164t-298 -61t-298 61t-245 164t-164 245t-61 298q0 182 80.5 343t226.5 270q43 32 95.5 25t83.5 -50q32 -42 24.5 -94.5t-49.5 -84.5q-98 -74 -151.5 -181t-53.5 -228q0 -104 40.5 -198.5t109.5 -163.5t163.5 -109.5 t198.5 -40.5t198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5q0 121 -53.5 228t-151.5 181q-42 32 -49.5 84.5t24.5 94.5q31 43 84 50t95 -25q146 -109 226.5 -270t80.5 -343zM896 1408v-640q0 -52 -38 -90t-90 -38t-90 38t-38 90v640q0 52 38 90t90 38t90 -38t38 -90z" />
-<glyph unicode="&#xf012;" horiz-adv-x="1792" d="M256 96v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM640 224v-320q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v320q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1024 480v-576q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23 v576q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1408 864v-960q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v960q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1792 1376v-1472q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v1472q0 14 9 23t23 9h192q14 0 23 -9t9 -23z" />
-<glyph unicode="&#xf013;" d="M1024 640q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM1536 749v-222q0 -12 -8 -23t-20 -13l-185 -28q-19 -54 -39 -91q35 -50 107 -138q10 -12 10 -25t-9 -23q-27 -37 -99 -108t-94 -71q-12 0 -26 9l-138 108q-44 -23 -91 -38 q-16 -136 -29 -186q-7 -28 -36 -28h-222q-14 0 -24.5 8.5t-11.5 21.5l-28 184q-49 16 -90 37l-141 -107q-10 -9 -25 -9q-14 0 -25 11q-126 114 -165 168q-7 10 -7 23q0 12 8 23q15 21 51 66.5t54 70.5q-27 50 -41 99l-183 27q-13 2 -21 12.5t-8 23.5v222q0 12 8 23t19 13 l186 28q14 46 39 92q-40 57 -107 138q-10 12 -10 24q0 10 9 23q26 36 98.5 107.5t94.5 71.5q13 0 26 -10l138 -107q44 23 91 38q16 136 29 186q7 28 36 28h222q14 0 24.5 -8.5t11.5 -21.5l28 -184q49 -16 90 -37l142 107q9 9 24 9q13 0 25 -10q129 -119 165 -170q7 -8 7 -22 q0 -12 -8 -23q-15 -21 -51 -66.5t-54 -70.5q26 -50 41 -98l183 -28q13 -2 21 -12.5t8 -23.5z" />
-<glyph unicode="&#xf014;" horiz-adv-x="1408" d="M512 800v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM768 800v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1024 800v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576 q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1152 76v948h-896v-948q0 -22 7 -40.5t14.5 -27t10.5 -8.5h832q3 0 10.5 8.5t14.5 27t7 40.5zM480 1152h448l-48 117q-7 9 -17 11h-317q-10 -2 -17 -11zM1408 1120v-64q0 -14 -9 -23t-23 -9h-96v-948q0 -83 -47 -143.5t-113 -60.5h-832 q-66 0 -113 58.5t-47 141.5v952h-96q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h309l70 167q15 37 54 63t79 26h320q40 0 79 -26t54 -63l70 -167h309q14 0 23 -9t9 -23z" />
-<glyph unicode="&#xf015;" horiz-adv-x="1664" d="M1408 544v-480q0 -26 -19 -45t-45 -19h-384v384h-256v-384h-384q-26 0 -45 19t-19 45v480q0 1 0.5 3t0.5 3l575 474l575 -474q1 -2 1 -6zM1631 613l-62 -74q-8 -9 -21 -11h-3q-13 0 -21 7l-692 577l-692 -577q-12 -8 -24 -7q-13 2 -21 11l-62 74q-8 10 -7 23.5t11 21.5 l719 599q32 26 76 26t76 -26l244 -204v195q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-408l219 -182q10 -8 11 -21.5t-7 -23.5z" />
-<glyph unicode="&#xf016;" d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z " />
-<glyph unicode="&#xf017;" d="M896 992v-448q0 -14 -9 -23t-23 -9h-320q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h224v352q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
-<glyph unicode="&#xf018;" horiz-adv-x="1920" d="M1111 540v4l-24 320q-1 13 -11 22.5t-23 9.5h-186q-13 0 -23 -9.5t-11 -22.5l-24 -320v-4q-1 -12 8 -20t21 -8h244q12 0 21 8t8 20zM1870 73q0 -73 -46 -73h-704q13 0 22 9.5t8 22.5l-20 256q-1 13 -11 22.5t-23 9.5h-272q-13 0 -23 -9.5t-11 -22.5l-20 -256 q-1 -13 8 -22.5t22 -9.5h-704q-46 0 -46 73q0 54 26 116l417 1044q8 19 26 33t38 14h339q-13 0 -23 -9.5t-11 -22.5l-15 -192q-1 -14 8 -23t22 -9h166q13 0 22 9t8 23l-15 192q-1 13 -11 22.5t-23 9.5h339q20 0 38 -14t26 -33l417 -1044q26 -62 26 -116z" />
-<glyph unicode="&#xf019;" horiz-adv-x="1664" d="M1280 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1536 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1664 416v-320q0 -40 -28 -68t-68 -28h-1472q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h465l135 -136 q58 -56 136 -56t136 56l136 136h464q40 0 68 -28t28 -68zM1339 985q17 -41 -14 -70l-448 -448q-18 -19 -45 -19t-45 19l-448 448q-31 29 -14 70q17 39 59 39h256v448q0 26 19 45t45 19h256q26 0 45 -19t19 -45v-448h256q42 0 59 -39z" />
-<glyph unicode="&#xf01a;" d="M1120 608q0 -12 -10 -24l-319 -319q-11 -9 -23 -9t-23 9l-320 320q-15 16 -7 35q8 20 30 20h192v352q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-352h192q14 0 23 -9t9 -23zM768 1184q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273 t-73 273t-198 198t-273 73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
-<glyph unicode="&#xf01b;" d="M1118 660q-8 -20 -30 -20h-192v-352q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v352h-192q-14 0 -23 9t-9 23q0 12 10 24l319 319q11 9 23 9t23 -9l320 -320q15 -16 7 -35zM768 1184q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198 t73 273t-73 273t-198 198t-273 73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
-<glyph unicode="&#xf01c;" d="M1023 576h316q-1 3 -2.5 8t-2.5 8l-212 496h-708l-212 -496q-1 -2 -2.5 -8t-2.5 -8h316l95 -192h320zM1536 546v-482q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v482q0 62 25 123l238 552q10 25 36.5 42t52.5 17h832q26 0 52.5 -17t36.5 -42l238 -552 q25 -61 25 -123z" />
-<glyph unicode="&#xf01d;" d="M1184 640q0 -37 -32 -55l-544 -320q-15 -9 -32 -9q-16 0 -32 8q-32 19 -32 56v640q0 37 32 56q33 18 64 -1l544 -320q32 -18 32 -55zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
-<glyph unicode="&#xf01e;" d="M1536 1280v-448q0 -26 -19 -45t-45 -19h-448q-42 0 -59 40q-17 39 14 69l138 138q-148 137 -349 137q-104 0 -198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5q119 0 225 52t179 147q7 10 23 12q14 0 25 -9 l137 -138q9 -8 9.5 -20.5t-7.5 -22.5q-109 -132 -264 -204.5t-327 -72.5q-156 0 -298 61t-245 164t-164 245t-61 298t61 298t164 245t245 164t298 61q147 0 284.5 -55.5t244.5 -156.5l130 129q29 31 70 14q39 -17 39 -59z" />
-<glyph unicode="&#xf021;" d="M1511 480q0 -5 -1 -7q-64 -268 -268 -434.5t-478 -166.5q-146 0 -282.5 55t-243.5 157l-129 -129q-19 -19 -45 -19t-45 19t-19 45v448q0 26 19 45t45 19h448q26 0 45 -19t19 -45t-19 -45l-137 -137q71 -66 161 -102t187 -36q134 0 250 65t186 179q11 17 53 117 q8 23 30 23h192q13 0 22.5 -9.5t9.5 -22.5zM1536 1280v-448q0 -26 -19 -45t-45 -19h-448q-26 0 -45 19t-19 45t19 45l138 138q-148 137 -349 137q-134 0 -250 -65t-186 -179q-11 -17 -53 -117q-8 -23 -30 -23h-199q-13 0 -22.5 9.5t-9.5 22.5v7q65 268 270 434.5t480 166.5 q146 0 284 -55.5t245 -156.5l130 129q19 19 45 19t45 -19t19 -45z" />
-<glyph unicode="&#xf022;" horiz-adv-x="1792" d="M384 352v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 608v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M384 864v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1536 352v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h960q13 0 22.5 -9.5t9.5 -22.5z M1536 608v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h960q13 0 22.5 -9.5t9.5 -22.5zM1536 864v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h960q13 0 22.5 -9.5 t9.5 -22.5zM1664 160v832q0 13 -9.5 22.5t-22.5 9.5h-1472q-13 0 -22.5 -9.5t-9.5 -22.5v-832q0 -13 9.5 -22.5t22.5 -9.5h1472q13 0 22.5 9.5t9.5 22.5zM1792 1248v-1088q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1472q66 0 113 -47 t47 -113z" />
-<glyph unicode="&#xf023;" horiz-adv-x="1152" d="M320 768h512v192q0 106 -75 181t-181 75t-181 -75t-75 -181v-192zM1152 672v-576q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v576q0 40 28 68t68 28h32v192q0 184 132 316t316 132t316 -132t132 -316v-192h32q40 0 68 -28t28 -68z" />
-<glyph unicode="&#xf024;" horiz-adv-x="1792" d="M320 1280q0 -72 -64 -110v-1266q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v1266q-64 38 -64 110q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1792 1216v-763q0 -25 -12.5 -38.5t-39.5 -27.5q-215 -116 -369 -116q-61 0 -123.5 22t-108.5 48 t-115.5 48t-142.5 22q-192 0 -464 -146q-17 -9 -33 -9q-26 0 -45 19t-19 45v742q0 32 31 55q21 14 79 43q236 120 421 120q107 0 200 -29t219 -88q38 -19 88 -19q54 0 117.5 21t110 47t88 47t54.5 21q26 0 45 -19t19 -45z" />
-<glyph unicode="&#xf025;" horiz-adv-x="1664" d="M1664 650q0 -166 -60 -314l-20 -49l-185 -33q-22 -83 -90.5 -136.5t-156.5 -53.5v-32q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-32q71 0 130 -35.5t93 -95.5l68 12q29 95 29 193q0 148 -88 279t-236.5 209t-315.5 78 t-315.5 -78t-236.5 -209t-88 -279q0 -98 29 -193l68 -12q34 60 93 95.5t130 35.5v32q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v32q-88 0 -156.5 53.5t-90.5 136.5l-185 33l-20 49q-60 148 -60 314q0 151 67 291t179 242.5 t266 163.5t320 61t320 -61t266 -163.5t179 -242.5t67 -291z" />
-<glyph unicode="&#xf026;" horiz-adv-x="768" d="M768 1184v-1088q0 -26 -19 -45t-45 -19t-45 19l-333 333h-262q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h262l333 333q19 19 45 19t45 -19t19 -45z" />
-<glyph unicode="&#xf027;" horiz-adv-x="1152" d="M768 1184v-1088q0 -26 -19 -45t-45 -19t-45 19l-333 333h-262q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h262l333 333q19 19 45 19t45 -19t19 -45zM1152 640q0 -76 -42.5 -141.5t-112.5 -93.5q-10 -5 -25 -5q-26 0 -45 18.5t-19 45.5q0 21 12 35.5t29 25t34 23t29 35.5 t12 57t-12 57t-29 35.5t-34 23t-29 25t-12 35.5q0 27 19 45.5t45 18.5q15 0 25 -5q70 -27 112.5 -93t42.5 -142z" />
-<glyph unicode="&#xf028;" horiz-adv-x="1664" d="M768 1184v-1088q0 -26 -19 -45t-45 -19t-45 19l-333 333h-262q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h262l333 333q19 19 45 19t45 -19t19 -45zM1152 640q0 -76 -42.5 -141.5t-112.5 -93.5q-10 -5 -25 -5q-26 0 -45 18.5t-19 45.5q0 21 12 35.5t29 25t34 23t29 35.5 t12 57t-12 57t-29 35.5t-34 23t-29 25t-12 35.5q0 27 19 45.5t45 18.5q15 0 25 -5q70 -27 112.5 -93t42.5 -142zM1408 640q0 -153 -85 -282.5t-225 -188.5q-13 -5 -25 -5q-27 0 -46 19t-19 45q0 39 39 59q56 29 76 44q74 54 115.5 135.5t41.5 173.5t-41.5 173.5 t-115.5 135.5q-20 15 -76 44q-39 20 -39 59q0 26 19 45t45 19q13 0 26 -5q140 -59 225 -188.5t85 -282.5zM1664 640q0 -230 -127 -422.5t-338 -283.5q-13 -5 -26 -5q-26 0 -45 19t-19 45q0 36 39 59q7 4 22.5 10.5t22.5 10.5q46 25 82 51q123 91 192 227t69 289t-69 289 t-192 227q-36 26 -82 51q-7 4 -22.5 10.5t-22.5 10.5q-39 23 -39 59q0 26 19 45t45 19q13 0 26 -5q211 -91 338 -283.5t127 -422.5z" />
-<glyph unicode="&#xf029;" horiz-adv-x="1408" d="M384 384v-128h-128v128h128zM384 1152v-128h-128v128h128zM1152 1152v-128h-128v128h128zM128 129h384v383h-384v-383zM128 896h384v384h-384v-384zM896 896h384v384h-384v-384zM640 640v-640h-640v640h640zM1152 128v-128h-128v128h128zM1408 128v-128h-128v128h128z M1408 640v-384h-384v128h-128v-384h-128v640h384v-128h128v128h128zM640 1408v-640h-640v640h640zM1408 1408v-640h-640v640h640z" />
-<glyph unicode="&#xf02a;" horiz-adv-x="1792" d="M63 0h-63v1408h63v-1408zM126 1h-32v1407h32v-1407zM220 1h-31v1407h31v-1407zM377 1h-31v1407h31v-1407zM534 1h-62v1407h62v-1407zM660 1h-31v1407h31v-1407zM723 1h-31v1407h31v-1407zM786 1h-31v1407h31v-1407zM943 1h-63v1407h63v-1407zM1100 1h-63v1407h63v-1407z M1226 1h-63v1407h63v-1407zM1352 1h-63v1407h63v-1407zM1446 1h-63v1407h63v-1407zM1635 1h-94v1407h94v-1407zM1698 1h-32v1407h32v-1407zM1792 0h-63v1408h63v-1408z" />
-<glyph unicode="&#xf02b;" d="M448 1088q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1515 512q0 -53 -37 -90l-491 -492q-39 -37 -91 -37q-53 0 -90 37l-715 716q-38 37 -64.5 101t-26.5 117v416q0 52 38 90t90 38h416q53 0 117 -26.5t102 -64.5 l715 -714q37 -39 37 -91z" />
-<glyph unicode="&#xf02c;" horiz-adv-x="1920" d="M448 1088q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1515 512q0 -53 -37 -90l-491 -492q-39 -37 -91 -37q-53 0 -90 37l-715 716q-38 37 -64.5 101t-26.5 117v416q0 52 38 90t90 38h416q53 0 117 -26.5t102 -64.5 l715 -714q37 -39 37 -91zM1899 512q0 -53 -37 -90l-491 -492q-39 -37 -91 -37q-36 0 -59 14t-53 45l470 470q37 37 37 90q0 52 -37 91l-715 714q-38 38 -102 64.5t-117 26.5h224q53 0 117 -26.5t102 -64.5l715 -714q37 -39 37 -91z" />
-<glyph unicode="&#xf02d;" horiz-adv-x="1664" d="M1639 1058q40 -57 18 -129l-275 -906q-19 -64 -76.5 -107.5t-122.5 -43.5h-923q-77 0 -148.5 53.5t-99.5 131.5q-24 67 -2 127q0 4 3 27t4 37q1 8 -3 21.5t-3 19.5q2 11 8 21t16.5 23.5t16.5 23.5q23 38 45 91.5t30 91.5q3 10 0.5 30t-0.5 28q3 11 17 28t17 23 q21 36 42 92t25 90q1 9 -2.5 32t0.5 28q4 13 22 30.5t22 22.5q19 26 42.5 84.5t27.5 96.5q1 8 -3 25.5t-2 26.5q2 8 9 18t18 23t17 21q8 12 16.5 30.5t15 35t16 36t19.5 32t26.5 23.5t36 11.5t47.5 -5.5l-1 -3q38 9 51 9h761q74 0 114 -56t18 -130l-274 -906 q-36 -119 -71.5 -153.5t-128.5 -34.5h-869q-27 0 -38 -15q-11 -16 -1 -43q24 -70 144 -70h923q29 0 56 15.5t35 41.5l300 987q7 22 5 57q38 -15 59 -43zM575 1056q-4 -13 2 -22.5t20 -9.5h608q13 0 25.5 9.5t16.5 22.5l21 64q4 13 -2 22.5t-20 9.5h-608q-13 0 -25.5 -9.5 t-16.5 -22.5zM492 800q-4 -13 2 -22.5t20 -9.5h608q13 0 25.5 9.5t16.5 22.5l21 64q4 13 -2 22.5t-20 9.5h-608q-13 0 -25.5 -9.5t-16.5 -22.5z" />
-<glyph unicode="&#xf02e;" horiz-adv-x="1280" d="M1164 1408q23 0 44 -9q33 -13 52.5 -41t19.5 -62v-1289q0 -34 -19.5 -62t-52.5 -41q-19 -8 -44 -8q-48 0 -83 32l-441 424l-441 -424q-36 -33 -83 -33q-23 0 -44 9q-33 13 -52.5 41t-19.5 62v1289q0 34 19.5 62t52.5 41q21 9 44 9h1048z" />
-<glyph unicode="&#xf02f;" horiz-adv-x="1664" d="M384 0h896v256h-896v-256zM384 640h896v384h-160q-40 0 -68 28t-28 68v160h-640v-640zM1536 576q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1664 576v-416q0 -13 -9.5 -22.5t-22.5 -9.5h-224v-160q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68 v160h-224q-13 0 -22.5 9.5t-9.5 22.5v416q0 79 56.5 135.5t135.5 56.5h64v544q0 40 28 68t68 28h672q40 0 88 -20t76 -48l152 -152q28 -28 48 -76t20 -88v-256h64q79 0 135.5 -56.5t56.5 -135.5z" />
-<glyph unicode="&#xf030;" horiz-adv-x="1920" d="M960 864q119 0 203.5 -84.5t84.5 -203.5t-84.5 -203.5t-203.5 -84.5t-203.5 84.5t-84.5 203.5t84.5 203.5t203.5 84.5zM1664 1280q106 0 181 -75t75 -181v-896q0 -106 -75 -181t-181 -75h-1408q-106 0 -181 75t-75 181v896q0 106 75 181t181 75h224l51 136 q19 49 69.5 84.5t103.5 35.5h512q53 0 103.5 -35.5t69.5 -84.5l51 -136h224zM960 128q185 0 316.5 131.5t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
-<glyph unicode="&#xf031;" horiz-adv-x="1664" d="M725 977l-170 -450q33 0 136.5 -2t160.5 -2q19 0 57 2q-87 253 -184 452zM0 -128l2 79q23 7 56 12.5t57 10.5t49.5 14.5t44.5 29t31 50.5l237 616l280 724h75h53q8 -14 11 -21l205 -480q33 -78 106 -257.5t114 -274.5q15 -34 58 -144.5t72 -168.5q20 -45 35 -57 q19 -15 88 -29.5t84 -20.5q6 -38 6 -57q0 -4 -0.5 -13t-0.5 -13q-63 0 -190 8t-191 8q-76 0 -215 -7t-178 -8q0 43 4 78l131 28q1 0 12.5 2.5t15.5 3.5t14.5 4.5t15 6.5t11 8t9 11t2.5 14q0 16 -31 96.5t-72 177.5t-42 100l-450 2q-26 -58 -76.5 -195.5t-50.5 -162.5 q0 -22 14 -37.5t43.5 -24.5t48.5 -13.5t57 -8.5t41 -4q1 -19 1 -58q0 -9 -2 -27q-58 0 -174.5 10t-174.5 10q-8 0 -26.5 -4t-21.5 -4q-80 -14 -188 -14z" />
-<glyph unicode="&#xf032;" horiz-adv-x="1408" d="M555 15q74 -32 140 -32q376 0 376 335q0 114 -41 180q-27 44 -61.5 74t-67.5 46.5t-80.5 25t-84 10.5t-94.5 2q-73 0 -101 -10q0 -53 -0.5 -159t-0.5 -158q0 -8 -1 -67.5t-0.5 -96.5t4.5 -83.5t12 -66.5zM541 761q42 -7 109 -7q82 0 143 13t110 44.5t74.5 89.5t25.5 142 q0 70 -29 122.5t-79 82t-108 43.5t-124 14q-50 0 -130 -13q0 -50 4 -151t4 -152q0 -27 -0.5 -80t-0.5 -79q0 -46 1 -69zM0 -128l2 94q15 4 85 16t106 27q7 12 12.5 27t8.5 33.5t5.5 32.5t3 37.5t0.5 34v35.5v30q0 982 -22 1025q-4 8 -22 14.5t-44.5 11t-49.5 7t-48.5 4.5 t-30.5 3l-4 83q98 2 340 11.5t373 9.5q23 0 68.5 -0.5t67.5 -0.5q70 0 136.5 -13t128.5 -42t108 -71t74 -104.5t28 -137.5q0 -52 -16.5 -95.5t-39 -72t-64.5 -57.5t-73 -45t-84 -40q154 -35 256.5 -134t102.5 -248q0 -100 -35 -179.5t-93.5 -130.5t-138 -85.5t-163.5 -48.5 t-176 -14q-44 0 -132 3t-132 3q-106 0 -307 -11t-231 -12z" />
-<glyph unicode="&#xf033;" horiz-adv-x="1024" d="M0 -126l17 85q6 2 81.5 21.5t111.5 37.5q28 35 41 101q1 7 62 289t114 543.5t52 296.5v25q-24 13 -54.5 18.5t-69.5 8t-58 5.5l19 103q33 -2 120 -6.5t149.5 -7t120.5 -2.5q48 0 98.5 2.5t121 7t98.5 6.5q-5 -39 -19 -89q-30 -10 -101.5 -28.5t-108.5 -33.5 q-8 -19 -14 -42.5t-9 -40t-7.5 -45.5t-6.5 -42q-27 -148 -87.5 -419.5t-77.5 -355.5q-2 -9 -13 -58t-20 -90t-16 -83.5t-6 -57.5l1 -18q17 -4 185 -31q-3 -44 -16 -99q-11 0 -32.5 -1.5t-32.5 -1.5q-29 0 -87 10t-86 10q-138 2 -206 2q-51 0 -143 -9t-121 -11z" />
-<glyph unicode="&#xf034;" horiz-adv-x="1792" d="M1744 128q33 0 42 -18.5t-11 -44.5l-126 -162q-20 -26 -49 -26t-49 26l-126 162q-20 26 -11 44.5t42 18.5h80v1024h-80q-33 0 -42 18.5t11 44.5l126 162q20 26 49 26t49 -26l126 -162q20 -26 11 -44.5t-42 -18.5h-80v-1024h80zM81 1407l54 -27q12 -5 211 -5q44 0 132 2 t132 2q36 0 107.5 -0.5t107.5 -0.5h293q6 0 21 -0.5t20.5 0t16 3t17.5 9t15 17.5l42 1q4 0 14 -0.5t14 -0.5q2 -112 2 -336q0 -80 -5 -109q-39 -14 -68 -18q-25 44 -54 128q-3 9 -11 48t-14.5 73.5t-7.5 35.5q-6 8 -12 12.5t-15.5 6t-13 2.5t-18 0.5t-16.5 -0.5 q-17 0 -66.5 0.5t-74.5 0.5t-64 -2t-71 -6q-9 -81 -8 -136q0 -94 2 -388t2 -455q0 -16 -2.5 -71.5t0 -91.5t12.5 -69q40 -21 124 -42.5t120 -37.5q5 -40 5 -50q0 -14 -3 -29l-34 -1q-76 -2 -218 8t-207 10q-50 0 -151 -9t-152 -9q-3 51 -3 52v9q17 27 61.5 43t98.5 29t78 27 q19 42 19 383q0 101 -3 303t-3 303v117q0 2 0.5 15.5t0.5 25t-1 25.5t-3 24t-5 14q-11 12 -162 12q-33 0 -93 -12t-80 -26q-19 -13 -34 -72.5t-31.5 -111t-42.5 -53.5q-42 26 -56 44v383z" />
-<glyph unicode="&#xf035;" d="M81 1407l54 -27q12 -5 211 -5q44 0 132 2t132 2q70 0 246.5 1t304.5 0.5t247 -4.5q33 -1 56 31l42 1q4 0 14 -0.5t14 -0.5q2 -112 2 -336q0 -80 -5 -109q-39 -14 -68 -18q-25 44 -54 128q-3 9 -11 47.5t-15 73.5t-7 36q-10 13 -27 19q-5 2 -66 2q-30 0 -93 1t-103 1 t-94 -2t-96 -7q-9 -81 -8 -136l1 -152v52q0 -55 1 -154t1.5 -180t0.5 -153q0 -16 -2.5 -71.5t0 -91.5t12.5 -69q40 -21 124 -42.5t120 -37.5q5 -40 5 -50q0 -14 -3 -29l-34 -1q-76 -2 -218 8t-207 10q-50 0 -151 -9t-152 -9q-3 51 -3 52v9q17 27 61.5 43t98.5 29t78 27 q7 16 11.5 74t6 145.5t1.5 155t-0.5 153.5t-0.5 89q0 7 -2.5 21.5t-2.5 22.5q0 7 0.5 44t1 73t0 76.5t-3 67.5t-6.5 32q-11 12 -162 12q-41 0 -163 -13.5t-138 -24.5q-19 -12 -34 -71.5t-31.5 -111.5t-42.5 -54q-42 26 -56 44v383zM1310 125q12 0 42 -19.5t57.5 -41.5 t59.5 -49t36 -30q26 -21 26 -49t-26 -49q-4 -3 -36 -30t-59.5 -49t-57.5 -41.5t-42 -19.5q-13 0 -20.5 10.5t-10 28.5t-2.5 33.5t1.5 33t1.5 19.5h-1024q0 -2 1.5 -19.5t1.5 -33t-2.5 -33.5t-10 -28.5t-20.5 -10.5q-12 0 -42 19.5t-57.5 41.5t-59.5 49t-36 30q-26 21 -26 49 t26 49q4 3 36 30t59.5 49t57.5 41.5t42 19.5q13 0 20.5 -10.5t10 -28.5t2.5 -33.5t-1.5 -33t-1.5 -19.5h1024q0 2 -1.5 19.5t-1.5 33t2.5 33.5t10 28.5t20.5 10.5z" />
-<glyph unicode="&#xf036;" horiz-adv-x="1792" d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1408 576v-128q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1280q26 0 45 -19t19 -45zM1664 960v-128q0 -26 -19 -45 t-45 -19h-1536q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1536q26 0 45 -19t19 -45zM1280 1344v-128q0 -26 -19 -45t-45 -19h-1152q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" />
-<glyph unicode="&#xf037;" horiz-adv-x="1792" d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1408 576v-128q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h896q26 0 45 -19t19 -45zM1664 960v-128q0 -26 -19 -45t-45 -19 h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1280 1344v-128q0 -26 -19 -45t-45 -19h-640q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h640q26 0 45 -19t19 -45z" />
-<glyph unicode="&#xf038;" horiz-adv-x="1792" d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 576v-128q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1280q26 0 45 -19t19 -45zM1792 960v-128q0 -26 -19 -45 t-45 -19h-1536q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1536q26 0 45 -19t19 -45zM1792 1344v-128q0 -26 -19 -45t-45 -19h-1152q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" />
-<glyph unicode="&#xf039;" horiz-adv-x="1792" d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 576v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 960v-128q0 -26 -19 -45 t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 1344v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45z" />
-<glyph unicode="&#xf03a;" horiz-adv-x="1792" d="M256 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5zM256 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5 t9.5 -22.5zM256 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1344 q13 0 22.5 -9.5t9.5 -22.5zM256 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5zM1792 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5 t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5zM1792 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5zM1792 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192 q0 13 9.5 22.5t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5z" />
-<glyph unicode="&#xf03b;" horiz-adv-x="1792" d="M384 992v-576q0 -13 -9.5 -22.5t-22.5 -9.5q-14 0 -23 9l-288 288q-9 9 -9 23t9 23l288 288q9 9 23 9q13 0 22.5 -9.5t9.5 -22.5zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5 t9.5 -22.5zM1792 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088q13 0 22.5 -9.5t9.5 -22.5zM1792 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088 q13 0 22.5 -9.5t9.5 -22.5zM1792 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5t9.5 -22.5z" />
-<glyph unicode="&#xf03c;" horiz-adv-x="1792" d="M352 704q0 -14 -9 -23l-288 -288q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5v576q0 13 9.5 22.5t22.5 9.5q14 0 23 -9l288 -288q9 -9 9 -23zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5 t9.5 -22.5zM1792 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088q13 0 22.5 -9.5t9.5 -22.5zM1792 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088 q13 0 22.5 -9.5t9.5 -22.5zM1792 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5t9.5 -22.5z" />
-<glyph unicode="&#xf03d;" horiz-adv-x="1792" d="M1792 1184v-1088q0 -42 -39 -59q-13 -5 -25 -5q-27 0 -45 19l-403 403v-166q0 -119 -84.5 -203.5t-203.5 -84.5h-704q-119 0 -203.5 84.5t-84.5 203.5v704q0 119 84.5 203.5t203.5 84.5h704q119 0 203.5 -84.5t84.5 -203.5v-165l403 402q18 19 45 19q12 0 25 -5 q39 -17 39 -59z" />
-<glyph unicode="&#xf03e;" horiz-adv-x="1920" d="M640 960q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1664 576v-448h-1408v192l320 320l160 -160l512 512zM1760 1280h-1600q-13 0 -22.5 -9.5t-9.5 -22.5v-1216q0 -13 9.5 -22.5t22.5 -9.5h1600q13 0 22.5 9.5t9.5 22.5v1216 q0 13 -9.5 22.5t-22.5 9.5zM1920 1248v-1216q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" />
-<glyph unicode="&#xf040;" d="M363 0l91 91l-235 235l-91 -91v-107h128v-128h107zM886 928q0 22 -22 22q-10 0 -17 -7l-542 -542q-7 -7 -7 -17q0 -22 22 -22q10 0 17 7l542 542q7 7 7 17zM832 1120l416 -416l-832 -832h-416v416zM1515 1024q0 -53 -37 -90l-166 -166l-416 416l166 165q36 38 90 38 q53 0 91 -38l235 -234q37 -39 37 -91z" />
-<glyph unicode="&#xf041;" horiz-adv-x="1024" d="M768 896q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM1024 896q0 -109 -33 -179l-364 -774q-16 -33 -47.5 -52t-67.5 -19t-67.5 19t-46.5 52l-365 774q-33 70 -33 179q0 212 150 362t362 150t362 -150t150 -362z" />
-<glyph unicode="&#xf042;" d="M768 96v1088q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
-<glyph unicode="&#xf043;" horiz-adv-x="1024" d="M512 384q0 36 -20 69q-1 1 -15.5 22.5t-25.5 38t-25 44t-21 50.5q-4 16 -21 16t-21 -16q-7 -23 -21 -50.5t-25 -44t-25.5 -38t-15.5 -22.5q-20 -33 -20 -69q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1024 512q0 -212 -150 -362t-362 -150t-362 150t-150 362 q0 145 81 275q6 9 62.5 90.5t101 151t99.5 178t83 201.5q9 30 34 47t51 17t51.5 -17t33.5 -47q28 -93 83 -201.5t99.5 -178t101 -151t62.5 -90.5q81 -127 81 -275z" />
-<glyph unicode="&#xf044;" horiz-adv-x="1792" d="M888 352l116 116l-152 152l-116 -116v-56h96v-96h56zM1328 1072q-16 16 -33 -1l-350 -350q-17 -17 -1 -33t33 1l350 350q17 17 1 33zM1408 478v-190q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832 q63 0 117 -25q15 -7 18 -23q3 -17 -9 -29l-49 -49q-14 -14 -32 -8q-23 6 -45 6h-832q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v126q0 13 9 22l64 64q15 15 35 7t20 -29zM1312 1216l288 -288l-672 -672h-288v288zM1756 1084l-92 -92 l-288 288l92 92q28 28 68 28t68 -28l152 -152q28 -28 28 -68t-28 -68z" />
-<glyph unicode="&#xf045;" horiz-adv-x="1664" d="M1408 547v-259q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h255v0q13 0 22.5 -9.5t9.5 -22.5q0 -27 -26 -32q-77 -26 -133 -60q-10 -4 -16 -4h-112q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832 q66 0 113 47t47 113v214q0 19 18 29q28 13 54 37q16 16 35 8q21 -9 21 -29zM1645 1043l-384 -384q-18 -19 -45 -19q-12 0 -25 5q-39 17 -39 59v192h-160q-323 0 -438 -131q-119 -137 -74 -473q3 -23 -20 -34q-8 -2 -12 -2q-16 0 -26 13q-10 14 -21 31t-39.5 68.5t-49.5 99.5 t-38.5 114t-17.5 122q0 49 3.5 91t14 90t28 88t47 81.5t68.5 74t94.5 61.5t124.5 48.5t159.5 30.5t196.5 11h160v192q0 42 39 59q13 5 25 5q26 0 45 -19l384 -384q19 -19 19 -45t-19 -45z" />
-<glyph unicode="&#xf046;" horiz-adv-x="1664" d="M1408 606v-318q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832q63 0 117 -25q15 -7 18 -23q3 -17 -9 -29l-49 -49q-10 -10 -23 -10q-3 0 -9 2q-23 6 -45 6h-832q-66 0 -113 -47t-47 -113v-832 q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v254q0 13 9 22l64 64q10 10 23 10q6 0 12 -3q20 -8 20 -29zM1639 1095l-814 -814q-24 -24 -57 -24t-57 24l-430 430q-24 24 -24 57t24 57l110 110q24 24 57 24t57 -24l263 -263l647 647q24 24 57 24t57 -24l110 -110 q24 -24 24 -57t-24 -57z" />
-<glyph unicode="&#xf047;" horiz-adv-x="1792" d="M1792 640q0 -26 -19 -45l-256 -256q-19 -19 -45 -19t-45 19t-19 45v128h-384v-384h128q26 0 45 -19t19 -45t-19 -45l-256 -256q-19 -19 -45 -19t-45 19l-256 256q-19 19 -19 45t19 45t45 19h128v384h-384v-128q0 -26 -19 -45t-45 -19t-45 19l-256 256q-19 19 -19 45 t19 45l256 256q19 19 45 19t45 -19t19 -45v-128h384v384h-128q-26 0 -45 19t-19 45t19 45l256 256q19 19 45 19t45 -19l256 -256q19 -19 19 -45t-19 -45t-45 -19h-128v-384h384v128q0 26 19 45t45 19t45 -19l256 -256q19 -19 19 -45z" />
-<glyph unicode="&#xf048;" horiz-adv-x="1024" d="M979 1395q19 19 32 13t13 -32v-1472q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-678q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-678q4 11 13 19z" />
-<glyph unicode="&#xf049;" horiz-adv-x="1792" d="M1747 1395q19 19 32 13t13 -32v-1472q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-710q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-678q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-678q4 11 13 19l710 710 q19 19 32 13t13 -32v-710q4 11 13 19z" />
-<glyph unicode="&#xf04a;" horiz-adv-x="1664" d="M1619 1395q19 19 32 13t13 -32v-1472q0 -26 -13 -32t-32 13l-710 710q-8 9 -13 19v-710q0 -26 -13 -32t-32 13l-710 710q-19 19 -19 45t19 45l710 710q19 19 32 13t13 -32v-710q5 11 13 19z" />
-<glyph unicode="&#xf04b;" horiz-adv-x="1408" d="M1384 609l-1328 -738q-23 -13 -39.5 -3t-16.5 36v1472q0 26 16.5 36t39.5 -3l1328 -738q23 -13 23 -31t-23 -31z" />
-<glyph unicode="&#xf04c;" d="M1536 1344v-1408q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h512q26 0 45 -19t19 -45zM640 1344v-1408q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h512q26 0 45 -19t19 -45z" />
-<glyph unicode="&#xf04d;" d="M1536 1344v-1408q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h1408q26 0 45 -19t19 -45z" />
-<glyph unicode="&#xf04e;" horiz-adv-x="1664" d="M45 -115q-19 -19 -32 -13t-13 32v1472q0 26 13 32t32 -13l710 -710q8 -8 13 -19v710q0 26 13 32t32 -13l710 -710q19 -19 19 -45t-19 -45l-710 -710q-19 -19 -32 -13t-13 32v710q-5 -10 -13 -19z" />
-<glyph unicode="&#xf050;" horiz-adv-x="1792" d="M45 -115q-19 -19 -32 -13t-13 32v1472q0 26 13 32t32 -13l710 -710q8 -8 13 -19v710q0 26 13 32t32 -13l710 -710q8 -8 13 -19v678q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-1408q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v678q-5 -10 -13 -19l-710 -710 q-19 -19 -32 -13t-13 32v710q-5 -10 -13 -19z" />
-<glyph unicode="&#xf051;" horiz-adv-x="1024" d="M45 -115q-19 -19 -32 -13t-13 32v1472q0 26 13 32t32 -13l710 -710q8 -8 13 -19v678q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-1408q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v678q-5 -10 -13 -19z" />
-<glyph unicode="&#xf052;" horiz-adv-x="1538" d="M14 557l710 710q19 19 45 19t45 -19l710 -710q19 -19 13 -32t-32 -13h-1472q-26 0 -32 13t13 32zM1473 0h-1408q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1408q26 0 45 -19t19 -45v-256q0 -26 -19 -45t-45 -19z" />
-<glyph unicode="&#xf053;" horiz-adv-x="1280" d="M1171 1235l-531 -531l531 -531q19 -19 19 -45t-19 -45l-166 -166q-19 -19 -45 -19t-45 19l-742 742q-19 19 -19 45t19 45l742 742q19 19 45 19t45 -19l166 -166q19 -19 19 -45t-19 -45z" />
-<glyph unicode="&#xf054;" horiz-adv-x="1280" d="M1107 659l-742 -742q-19 -19 -45 -19t-45 19l-166 166q-19 19 -19 45t19 45l531 531l-531 531q-19 19 -19 45t19 45l166 166q19 19 45 19t45 -19l742 -742q19 -19 19 -45t-19 -45z" />
-<glyph unicode="&#xf055;" d="M1216 576v128q0 26 -19 45t-45 19h-256v256q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-256h-256q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h256v-256q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v256h256q26 0 45 19t19 45zM1536 640q0 -209 -103 -385.5 t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
-<glyph unicode="&#xf056;" d="M1216 576v128q0 26 -19 45t-45 19h-768q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h768q26 0 45 19t19 45zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5 t103 -385.5z" />
-<glyph unicode="&#xf057;" d="M1149 414q0 26 -19 45l-181 181l181 181q19 19 19 45q0 27 -19 46l-90 90q-19 19 -46 19q-26 0 -45 -19l-181 -181l-181 181q-19 19 -45 19q-27 0 -46 -19l-90 -90q-19 -19 -19 -46q0 -26 19 -45l181 -181l-181 -181q-19 -19 -19 -45q0 -27 19 -46l90 -90q19 -19 46 -19 q26 0 45 19l181 181l181 -181q19 -19 45 -19q27 0 46 19l90 90q19 19 19 46zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
-<glyph unicode="&#xf058;" d="M1284 802q0 28 -18 46l-91 90q-19 19 -45 19t-45 -19l-408 -407l-226 226q-19 19 -45 19t-45 -19l-91 -90q-18 -18 -18 -46q0 -27 18 -45l362 -362q19 -19 45 -19q27 0 46 19l543 543q18 18 18 45zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103 t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
-<glyph unicode="&#xf059;" d="M896 160v192q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h192q14 0 23 9t9 23zM1152 832q0 88 -55.5 163t-138.5 116t-170 41q-243 0 -371 -213q-15 -24 8 -42l132 -100q7 -6 19 -6q16 0 25 12q53 68 86 92q34 24 86 24q48 0 85.5 -26t37.5 -59 q0 -38 -20 -61t-68 -45q-63 -28 -115.5 -86.5t-52.5 -125.5v-36q0 -14 9 -23t23 -9h192q14 0 23 9t9 23q0 19 21.5 49.5t54.5 49.5q32 18 49 28.5t46 35t44.5 48t28 60.5t12.5 81zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5 t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
-<glyph unicode="&#xf05a;" d="M1024 160v160q0 14 -9 23t-23 9h-96v512q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-160q0 -14 9 -23t23 -9h96v-320h-96q-14 0 -23 -9t-9 -23v-160q0 -14 9 -23t23 -9h448q14 0 23 9t9 23zM896 1056v160q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-160q0 -14 9 -23 t23 -9h192q14 0 23 9t9 23zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
-<glyph unicode="&#xf05b;" d="M1197 512h-109q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h109q-32 108 -112.5 188.5t-188.5 112.5v-109q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v109q-108 -32 -188.5 -112.5t-112.5 -188.5h109q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-109 q32 -108 112.5 -188.5t188.5 -112.5v109q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-109q108 32 188.5 112.5t112.5 188.5zM1536 704v-128q0 -26 -19 -45t-45 -19h-143q-37 -161 -154.5 -278.5t-278.5 -154.5v-143q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v143 q-161 37 -278.5 154.5t-154.5 278.5h-143q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h143q37 161 154.5 278.5t278.5 154.5v143q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-143q161 -37 278.5 -154.5t154.5 -278.5h143q26 0 45 -19t19 -45z" />
-<glyph unicode="&#xf05c;" d="M1097 457l-146 -146q-10 -10 -23 -10t-23 10l-137 137l-137 -137q-10 -10 -23 -10t-23 10l-146 146q-10 10 -10 23t10 23l137 137l-137 137q-10 10 -10 23t10 23l146 146q10 10 23 10t23 -10l137 -137l137 137q10 10 23 10t23 -10l146 -146q10 -10 10 -23t-10 -23 l-137 -137l137 -137q10 -10 10 -23t-10 -23zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5 t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
-<glyph unicode="&#xf05d;" d="M1171 723l-422 -422q-19 -19 -45 -19t-45 19l-294 294q-19 19 -19 45t19 45l102 102q19 19 45 19t45 -19l147 -147l275 275q19 19 45 19t45 -19l102 -102q19 -19 19 -45t-19 -45zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198 t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
-<glyph unicode="&#xf05e;" d="M1312 643q0 161 -87 295l-754 -753q137 -89 297 -89q111 0 211.5 43.5t173.5 116.5t116 174.5t43 212.5zM313 344l755 754q-135 91 -300 91q-148 0 -273 -73t-198 -199t-73 -274q0 -162 89 -299zM1536 643q0 -157 -61 -300t-163.5 -246t-245 -164t-298.5 -61t-298.5 61 t-245 164t-163.5 246t-61 300t61 299.5t163.5 245.5t245 164t298.5 61t298.5 -61t245 -164t163.5 -245.5t61 -299.5z" />
-<glyph unicode="&#xf060;" d="M1536 640v-128q0 -53 -32.5 -90.5t-84.5 -37.5h-704l293 -294q38 -36 38 -90t-38 -90l-75 -76q-37 -37 -90 -37q-52 0 -91 37l-651 652q-37 37 -37 90q0 52 37 91l651 650q38 38 91 38q52 0 90 -38l75 -74q38 -38 38 -91t-38 -91l-293 -293h704q52 0 84.5 -37.5 t32.5 -90.5z" />
-<glyph unicode="&#xf061;" d="M1472 576q0 -54 -37 -91l-651 -651q-39 -37 -91 -37q-51 0 -90 37l-75 75q-38 38 -38 91t38 91l293 293h-704q-52 0 -84.5 37.5t-32.5 90.5v128q0 53 32.5 90.5t84.5 37.5h704l-293 294q-38 36 -38 90t38 90l75 75q38 38 90 38q53 0 91 -38l651 -651q37 -35 37 -90z" />
-<glyph unicode="&#xf062;" horiz-adv-x="1664" d="M1611 565q0 -51 -37 -90l-75 -75q-38 -38 -91 -38q-54 0 -90 38l-294 293v-704q0 -52 -37.5 -84.5t-90.5 -32.5h-128q-53 0 -90.5 32.5t-37.5 84.5v704l-294 -293q-36 -38 -90 -38t-90 38l-75 75q-38 38 -38 90q0 53 38 91l651 651q35 37 90 37q54 0 91 -37l651 -651 q37 -39 37 -91z" />
-<glyph unicode="&#xf063;" horiz-adv-x="1664" d="M1611 704q0 -53 -37 -90l-651 -652q-39 -37 -91 -37q-53 0 -90 37l-651 652q-38 36 -38 90q0 53 38 91l74 75q39 37 91 37q53 0 90 -37l294 -294v704q0 52 38 90t90 38h128q52 0 90 -38t38 -90v-704l294 294q37 37 90 37q52 0 91 -37l75 -75q37 -39 37 -91z" />
-<glyph unicode="&#xf064;" horiz-adv-x="1792" d="M1792 896q0 -26 -19 -45l-512 -512q-19 -19 -45 -19t-45 19t-19 45v256h-224q-98 0 -175.5 -6t-154 -21.5t-133 -42.5t-105.5 -69.5t-80 -101t-48.5 -138.5t-17.5 -181q0 -55 5 -123q0 -6 2.5 -23.5t2.5 -26.5q0 -15 -8.5 -25t-23.5 -10q-16 0 -28 17q-7 9 -13 22 t-13.5 30t-10.5 24q-127 285 -127 451q0 199 53 333q162 403 875 403h224v256q0 26 19 45t45 19t45 -19l512 -512q19 -19 19 -45z" />
-<glyph unicode="&#xf065;" d="M755 480q0 -13 -10 -23l-332 -332l144 -144q19 -19 19 -45t-19 -45t-45 -19h-448q-26 0 -45 19t-19 45v448q0 26 19 45t45 19t45 -19l144 -144l332 332q10 10 23 10t23 -10l114 -114q10 -10 10 -23zM1536 1344v-448q0 -26 -19 -45t-45 -19t-45 19l-144 144l-332 -332 q-10 -10 -23 -10t-23 10l-114 114q-10 10 -10 23t10 23l332 332l-144 144q-19 19 -19 45t19 45t45 19h448q26 0 45 -19t19 -45z" />
-<glyph unicode="&#xf066;" d="M768 576v-448q0 -26 -19 -45t-45 -19t-45 19l-144 144l-332 -332q-10 -10 -23 -10t-23 10l-114 114q-10 10 -10 23t10 23l332 332l-144 144q-19 19 -19 45t19 45t45 19h448q26 0 45 -19t19 -45zM1523 1248q0 -13 -10 -23l-332 -332l144 -144q19 -19 19 -45t-19 -45 t-45 -19h-448q-26 0 -45 19t-19 45v448q0 26 19 45t45 19t45 -19l144 -144l332 332q10 10 23 10t23 -10l114 -114q10 -10 10 -23z" />
-<glyph unicode="&#xf067;" horiz-adv-x="1408" d="M1408 800v-192q0 -40 -28 -68t-68 -28h-416v-416q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v416h-416q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h416v416q0 40 28 68t68 28h192q40 0 68 -28t28 -68v-416h416q40 0 68 -28t28 -68z" />
-<glyph unicode="&#xf068;" horiz-adv-x="1408" d="M1408 800v-192q0 -40 -28 -68t-68 -28h-1216q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h1216q40 0 68 -28t28 -68z" />
-<glyph unicode="&#xf069;" horiz-adv-x="1664" d="M1482 486q46 -26 59.5 -77.5t-12.5 -97.5l-64 -110q-26 -46 -77.5 -59.5t-97.5 12.5l-266 153v-307q0 -52 -38 -90t-90 -38h-128q-52 0 -90 38t-38 90v307l-266 -153q-46 -26 -97.5 -12.5t-77.5 59.5l-64 110q-26 46 -12.5 97.5t59.5 77.5l266 154l-266 154 q-46 26 -59.5 77.5t12.5 97.5l64 110q26 46 77.5 59.5t97.5 -12.5l266 -153v307q0 52 38 90t90 38h128q52 0 90 -38t38 -90v-307l266 153q46 26 97.5 12.5t77.5 -59.5l64 -110q26 -46 12.5 -97.5t-59.5 -77.5l-266 -154z" />
-<glyph unicode="&#xf06a;" d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM896 161v190q0 14 -9 23.5t-22 9.5h-192q-13 0 -23 -10t-10 -23v-190q0 -13 10 -23t23 -10h192 q13 0 22 9.5t9 23.5zM894 505l18 621q0 12 -10 18q-10 8 -24 8h-220q-14 0 -24 -8q-10 -6 -10 -18l17 -621q0 -10 10 -17.5t24 -7.5h185q14 0 23.5 7.5t10.5 17.5z" />
-<glyph unicode="&#xf06b;" d="M928 180v56v468v192h-320v-192v-468v-56q0 -25 18 -38.5t46 -13.5h192q28 0 46 13.5t18 38.5zM472 1024h195l-126 161q-26 31 -69 31q-40 0 -68 -28t-28 -68t28 -68t68 -28zM1160 1120q0 40 -28 68t-68 28q-43 0 -69 -31l-125 -161h194q40 0 68 28t28 68zM1536 864v-320 q0 -14 -9 -23t-23 -9h-96v-416q0 -40 -28 -68t-68 -28h-1088q-40 0 -68 28t-28 68v416h-96q-14 0 -23 9t-9 23v320q0 14 9 23t23 9h440q-93 0 -158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5q107 0 168 -77l128 -165l128 165q61 77 168 77q93 0 158.5 -65.5t65.5 -158.5 t-65.5 -158.5t-158.5 -65.5h440q14 0 23 -9t9 -23z" />
-<glyph unicode="&#xf06c;" horiz-adv-x="1792" d="M1280 832q0 26 -19 45t-45 19q-172 0 -318 -49.5t-259.5 -134t-235.5 -219.5q-19 -21 -19 -45q0 -26 19 -45t45 -19q24 0 45 19q27 24 74 71t67 66q137 124 268.5 176t313.5 52q26 0 45 19t19 45zM1792 1030q0 -95 -20 -193q-46 -224 -184.5 -383t-357.5 -268 q-214 -108 -438 -108q-148 0 -286 47q-15 5 -88 42t-96 37q-16 0 -39.5 -32t-45 -70t-52.5 -70t-60 -32q-30 0 -51 11t-31 24t-27 42q-2 4 -6 11t-5.5 10t-3 9.5t-1.5 13.5q0 35 31 73.5t68 65.5t68 56t31 48q0 4 -14 38t-16 44q-9 51 -9 104q0 115 43.5 220t119 184.5 t170.5 139t204 95.5q55 18 145 25.5t179.5 9t178.5 6t163.5 24t113.5 56.5l29.5 29.5t29.5 28t27 20t36.5 16t43.5 4.5q39 0 70.5 -46t47.5 -112t24 -124t8 -96z" />
-<glyph unicode="&#xf06d;" horiz-adv-x="1408" d="M1408 -160v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5zM1152 896q0 -78 -24.5 -144t-64 -112.5t-87.5 -88t-96 -77.5t-87.5 -72t-64 -81.5t-24.5 -96.5q0 -96 67 -224l-4 1l1 -1 q-90 41 -160 83t-138.5 100t-113.5 122.5t-72.5 150.5t-27.5 184q0 78 24.5 144t64 112.5t87.5 88t96 77.5t87.5 72t64 81.5t24.5 96.5q0 94 -66 224l3 -1l-1 1q90 -41 160 -83t138.5 -100t113.5 -122.5t72.5 -150.5t27.5 -184z" />
-<glyph unicode="&#xf06e;" horiz-adv-x="1792" d="M1664 576q-152 236 -381 353q61 -104 61 -225q0 -185 -131.5 -316.5t-316.5 -131.5t-316.5 131.5t-131.5 316.5q0 121 61 225q-229 -117 -381 -353q133 -205 333.5 -326.5t434.5 -121.5t434.5 121.5t333.5 326.5zM944 960q0 20 -14 34t-34 14q-125 0 -214.5 -89.5 t-89.5 -214.5q0 -20 14 -34t34 -14t34 14t14 34q0 86 61 147t147 61q20 0 34 14t14 34zM1792 576q0 -34 -20 -69q-140 -230 -376.5 -368.5t-499.5 -138.5t-499.5 139t-376.5 368q-20 35 -20 69t20 69q140 229 376.5 368t499.5 139t499.5 -139t376.5 -368q20 -35 20 -69z" />
-<glyph unicode="&#xf070;" horiz-adv-x="1792" d="M555 201l78 141q-87 63 -136 159t-49 203q0 121 61 225q-229 -117 -381 -353q167 -258 427 -375zM944 960q0 20 -14 34t-34 14q-125 0 -214.5 -89.5t-89.5 -214.5q0 -20 14 -34t34 -14t34 14t14 34q0 86 61 147t147 61q20 0 34 14t14 34zM1307 1151q0 -7 -1 -9 q-105 -188 -315 -566t-316 -567l-49 -89q-10 -16 -28 -16q-12 0 -134 70q-16 10 -16 28q0 12 44 87q-143 65 -263.5 173t-208.5 245q-20 31 -20 69t20 69q153 235 380 371t496 136q89 0 180 -17l54 97q10 16 28 16q5 0 18 -6t31 -15.5t33 -18.5t31.5 -18.5t19.5 -11.5 q16 -10 16 -27zM1344 704q0 -139 -79 -253.5t-209 -164.5l280 502q8 -45 8 -84zM1792 576q0 -35 -20 -69q-39 -64 -109 -145q-150 -172 -347.5 -267t-419.5 -95l74 132q212 18 392.5 137t301.5 307q-115 179 -282 294l63 112q95 -64 182.5 -153t144.5 -184q20 -34 20 -69z " />
-<glyph unicode="&#xf071;" horiz-adv-x="1792" d="M1024 161v190q0 14 -9.5 23.5t-22.5 9.5h-192q-13 0 -22.5 -9.5t-9.5 -23.5v-190q0 -14 9.5 -23.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 23.5zM1022 535l18 459q0 12 -10 19q-13 11 -24 11h-220q-11 0 -24 -11q-10 -7 -10 -21l17 -457q0 -10 10 -16.5t24 -6.5h185 q14 0 23.5 6.5t10.5 16.5zM1008 1469l768 -1408q35 -63 -2 -126q-17 -29 -46.5 -46t-63.5 -17h-1536q-34 0 -63.5 17t-46.5 46q-37 63 -2 126l768 1408q17 31 47 49t65 18t65 -18t47 -49z" />
-<glyph unicode="&#xf072;" horiz-adv-x="1408" d="M1376 1376q44 -52 12 -148t-108 -172l-161 -161l160 -696q5 -19 -12 -33l-128 -96q-7 -6 -19 -6q-4 0 -7 1q-15 3 -21 16l-279 508l-259 -259l53 -194q5 -17 -8 -31l-96 -96q-9 -9 -23 -9h-2q-15 2 -24 13l-189 252l-252 189q-11 7 -13 23q-1 13 9 25l96 97q9 9 23 9 q6 0 8 -1l194 -53l259 259l-508 279q-14 8 -17 24q-2 16 9 27l128 128q14 13 30 8l665 -159l160 160q76 76 172 108t148 -12z" />
-<glyph unicode="&#xf073;" horiz-adv-x="1664" d="M128 -128h288v288h-288v-288zM480 -128h320v288h-320v-288zM128 224h288v320h-288v-320zM480 224h320v320h-320v-320zM128 608h288v288h-288v-288zM864 -128h320v288h-320v-288zM480 608h320v288h-320v-288zM1248 -128h288v288h-288v-288zM864 224h320v320h-320v-320z M512 1088v288q0 13 -9.5 22.5t-22.5 9.5h-64q-13 0 -22.5 -9.5t-9.5 -22.5v-288q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5zM1248 224h288v320h-288v-320zM864 608h320v288h-320v-288zM1248 608h288v288h-288v-288zM1280 1088v288q0 13 -9.5 22.5t-22.5 9.5h-64 q-13 0 -22.5 -9.5t-9.5 -22.5v-288q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5zM1664 1152v-1280q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h384v96q0 66 47 113t113 47 h64q66 0 113 -47t47 -113v-96h128q52 0 90 -38t38 -90z" />
-<glyph unicode="&#xf074;" horiz-adv-x="1792" d="M666 1055q-60 -92 -137 -273q-22 45 -37 72.5t-40.5 63.5t-51 56.5t-63 35t-81.5 14.5h-224q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h224q250 0 410 -225zM1792 256q0 -14 -9 -23l-320 -320q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5v192q-32 0 -85 -0.5t-81 -1t-73 1 t-71 5t-64 10.5t-63 18.5t-58 28.5t-59 40t-55 53.5t-56 69.5q59 93 136 273q22 -45 37 -72.5t40.5 -63.5t51 -56.5t63 -35t81.5 -14.5h256v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23zM1792 1152q0 -14 -9 -23l-320 -320q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5 v192h-256q-48 0 -87 -15t-69 -45t-51 -61.5t-45 -77.5q-32 -62 -78 -171q-29 -66 -49.5 -111t-54 -105t-64 -100t-74 -83t-90 -68.5t-106.5 -42t-128 -16.5h-224q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h224q48 0 87 15t69 45t51 61.5t45 77.5q32 62 78 171q29 66 49.5 111 t54 105t64 100t74 83t90 68.5t106.5 42t128 16.5h256v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23z" />
-<glyph unicode="&#xf075;" horiz-adv-x="1792" d="M1792 640q0 -174 -120 -321.5t-326 -233t-450 -85.5q-70 0 -145 8q-198 -175 -460 -242q-49 -14 -114 -22q-17 -2 -30.5 9t-17.5 29v1q-3 4 -0.5 12t2 10t4.5 9.5l6 9t7 8.5t8 9q7 8 31 34.5t34.5 38t31 39.5t32.5 51t27 59t26 76q-157 89 -247.5 220t-90.5 281 q0 130 71 248.5t191 204.5t286 136.5t348 50.5q244 0 450 -85.5t326 -233t120 -321.5z" />
-<glyph unicode="&#xf076;" d="M1536 704v-128q0 -201 -98.5 -362t-274 -251.5t-395.5 -90.5t-395.5 90.5t-274 251.5t-98.5 362v128q0 26 19 45t45 19h384q26 0 45 -19t19 -45v-128q0 -52 23.5 -90t53.5 -57t71 -30t64 -13t44 -2t44 2t64 13t71 30t53.5 57t23.5 90v128q0 26 19 45t45 19h384 q26 0 45 -19t19 -45zM512 1344v-384q0 -26 -19 -45t-45 -19h-384q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h384q26 0 45 -19t19 -45zM1536 1344v-384q0 -26 -19 -45t-45 -19h-384q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h384q26 0 45 -19t19 -45z" />
-<glyph unicode="&#xf077;" horiz-adv-x="1792" d="M1683 205l-166 -165q-19 -19 -45 -19t-45 19l-531 531l-531 -531q-19 -19 -45 -19t-45 19l-166 165q-19 19 -19 45.5t19 45.5l742 741q19 19 45 19t45 -19l742 -741q19 -19 19 -45.5t-19 -45.5z" />
-<glyph unicode="&#xf078;" horiz-adv-x="1792" d="M1683 728l-742 -741q-19 -19 -45 -19t-45 19l-742 741q-19 19 -19 45.5t19 45.5l166 165q19 19 45 19t45 -19l531 -531l531 531q19 19 45 19t45 -19l166 -165q19 -19 19 -45.5t-19 -45.5z" />
-<glyph unicode="&#xf079;" horiz-adv-x="1920" d="M1280 32q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-8 0 -13.5 2t-9 7t-5.5 8t-3 11.5t-1 11.5v13v11v160v416h-192q-26 0 -45 19t-19 45q0 24 15 41l320 384q19 22 49 22t49 -22l320 -384q15 -17 15 -41q0 -26 -19 -45t-45 -19h-192v-384h576q16 0 25 -11l160 -192q7 -11 7 -21 zM1920 448q0 -24 -15 -41l-320 -384q-20 -23 -49 -23t-49 23l-320 384q-15 17 -15 41q0 26 19 45t45 19h192v384h-576q-16 0 -25 12l-160 192q-7 9 -7 20q0 13 9.5 22.5t22.5 9.5h960q8 0 13.5 -2t9 -7t5.5 -8t3 -11.5t1 -11.5v-13v-11v-160v-416h192q26 0 45 -19t19 -45z " />
-<glyph unicode="&#xf07a;" horiz-adv-x="1664" d="M640 0q0 -52 -38 -90t-90 -38t-90 38t-38 90t38 90t90 38t90 -38t38 -90zM1536 0q0 -52 -38 -90t-90 -38t-90 38t-38 90t38 90t90 38t90 -38t38 -90zM1664 1088v-512q0 -24 -16.5 -42.5t-40.5 -21.5l-1044 -122q13 -60 13 -70q0 -16 -24 -64h920q26 0 45 -19t19 -45 t-19 -45t-45 -19h-1024q-26 0 -45 19t-19 45q0 11 8 31.5t16 36t21.5 40t15.5 29.5l-177 823h-204q-26 0 -45 19t-19 45t19 45t45 19h256q16 0 28.5 -6.5t19.5 -15.5t13 -24.5t8 -26t5.5 -29.5t4.5 -26h1201q26 0 45 -19t19 -45z" />
-<glyph unicode="&#xf07b;" horiz-adv-x="1664" d="M1664 928v-704q0 -92 -66 -158t-158 -66h-1216q-92 0 -158 66t-66 158v960q0 92 66 158t158 66h320q92 0 158 -66t66 -158v-32h672q92 0 158 -66t66 -158z" />
-<glyph unicode="&#xf07c;" horiz-adv-x="1920" d="M1879 584q0 -31 -31 -66l-336 -396q-43 -51 -120.5 -86.5t-143.5 -35.5h-1088q-34 0 -60.5 13t-26.5 43q0 31 31 66l336 396q43 51 120.5 86.5t143.5 35.5h1088q34 0 60.5 -13t26.5 -43zM1536 928v-160h-832q-94 0 -197 -47.5t-164 -119.5l-337 -396l-5 -6q0 4 -0.5 12.5 t-0.5 12.5v960q0 92 66 158t158 66h320q92 0 158 -66t66 -158v-32h544q92 0 158 -66t66 -158z" />
-<glyph unicode="&#xf07d;" horiz-adv-x="768" d="M704 1216q0 -26 -19 -45t-45 -19h-128v-1024h128q26 0 45 -19t19 -45t-19 -45l-256 -256q-19 -19 -45 -19t-45 19l-256 256q-19 19 -19 45t19 45t45 19h128v1024h-128q-26 0 -45 19t-19 45t19 45l256 256q19 19 45 19t45 -19l256 -256q19 -19 19 -45z" />
-<glyph unicode="&#xf07e;" horiz-adv-x="1792" d="M1792 640q0 -26 -19 -45l-256 -256q-19 -19 -45 -19t-45 19t-19 45v128h-1024v-128q0 -26 -19 -45t-45 -19t-45 19l-256 256q-19 19 -19 45t19 45l256 256q19 19 45 19t45 -19t19 -45v-128h1024v128q0 26 19 45t45 19t45 -19l256 -256q19 -19 19 -45z" />
-<glyph unicode="&#xf080;" horiz-adv-x="2048" d="M640 640v-512h-256v512h256zM1024 1152v-1024h-256v1024h256zM2048 0v-128h-2048v1536h128v-1408h1920zM1408 896v-768h-256v768h256zM1792 1280v-1152h-256v1152h256z" />
-<glyph unicode="&#xf081;" d="M1280 926q-56 -25 -121 -34q68 40 93 117q-65 -38 -134 -51q-61 66 -153 66q-87 0 -148.5 -61.5t-61.5 -148.5q0 -29 5 -48q-129 7 -242 65t-192 155q-29 -50 -29 -106q0 -114 91 -175q-47 1 -100 26v-2q0 -75 50 -133.5t123 -72.5q-29 -8 -51 -8q-13 0 -39 4 q21 -63 74.5 -104t121.5 -42q-116 -90 -261 -90q-26 0 -50 3q148 -94 322 -94q112 0 210 35.5t168 95t120.5 137t75 162t24.5 168.5q0 18 -1 27q63 45 105 109zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5 t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
-<glyph unicode="&#xf082;" d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-188v595h199l30 232h-229v148q0 56 23.5 84t91.5 28l122 1v207q-63 9 -178 9q-136 0 -217.5 -80t-81.5 -226v-171h-200v-232h200v-595h-532q-119 0 -203.5 84.5t-84.5 203.5v960 q0 119 84.5 203.5t203.5 84.5h960z" />
-<glyph unicode="&#xf083;" horiz-adv-x="1792" d="M928 704q0 14 -9 23t-23 9q-66 0 -113 -47t-47 -113q0 -14 9 -23t23 -9t23 9t9 23q0 40 28 68t68 28q14 0 23 9t9 23zM1152 574q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75t75 -181zM128 0h1536v128h-1536v-128zM1280 574q0 159 -112.5 271.5 t-271.5 112.5t-271.5 -112.5t-112.5 -271.5t112.5 -271.5t271.5 -112.5t271.5 112.5t112.5 271.5zM256 1216h384v128h-384v-128zM128 1024h1536v118v138h-828l-64 -128h-644v-128zM1792 1280v-1280q0 -53 -37.5 -90.5t-90.5 -37.5h-1536q-53 0 -90.5 37.5t-37.5 90.5v1280 q0 53 37.5 90.5t90.5 37.5h1536q53 0 90.5 -37.5t37.5 -90.5z" />
-<glyph unicode="&#xf084;" horiz-adv-x="1792" d="M832 1024q0 80 -56 136t-136 56t-136 -56t-56 -136q0 -42 19 -83q-41 19 -83 19q-80 0 -136 -56t-56 -136t56 -136t136 -56t136 56t56 136q0 42 -19 83q41 -19 83 -19q80 0 136 56t56 136zM1683 320q0 -17 -49 -66t-66 -49q-9 0 -28.5 16t-36.5 33t-38.5 40t-24.5 26 l-96 -96l220 -220q28 -28 28 -68q0 -42 -39 -81t-81 -39q-40 0 -68 28l-671 671q-176 -131 -365 -131q-163 0 -265.5 102.5t-102.5 265.5q0 160 95 313t248 248t313 95q163 0 265.5 -102.5t102.5 -265.5q0 -189 -131 -365l355 -355l96 96q-3 3 -26 24.5t-40 38.5t-33 36.5 t-16 28.5q0 17 49 66t66 49q13 0 23 -10q6 -6 46 -44.5t82 -79.5t86.5 -86t73 -78t28.5 -41z" />
-<glyph unicode="&#xf085;" horiz-adv-x="1920" d="M896 640q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM1664 128q0 52 -38 90t-90 38t-90 -38t-38 -90q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1664 1152q0 52 -38 90t-90 38t-90 -38t-38 -90q0 -53 37.5 -90.5t90.5 -37.5 t90.5 37.5t37.5 90.5zM1280 731v-185q0 -10 -7 -19.5t-16 -10.5l-155 -24q-11 -35 -32 -76q34 -48 90 -115q7 -10 7 -20q0 -12 -7 -19q-23 -30 -82.5 -89.5t-78.5 -59.5q-11 0 -21 7l-115 90q-37 -19 -77 -31q-11 -108 -23 -155q-7 -24 -30 -24h-186q-11 0 -20 7.5t-10 17.5 l-23 153q-34 10 -75 31l-118 -89q-7 -7 -20 -7q-11 0 -21 8q-144 133 -144 160q0 9 7 19q10 14 41 53t47 61q-23 44 -35 82l-152 24q-10 1 -17 9.5t-7 19.5v185q0 10 7 19.5t16 10.5l155 24q11 35 32 76q-34 48 -90 115q-7 11 -7 20q0 12 7 20q22 30 82 89t79 59q11 0 21 -7 l115 -90q34 18 77 32q11 108 23 154q7 24 30 24h186q11 0 20 -7.5t10 -17.5l23 -153q34 -10 75 -31l118 89q8 7 20 7q11 0 21 -8q144 -133 144 -160q0 -9 -7 -19q-12 -16 -42 -54t-45 -60q23 -48 34 -82l152 -23q10 -2 17 -10.5t7 -19.5zM1920 198v-140q0 -16 -149 -31 q-12 -27 -30 -52q51 -113 51 -138q0 -4 -4 -7q-122 -71 -124 -71q-8 0 -46 47t-52 68q-20 -2 -30 -2t-30 2q-14 -21 -52 -68t-46 -47q-2 0 -124 71q-4 3 -4 7q0 25 51 138q-18 25 -30 52q-149 15 -149 31v140q0 16 149 31q13 29 30 52q-51 113 -51 138q0 4 4 7q4 2 35 20 t59 34t30 16q8 0 46 -46.5t52 -67.5q20 2 30 2t30 -2q51 71 92 112l6 2q4 0 124 -70q4 -3 4 -7q0 -25 -51 -138q17 -23 30 -52q149 -15 149 -31zM1920 1222v-140q0 -16 -149 -31q-12 -27 -30 -52q51 -113 51 -138q0 -4 -4 -7q-122 -71 -124 -71q-8 0 -46 47t-52 68 q-20 -2 -30 -2t-30 2q-14 -21 -52 -68t-46 -47q-2 0 -124 71q-4 3 -4 7q0 25 51 138q-18 25 -30 52q-149 15 -149 31v140q0 16 149 31q13 29 30 52q-51 113 -51 138q0 4 4 7q4 2 35 20t59 34t30 16q8 0 46 -46.5t52 -67.5q20 2 30 2t30 -2q51 71 92 112l6 2q4 0 124 -70 q4 -3 4 -7q0 -25 -51 -138q17 -23 30 -52q149 -15 149 -31z" />
-<glyph unicode="&#xf086;" horiz-adv-x="1792" d="M1408 768q0 -139 -94 -257t-256.5 -186.5t-353.5 -68.5q-86 0 -176 16q-124 -88 -278 -128q-36 -9 -86 -16h-3q-11 0 -20.5 8t-11.5 21q-1 3 -1 6.5t0.5 6.5t2 6l2.5 5t3.5 5.5t4 5t4.5 5t4 4.5q5 6 23 25t26 29.5t22.5 29t25 38.5t20.5 44q-124 72 -195 177t-71 224 q0 139 94 257t256.5 186.5t353.5 68.5t353.5 -68.5t256.5 -186.5t94 -257zM1792 512q0 -120 -71 -224.5t-195 -176.5q10 -24 20.5 -44t25 -38.5t22.5 -29t26 -29.5t23 -25q1 -1 4 -4.5t4.5 -5t4 -5t3.5 -5.5l2.5 -5t2 -6t0.5 -6.5t-1 -6.5q-3 -14 -13 -22t-22 -7 q-50 7 -86 16q-154 40 -278 128q-90 -16 -176 -16q-271 0 -472 132q58 -4 88 -4q161 0 309 45t264 129q125 92 192 212t67 254q0 77 -23 152q129 -71 204 -178t75 -230z" />
-<glyph unicode="&#xf087;" d="M256 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 768q0 51 -39 89.5t-89 38.5h-352q0 58 48 159.5t48 160.5q0 98 -32 145t-128 47q-26 -26 -38 -85t-30.5 -125.5t-59.5 -109.5q-22 -23 -77 -91q-4 -5 -23 -30t-31.5 -41t-34.5 -42.5 t-40 -44t-38.5 -35.5t-40 -27t-35.5 -9h-32v-640h32q13 0 31.5 -3t33 -6.5t38 -11t35 -11.5t35.5 -12.5t29 -10.5q211 -73 342 -73h121q192 0 192 167q0 26 -5 56q30 16 47.5 52.5t17.5 73.5t-18 69q53 50 53 119q0 25 -10 55.5t-25 47.5q32 1 53.5 47t21.5 81zM1536 769 q0 -89 -49 -163q9 -33 9 -69q0 -77 -38 -144q3 -21 3 -43q0 -101 -60 -178q1 -139 -85 -219.5t-227 -80.5h-36h-93q-96 0 -189.5 22.5t-216.5 65.5q-116 40 -138 40h-288q-53 0 -90.5 37.5t-37.5 90.5v640q0 53 37.5 90.5t90.5 37.5h274q36 24 137 155q58 75 107 128 q24 25 35.5 85.5t30.5 126.5t62 108q39 37 90 37q84 0 151 -32.5t102 -101.5t35 -186q0 -93 -48 -192h176q104 0 180 -76t76 -179z" />
-<glyph unicode="&#xf088;" d="M256 1088q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 512q0 35 -21.5 81t-53.5 47q15 17 25 47.5t10 55.5q0 69 -53 119q18 32 18 69t-17.5 73.5t-47.5 52.5q5 30 5 56q0 85 -49 126t-136 41h-128q-131 0 -342 -73q-5 -2 -29 -10.5 t-35.5 -12.5t-35 -11.5t-38 -11t-33 -6.5t-31.5 -3h-32v-640h32q16 0 35.5 -9t40 -27t38.5 -35.5t40 -44t34.5 -42.5t31.5 -41t23 -30q55 -68 77 -91q41 -43 59.5 -109.5t30.5 -125.5t38 -85q96 0 128 47t32 145q0 59 -48 160.5t-48 159.5h352q50 0 89 38.5t39 89.5z M1536 511q0 -103 -76 -179t-180 -76h-176q48 -99 48 -192q0 -118 -35 -186q-35 -69 -102 -101.5t-151 -32.5q-51 0 -90 37q-34 33 -54 82t-25.5 90.5t-17.5 84.5t-31 64q-48 50 -107 127q-101 131 -137 155h-274q-53 0 -90.5 37.5t-37.5 90.5v640q0 53 37.5 90.5t90.5 37.5 h288q22 0 138 40q128 44 223 66t200 22h112q140 0 226.5 -79t85.5 -216v-5q60 -77 60 -178q0 -22 -3 -43q38 -67 38 -144q0 -36 -9 -69q49 -74 49 -163z" />
-<glyph unicode="&#xf089;" horiz-adv-x="896" d="M832 1504v-1339l-449 -236q-22 -12 -40 -12q-21 0 -31.5 14.5t-10.5 35.5q0 6 2 20l86 500l-364 354q-25 27 -25 48q0 37 56 46l502 73l225 455q19 41 49 41z" />
-<glyph unicode="&#xf08a;" horiz-adv-x="1792" d="M1664 940q0 81 -21.5 143t-55 98.5t-81.5 59.5t-94 31t-98 8t-112 -25.5t-110.5 -64t-86.5 -72t-60 -61.5q-18 -22 -49 -22t-49 22q-24 28 -60 61.5t-86.5 72t-110.5 64t-112 25.5t-98 -8t-94 -31t-81.5 -59.5t-55 -98.5t-21.5 -143q0 -168 187 -355l581 -560l580 559 q188 188 188 356zM1792 940q0 -221 -229 -450l-623 -600q-18 -18 -44 -18t-44 18l-624 602q-10 8 -27.5 26t-55.5 65.5t-68 97.5t-53.5 121t-23.5 138q0 220 127 344t351 124q62 0 126.5 -21.5t120 -58t95.5 -68.5t76 -68q36 36 76 68t95.5 68.5t120 58t126.5 21.5 q224 0 351 -124t127 -344z" />
-<glyph unicode="&#xf08b;" horiz-adv-x="1664" d="M640 96q0 -4 1 -20t0.5 -26.5t-3 -23.5t-10 -19.5t-20.5 -6.5h-320q-119 0 -203.5 84.5t-84.5 203.5v704q0 119 84.5 203.5t203.5 84.5h320q13 0 22.5 -9.5t9.5 -22.5q0 -4 1 -20t0.5 -26.5t-3 -23.5t-10 -19.5t-20.5 -6.5h-320q-66 0 -113 -47t-47 -113v-704 q0 -66 47 -113t113 -47h288h11h13t11.5 -1t11.5 -3t8 -5.5t7 -9t2 -13.5zM1568 640q0 -26 -19 -45l-544 -544q-19 -19 -45 -19t-45 19t-19 45v288h-448q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h448v288q0 26 19 45t45 19t45 -19l544 -544q19 -19 19 -45z" />
-<glyph unicode="&#xf08c;" d="M237 122h231v694h-231v-694zM483 1030q-1 52 -36 86t-93 34t-94.5 -34t-36.5 -86q0 -51 35.5 -85.5t92.5 -34.5h1q59 0 95 34.5t36 85.5zM1068 122h231v398q0 154 -73 233t-193 79q-136 0 -209 -117h2v101h-231q3 -66 0 -694h231v388q0 38 7 56q15 35 45 59.5t74 24.5 q116 0 116 -157v-371zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
-<glyph unicode="&#xf08d;" horiz-adv-x="1152" d="M480 672v448q0 14 -9 23t-23 9t-23 -9t-9 -23v-448q0 -14 9 -23t23 -9t23 9t9 23zM1152 320q0 -26 -19 -45t-45 -19h-429l-51 -483q-2 -12 -10.5 -20.5t-20.5 -8.5h-1q-27 0 -32 27l-76 485h-404q-26 0 -45 19t-19 45q0 123 78.5 221.5t177.5 98.5v512q-52 0 -90 38 t-38 90t38 90t90 38h640q52 0 90 -38t38 -90t-38 -90t-90 -38v-512q99 0 177.5 -98.5t78.5 -221.5z" />
-<glyph unicode="&#xf08e;" horiz-adv-x="1792" d="M1408 608v-320q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h704q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-704q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v320 q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1792 1472v-512q0 -26 -19 -45t-45 -19t-45 19l-176 176l-652 -652q-10 -10 -23 -10t-23 10l-114 114q-10 10 -10 23t10 23l652 652l-176 176q-19 19 -19 45t19 45t45 19h512q26 0 45 -19t19 -45z" />
-<glyph unicode="&#xf090;" d="M1184 640q0 -26 -19 -45l-544 -544q-19 -19 -45 -19t-45 19t-19 45v288h-448q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h448v288q0 26 19 45t45 19t45 -19l544 -544q19 -19 19 -45zM1536 992v-704q0 -119 -84.5 -203.5t-203.5 -84.5h-320q-13 0 -22.5 9.5t-9.5 22.5 q0 4 -1 20t-0.5 26.5t3 23.5t10 19.5t20.5 6.5h320q66 0 113 47t47 113v704q0 66 -47 113t-113 47h-288h-11h-13t-11.5 1t-11.5 3t-8 5.5t-7 9t-2 13.5q0 4 -1 20t-0.5 26.5t3 23.5t10 19.5t20.5 6.5h320q119 0 203.5 -84.5t84.5 -203.5z" />
-<glyph unicode="&#xf091;" horiz-adv-x="1664" d="M458 653q-74 162 -74 371h-256v-96q0 -78 94.5 -162t235.5 -113zM1536 928v96h-256q0 -209 -74 -371q141 29 235.5 113t94.5 162zM1664 1056v-128q0 -71 -41.5 -143t-112 -130t-173 -97.5t-215.5 -44.5q-42 -54 -95 -95q-38 -34 -52.5 -72.5t-14.5 -89.5q0 -54 30.5 -91 t97.5 -37q75 0 133.5 -45.5t58.5 -114.5v-64q0 -14 -9 -23t-23 -9h-832q-14 0 -23 9t-9 23v64q0 69 58.5 114.5t133.5 45.5q67 0 97.5 37t30.5 91q0 51 -14.5 89.5t-52.5 72.5q-53 41 -95 95q-113 5 -215.5 44.5t-173 97.5t-112 130t-41.5 143v128q0 40 28 68t68 28h288v96 q0 66 47 113t113 47h576q66 0 113 -47t47 -113v-96h288q40 0 68 -28t28 -68z" />
-<glyph unicode="&#xf092;" d="M519 336q4 6 -3 13q-9 7 -14 2q-4 -6 3 -13q9 -7 14 -2zM491 377q-5 7 -12 4q-6 -4 0 -12q7 -8 12 -5q6 4 0 13zM450 417q2 4 -5 8q-7 2 -8 -2q-3 -5 4 -8q8 -2 9 2zM471 394q2 1 1.5 4.5t-3.5 5.5q-6 7 -10 3t1 -11q6 -6 11 -2zM557 319q2 7 -9 11q-9 3 -13 -4 q-2 -7 9 -11q9 -3 13 4zM599 316q0 8 -12 8q-10 0 -10 -8t11 -8t11 8zM638 323q-2 7 -13 5t-9 -9q2 -8 12 -6t10 10zM1280 640q0 212 -150 362t-362 150t-362 -150t-150 -362q0 -167 98 -300.5t252 -185.5q18 -3 26.5 5t8.5 20q0 52 -1 95q-6 -1 -15.5 -2.5t-35.5 -2t-48 4 t-43.5 20t-29.5 41.5q-23 59 -57 74q-2 1 -4.5 3.5l-8 8t-7 9.5t4 7.5t19.5 3.5q6 0 15 -2t30 -15.5t33 -35.5q16 -28 37.5 -42t43.5 -14t38 3.5t30 9.5q7 47 33 69q-49 6 -86 18.5t-73 39t-55.5 76t-19.5 119.5q0 79 53 137q-24 62 5 136q19 6 54.5 -7.5t60.5 -29.5l26 -16 q58 17 128 17t128 -17q11 7 28.5 18t55.5 26t57 9q29 -74 5 -136q53 -58 53 -137q0 -57 -14 -100.5t-35.5 -70t-53.5 -44.5t-62.5 -26t-68.5 -12q35 -31 35 -95q0 -40 -0.5 -89t-0.5 -51q0 -12 8.5 -20t26.5 -5q154 52 252 185.5t98 300.5zM1536 1120v-960 q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
-<glyph unicode="&#xf093;" horiz-adv-x="1664" d="M1280 64q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1536 64q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1664 288v-320q0 -40 -28 -68t-68 -28h-1472q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h427q21 -56 70.5 -92 t110.5 -36h256q61 0 110.5 36t70.5 92h427q40 0 68 -28t28 -68zM1339 936q-17 -40 -59 -40h-256v-448q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v448h-256q-42 0 -59 40q-17 39 14 69l448 448q18 19 45 19t45 -19l448 -448q31 -30 14 -69z" />
-<glyph unicode="&#xf094;" d="M1407 710q0 44 -7 113.5t-18 96.5q-12 30 -17 44t-9 36.5t-4 48.5q0 23 5 68.5t5 67.5q0 37 -10 55q-4 1 -13 1q-19 0 -58 -4.5t-59 -4.5q-60 0 -176 24t-175 24q-43 0 -94.5 -11.5t-85 -23.5t-89.5 -34q-137 -54 -202 -103q-96 -73 -159.5 -189.5t-88 -236t-24.5 -248.5 q0 -40 12.5 -120t12.5 -121q0 -23 -11 -66.5t-11 -65.5t12 -36.5t34 -14.5q24 0 72.5 11t73.5 11q57 0 169.5 -15.5t169.5 -15.5q181 0 284 36q129 45 235.5 152.5t166 245.5t59.5 275zM1535 712q0 -165 -70 -327.5t-196 -288t-281 -180.5q-124 -44 -326 -44 q-57 0 -170 14.5t-169 14.5q-24 0 -72.5 -14.5t-73.5 -14.5q-73 0 -123.5 55.5t-50.5 128.5q0 24 11 68t11 67q0 40 -12.5 120.5t-12.5 121.5q0 111 18 217.5t54.5 209.5t100.5 194t150 156q78 59 232 120q194 78 316 78q60 0 175.5 -24t173.5 -24q19 0 57 5t58 5 q81 0 118 -50.5t37 -134.5q0 -23 -5 -68t-5 -68q0 -10 1 -18.5t3 -17t4 -13.5t6.5 -16t6.5 -17q16 -40 25 -118.5t9 -136.5z" />
-<glyph unicode="&#xf095;" horiz-adv-x="1408" d="M1408 296q0 -27 -10 -70.5t-21 -68.5q-21 -50 -122 -106q-94 -51 -186 -51q-27 0 -52.5 3.5t-57.5 12.5t-47.5 14.5t-55.5 20.5t-49 18q-98 35 -175 83q-128 79 -264.5 215.5t-215.5 264.5q-48 77 -83 175q-3 9 -18 49t-20.5 55.5t-14.5 47.5t-12.5 57.5t-3.5 52.5 q0 92 51 186q56 101 106 122q25 11 68.5 21t70.5 10q14 0 21 -3q18 -6 53 -76q11 -19 30 -54t35 -63.5t31 -53.5q3 -4 17.5 -25t21.5 -35.5t7 -28.5q0 -20 -28.5 -50t-62 -55t-62 -53t-28.5 -46q0 -9 5 -22.5t8.5 -20.5t14 -24t11.5 -19q76 -137 174 -235t235 -174 q2 -1 19 -11.5t24 -14t20.5 -8.5t22.5 -5q18 0 46 28.5t53 62t55 62t50 28.5q14 0 28.5 -7t35.5 -21.5t25 -17.5q25 -15 53.5 -31t63.5 -35t54 -30q70 -35 76 -53q3 -7 3 -21z" />
-<glyph unicode="&#xf096;" horiz-adv-x="1408" d="M1120 1280h-832q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v832q0 66 -47 113t-113 47zM1408 1120v-832q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832 q119 0 203.5 -84.5t84.5 -203.5z" />
-<glyph unicode="&#xf097;" horiz-adv-x="1280" d="M1152 1280h-1024v-1242l423 406l89 85l89 -85l423 -406v1242zM1164 1408q23 0 44 -9q33 -13 52.5 -41t19.5 -62v-1289q0 -34 -19.5 -62t-52.5 -41q-19 -8 -44 -8q-48 0 -83 32l-441 424l-441 -424q-36 -33 -83 -33q-23 0 -44 9q-33 13 -52.5 41t-19.5 62v1289 q0 34 19.5 62t52.5 41q21 9 44 9h1048z" />
-<glyph unicode="&#xf098;" d="M1280 343q0 11 -2 16q-3 8 -38.5 29.5t-88.5 49.5l-53 29q-5 3 -19 13t-25 15t-21 5q-18 0 -47 -32.5t-57 -65.5t-44 -33q-7 0 -16.5 3.5t-15.5 6.5t-17 9.5t-14 8.5q-99 55 -170.5 126.5t-126.5 170.5q-2 3 -8.5 14t-9.5 17t-6.5 15.5t-3.5 16.5q0 13 20.5 33.5t45 38.5 t45 39.5t20.5 36.5q0 10 -5 21t-15 25t-13 19q-3 6 -15 28.5t-25 45.5t-26.5 47.5t-25 40.5t-16.5 18t-16 2q-48 0 -101 -22q-46 -21 -80 -94.5t-34 -130.5q0 -16 2.5 -34t5 -30.5t9 -33t10 -29.5t12.5 -33t11 -30q60 -164 216.5 -320.5t320.5 -216.5q6 -2 30 -11t33 -12.5 t29.5 -10t33 -9t30.5 -5t34 -2.5q57 0 130.5 34t94.5 80q22 53 22 101zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
-<glyph unicode="&#xf099;" horiz-adv-x="1664" d="M1620 1128q-67 -98 -162 -167q1 -14 1 -42q0 -130 -38 -259.5t-115.5 -248.5t-184.5 -210.5t-258 -146t-323 -54.5q-271 0 -496 145q35 -4 78 -4q225 0 401 138q-105 2 -188 64.5t-114 159.5q33 -5 61 -5q43 0 85 11q-112 23 -185.5 111.5t-73.5 205.5v4q68 -38 146 -41 q-66 44 -105 115t-39 154q0 88 44 163q121 -149 294.5 -238.5t371.5 -99.5q-8 38 -8 74q0 134 94.5 228.5t228.5 94.5q140 0 236 -102q109 21 205 78q-37 -115 -142 -178q93 10 186 50z" />
-<glyph unicode="&#xf09a;" horiz-adv-x="1024" d="M959 1524v-264h-157q-86 0 -116 -36t-30 -108v-189h293l-39 -296h-254v-759h-306v759h-255v296h255v218q0 186 104 288.5t277 102.5q147 0 228 -12z" />
-<glyph unicode="&#xf09b;" d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5q0 -251 -146.5 -451.5t-378.5 -277.5q-27 -5 -40 7t-13 30q0 3 0.5 76.5t0.5 134.5q0 97 -52 142q57 6 102.5 18t94 39t81 66.5t53 105t20.5 150.5q0 119 -79 206q37 91 -8 204q-28 9 -81 -11t-92 -44l-38 -24 q-93 26 -192 26t-192 -26q-16 11 -42.5 27t-83.5 38.5t-85 13.5q-45 -113 -8 -204q-79 -87 -79 -206q0 -85 20.5 -150t52.5 -105t80.5 -67t94 -39t102.5 -18q-39 -36 -49 -103q-21 -10 -45 -15t-57 -5t-65.5 21.5t-55.5 62.5q-19 32 -48.5 52t-49.5 24l-20 3q-21 0 -29 -4.5 t-5 -11.5t9 -14t13 -12l7 -5q22 -10 43.5 -38t31.5 -51l10 -23q13 -38 44 -61.5t67 -30t69.5 -7t55.5 3.5l23 4q0 -38 0.5 -88.5t0.5 -54.5q0 -18 -13 -30t-40 -7q-232 77 -378.5 277.5t-146.5 451.5q0 209 103 385.5t279.5 279.5t385.5 103zM291 305q3 7 -7 12 q-10 3 -13 -2q-3 -7 7 -12q9 -6 13 2zM322 271q7 5 -2 16q-10 9 -16 3q-7 -5 2 -16q10 -10 16 -3zM352 226q9 7 0 19q-8 13 -17 6q-9 -5 0 -18t17 -7zM394 184q8 8 -4 19q-12 12 -20 3q-9 -8 4 -19q12 -12 20 -3zM451 159q3 11 -13 16q-15 4 -19 -7t13 -15q15 -6 19 6z M514 154q0 13 -17 11q-16 0 -16 -11q0 -13 17 -11q16 0 16 11zM572 164q-2 11 -18 9q-16 -3 -14 -15t18 -8t14 14z" />
-<glyph unicode="&#xf09c;" horiz-adv-x="1664" d="M1664 960v-256q0 -26 -19 -45t-45 -19h-64q-26 0 -45 19t-19 45v256q0 106 -75 181t-181 75t-181 -75t-75 -181v-192h96q40 0 68 -28t28 -68v-576q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v576q0 40 28 68t68 28h672v192q0 185 131.5 316.5t316.5 131.5 t316.5 -131.5t131.5 -316.5z" />
-<glyph unicode="&#xf09d;" horiz-adv-x="1920" d="M1760 1408q66 0 113 -47t47 -113v-1216q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1600zM160 1280q-13 0 -22.5 -9.5t-9.5 -22.5v-224h1664v224q0 13 -9.5 22.5t-22.5 9.5h-1600zM1760 0q13 0 22.5 9.5t9.5 22.5v608h-1664v-608 q0 -13 9.5 -22.5t22.5 -9.5h1600zM256 128v128h256v-128h-256zM640 128v128h384v-128h-384z" />
-<glyph unicode="&#xf09e;" horiz-adv-x="1408" d="M384 192q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM896 69q2 -28 -17 -48q-18 -21 -47 -21h-135q-25 0 -43 16.5t-20 41.5q-22 229 -184.5 391.5t-391.5 184.5q-25 2 -41.5 20t-16.5 43v135q0 29 21 47q17 17 43 17h5q160 -13 306 -80.5 t259 -181.5q114 -113 181.5 -259t80.5 -306zM1408 67q2 -27 -18 -47q-18 -20 -46 -20h-143q-26 0 -44.5 17.5t-19.5 42.5q-12 215 -101 408.5t-231.5 336t-336 231.5t-408.5 102q-25 1 -42.5 19.5t-17.5 43.5v143q0 28 20 46q18 18 44 18h3q262 -13 501.5 -120t425.5 -294 q187 -186 294 -425.5t120 -501.5z" />
-<glyph unicode="&#xf0a0;" d="M1040 320q0 -33 -23.5 -56.5t-56.5 -23.5t-56.5 23.5t-23.5 56.5t23.5 56.5t56.5 23.5t56.5 -23.5t23.5 -56.5zM1296 320q0 -33 -23.5 -56.5t-56.5 -23.5t-56.5 23.5t-23.5 56.5t23.5 56.5t56.5 23.5t56.5 -23.5t23.5 -56.5zM1408 160v320q0 13 -9.5 22.5t-22.5 9.5 h-1216q-13 0 -22.5 -9.5t-9.5 -22.5v-320q0 -13 9.5 -22.5t22.5 -9.5h1216q13 0 22.5 9.5t9.5 22.5zM178 640h1180l-157 482q-4 13 -16 21.5t-26 8.5h-782q-14 0 -26 -8.5t-16 -21.5zM1536 480v-320q0 -66 -47 -113t-113 -47h-1216q-66 0 -113 47t-47 113v320q0 25 16 75 l197 606q17 53 63 86t101 33h782q55 0 101 -33t63 -86l197 -606q16 -50 16 -75z" />
-<glyph unicode="&#xf0a1;" horiz-adv-x="1792" d="M1664 896q53 0 90.5 -37.5t37.5 -90.5t-37.5 -90.5t-90.5 -37.5v-384q0 -52 -38 -90t-90 -38q-417 347 -812 380q-58 -19 -91 -66t-31 -100.5t40 -92.5q-20 -33 -23 -65.5t6 -58t33.5 -55t48 -50t61.5 -50.5q-29 -58 -111.5 -83t-168.5 -11.5t-132 55.5q-7 23 -29.5 87.5 t-32 94.5t-23 89t-15 101t3.5 98.5t22 110.5h-122q-66 0 -113 47t-47 113v192q0 66 47 113t113 47h480q435 0 896 384q52 0 90 -38t38 -90v-384zM1536 292v954q-394 -302 -768 -343v-270q377 -42 768 -341z" />
-<glyph unicode="&#xf0a2;" horiz-adv-x="1792" d="M912 -160q0 16 -16 16q-59 0 -101.5 42.5t-42.5 101.5q0 16 -16 16t-16 -16q0 -73 51.5 -124.5t124.5 -51.5q16 0 16 16zM246 128h1300q-266 300 -266 832q0 51 -24 105t-69 103t-121.5 80.5t-169.5 31.5t-169.5 -31.5t-121.5 -80.5t-69 -103t-24 -105q0 -532 -266 -832z M1728 128q0 -52 -38 -90t-90 -38h-448q0 -106 -75 -181t-181 -75t-181 75t-75 181h-448q-52 0 -90 38t-38 90q50 42 91 88t85 119.5t74.5 158.5t50 206t19.5 260q0 152 117 282.5t307 158.5q-8 19 -8 39q0 40 28 68t68 28t68 -28t28 -68q0 -20 -8 -39q190 -28 307 -158.5 t117 -282.5q0 -139 19.5 -260t50 -206t74.5 -158.5t85 -119.5t91 -88z" />
-<glyph unicode="&#xf0a3;" d="M1376 640l138 -135q30 -28 20 -70q-12 -41 -52 -51l-188 -48l53 -186q12 -41 -19 -70q-29 -31 -70 -19l-186 53l-48 -188q-10 -40 -51 -52q-12 -2 -19 -2q-31 0 -51 22l-135 138l-135 -138q-28 -30 -70 -20q-41 11 -51 52l-48 188l-186 -53q-41 -12 -70 19q-31 29 -19 70 l53 186l-188 48q-40 10 -52 51q-10 42 20 70l138 135l-138 135q-30 28 -20 70q12 41 52 51l188 48l-53 186q-12 41 19 70q29 31 70 19l186 -53l48 188q10 41 51 51q41 12 70 -19l135 -139l135 139q29 30 70 19q41 -10 51 -51l48 -188l186 53q41 12 70 -19q31 -29 19 -70 l-53 -186l188 -48q40 -10 52 -51q10 -42 -20 -70z" />
-<glyph unicode="&#xf0a4;" horiz-adv-x="1792" d="M256 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1664 768q0 51 -39 89.5t-89 38.5h-576q0 20 15 48.5t33 55t33 68t15 84.5q0 67 -44.5 97.5t-115.5 30.5q-24 0 -90 -139q-24 -44 -37 -65q-40 -64 -112 -145q-71 -81 -101 -106 q-69 -57 -140 -57h-32v-640h32q72 0 167 -32t193.5 -64t179.5 -32q189 0 189 167q0 26 -5 56q30 16 47.5 52.5t17.5 73.5t-18 69q53 50 53 119q0 25 -10 55.5t-25 47.5h331q52 0 90 38t38 90zM1792 769q0 -105 -75.5 -181t-180.5 -76h-169q-4 -62 -37 -119q3 -21 3 -43 q0 -101 -60 -178q1 -139 -85 -219.5t-227 -80.5q-133 0 -322 69q-164 59 -223 59h-288q-53 0 -90.5 37.5t-37.5 90.5v640q0 53 37.5 90.5t90.5 37.5h288q10 0 21.5 4.5t23.5 14t22.5 18t24 22.5t20.5 21.5t19 21.5t14 17q65 74 100 129q13 21 33 62t37 72t40.5 63t55 49.5 t69.5 17.5q125 0 206.5 -67t81.5 -189q0 -68 -22 -128h374q104 0 180 -76t76 -179z" />
-<glyph unicode="&#xf0a5;" horiz-adv-x="1792" d="M1376 128h32v640h-32q-35 0 -67.5 12t-62.5 37t-50 46t-49 54q-2 3 -3.5 4.5t-4 4.5t-4.5 5q-72 81 -112 145q-14 22 -38 68q-1 3 -10.5 22.5t-18.5 36t-20 35.5t-21.5 30.5t-18.5 11.5q-71 0 -115.5 -30.5t-44.5 -97.5q0 -43 15 -84.5t33 -68t33 -55t15 -48.5h-576 q-50 0 -89 -38.5t-39 -89.5q0 -52 38 -90t90 -38h331q-15 -17 -25 -47.5t-10 -55.5q0 -69 53 -119q-18 -32 -18 -69t17.5 -73.5t47.5 -52.5q-4 -24 -4 -56q0 -85 48.5 -126t135.5 -41q84 0 183 32t194 64t167 32zM1664 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45 t45 -19t45 19t19 45zM1792 768v-640q0 -53 -37.5 -90.5t-90.5 -37.5h-288q-59 0 -223 -59q-190 -69 -317 -69q-142 0 -230 77.5t-87 217.5l1 5q-61 76 -61 178q0 22 3 43q-33 57 -37 119h-169q-105 0 -180.5 76t-75.5 181q0 103 76 179t180 76h374q-22 60 -22 128 q0 122 81.5 189t206.5 67q38 0 69.5 -17.5t55 -49.5t40.5 -63t37 -72t33 -62q35 -55 100 -129q2 -3 14 -17t19 -21.5t20.5 -21.5t24 -22.5t22.5 -18t23.5 -14t21.5 -4.5h288q53 0 90.5 -37.5t37.5 -90.5z" />
-<glyph unicode="&#xf0a6;" d="M1280 -64q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 700q0 189 -167 189q-26 0 -56 -5q-16 30 -52.5 47.5t-73.5 17.5t-69 -18q-50 53 -119 53q-25 0 -55.5 -10t-47.5 -25v331q0 52 -38 90t-90 38q-51 0 -89.5 -39t-38.5 -89v-576 q-20 0 -48.5 15t-55 33t-68 33t-84.5 15q-67 0 -97.5 -44.5t-30.5 -115.5q0 -24 139 -90q44 -24 65 -37q64 -40 145 -112q81 -71 106 -101q57 -69 57 -140v-32h640v32q0 72 32 167t64 193.5t32 179.5zM1536 705q0 -133 -69 -322q-59 -164 -59 -223v-288q0 -53 -37.5 -90.5 t-90.5 -37.5h-640q-53 0 -90.5 37.5t-37.5 90.5v288q0 10 -4.5 21.5t-14 23.5t-18 22.5t-22.5 24t-21.5 20.5t-21.5 19t-17 14q-74 65 -129 100q-21 13 -62 33t-72 37t-63 40.5t-49.5 55t-17.5 69.5q0 125 67 206.5t189 81.5q68 0 128 -22v374q0 104 76 180t179 76 q105 0 181 -75.5t76 -180.5v-169q62 -4 119 -37q21 3 43 3q101 0 178 -60q139 1 219.5 -85t80.5 -227z" />
-<glyph unicode="&#xf0a7;" d="M1408 576q0 84 -32 183t-64 194t-32 167v32h-640v-32q0 -35 -12 -67.5t-37 -62.5t-46 -50t-54 -49q-9 -8 -14 -12q-81 -72 -145 -112q-22 -14 -68 -38q-3 -1 -22.5 -10.5t-36 -18.5t-35.5 -20t-30.5 -21.5t-11.5 -18.5q0 -71 30.5 -115.5t97.5 -44.5q43 0 84.5 15t68 33 t55 33t48.5 15v-576q0 -50 38.5 -89t89.5 -39q52 0 90 38t38 90v331q46 -35 103 -35q69 0 119 53q32 -18 69 -18t73.5 17.5t52.5 47.5q24 -4 56 -4q85 0 126 48.5t41 135.5zM1280 1344q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1536 580 q0 -142 -77.5 -230t-217.5 -87l-5 1q-76 -61 -178 -61q-22 0 -43 3q-54 -30 -119 -37v-169q0 -105 -76 -180.5t-181 -75.5q-103 0 -179 76t-76 180v374q-54 -22 -128 -22q-121 0 -188.5 81.5t-67.5 206.5q0 38 17.5 69.5t49.5 55t63 40.5t72 37t62 33q55 35 129 100 q3 2 17 14t21.5 19t21.5 20.5t22.5 24t18 22.5t14 23.5t4.5 21.5v288q0 53 37.5 90.5t90.5 37.5h640q53 0 90.5 -37.5t37.5 -90.5v-288q0 -59 59 -223q69 -190 69 -317z" />
-<glyph unicode="&#xf0a8;" d="M1280 576v128q0 26 -19 45t-45 19h-502l189 189q19 19 19 45t-19 45l-91 91q-18 18 -45 18t-45 -18l-362 -362l-91 -91q-18 -18 -18 -45t18 -45l91 -91l362 -362q18 -18 45 -18t45 18l91 91q18 18 18 45t-18 45l-189 189h502q26 0 45 19t19 45zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
-<glyph unicode="&#xf0a9;" d="M1285 640q0 27 -18 45l-91 91l-362 362q-18 18 -45 18t-45 -18l-91 -91q-18 -18 -18 -45t18 -45l189 -189h-502q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h502l-189 -189q-19 -19 -19 -45t19 -45l91 -91q18 -18 45 -18t45 18l362 362l91 91q18 18 18 45zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
-<glyph unicode="&#xf0aa;" d="M1284 641q0 27 -18 45l-362 362l-91 91q-18 18 -45 18t-45 -18l-91 -91l-362 -362q-18 -18 -18 -45t18 -45l91 -91q18 -18 45 -18t45 18l189 189v-502q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v502l189 -189q19 -19 45 -19t45 19l91 91q18 18 18 45zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
-<glyph unicode="&#xf0ab;" d="M1284 639q0 27 -18 45l-91 91q-18 18 -45 18t-45 -18l-189 -189v502q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-502l-189 189q-19 19 -45 19t-45 -19l-91 -91q-18 -18 -18 -45t18 -45l362 -362l91 -91q18 -18 45 -18t45 18l91 91l362 362q18 18 18 45zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
-<glyph unicode="&#xf0ac;" d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM1042 887q-2 -1 -9.5 -9.5t-13.5 -9.5q2 0 4.5 5t5 11t3.5 7q6 7 22 15q14 6 52 12q34 8 51 -11 q-2 2 9.5 13t14.5 12q3 2 15 4.5t15 7.5l2 22q-12 -1 -17.5 7t-6.5 21q0 -2 -6 -8q0 7 -4.5 8t-11.5 -1t-9 -1q-10 3 -15 7.5t-8 16.5t-4 15q-2 5 -9.5 10.5t-9.5 10.5q-1 2 -2.5 5.5t-3 6.5t-4 5.5t-5.5 2.5t-7 -5t-7.5 -10t-4.5 -5q-3 2 -6 1.5t-4.5 -1t-4.5 -3t-5 -3.5 q-3 -2 -8.5 -3t-8.5 -2q15 5 -1 11q-10 4 -16 3q9 4 7.5 12t-8.5 14h5q-1 4 -8.5 8.5t-17.5 8.5t-13 6q-8 5 -34 9.5t-33 0.5q-5 -6 -4.5 -10.5t4 -14t3.5 -12.5q1 -6 -5.5 -13t-6.5 -12q0 -7 14 -15.5t10 -21.5q-3 -8 -16 -16t-16 -12q-5 -8 -1.5 -18.5t10.5 -16.5 q2 -2 1.5 -4t-3.5 -4.5t-5.5 -4t-6.5 -3.5l-3 -2q-11 -5 -20.5 6t-13.5 26q-7 25 -16 30q-23 8 -29 -1q-5 13 -41 26q-25 9 -58 4q6 1 0 15q-7 15 -19 12q3 6 4 17.5t1 13.5q3 13 12 23q1 1 7 8.5t9.5 13.5t0.5 6q35 -4 50 11q5 5 11.5 17t10.5 17q9 6 14 5.5t14.5 -5.5 t14.5 -5q14 -1 15.5 11t-7.5 20q12 -1 3 17q-5 7 -8 9q-12 4 -27 -5q-8 -4 2 -8q-1 1 -9.5 -10.5t-16.5 -17.5t-16 5q-1 1 -5.5 13.5t-9.5 13.5q-8 0 -16 -15q3 8 -11 15t-24 8q19 12 -8 27q-7 4 -20.5 5t-19.5 -4q-5 -7 -5.5 -11.5t5 -8t10.5 -5.5t11.5 -4t8.5 -3 q14 -10 8 -14q-2 -1 -8.5 -3.5t-11.5 -4.5t-6 -4q-3 -4 0 -14t-2 -14q-5 5 -9 17.5t-7 16.5q7 -9 -25 -6l-10 1q-4 0 -16 -2t-20.5 -1t-13.5 8q-4 8 0 20q1 4 4 2q-4 3 -11 9.5t-10 8.5q-46 -15 -94 -41q6 -1 12 1q5 2 13 6.5t10 5.5q34 14 42 7l5 5q14 -16 20 -25 q-7 4 -30 1q-20 -6 -22 -12q7 -12 5 -18q-4 3 -11.5 10t-14.5 11t-15 5q-16 0 -22 -1q-146 -80 -235 -222q7 -7 12 -8q4 -1 5 -9t2.5 -11t11.5 3q9 -8 3 -19q1 1 44 -27q19 -17 21 -21q3 -11 -10 -18q-1 2 -9 9t-9 4q-3 -5 0.5 -18.5t10.5 -12.5q-7 0 -9.5 -16t-2.5 -35.5 t-1 -23.5l2 -1q-3 -12 5.5 -34.5t21.5 -19.5q-13 -3 20 -43q6 -8 8 -9q3 -2 12 -7.5t15 -10t10 -10.5q4 -5 10 -22.5t14 -23.5q-2 -6 9.5 -20t10.5 -23q-1 0 -2.5 -1t-2.5 -1q3 -7 15.5 -14t15.5 -13q1 -3 2 -10t3 -11t8 -2q2 20 -24 62q-15 25 -17 29q-3 5 -5.5 15.5 t-4.5 14.5q2 0 6 -1.5t8.5 -3.5t7.5 -4t2 -3q-3 -7 2 -17.5t12 -18.5t17 -19t12 -13q6 -6 14 -19.5t0 -13.5q9 0 20 -10t17 -20q5 -8 8 -26t5 -24q2 -7 8.5 -13.5t12.5 -9.5l16 -8t13 -7q5 -2 18.5 -10.5t21.5 -11.5q10 -4 16 -4t14.5 2.5t13.5 3.5q15 2 29 -15t21 -21 q36 -19 55 -11q-2 -1 0.5 -7.5t8 -15.5t9 -14.5t5.5 -8.5q5 -6 18 -15t18 -15q6 4 7 9q-3 -8 7 -20t18 -10q14 3 14 32q-31 -15 -49 18q0 1 -2.5 5.5t-4 8.5t-2.5 8.5t0 7.5t5 3q9 0 10 3.5t-2 12.5t-4 13q-1 8 -11 20t-12 15q-5 -9 -16 -8t-16 9q0 -1 -1.5 -5.5t-1.5 -6.5 q-13 0 -15 1q1 3 2.5 17.5t3.5 22.5q1 4 5.5 12t7.5 14.5t4 12.5t-4.5 9.5t-17.5 2.5q-19 -1 -26 -20q-1 -3 -3 -10.5t-5 -11.5t-9 -7q-7 -3 -24 -2t-24 5q-13 8 -22.5 29t-9.5 37q0 10 2.5 26.5t3 25t-5.5 24.5q3 2 9 9.5t10 10.5q2 1 4.5 1.5t4.5 0t4 1.5t3 6q-1 1 -4 3 q-3 3 -4 3q7 -3 28.5 1.5t27.5 -1.5q15 -11 22 2q0 1 -2.5 9.5t-0.5 13.5q5 -27 29 -9q3 -3 15.5 -5t17.5 -5q3 -2 7 -5.5t5.5 -4.5t5 0.5t8.5 6.5q10 -14 12 -24q11 -40 19 -44q7 -3 11 -2t4.5 9.5t0 14t-1.5 12.5l-1 8v18l-1 8q-15 3 -18.5 12t1.5 18.5t15 18.5q1 1 8 3.5 t15.5 6.5t12.5 8q21 19 15 35q7 0 11 9q-1 0 -5 3t-7.5 5t-4.5 2q9 5 2 16q5 3 7.5 11t7.5 10q9 -12 21 -2q7 8 1 16q5 7 20.5 10.5t18.5 9.5q7 -2 8 2t1 12t3 12q4 5 15 9t13 5l17 11q3 4 0 4q18 -2 31 11q10 11 -6 20q3 6 -3 9.5t-15 5.5q3 1 11.5 0.5t10.5 1.5 q15 10 -7 16q-17 5 -43 -12zM879 10q206 36 351 189q-3 3 -12.5 4.5t-12.5 3.5q-18 7 -24 8q1 7 -2.5 13t-8 9t-12.5 8t-11 7q-2 2 -7 6t-7 5.5t-7.5 4.5t-8.5 2t-10 -1l-3 -1q-3 -1 -5.5 -2.5t-5.5 -3t-4 -3t0 -2.5q-21 17 -36 22q-5 1 -11 5.5t-10.5 7t-10 1.5t-11.5 -7 q-5 -5 -6 -15t-2 -13q-7 5 0 17.5t2 18.5q-3 6 -10.5 4.5t-12 -4.5t-11.5 -8.5t-9 -6.5t-8.5 -5.5t-8.5 -7.5q-3 -4 -6 -12t-5 -11q-2 4 -11.5 6.5t-9.5 5.5q2 -10 4 -35t5 -38q7 -31 -12 -48q-27 -25 -29 -40q-4 -22 12 -26q0 -7 -8 -20.5t-7 -21.5q0 -6 2 -16z" />
-<glyph unicode="&#xf0ad;" horiz-adv-x="1664" d="M384 64q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1028 484l-682 -682q-37 -37 -90 -37q-52 0 -91 37l-106 108q-38 36 -38 90q0 53 38 91l681 681q39 -98 114.5 -173.5t173.5 -114.5zM1662 919q0 -39 -23 -106q-47 -134 -164.5 -217.5 t-258.5 -83.5q-185 0 -316.5 131.5t-131.5 316.5t131.5 316.5t316.5 131.5q58 0 121.5 -16.5t107.5 -46.5q16 -11 16 -28t-16 -28l-293 -169v-224l193 -107q5 3 79 48.5t135.5 81t70.5 35.5q15 0 23.5 -10t8.5 -25z" />
-<glyph unicode="&#xf0ae;" horiz-adv-x="1792" d="M1024 128h640v128h-640v-128zM640 640h1024v128h-1024v-128zM1280 1152h384v128h-384v-128zM1792 320v-256q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 832v-256q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19 t-19 45v256q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 1344v-256q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1664q26 0 45 -19t19 -45z" />
-<glyph unicode="&#xf0b0;" horiz-adv-x="1408" d="M1403 1241q17 -41 -14 -70l-493 -493v-742q0 -42 -39 -59q-13 -5 -25 -5q-27 0 -45 19l-256 256q-19 19 -19 45v486l-493 493q-31 29 -14 70q17 39 59 39h1280q42 0 59 -39z" />
-<glyph unicode="&#xf0b1;" horiz-adv-x="1792" d="M640 1280h512v128h-512v-128zM1792 640v-480q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v480h672v-160q0 -26 19 -45t45 -19h320q26 0 45 19t19 45v160h672zM1024 640v-128h-256v128h256zM1792 1120v-384h-1792v384q0 66 47 113t113 47h352v160q0 40 28 68 t68 28h576q40 0 68 -28t28 -68v-160h352q66 0 113 -47t47 -113z" />
-<glyph unicode="&#xf0b2;" d="M1283 995l-355 -355l355 -355l144 144q29 31 70 14q39 -17 39 -59v-448q0 -26 -19 -45t-45 -19h-448q-42 0 -59 40q-17 39 14 69l144 144l-355 355l-355 -355l144 -144q31 -30 14 -69q-17 -40 -59 -40h-448q-26 0 -45 19t-19 45v448q0 42 40 59q39 17 69 -14l144 -144 l355 355l-355 355l-144 -144q-19 -19 -45 -19q-12 0 -24 5q-40 17 -40 59v448q0 26 19 45t45 19h448q42 0 59 -40q17 -39 -14 -69l-144 -144l355 -355l355 355l-144 144q-31 30 -14 69q17 40 59 40h448q26 0 45 -19t19 -45v-448q0 -42 -39 -59q-13 -5 -25 -5q-26 0 -45 19z " />
-<glyph unicode="&#xf0c0;" horiz-adv-x="1920" d="M593 640q-162 -5 -265 -128h-134q-82 0 -138 40.5t-56 118.5q0 353 124 353q6 0 43.5 -21t97.5 -42.5t119 -21.5q67 0 133 23q-5 -37 -5 -66q0 -139 81 -256zM1664 3q0 -120 -73 -189.5t-194 -69.5h-874q-121 0 -194 69.5t-73 189.5q0 53 3.5 103.5t14 109t26.5 108.5 t43 97.5t62 81t85.5 53.5t111.5 20q10 0 43 -21.5t73 -48t107 -48t135 -21.5t135 21.5t107 48t73 48t43 21.5q61 0 111.5 -20t85.5 -53.5t62 -81t43 -97.5t26.5 -108.5t14 -109t3.5 -103.5zM640 1280q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75 t75 -181zM1344 896q0 -159 -112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5zM1920 671q0 -78 -56 -118.5t-138 -40.5h-134q-103 123 -265 128q81 117 81 256q0 29 -5 66q66 -23 133 -23q59 0 119 21.5t97.5 42.5 t43.5 21q124 0 124 -353zM1792 1280q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75t75 -181z" />
-<glyph unicode="&#xf0c1;" horiz-adv-x="1664" d="M1456 320q0 40 -28 68l-208 208q-28 28 -68 28q-42 0 -72 -32q3 -3 19 -18.5t21.5 -21.5t15 -19t13 -25.5t3.5 -27.5q0 -40 -28 -68t-68 -28q-15 0 -27.5 3.5t-25.5 13t-19 15t-21.5 21.5t-18.5 19q-33 -31 -33 -73q0 -40 28 -68l206 -207q27 -27 68 -27q40 0 68 26 l147 146q28 28 28 67zM753 1025q0 40 -28 68l-206 207q-28 28 -68 28q-39 0 -68 -27l-147 -146q-28 -28 -28 -67q0 -40 28 -68l208 -208q27 -27 68 -27q42 0 72 31q-3 3 -19 18.5t-21.5 21.5t-15 19t-13 25.5t-3.5 27.5q0 40 28 68t68 28q15 0 27.5 -3.5t25.5 -13t19 -15 t21.5 -21.5t18.5 -19q33 31 33 73zM1648 320q0 -120 -85 -203l-147 -146q-83 -83 -203 -83q-121 0 -204 85l-206 207q-83 83 -83 203q0 123 88 209l-88 88q-86 -88 -208 -88q-120 0 -204 84l-208 208q-84 84 -84 204t85 203l147 146q83 83 203 83q121 0 204 -85l206 -207 q83 -83 83 -203q0 -123 -88 -209l88 -88q86 88 208 88q120 0 204 -84l208 -208q84 -84 84 -204z" />
-<glyph unicode="&#xf0c2;" horiz-adv-x="1920" d="M1920 384q0 -159 -112.5 -271.5t-271.5 -112.5h-1088q-185 0 -316.5 131.5t-131.5 316.5q0 132 71 241.5t187 163.5q-2 28 -2 43q0 212 150 362t362 150q158 0 286.5 -88t187.5 -230q70 62 166 62q106 0 181 -75t75 -181q0 -75 -41 -138q129 -30 213 -134.5t84 -239.5z " />
-<glyph unicode="&#xf0c3;" horiz-adv-x="1664" d="M1527 88q56 -89 21.5 -152.5t-140.5 -63.5h-1152q-106 0 -140.5 63.5t21.5 152.5l503 793v399h-64q-26 0 -45 19t-19 45t19 45t45 19h512q26 0 45 -19t19 -45t-19 -45t-45 -19h-64v-399zM748 813l-272 -429h712l-272 429l-20 31v37v399h-128v-399v-37z" />
-<glyph unicode="&#xf0c4;" horiz-adv-x="1792" d="M960 640q26 0 45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45t19 45t45 19zM1260 576l507 -398q28 -20 25 -56q-5 -35 -35 -51l-128 -64q-13 -7 -29 -7q-17 0 -31 8l-690 387l-110 -66q-8 -4 -12 -5q14 -49 10 -97q-7 -77 -56 -147.5t-132 -123.5q-132 -84 -277 -84 q-136 0 -222 78q-90 84 -79 207q7 76 56 147t131 124q132 84 278 84q83 0 151 -31q9 13 22 22l122 73l-122 73q-13 9 -22 22q-68 -31 -151 -31q-146 0 -278 84q-82 53 -131 124t-56 147q-5 59 15.5 113t63.5 93q85 79 222 79q145 0 277 -84q83 -52 132 -123t56 -148 q4 -48 -10 -97q4 -1 12 -5l110 -66l690 387q14 8 31 8q16 0 29 -7l128 -64q30 -16 35 -51q3 -36 -25 -56zM579 836q46 42 21 108t-106 117q-92 59 -192 59q-74 0 -113 -36q-46 -42 -21 -108t106 -117q92 -59 192 -59q74 0 113 36zM494 91q81 51 106 117t-21 108 q-39 36 -113 36q-100 0 -192 -59q-81 -51 -106 -117t21 -108q39 -36 113 -36q100 0 192 59zM672 704l96 -58v11q0 36 33 56l14 8l-79 47l-26 -26q-3 -3 -10 -11t-12 -12q-2 -2 -4 -3.5t-3 -2.5zM896 480l96 -32l736 576l-128 64l-768 -431v-113l-160 -96l9 -8q2 -2 7 -6 q4 -4 11 -12t11 -12l26 -26zM1600 64l128 64l-520 408l-177 -138q-2 -3 -13 -7z" />
-<glyph unicode="&#xf0c5;" horiz-adv-x="1792" d="M1696 1152q40 0 68 -28t28 -68v-1216q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v288h-544q-40 0 -68 28t-28 68v672q0 40 20 88t48 76l408 408q28 28 76 48t88 20h416q40 0 68 -28t28 -68v-328q68 40 128 40h416zM1152 939l-299 -299h299v299zM512 1323l-299 -299 h299v299zM708 676l316 316v416h-384v-416q0 -40 -28 -68t-68 -28h-416v-640h512v256q0 40 20 88t48 76zM1664 -128v1152h-384v-416q0 -40 -28 -68t-68 -28h-416v-640h896z" />
-<glyph unicode="&#xf0c6;" horiz-adv-x="1408" d="M1404 151q0 -117 -79 -196t-196 -79q-135 0 -235 100l-777 776q-113 115 -113 271q0 159 110 270t269 111q158 0 273 -113l605 -606q10 -10 10 -22q0 -16 -30.5 -46.5t-46.5 -30.5q-13 0 -23 10l-606 607q-79 77 -181 77q-106 0 -179 -75t-73 -181q0 -105 76 -181 l776 -777q63 -63 145 -63q64 0 106 42t42 106q0 82 -63 145l-581 581q-26 24 -60 24q-29 0 -48 -19t-19 -48q0 -32 25 -59l410 -410q10 -10 10 -22q0 -16 -31 -47t-47 -31q-12 0 -22 10l-410 410q-63 61 -63 149q0 82 57 139t139 57q88 0 149 -63l581 -581q100 -98 100 -235 z" />
-<glyph unicode="&#xf0c7;" d="M384 0h768v384h-768v-384zM1280 0h128v896q0 14 -10 38.5t-20 34.5l-281 281q-10 10 -34 20t-39 10v-416q0 -40 -28 -68t-68 -28h-576q-40 0 -68 28t-28 68v416h-128v-1280h128v416q0 40 28 68t68 28h832q40 0 68 -28t28 -68v-416zM896 928v320q0 13 -9.5 22.5t-22.5 9.5 h-192q-13 0 -22.5 -9.5t-9.5 -22.5v-320q0 -13 9.5 -22.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 22.5zM1536 896v-928q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h928q40 0 88 -20t76 -48l280 -280q28 -28 48 -76t20 -88z" />
-<glyph unicode="&#xf0c8;" d="M1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
-<glyph unicode="&#xf0c9;" d="M1536 192v-128q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1536 704v-128q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1536 1216v-128q0 -26 -19 -45 t-45 -19h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45z" />
-<glyph unicode="&#xf0ca;" horiz-adv-x="1792" d="M384 128q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM384 640q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5 t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5zM384 1152q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1792 736v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5z M1792 1248v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5z" />
-<glyph unicode="&#xf0cb;" horiz-adv-x="1792" d="M381 -84q0 -80 -54.5 -126t-135.5 -46q-106 0 -172 66l57 88q49 -45 106 -45q29 0 50.5 14.5t21.5 42.5q0 64 -105 56l-26 56q8 10 32.5 43.5t42.5 54t37 38.5v1q-16 0 -48.5 -1t-48.5 -1v-53h-106v152h333v-88l-95 -115q51 -12 81 -49t30 -88zM383 543v-159h-362 q-6 36 -6 54q0 51 23.5 93t56.5 68t66 47.5t56.5 43.5t23.5 45q0 25 -14.5 38.5t-39.5 13.5q-46 0 -81 -58l-85 59q24 51 71.5 79.5t105.5 28.5q73 0 123 -41.5t50 -112.5q0 -50 -34 -91.5t-75 -64.5t-75.5 -50.5t-35.5 -52.5h127v60h105zM1792 224v-192q0 -13 -9.5 -22.5 t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 14 9 23t23 9h1216q13 0 22.5 -9.5t9.5 -22.5zM384 1123v-99h-335v99h107q0 41 0.5 122t0.5 121v12h-2q-8 -17 -50 -54l-71 76l136 127h106v-404h108zM1792 736v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5 t-9.5 22.5v192q0 14 9 23t23 9h1216q13 0 22.5 -9.5t9.5 -22.5zM1792 1248v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5z" />
-<glyph unicode="&#xf0cc;" horiz-adv-x="1792" d="M1760 640q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-1728q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h1728zM483 704q-28 35 -51 80q-48 97 -48 188q0 181 134 309q133 127 393 127q50 0 167 -19q66 -12 177 -48q10 -38 21 -118q14 -123 14 -183q0 -18 -5 -45l-12 -3l-84 6 l-14 2q-50 149 -103 205q-88 91 -210 91q-114 0 -182 -59q-67 -58 -67 -146q0 -73 66 -140t279 -129q69 -20 173 -66q58 -28 95 -52h-743zM990 448h411q7 -39 7 -92q0 -111 -41 -212q-23 -55 -71 -104q-37 -35 -109 -81q-80 -48 -153 -66q-80 -21 -203 -21q-114 0 -195 23 l-140 40q-57 16 -72 28q-8 8 -8 22v13q0 108 -2 156q-1 30 0 68l2 37v44l102 2q15 -34 30 -71t22.5 -56t12.5 -27q35 -57 80 -94q43 -36 105 -57q59 -22 132 -22q64 0 139 27q77 26 122 86q47 61 47 129q0 84 -81 157q-34 29 -137 71z" />
-<glyph unicode="&#xf0cd;" d="M48 1313q-37 2 -45 4l-3 88q13 1 40 1q60 0 112 -4q132 -7 166 -7q86 0 168 3q116 4 146 5q56 0 86 2l-1 -14l2 -64v-9q-60 -9 -124 -9q-60 0 -79 -25q-13 -14 -13 -132q0 -13 0.5 -32.5t0.5 -25.5l1 -229l14 -280q6 -124 51 -202q35 -59 96 -92q88 -47 177 -47 q104 0 191 28q56 18 99 51q48 36 65 64q36 56 53 114q21 73 21 229q0 79 -3.5 128t-11 122.5t-13.5 159.5l-4 59q-5 67 -24 88q-34 35 -77 34l-100 -2l-14 3l2 86h84l205 -10q76 -3 196 10l18 -2q6 -38 6 -51q0 -7 -4 -31q-45 -12 -84 -13q-73 -11 -79 -17q-15 -15 -15 -41 q0 -7 1.5 -27t1.5 -31q8 -19 22 -396q6 -195 -15 -304q-15 -76 -41 -122q-38 -65 -112 -123q-75 -57 -182 -89q-109 -33 -255 -33q-167 0 -284 46q-119 47 -179 122q-61 76 -83 195q-16 80 -16 237v333q0 188 -17 213q-25 36 -147 39zM1536 -96v64q0 14 -9 23t-23 9h-1472 q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h1472q14 0 23 9t9 23z" />
-<glyph unicode="&#xf0ce;" horiz-adv-x="1664" d="M512 160v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM512 544v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1024 160v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23 v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM512 928v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1024 544v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1536 160v192 q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1024 928v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1536 544v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192 q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1536 928v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1664 1248v-1088q0 -66 -47 -113t-113 -47h-1344q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1344q66 0 113 -47t47 -113 z" />
-<glyph unicode="&#xf0d0;" horiz-adv-x="1664" d="M1190 955l293 293l-107 107l-293 -293zM1637 1248q0 -27 -18 -45l-1286 -1286q-18 -18 -45 -18t-45 18l-198 198q-18 18 -18 45t18 45l1286 1286q18 18 45 18t45 -18l198 -198q18 -18 18 -45zM286 1438l98 -30l-98 -30l-30 -98l-30 98l-98 30l98 30l30 98zM636 1276 l196 -60l-196 -60l-60 -196l-60 196l-196 60l196 60l60 196zM1566 798l98 -30l-98 -30l-30 -98l-30 98l-98 30l98 30l30 98zM926 1438l98 -30l-98 -30l-30 -98l-30 98l-98 30l98 30l30 98z" />
-<glyph unicode="&#xf0d1;" horiz-adv-x="1792" d="M640 128q0 52 -38 90t-90 38t-90 -38t-38 -90t38 -90t90 -38t90 38t38 90zM256 640h384v256h-158q-13 0 -22 -9l-195 -195q-9 -9 -9 -22v-30zM1536 128q0 52 -38 90t-90 38t-90 -38t-38 -90t38 -90t90 -38t90 38t38 90zM1792 1216v-1024q0 -15 -4 -26.5t-13.5 -18.5 t-16.5 -11.5t-23.5 -6t-22.5 -2t-25.5 0t-22.5 0.5q0 -106 -75 -181t-181 -75t-181 75t-75 181h-384q0 -106 -75 -181t-181 -75t-181 75t-75 181h-64q-3 0 -22.5 -0.5t-25.5 0t-22.5 2t-23.5 6t-16.5 11.5t-13.5 18.5t-4 26.5q0 26 19 45t45 19v320q0 8 -0.5 35t0 38 t2.5 34.5t6.5 37t14 30.5t22.5 30l198 198q19 19 50.5 32t58.5 13h160v192q0 26 19 45t45 19h1024q26 0 45 -19t19 -45z" />
-<glyph unicode="&#xf0d2;" d="M1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103q-111 0 -218 32q59 93 78 164q9 34 54 211q20 -39 73 -67.5t114 -28.5q121 0 216 68.5t147 188.5t52 270q0 114 -59.5 214t-172.5 163t-255 63q-105 0 -196 -29t-154.5 -77t-109 -110.5t-67 -129.5t-21.5 -134 q0 -104 40 -183t117 -111q30 -12 38 20q2 7 8 31t8 30q6 23 -11 43q-51 61 -51 151q0 151 104.5 259.5t273.5 108.5q151 0 235.5 -82t84.5 -213q0 -170 -68.5 -289t-175.5 -119q-61 0 -98 43.5t-23 104.5q8 35 26.5 93.5t30 103t11.5 75.5q0 50 -27 83t-77 33 q-62 0 -105 -57t-43 -142q0 -73 25 -122l-99 -418q-17 -70 -13 -177q-206 91 -333 281t-127 423q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
-<glyph unicode="&#xf0d3;" d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-725q85 122 108 210q9 34 53 209q21 -39 73.5 -67t112.5 -28q181 0 295.5 147.5t114.5 373.5q0 84 -35 162.5t-96.5 139t-152.5 97t-197 36.5q-104 0 -194.5 -28.5t-153 -76.5 t-107.5 -109.5t-66.5 -128t-21.5 -132.5q0 -102 39.5 -180t116.5 -110q13 -5 23.5 0t14.5 19q10 44 15 61q6 23 -11 42q-50 62 -50 150q0 150 103.5 256.5t270.5 106.5q149 0 232.5 -81t83.5 -210q0 -168 -67.5 -286t-173.5 -118q-60 0 -97 43.5t-23 103.5q8 34 26.5 92.5 t29.5 102t11 74.5q0 49 -26.5 81.5t-75.5 32.5q-61 0 -103.5 -56.5t-42.5 -139.5q0 -72 24 -121l-98 -414q-24 -100 -7 -254h-183q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960z" />
-<glyph unicode="&#xf0d4;" d="M917 631q0 26 -6 64h-362v-132h217q-3 -24 -16.5 -50t-37.5 -53t-66.5 -44.5t-96.5 -17.5q-99 0 -169 71t-70 171t70 171t169 71q92 0 153 -59l104 101q-108 100 -257 100q-160 0 -272 -112.5t-112 -271.5t112 -271.5t272 -112.5q165 0 266.5 105t101.5 270zM1262 585 h109v110h-109v110h-110v-110h-110v-110h110v-110h110v110zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
-<glyph unicode="&#xf0d5;" horiz-adv-x="2304" d="M1437 623q0 -208 -87 -370.5t-248 -254t-369 -91.5q-149 0 -285 58t-234 156t-156 234t-58 285t58 285t156 234t234 156t285 58q286 0 491 -192l-199 -191q-117 113 -292 113q-123 0 -227.5 -62t-165.5 -168.5t-61 -232.5t61 -232.5t165.5 -168.5t227.5 -62 q83 0 152.5 23t114.5 57.5t78.5 78.5t49 83t21.5 74h-416v252h692q12 -63 12 -122zM2304 745v-210h-209v-209h-210v209h-209v210h209v209h210v-209h209z" />
-<glyph unicode="&#xf0d6;" horiz-adv-x="1920" d="M768 384h384v96h-128v448h-114l-148 -137l77 -80q42 37 55 57h2v-288h-128v-96zM1280 640q0 -70 -21 -142t-59.5 -134t-101.5 -101t-138 -39t-138 39t-101.5 101t-59.5 134t-21 142t21 142t59.5 134t101.5 101t138 39t138 -39t101.5 -101t59.5 -134t21 -142zM1792 384 v512q-106 0 -181 75t-75 181h-1152q0 -106 -75 -181t-181 -75v-512q106 0 181 -75t75 -181h1152q0 106 75 181t181 75zM1920 1216v-1152q0 -26 -19 -45t-45 -19h-1792q-26 0 -45 19t-19 45v1152q0 26 19 45t45 19h1792q26 0 45 -19t19 -45z" />
-<glyph unicode="&#xf0d7;" horiz-adv-x="1024" d="M1024 832q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19l-448 448q-19 19 -19 45t19 45t45 19h896q26 0 45 -19t19 -45z" />
-<glyph unicode="&#xf0d8;" horiz-adv-x="1024" d="M1024 320q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45l448 448q19 19 45 19t45 -19l448 -448q19 -19 19 -45z" />
-<glyph unicode="&#xf0d9;" horiz-adv-x="640" d="M640 1088v-896q0 -26 -19 -45t-45 -19t-45 19l-448 448q-19 19 -19 45t19 45l448 448q19 19 45 19t45 -19t19 -45z" />
-<glyph unicode="&#xf0da;" horiz-adv-x="640" d="M576 640q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19t-19 45v896q0 26 19 45t45 19t45 -19l448 -448q19 -19 19 -45z" />
-<glyph unicode="&#xf0db;" horiz-adv-x="1664" d="M160 0h608v1152h-640v-1120q0 -13 9.5 -22.5t22.5 -9.5zM1536 32v1120h-640v-1152h608q13 0 22.5 9.5t9.5 22.5zM1664 1248v-1216q0 -66 -47 -113t-113 -47h-1344q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1344q66 0 113 -47t47 -113z" />
-<glyph unicode="&#xf0dc;" horiz-adv-x="1024" d="M1024 448q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19l-448 448q-19 19 -19 45t19 45t45 19h896q26 0 45 -19t19 -45zM1024 832q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45l448 448q19 19 45 19t45 -19l448 -448q19 -19 19 -45z" />
-<glyph unicode="&#xf0dd;" horiz-adv-x="1024" d="M1024 448q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19l-448 448q-19 19 -19 45t19 45t45 19h896q26 0 45 -19t19 -45z" />
-<glyph unicode="&#xf0de;" horiz-adv-x="1024" d="M1024 832q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45l448 448q19 19 45 19t45 -19l448 -448q19 -19 19 -45z" />
-<glyph unicode="&#xf0e0;" horiz-adv-x="1792" d="M1792 826v-794q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v794q44 -49 101 -87q362 -246 497 -345q57 -42 92.5 -65.5t94.5 -48t110 -24.5h1h1q51 0 110 24.5t94.5 48t92.5 65.5q170 123 498 345q57 39 100 87zM1792 1120q0 -79 -49 -151t-122 -123 q-376 -261 -468 -325q-10 -7 -42.5 -30.5t-54 -38t-52 -32.5t-57.5 -27t-50 -9h-1h-1q-23 0 -50 9t-57.5 27t-52 32.5t-54 38t-42.5 30.5q-91 64 -262 182.5t-205 142.5q-62 42 -117 115.5t-55 136.5q0 78 41.5 130t118.5 52h1472q65 0 112.5 -47t47.5 -113z" />
-<glyph unicode="&#xf0e1;" d="M349 911v-991h-330v991h330zM370 1217q1 -73 -50.5 -122t-135.5 -49h-2q-82 0 -132 49t-50 122q0 74 51.5 122.5t134.5 48.5t133 -48.5t51 -122.5zM1536 488v-568h-329v530q0 105 -40.5 164.5t-126.5 59.5q-63 0 -105.5 -34.5t-63.5 -85.5q-11 -30 -11 -81v-553h-329 q2 399 2 647t-1 296l-1 48h329v-144h-2q20 32 41 56t56.5 52t87 43.5t114.5 15.5q171 0 275 -113.5t104 -332.5z" />
-<glyph unicode="&#xf0e2;" d="M1536 640q0 -156 -61 -298t-164 -245t-245 -164t-298 -61q-172 0 -327 72.5t-264 204.5q-7 10 -6.5 22.5t8.5 20.5l137 138q10 9 25 9q16 -2 23 -12q73 -95 179 -147t225 -52q104 0 198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5t-40.5 198.5t-109.5 163.5 t-163.5 109.5t-198.5 40.5q-98 0 -188 -35.5t-160 -101.5l137 -138q31 -30 14 -69q-17 -40 -59 -40h-448q-26 0 -45 19t-19 45v448q0 42 40 59q39 17 69 -14l130 -129q107 101 244.5 156.5t284.5 55.5q156 0 298 -61t245 -164t164 -245t61 -298z" />
-<glyph unicode="&#xf0e3;" horiz-adv-x="1792" d="M1771 0q0 -53 -37 -90l-107 -108q-39 -37 -91 -37q-53 0 -90 37l-363 364q-38 36 -38 90q0 53 43 96l-256 256l-126 -126q-14 -14 -34 -14t-34 14q2 -2 12.5 -12t12.5 -13t10 -11.5t10 -13.5t6 -13.5t5.5 -16.5t1.5 -18q0 -38 -28 -68q-3 -3 -16.5 -18t-19 -20.5 t-18.5 -16.5t-22 -15.5t-22 -9t-26 -4.5q-40 0 -68 28l-408 408q-28 28 -28 68q0 13 4.5 26t9 22t15.5 22t16.5 18.5t20.5 19t18 16.5q30 28 68 28q10 0 18 -1.5t16.5 -5.5t13.5 -6t13.5 -10t11.5 -10t13 -12.5t12 -12.5q-14 14 -14 34t14 34l348 348q14 14 34 14t34 -14 q-2 2 -12.5 12t-12.5 13t-10 11.5t-10 13.5t-6 13.5t-5.5 16.5t-1.5 18q0 38 28 68q3 3 16.5 18t19 20.5t18.5 16.5t22 15.5t22 9t26 4.5q40 0 68 -28l408 -408q28 -28 28 -68q0 -13 -4.5 -26t-9 -22t-15.5 -22t-16.5 -18.5t-20.5 -19t-18 -16.5q-30 -28 -68 -28 q-10 0 -18 1.5t-16.5 5.5t-13.5 6t-13.5 10t-11.5 10t-13 12.5t-12 12.5q14 -14 14 -34t-14 -34l-126 -126l256 -256q43 43 96 43q52 0 91 -37l363 -363q37 -39 37 -91z" />
-<glyph unicode="&#xf0e4;" horiz-adv-x="1792" d="M384 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM576 832q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1004 351l101 382q6 26 -7.5 48.5t-38.5 29.5 t-48 -6.5t-30 -39.5l-101 -382q-60 -5 -107 -43.5t-63 -98.5q-20 -77 20 -146t117 -89t146 20t89 117q16 60 -6 117t-72 91zM1664 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1024 1024q0 53 -37.5 90.5 t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1472 832q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1792 384q0 -261 -141 -483q-19 -29 -54 -29h-1402q-35 0 -54 29 q-141 221 -141 483q0 182 71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
-<glyph unicode="&#xf0e5;" horiz-adv-x="1792" d="M896 1152q-204 0 -381.5 -69.5t-282 -187.5t-104.5 -255q0 -112 71.5 -213.5t201.5 -175.5l87 -50l-27 -96q-24 -91 -70 -172q152 63 275 171l43 38l57 -6q69 -8 130 -8q204 0 381.5 69.5t282 187.5t104.5 255t-104.5 255t-282 187.5t-381.5 69.5zM1792 640 q0 -174 -120 -321.5t-326 -233t-450 -85.5q-70 0 -145 8q-198 -175 -460 -242q-49 -14 -114 -22h-5q-15 0 -27 10.5t-16 27.5v1q-3 4 -0.5 12t2 10t4.5 9.5l6 9t7 8.5t8 9q7 8 31 34.5t34.5 38t31 39.5t32.5 51t27 59t26 76q-157 89 -247.5 220t-90.5 281q0 174 120 321.5 t326 233t450 85.5t450 -85.5t326 -233t120 -321.5z" />
-<glyph unicode="&#xf0e6;" horiz-adv-x="1792" d="M704 1152q-153 0 -286 -52t-211.5 -141t-78.5 -191q0 -82 53 -158t149 -132l97 -56l-35 -84q34 20 62 39l44 31l53 -10q78 -14 153 -14q153 0 286 52t211.5 141t78.5 191t-78.5 191t-211.5 141t-286 52zM704 1280q191 0 353.5 -68.5t256.5 -186.5t94 -257t-94 -257 t-256.5 -186.5t-353.5 -68.5q-86 0 -176 16q-124 -88 -278 -128q-36 -9 -86 -16h-3q-11 0 -20.5 8t-11.5 21q-1 3 -1 6.5t0.5 6.5t2 6l2.5 5t3.5 5.5t4 5t4.5 5t4 4.5q5 6 23 25t26 29.5t22.5 29t25 38.5t20.5 44q-124 72 -195 177t-71 224q0 139 94 257t256.5 186.5 t353.5 68.5zM1526 111q10 -24 20.5 -44t25 -38.5t22.5 -29t26 -29.5t23 -25q1 -1 4 -4.5t4.5 -5t4 -5t3.5 -5.5l2.5 -5t2 -6t0.5 -6.5t-1 -6.5q-3 -14 -13 -22t-22 -7q-50 7 -86 16q-154 40 -278 128q-90 -16 -176 -16q-271 0 -472 132q58 -4 88 -4q161 0 309 45t264 129 q125 92 192 212t67 254q0 77 -23 152q129 -71 204 -178t75 -230q0 -120 -71 -224.5t-195 -176.5z" />
-<glyph unicode="&#xf0e7;" horiz-adv-x="896" d="M885 970q18 -20 7 -44l-540 -1157q-13 -25 -42 -25q-4 0 -14 2q-17 5 -25.5 19t-4.5 30l197 808l-406 -101q-4 -1 -12 -1q-18 0 -31 11q-18 15 -13 39l201 825q4 14 16 23t28 9h328q19 0 32 -12.5t13 -29.5q0 -8 -5 -18l-171 -463l396 98q8 2 12 2q19 0 34 -15z" />
-<glyph unicode="&#xf0e8;" horiz-adv-x="1792" d="M1792 288v-320q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h96v192h-512v-192h96q40 0 68 -28t28 -68v-320q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h96v192h-512v-192h96q40 0 68 -28t28 -68v-320 q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h96v192q0 52 38 90t90 38h512v192h-96q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h320q40 0 68 -28t28 -68v-320q0 -40 -28 -68t-68 -28h-96v-192h512q52 0 90 -38t38 -90v-192h96q40 0 68 -28t28 -68 z" />
-<glyph unicode="&#xf0e9;" horiz-adv-x="1664" d="M896 708v-580q0 -104 -76 -180t-180 -76t-180 76t-76 180q0 26 19 45t45 19t45 -19t19 -45q0 -50 39 -89t89 -39t89 39t39 89v580q33 11 64 11t64 -11zM1664 681q0 -13 -9.5 -22.5t-22.5 -9.5q-11 0 -23 10q-49 46 -93 69t-102 23q-68 0 -128 -37t-103 -97 q-7 -10 -17.5 -28t-14.5 -24q-11 -17 -28 -17q-18 0 -29 17q-4 6 -14.5 24t-17.5 28q-43 60 -102.5 97t-127.5 37t-127.5 -37t-102.5 -97q-7 -10 -17.5 -28t-14.5 -24q-11 -17 -29 -17q-17 0 -28 17q-4 6 -14.5 24t-17.5 28q-43 60 -103 97t-128 37q-58 0 -102 -23t-93 -69 q-12 -10 -23 -10q-13 0 -22.5 9.5t-9.5 22.5q0 5 1 7q45 183 172.5 319.5t298 204.5t360.5 68q140 0 274.5 -40t246.5 -113.5t194.5 -187t115.5 -251.5q1 -2 1 -7zM896 1408v-98q-42 2 -64 2t-64 -2v98q0 26 19 45t45 19t45 -19t19 -45z" />
-<glyph unicode="&#xf0ea;" horiz-adv-x="1792" d="M768 -128h896v640h-416q-40 0 -68 28t-28 68v416h-384v-1152zM1024 1312v64q0 13 -9.5 22.5t-22.5 9.5h-704q-13 0 -22.5 -9.5t-9.5 -22.5v-64q0 -13 9.5 -22.5t22.5 -9.5h704q13 0 22.5 9.5t9.5 22.5zM1280 640h299l-299 299v-299zM1792 512v-672q0 -40 -28 -68t-68 -28 h-960q-40 0 -68 28t-28 68v160h-544q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h1088q40 0 68 -28t28 -68v-328q21 -13 36 -28l408 -408q28 -28 48 -76t20 -88z" />
-<glyph unicode="&#xf0eb;" horiz-adv-x="1024" d="M736 960q0 -13 -9.5 -22.5t-22.5 -9.5t-22.5 9.5t-9.5 22.5q0 46 -54 71t-106 25q-13 0 -22.5 9.5t-9.5 22.5t9.5 22.5t22.5 9.5q50 0 99.5 -16t87 -54t37.5 -90zM896 960q0 72 -34.5 134t-90 101.5t-123 62t-136.5 22.5t-136.5 -22.5t-123 -62t-90 -101.5t-34.5 -134 q0 -101 68 -180q10 -11 30.5 -33t30.5 -33q128 -153 141 -298h228q13 145 141 298q10 11 30.5 33t30.5 33q68 79 68 180zM1024 960q0 -155 -103 -268q-45 -49 -74.5 -87t-59.5 -95.5t-34 -107.5q47 -28 47 -82q0 -37 -25 -64q25 -27 25 -64q0 -52 -45 -81q13 -23 13 -47 q0 -46 -31.5 -71t-77.5 -25q-20 -44 -60 -70t-87 -26t-87 26t-60 70q-46 0 -77.5 25t-31.5 71q0 24 13 47q-45 29 -45 81q0 37 25 64q-25 27 -25 64q0 54 47 82q-4 50 -34 107.5t-59.5 95.5t-74.5 87q-103 113 -103 268q0 99 44.5 184.5t117 142t164 89t186.5 32.5 t186.5 -32.5t164 -89t117 -142t44.5 -184.5z" />
-<glyph unicode="&#xf0ec;" horiz-adv-x="1792" d="M1792 352v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5q-12 0 -24 10l-319 320q-9 9 -9 22q0 14 9 23l320 320q9 9 23 9q13 0 22.5 -9.5t9.5 -22.5v-192h1376q13 0 22.5 -9.5t9.5 -22.5zM1792 896q0 -14 -9 -23l-320 -320q-9 -9 -23 -9 q-13 0 -22.5 9.5t-9.5 22.5v192h-1376q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1376v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23z" />
-<glyph unicode="&#xf0ed;" horiz-adv-x="1920" d="M1280 608q0 14 -9 23t-23 9h-224v352q0 13 -9.5 22.5t-22.5 9.5h-192q-13 0 -22.5 -9.5t-9.5 -22.5v-352h-224q-13 0 -22.5 -9.5t-9.5 -22.5q0 -14 9 -23l352 -352q9 -9 23 -9t23 9l351 351q10 12 10 24zM1920 384q0 -159 -112.5 -271.5t-271.5 -112.5h-1088 q-185 0 -316.5 131.5t-131.5 316.5q0 130 70 240t188 165q-2 30 -2 43q0 212 150 362t362 150q156 0 285.5 -87t188.5 -231q71 62 166 62q106 0 181 -75t75 -181q0 -76 -41 -138q130 -31 213.5 -135.5t83.5 -238.5z" />
-<glyph unicode="&#xf0ee;" horiz-adv-x="1920" d="M1280 672q0 14 -9 23l-352 352q-9 9 -23 9t-23 -9l-351 -351q-10 -12 -10 -24q0 -14 9 -23t23 -9h224v-352q0 -13 9.5 -22.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 22.5v352h224q13 0 22.5 9.5t9.5 22.5zM1920 384q0 -159 -112.5 -271.5t-271.5 -112.5h-1088 q-185 0 -316.5 131.5t-131.5 316.5q0 130 70 240t188 165q-2 30 -2 43q0 212 150 362t362 150q156 0 285.5 -87t188.5 -231q71 62 166 62q106 0 181 -75t75 -181q0 -76 -41 -138q130 -31 213.5 -135.5t83.5 -238.5z" />
-<glyph unicode="&#xf0f0;" horiz-adv-x="1408" d="M384 192q0 -26 -19 -45t-45 -19t-45 19t-19 45t19 45t45 19t45 -19t19 -45zM1408 131q0 -121 -73 -190t-194 -69h-874q-121 0 -194 69t-73 190q0 68 5.5 131t24 138t47.5 132.5t81 103t120 60.5q-22 -52 -22 -120v-203q-58 -20 -93 -70t-35 -111q0 -80 56 -136t136 -56 t136 56t56 136q0 61 -35.5 111t-92.5 70v203q0 62 25 93q132 -104 295 -104t295 104q25 -31 25 -93v-64q-106 0 -181 -75t-75 -181v-89q-32 -29 -32 -71q0 -40 28 -68t68 -28t68 28t28 68q0 42 -32 71v89q0 52 38 90t90 38t90 -38t38 -90v-89q-32 -29 -32 -71q0 -40 28 -68 t68 -28t68 28t28 68q0 42 -32 71v89q0 68 -34.5 127.5t-93.5 93.5q0 10 0.5 42.5t0 48t-2.5 41.5t-7 47t-13 40q68 -15 120 -60.5t81 -103t47.5 -132.5t24 -138t5.5 -131zM1088 1024q0 -159 -112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5 t271.5 -112.5t112.5 -271.5z" />
-<glyph unicode="&#xf0f1;" horiz-adv-x="1408" d="M1280 832q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 832q0 -62 -35.5 -111t-92.5 -70v-395q0 -159 -131.5 -271.5t-316.5 -112.5t-316.5 112.5t-131.5 271.5v132q-164 20 -274 128t-110 252v512q0 26 19 45t45 19q6 0 16 -2q17 30 47 48 t65 18q53 0 90.5 -37.5t37.5 -90.5t-37.5 -90.5t-90.5 -37.5q-33 0 -64 18v-402q0 -106 94 -181t226 -75t226 75t94 181v402q-31 -18 -64 -18q-53 0 -90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5q35 0 65 -18t47 -48q10 2 16 2q26 0 45 -19t19 -45v-512q0 -144 -110 -252 t-274 -128v-132q0 -106 94 -181t226 -75t226 75t94 181v395q-57 21 -92.5 70t-35.5 111q0 80 56 136t136 56t136 -56t56 -136z" />
-<glyph unicode="&#xf0f2;" horiz-adv-x="1792" d="M640 1152h512v128h-512v-128zM288 1152v-1280h-64q-92 0 -158 66t-66 158v832q0 92 66 158t158 66h64zM1408 1152v-1280h-1024v1280h128v160q0 40 28 68t68 28h576q40 0 68 -28t28 -68v-160h128zM1792 928v-832q0 -92 -66 -158t-158 -66h-64v1280h64q92 0 158 -66 t66 -158z" />
-<glyph unicode="&#xf0f3;" horiz-adv-x="1792" d="M912 -160q0 16 -16 16q-59 0 -101.5 42.5t-42.5 101.5q0 16 -16 16t-16 -16q0 -73 51.5 -124.5t124.5 -51.5q16 0 16 16zM1728 128q0 -52 -38 -90t-90 -38h-448q0 -106 -75 -181t-181 -75t-181 75t-75 181h-448q-52 0 -90 38t-38 90q50 42 91 88t85 119.5t74.5 158.5 t50 206t19.5 260q0 152 117 282.5t307 158.5q-8 19 -8 39q0 40 28 68t68 28t68 -28t28 -68q0 -20 -8 -39q190 -28 307 -158.5t117 -282.5q0 -139 19.5 -260t50 -206t74.5 -158.5t85 -119.5t91 -88z" />
-<glyph unicode="&#xf0f4;" horiz-adv-x="1920" d="M1664 896q0 80 -56 136t-136 56h-64v-384h64q80 0 136 56t56 136zM0 128h1792q0 -106 -75 -181t-181 -75h-1280q-106 0 -181 75t-75 181zM1856 896q0 -159 -112.5 -271.5t-271.5 -112.5h-64v-32q0 -92 -66 -158t-158 -66h-704q-92 0 -158 66t-66 158v736q0 26 19 45 t45 19h1152q159 0 271.5 -112.5t112.5 -271.5z" />
-<glyph unicode="&#xf0f5;" horiz-adv-x="1408" d="M640 1472v-640q0 -61 -35.5 -111t-92.5 -70v-779q0 -52 -38 -90t-90 -38h-128q-52 0 -90 38t-38 90v779q-57 20 -92.5 70t-35.5 111v640q0 26 19 45t45 19t45 -19t19 -45v-416q0 -26 19 -45t45 -19t45 19t19 45v416q0 26 19 45t45 19t45 -19t19 -45v-416q0 -26 19 -45 t45 -19t45 19t19 45v416q0 26 19 45t45 19t45 -19t19 -45zM1408 1472v-1600q0 -52 -38 -90t-90 -38h-128q-52 0 -90 38t-38 90v512h-224q-13 0 -22.5 9.5t-9.5 22.5v800q0 132 94 226t226 94h256q26 0 45 -19t19 -45z" />
-<glyph unicode="&#xf0f6;" d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z M384 736q0 14 9 23t23 9h704q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-704q-14 0 -23 9t-9 23v64zM1120 512q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-704q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h704zM1120 256q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-704 q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h704z" />
-<glyph unicode="&#xf0f7;" horiz-adv-x="1408" d="M384 224v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M1152 224v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM896 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 992v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M1152 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM896 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 992v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 1248v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M1152 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM896 992v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 1248v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1152 992v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M896 1248v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1152 1248v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M896 -128h384v1536h-1152v-1536h384v224q0 13 9.5 22.5t22.5 9.5h320q13 0 22.5 -9.5t9.5 -22.5v-224zM1408 1472v-1664q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v1664q0 26 19 45t45 19h1280q26 0 45 -19t19 -45z" />
-<glyph unicode="&#xf0f8;" horiz-adv-x="1408" d="M384 224v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M1152 224v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM896 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1152 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M896 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1152 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M896 -128h384v1152h-256v-32q0 -40 -28 -68t-68 -28h-448q-40 0 -68 28t-28 68v32h-256v-1152h384v224q0 13 9.5 22.5t22.5 9.5h320q13 0 22.5 -9.5t9.5 -22.5v-224zM896 1056v320q0 13 -9.5 22.5t-22.5 9.5h-64q-13 0 -22.5 -9.5t-9.5 -22.5v-96h-128v96q0 13 -9.5 22.5 t-22.5 9.5h-64q-13 0 -22.5 -9.5t-9.5 -22.5v-320q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5v96h128v-96q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5zM1408 1088v-1280q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v1280q0 26 19 45t45 19h320 v288q0 40 28 68t68 28h448q40 0 68 -28t28 -68v-288h320q26 0 45 -19t19 -45z" />
-<glyph unicode="&#xf0f9;" horiz-adv-x="1920" d="M640 128q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM256 640h384v256h-158q-14 -2 -22 -9l-195 -195q-7 -12 -9 -22v-30zM1536 128q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5 t90.5 37.5t37.5 90.5zM1664 800v192q0 14 -9 23t-23 9h-224v224q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-224h-224q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h224v-224q0 -14 9 -23t23 -9h192q14 0 23 9t9 23v224h224q14 0 23 9t9 23zM1920 1344v-1152 q0 -26 -19 -45t-45 -19h-192q0 -106 -75 -181t-181 -75t-181 75t-75 181h-384q0 -106 -75 -181t-181 -75t-181 75t-75 181h-128q-26 0 -45 19t-19 45t19 45t45 19v416q0 26 13 58t32 51l198 198q19 19 51 32t58 13h160v320q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" />
-<glyph unicode="&#xf0fa;" horiz-adv-x="1792" d="M1280 416v192q0 14 -9 23t-23 9h-224v224q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-224h-224q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h224v-224q0 -14 9 -23t23 -9h192q14 0 23 9t9 23v224h224q14 0 23 9t9 23zM640 1152h512v128h-512v-128zM256 1152v-1280h-32 q-92 0 -158 66t-66 158v832q0 92 66 158t158 66h32zM1440 1152v-1280h-1088v1280h160v160q0 40 28 68t68 28h576q40 0 68 -28t28 -68v-160h160zM1792 928v-832q0 -92 -66 -158t-158 -66h-32v1280h32q92 0 158 -66t66 -158z" />
-<glyph unicode="&#xf0fb;" horiz-adv-x="1920" d="M1920 576q-1 -32 -288 -96l-352 -32l-224 -64h-64l-293 -352h69q26 0 45 -4.5t19 -11.5t-19 -11.5t-45 -4.5h-96h-160h-64v32h64v416h-160l-192 -224h-96l-32 32v192h32v32h128v8l-192 24v128l192 24v8h-128v32h-32v192l32 32h96l192 -224h160v416h-64v32h64h160h96 q26 0 45 -4.5t19 -11.5t-19 -11.5t-45 -4.5h-69l293 -352h64l224 -64l352 -32q261 -58 287 -93z" />
-<glyph unicode="&#xf0fc;" horiz-adv-x="1664" d="M640 640v384h-256v-256q0 -53 37.5 -90.5t90.5 -37.5h128zM1664 192v-192h-1152v192l128 192h-128q-159 0 -271.5 112.5t-112.5 271.5v320l-64 64l32 128h480l32 128h960l32 -192l-64 -32v-800z" />
-<glyph unicode="&#xf0fd;" d="M1280 192v896q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-320h-512v320q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-896q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v320h512v-320q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1536 1120v-960 q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
-<glyph unicode="&#xf0fe;" d="M1280 576v128q0 26 -19 45t-45 19h-320v320q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-320h-320q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h320v-320q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v320h320q26 0 45 19t19 45zM1536 1120v-960 q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
-<glyph unicode="&#xf100;" horiz-adv-x="1024" d="M627 160q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23t-10 -23l-393 -393l393 -393q10 -10 10 -23zM1011 160q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23 t10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23t-10 -23l-393 -393l393 -393q10 -10 10 -23z" />
-<glyph unicode="&#xf101;" horiz-adv-x="1024" d="M595 576q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23zM979 576q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23 l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" />
-<glyph unicode="&#xf102;" horiz-adv-x="1152" d="M1075 224q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-393 393l-393 -393q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l466 -466q10 -10 10 -23zM1075 608q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-393 393l-393 -393 q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" />
-<glyph unicode="&#xf103;" horiz-adv-x="1152" d="M1075 672q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l393 -393l393 393q10 10 23 10t23 -10l50 -50q10 -10 10 -23zM1075 1056q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23 t10 23l50 50q10 10 23 10t23 -10l393 -393l393 393q10 10 23 10t23 -10l50 -50q10 -10 10 -23z" />
-<glyph unicode="&#xf104;" horiz-adv-x="640" d="M627 992q0 -13 -10 -23l-393 -393l393 -393q10 -10 10 -23t-10 -23l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23z" />
-<glyph unicode="&#xf105;" horiz-adv-x="640" d="M595 576q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" />
-<glyph unicode="&#xf106;" horiz-adv-x="1152" d="M1075 352q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-393 393l-393 -393q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" />
-<glyph unicode="&#xf107;" horiz-adv-x="1152" d="M1075 800q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l393 -393l393 393q10 10 23 10t23 -10l50 -50q10 -10 10 -23z" />
-<glyph unicode="&#xf108;" horiz-adv-x="1920" d="M1792 544v832q0 13 -9.5 22.5t-22.5 9.5h-1600q-13 0 -22.5 -9.5t-9.5 -22.5v-832q0 -13 9.5 -22.5t22.5 -9.5h1600q13 0 22.5 9.5t9.5 22.5zM1920 1376v-1088q0 -66 -47 -113t-113 -47h-544q0 -37 16 -77.5t32 -71t16 -43.5q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19 t-19 45q0 14 16 44t32 70t16 78h-544q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" />
-<glyph unicode="&#xf109;" horiz-adv-x="1920" d="M416 256q-66 0 -113 47t-47 113v704q0 66 47 113t113 47h1088q66 0 113 -47t47 -113v-704q0 -66 -47 -113t-113 -47h-1088zM384 1120v-704q0 -13 9.5 -22.5t22.5 -9.5h1088q13 0 22.5 9.5t9.5 22.5v704q0 13 -9.5 22.5t-22.5 9.5h-1088q-13 0 -22.5 -9.5t-9.5 -22.5z M1760 192h160v-96q0 -40 -47 -68t-113 -28h-1600q-66 0 -113 28t-47 68v96h160h1600zM1040 96q16 0 16 16t-16 16h-160q-16 0 -16 -16t16 -16h160z" />
-<glyph unicode="&#xf10a;" horiz-adv-x="1152" d="M640 128q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1024 288v960q0 13 -9.5 22.5t-22.5 9.5h-832q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h832q13 0 22.5 9.5t9.5 22.5zM1152 1248v-1088q0 -66 -47 -113t-113 -47h-832 q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h832q66 0 113 -47t47 -113z" />
-<glyph unicode="&#xf10b;" horiz-adv-x="768" d="M464 128q0 33 -23.5 56.5t-56.5 23.5t-56.5 -23.5t-23.5 -56.5t23.5 -56.5t56.5 -23.5t56.5 23.5t23.5 56.5zM672 288v704q0 13 -9.5 22.5t-22.5 9.5h-512q-13 0 -22.5 -9.5t-9.5 -22.5v-704q0 -13 9.5 -22.5t22.5 -9.5h512q13 0 22.5 9.5t9.5 22.5zM480 1136 q0 16 -16 16h-160q-16 0 -16 -16t16 -16h160q16 0 16 16zM768 1152v-1024q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v1024q0 52 38 90t90 38h512q52 0 90 -38t38 -90z" />
-<glyph unicode="&#xf10c;" d="M768 1184q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273t-73 273t-198 198t-273 73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103 t279.5 -279.5t103 -385.5z" />
-<glyph unicode="&#xf10d;" horiz-adv-x="1664" d="M768 576v-384q0 -80 -56 -136t-136 -56h-384q-80 0 -136 56t-56 136v704q0 104 40.5 198.5t109.5 163.5t163.5 109.5t198.5 40.5h64q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-64q-106 0 -181 -75t-75 -181v-32q0 -40 28 -68t68 -28h224q80 0 136 -56t56 -136z M1664 576v-384q0 -80 -56 -136t-136 -56h-384q-80 0 -136 56t-56 136v704q0 104 40.5 198.5t109.5 163.5t163.5 109.5t198.5 40.5h64q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-64q-106 0 -181 -75t-75 -181v-32q0 -40 28 -68t68 -28h224q80 0 136 -56t56 -136z" />
-<glyph unicode="&#xf10e;" horiz-adv-x="1664" d="M768 1216v-704q0 -104 -40.5 -198.5t-109.5 -163.5t-163.5 -109.5t-198.5 -40.5h-64q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h64q106 0 181 75t75 181v32q0 40 -28 68t-68 28h-224q-80 0 -136 56t-56 136v384q0 80 56 136t136 56h384q80 0 136 -56t56 -136zM1664 1216 v-704q0 -104 -40.5 -198.5t-109.5 -163.5t-163.5 -109.5t-198.5 -40.5h-64q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h64q106 0 181 75t75 181v32q0 40 -28 68t-68 28h-224q-80 0 -136 56t-56 136v384q0 80 56 136t136 56h384q80 0 136 -56t56 -136z" />
-<glyph unicode="&#xf110;" horiz-adv-x="1792" d="M526 142q0 -53 -37.5 -90.5t-90.5 -37.5q-52 0 -90 38t-38 90q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1024 -64q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM320 640q0 -53 -37.5 -90.5t-90.5 -37.5 t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1522 142q0 -52 -38 -90t-90 -38q-53 0 -90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM558 1138q0 -66 -47 -113t-113 -47t-113 47t-47 113t47 113t113 47t113 -47t47 -113z M1728 640q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1088 1344q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1618 1138q0 -93 -66 -158.5t-158 -65.5q-93 0 -158.5 65.5t-65.5 158.5 q0 92 65.5 158t158.5 66q92 0 158 -66t66 -158z" />
-<glyph unicode="&#xf111;" d="M1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
-<glyph unicode="&#xf112;" horiz-adv-x="1792" d="M1792 416q0 -166 -127 -451q-3 -7 -10.5 -24t-13.5 -30t-13 -22q-12 -17 -28 -17q-15 0 -23.5 10t-8.5 25q0 9 2.5 26.5t2.5 23.5q5 68 5 123q0 101 -17.5 181t-48.5 138.5t-80 101t-105.5 69.5t-133 42.5t-154 21.5t-175.5 6h-224v-256q0 -26 -19 -45t-45 -19t-45 19 l-512 512q-19 19 -19 45t19 45l512 512q19 19 45 19t45 -19t19 -45v-256h224q713 0 875 -403q53 -134 53 -333z" />
-<glyph unicode="&#xf113;" horiz-adv-x="1664" d="M640 320q0 -40 -12.5 -82t-43 -76t-72.5 -34t-72.5 34t-43 76t-12.5 82t12.5 82t43 76t72.5 34t72.5 -34t43 -76t12.5 -82zM1280 320q0 -40 -12.5 -82t-43 -76t-72.5 -34t-72.5 34t-43 76t-12.5 82t12.5 82t43 76t72.5 34t72.5 -34t43 -76t12.5 -82zM1440 320 q0 120 -69 204t-187 84q-41 0 -195 -21q-71 -11 -157 -11t-157 11q-152 21 -195 21q-118 0 -187 -84t-69 -204q0 -88 32 -153.5t81 -103t122 -60t140 -29.5t149 -7h168q82 0 149 7t140 29.5t122 60t81 103t32 153.5zM1664 496q0 -207 -61 -331q-38 -77 -105.5 -133t-141 -86 t-170 -47.5t-171.5 -22t-167 -4.5q-78 0 -142 3t-147.5 12.5t-152.5 30t-137 51.5t-121 81t-86 115q-62 123 -62 331q0 237 136 396q-27 82 -27 170q0 116 51 218q108 0 190 -39.5t189 -123.5q147 35 309 35q148 0 280 -32q105 82 187 121t189 39q51 -102 51 -218 q0 -87 -27 -168q136 -160 136 -398z" />
-<glyph unicode="&#xf114;" horiz-adv-x="1664" d="M1536 224v704q0 40 -28 68t-68 28h-704q-40 0 -68 28t-28 68v64q0 40 -28 68t-68 28h-320q-40 0 -68 -28t-28 -68v-960q0 -40 28 -68t68 -28h1216q40 0 68 28t28 68zM1664 928v-704q0 -92 -66 -158t-158 -66h-1216q-92 0 -158 66t-66 158v960q0 92 66 158t158 66h320 q92 0 158 -66t66 -158v-32h672q92 0 158 -66t66 -158z" />
-<glyph unicode="&#xf115;" horiz-adv-x="1920" d="M1781 605q0 35 -53 35h-1088q-40 0 -85.5 -21.5t-71.5 -52.5l-294 -363q-18 -24 -18 -40q0 -35 53 -35h1088q40 0 86 22t71 53l294 363q18 22 18 39zM640 768h768v160q0 40 -28 68t-68 28h-576q-40 0 -68 28t-28 68v64q0 40 -28 68t-68 28h-320q-40 0 -68 -28t-28 -68 v-853l256 315q44 53 116 87.5t140 34.5zM1909 605q0 -62 -46 -120l-295 -363q-43 -53 -116 -87.5t-140 -34.5h-1088q-92 0 -158 66t-66 158v960q0 92 66 158t158 66h320q92 0 158 -66t66 -158v-32h544q92 0 158 -66t66 -158v-160h192q54 0 99 -24.5t67 -70.5q15 -32 15 -68z " />
-<glyph unicode="&#xf116;" horiz-adv-x="1792" />
-<glyph unicode="&#xf117;" horiz-adv-x="1792" />
-<glyph unicode="&#xf118;" d="M1134 461q-37 -121 -138 -195t-228 -74t-228 74t-138 195q-8 25 4 48.5t38 31.5q25 8 48.5 -4t31.5 -38q25 -80 92.5 -129.5t151.5 -49.5t151.5 49.5t92.5 129.5q8 26 32 38t49 4t37 -31.5t4 -48.5zM640 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5 t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1152 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1408 640q0 130 -51 248.5t-136.5 204t-204 136.5t-248.5 51t-248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5 t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
-<glyph unicode="&#xf119;" d="M1134 307q8 -25 -4 -48.5t-37 -31.5t-49 4t-32 38q-25 80 -92.5 129.5t-151.5 49.5t-151.5 -49.5t-92.5 -129.5q-8 -26 -31.5 -38t-48.5 -4q-26 8 -38 31.5t-4 48.5q37 121 138 195t228 74t228 -74t138 -195zM640 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5 t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1152 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1408 640q0 130 -51 248.5t-136.5 204t-204 136.5t-248.5 51t-248.5 -51t-204 -136.5t-136.5 -204 t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
-<glyph unicode="&#xf11a;" d="M1152 448q0 -26 -19 -45t-45 -19h-640q-26 0 -45 19t-19 45t19 45t45 19h640q26 0 45 -19t19 -45zM640 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1152 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5 t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1408 640q0 130 -51 248.5t-136.5 204t-204 136.5t-248.5 51t-248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
-<glyph unicode="&#xf11b;" horiz-adv-x="1920" d="M832 448v128q0 14 -9 23t-23 9h-192v192q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-192h-192q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h192v-192q0 -14 9 -23t23 -9h128q14 0 23 9t9 23v192h192q14 0 23 9t9 23zM1408 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5 t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1664 640q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1920 512q0 -212 -150 -362t-362 -150q-192 0 -338 128h-220q-146 -128 -338 -128q-212 0 -362 150 t-150 362t150 362t362 150h896q212 0 362 -150t150 -362z" />
-<glyph unicode="&#xf11c;" horiz-adv-x="1920" d="M384 368v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM512 624v-96q0 -16 -16 -16h-224q-16 0 -16 16v96q0 16 16 16h224q16 0 16 -16zM384 880v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1408 368v-96q0 -16 -16 -16 h-864q-16 0 -16 16v96q0 16 16 16h864q16 0 16 -16zM768 624v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM640 880v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1024 624v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16 h96q16 0 16 -16zM896 880v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1280 624v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1664 368v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1152 880v-96 q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1408 880v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1664 880v-352q0 -16 -16 -16h-224q-16 0 -16 16v96q0 16 16 16h112v240q0 16 16 16h96q16 0 16 -16zM1792 128v896h-1664v-896 h1664zM1920 1024v-896q0 -53 -37.5 -90.5t-90.5 -37.5h-1664q-53 0 -90.5 37.5t-37.5 90.5v896q0 53 37.5 90.5t90.5 37.5h1664q53 0 90.5 -37.5t37.5 -90.5z" />
-<glyph unicode="&#xf11d;" horiz-adv-x="1792" d="M1664 491v616q-169 -91 -306 -91q-82 0 -145 32q-100 49 -184 76.5t-178 27.5q-173 0 -403 -127v-599q245 113 433 113q55 0 103.5 -7.5t98 -26t77 -31t82.5 -39.5l28 -14q44 -22 101 -22q120 0 293 92zM320 1280q0 -35 -17.5 -64t-46.5 -46v-1266q0 -14 -9 -23t-23 -9 h-64q-14 0 -23 9t-9 23v1266q-29 17 -46.5 46t-17.5 64q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1792 1216v-763q0 -39 -35 -57q-10 -5 -17 -9q-218 -116 -369 -116q-88 0 -158 35l-28 14q-64 33 -99 48t-91 29t-114 14q-102 0 -235.5 -44t-228.5 -102 q-15 -9 -33 -9q-16 0 -32 8q-32 19 -32 56v742q0 35 31 55q35 21 78.5 42.5t114 52t152.5 49.5t155 19q112 0 209 -31t209 -86q38 -19 89 -19q122 0 310 112q22 12 31 17q31 16 62 -2q31 -20 31 -55z" />
-<glyph unicode="&#xf11e;" horiz-adv-x="1792" d="M832 536v192q-181 -16 -384 -117v-185q205 96 384 110zM832 954v197q-172 -8 -384 -126v-189q215 111 384 118zM1664 491v184q-235 -116 -384 -71v224q-20 6 -39 15q-5 3 -33 17t-34.5 17t-31.5 15t-34.5 15.5t-32.5 13t-36 12.5t-35 8.5t-39.5 7.5t-39.5 4t-44 2 q-23 0 -49 -3v-222h19q102 0 192.5 -29t197.5 -82q19 -9 39 -15v-188q42 -17 91 -17q120 0 293 92zM1664 918v189q-169 -91 -306 -91q-45 0 -78 8v-196q148 -42 384 90zM320 1280q0 -35 -17.5 -64t-46.5 -46v-1266q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v1266 q-29 17 -46.5 46t-17.5 64q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1792 1216v-763q0 -39 -35 -57q-10 -5 -17 -9q-218 -116 -369 -116q-88 0 -158 35l-28 14q-64 33 -99 48t-91 29t-114 14q-102 0 -235.5 -44t-228.5 -102q-15 -9 -33 -9q-16 0 -32 8 q-32 19 -32 56v742q0 35 31 55q35 21 78.5 42.5t114 52t152.5 49.5t155 19q112 0 209 -31t209 -86q38 -19 89 -19q122 0 310 112q22 12 31 17q31 16 62 -2q31 -20 31 -55z" />
-<glyph unicode="&#xf120;" horiz-adv-x="1664" d="M585 553l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23t-10 -23zM1664 96v-64q0 -14 -9 -23t-23 -9h-960q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h960q14 0 23 -9 t9 -23z" />
-<glyph unicode="&#xf121;" horiz-adv-x="1920" d="M617 137l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23t-10 -23l-393 -393l393 -393q10 -10 10 -23t-10 -23zM1208 1204l-373 -1291q-4 -13 -15.5 -19.5t-23.5 -2.5l-62 17q-13 4 -19.5 15.5t-2.5 24.5 l373 1291q4 13 15.5 19.5t23.5 2.5l62 -17q13 -4 19.5 -15.5t2.5 -24.5zM1865 553l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23t-10 -23z" />
-<glyph unicode="&#xf122;" horiz-adv-x="1792" d="M640 454v-70q0 -42 -39 -59q-13 -5 -25 -5q-27 0 -45 19l-512 512q-19 19 -19 45t19 45l512 512q29 31 70 14q39 -17 39 -59v-69l-397 -398q-19 -19 -19 -45t19 -45zM1792 416q0 -58 -17 -133.5t-38.5 -138t-48 -125t-40.5 -90.5l-20 -40q-8 -17 -28 -17q-6 0 -9 1 q-25 8 -23 34q43 400 -106 565q-64 71 -170.5 110.5t-267.5 52.5v-251q0 -42 -39 -59q-13 -5 -25 -5q-27 0 -45 19l-512 512q-19 19 -19 45t19 45l512 512q29 31 70 14q39 -17 39 -59v-262q411 -28 599 -221q169 -173 169 -509z" />
-<glyph unicode="&#xf123;" horiz-adv-x="1664" d="M1186 579l257 250l-356 52l-66 10l-30 60l-159 322v-963l59 -31l318 -168l-60 355l-12 66zM1638 841l-363 -354l86 -500q5 -33 -6 -51.5t-34 -18.5q-17 0 -40 12l-449 236l-449 -236q-23 -12 -40 -12q-23 0 -34 18.5t-6 51.5l86 500l-364 354q-32 32 -23 59.5t54 34.5 l502 73l225 455q20 41 49 41q28 0 49 -41l225 -455l502 -73q45 -7 54 -34.5t-24 -59.5z" />
-<glyph unicode="&#xf124;" horiz-adv-x="1408" d="M1401 1187l-640 -1280q-17 -35 -57 -35q-5 0 -15 2q-22 5 -35.5 22.5t-13.5 39.5v576h-576q-22 0 -39.5 13.5t-22.5 35.5t4 42t29 30l1280 640q13 7 29 7q27 0 45 -19q15 -14 18.5 -34.5t-6.5 -39.5z" />
-<glyph unicode="&#xf125;" horiz-adv-x="1664" d="M557 256h595v595zM512 301l595 595h-595v-595zM1664 224v-192q0 -14 -9 -23t-23 -9h-224v-224q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v224h-864q-14 0 -23 9t-9 23v864h-224q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h224v224q0 14 9 23t23 9h192q14 0 23 -9t9 -23 v-224h851l246 247q10 9 23 9t23 -9q9 -10 9 -23t-9 -23l-247 -246v-851h224q14 0 23 -9t9 -23z" />
-<glyph unicode="&#xf126;" horiz-adv-x="1024" d="M288 64q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM288 1216q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM928 1088q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM1024 1088q0 -52 -26 -96.5t-70 -69.5 q-2 -287 -226 -414q-68 -38 -203 -81q-128 -40 -169.5 -71t-41.5 -100v-26q44 -25 70 -69.5t26 -96.5q0 -80 -56 -136t-136 -56t-136 56t-56 136q0 52 26 96.5t70 69.5v820q-44 25 -70 69.5t-26 96.5q0 80 56 136t136 56t136 -56t56 -136q0 -52 -26 -96.5t-70 -69.5v-497 q54 26 154 57q55 17 87.5 29.5t70.5 31t59 39.5t40.5 51t28 69.5t8.5 91.5q-44 25 -70 69.5t-26 96.5q0 80 56 136t136 56t136 -56t56 -136z" />
-<glyph unicode="&#xf127;" horiz-adv-x="1664" d="M439 265l-256 -256q-10 -9 -23 -9q-12 0 -23 9q-9 10 -9 23t9 23l256 256q10 9 23 9t23 -9q9 -10 9 -23t-9 -23zM608 224v-320q0 -14 -9 -23t-23 -9t-23 9t-9 23v320q0 14 9 23t23 9t23 -9t9 -23zM384 448q0 -14 -9 -23t-23 -9h-320q-14 0 -23 9t-9 23t9 23t23 9h320 q14 0 23 -9t9 -23zM1648 320q0 -120 -85 -203l-147 -146q-83 -83 -203 -83q-121 0 -204 85l-334 335q-21 21 -42 56l239 18l273 -274q27 -27 68 -27.5t68 26.5l147 146q28 28 28 67q0 40 -28 68l-274 275l18 239q35 -21 56 -42l336 -336q84 -86 84 -204zM1031 1044l-239 -18 l-273 274q-28 28 -68 28q-39 0 -68 -27l-147 -146q-28 -28 -28 -67q0 -40 28 -68l274 -274l-18 -240q-35 21 -56 42l-336 336q-84 86 -84 204q0 120 85 203l147 146q83 83 203 83q121 0 204 -85l334 -335q21 -21 42 -56zM1664 960q0 -14 -9 -23t-23 -9h-320q-14 0 -23 9 t-9 23t9 23t23 9h320q14 0 23 -9t9 -23zM1120 1504v-320q0 -14 -9 -23t-23 -9t-23 9t-9 23v320q0 14 9 23t23 9t23 -9t9 -23zM1527 1353l-256 -256q-11 -9 -23 -9t-23 9q-9 10 -9 23t9 23l256 256q10 9 23 9t23 -9q9 -10 9 -23t-9 -23z" />
-<glyph unicode="&#xf128;" horiz-adv-x="1024" d="M704 280v-240q0 -16 -12 -28t-28 -12h-240q-16 0 -28 12t-12 28v240q0 16 12 28t28 12h240q16 0 28 -12t12 -28zM1020 880q0 -54 -15.5 -101t-35 -76.5t-55 -59.5t-57.5 -43.5t-61 -35.5q-41 -23 -68.5 -65t-27.5 -67q0 -17 -12 -32.5t-28 -15.5h-240q-15 0 -25.5 18.5 t-10.5 37.5v45q0 83 65 156.5t143 108.5q59 27 84 56t25 76q0 42 -46.5 74t-107.5 32q-65 0 -108 -29q-35 -25 -107 -115q-13 -16 -31 -16q-12 0 -25 8l-164 125q-13 10 -15.5 25t5.5 28q160 266 464 266q80 0 161 -31t146 -83t106 -127.5t41 -158.5z" />
-<glyph unicode="&#xf129;" horiz-adv-x="640" d="M640 192v-128q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h64v384h-64q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h384q26 0 45 -19t19 -45v-576h64q26 0 45 -19t19 -45zM512 1344v-192q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v192 q0 26 19 45t45 19h256q26 0 45 -19t19 -45z" />
-<glyph unicode="&#xf12a;" horiz-adv-x="640" d="M512 288v-224q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v224q0 26 19 45t45 19h256q26 0 45 -19t19 -45zM542 1344l-28 -768q-1 -26 -20.5 -45t-45.5 -19h-256q-26 0 -45.5 19t-20.5 45l-28 768q-1 26 17.5 45t44.5 19h320q26 0 44.5 -19t17.5 -45z" />
-<glyph unicode="&#xf12b;" d="M897 167v-167h-248l-159 252l-24 42q-8 9 -11 21h-3l-9 -21q-10 -20 -25 -44l-155 -250h-258v167h128l197 291l-185 272h-137v168h276l139 -228q2 -4 23 -42q8 -9 11 -21h3q3 9 11 21l25 42l140 228h257v-168h-125l-184 -267l204 -296h109zM1534 846v-206h-514l-3 27 q-4 28 -4 46q0 64 26 117t65 86.5t84 65t84 54.5t65 54t26 64q0 38 -29.5 62.5t-70.5 24.5q-51 0 -97 -39q-14 -11 -36 -38l-105 92q26 37 63 66q83 65 188 65q110 0 178 -59.5t68 -158.5q0 -56 -24.5 -103t-62 -76.5t-81.5 -58.5t-82 -50.5t-65.5 -51.5t-30.5 -63h232v80 h126z" />
-<glyph unicode="&#xf12c;" d="M897 167v-167h-248l-159 252l-24 42q-8 9 -11 21h-3l-9 -21q-10 -20 -25 -44l-155 -250h-258v167h128l197 291l-185 272h-137v168h276l139 -228q2 -4 23 -42q8 -9 11 -21h3q3 9 11 21l25 42l140 228h257v-168h-125l-184 -267l204 -296h109zM1536 -50v-206h-514l-4 27 q-3 45 -3 46q0 64 26 117t65 86.5t84 65t84 54.5t65 54t26 64q0 38 -29.5 62.5t-70.5 24.5q-51 0 -97 -39q-14 -11 -36 -38l-105 92q26 37 63 66q80 65 188 65q110 0 178 -59.5t68 -158.5q0 -66 -34.5 -118.5t-84 -86t-99.5 -62.5t-87 -63t-41 -73h232v80h126z" />
-<glyph unicode="&#xf12d;" horiz-adv-x="1920" d="M896 128l336 384h-768l-336 -384h768zM1909 1205q15 -34 9.5 -71.5t-30.5 -65.5l-896 -1024q-38 -44 -96 -44h-768q-38 0 -69.5 20.5t-47.5 54.5q-15 34 -9.5 71.5t30.5 65.5l896 1024q38 44 96 44h768q38 0 69.5 -20.5t47.5 -54.5z" />
-<glyph unicode="&#xf12e;" horiz-adv-x="1664" d="M1664 438q0 -81 -44.5 -135t-123.5 -54q-41 0 -77.5 17.5t-59 38t-56.5 38t-71 17.5q-110 0 -110 -124q0 -39 16 -115t15 -115v-5q-22 0 -33 -1q-34 -3 -97.5 -11.5t-115.5 -13.5t-98 -5q-61 0 -103 26.5t-42 83.5q0 37 17.5 71t38 56.5t38 59t17.5 77.5q0 79 -54 123.5 t-135 44.5q-84 0 -143 -45.5t-59 -127.5q0 -43 15 -83t33.5 -64.5t33.5 -53t15 -50.5q0 -45 -46 -89q-37 -35 -117 -35q-95 0 -245 24q-9 2 -27.5 4t-27.5 4l-13 2q-1 0 -3 1q-2 0 -2 1v1024q2 -1 17.5 -3.5t34 -5t21.5 -3.5q150 -24 245 -24q80 0 117 35q46 44 46 89 q0 22 -15 50.5t-33.5 53t-33.5 64.5t-15 83q0 82 59 127.5t144 45.5q80 0 134 -44.5t54 -123.5q0 -41 -17.5 -77.5t-38 -59t-38 -56.5t-17.5 -71q0 -57 42 -83.5t103 -26.5q64 0 180 15t163 17v-2q-1 -2 -3.5 -17.5t-5 -34t-3.5 -21.5q-24 -150 -24 -245q0 -80 35 -117 q44 -46 89 -46q22 0 50.5 15t53 33.5t64.5 33.5t83 15q82 0 127.5 -59t45.5 -143z" />
-<glyph unicode="&#xf130;" horiz-adv-x="1152" d="M1152 832v-128q0 -221 -147.5 -384.5t-364.5 -187.5v-132h256q26 0 45 -19t19 -45t-19 -45t-45 -19h-640q-26 0 -45 19t-19 45t19 45t45 19h256v132q-217 24 -364.5 187.5t-147.5 384.5v128q0 26 19 45t45 19t45 -19t19 -45v-128q0 -185 131.5 -316.5t316.5 -131.5 t316.5 131.5t131.5 316.5v128q0 26 19 45t45 19t45 -19t19 -45zM896 1216v-512q0 -132 -94 -226t-226 -94t-226 94t-94 226v512q0 132 94 226t226 94t226 -94t94 -226z" />
-<glyph unicode="&#xf131;" horiz-adv-x="1408" d="M271 591l-101 -101q-42 103 -42 214v128q0 26 19 45t45 19t45 -19t19 -45v-128q0 -53 15 -113zM1385 1193l-361 -361v-128q0 -132 -94 -226t-226 -94q-55 0 -109 19l-96 -96q97 -51 205 -51q185 0 316.5 131.5t131.5 316.5v128q0 26 19 45t45 19t45 -19t19 -45v-128 q0 -221 -147.5 -384.5t-364.5 -187.5v-132h256q26 0 45 -19t19 -45t-19 -45t-45 -19h-640q-26 0 -45 19t-19 45t19 45t45 19h256v132q-125 13 -235 81l-254 -254q-10 -10 -23 -10t-23 10l-82 82q-10 10 -10 23t10 23l1234 1234q10 10 23 10t23 -10l82 -82q10 -10 10 -23 t-10 -23zM1005 1325l-621 -621v512q0 132 94 226t226 94q102 0 184.5 -59t116.5 -152z" />
-<glyph unicode="&#xf132;" horiz-adv-x="1280" d="M1088 576v640h-448v-1137q119 63 213 137q235 184 235 360zM1280 1344v-768q0 -86 -33.5 -170.5t-83 -150t-118 -127.5t-126.5 -103t-121 -77.5t-89.5 -49.5t-42.5 -20q-12 -6 -26 -6t-26 6q-16 7 -42.5 20t-89.5 49.5t-121 77.5t-126.5 103t-118 127.5t-83 150 t-33.5 170.5v768q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" />
-<glyph unicode="&#xf133;" horiz-adv-x="1664" d="M128 -128h1408v1024h-1408v-1024zM512 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1280 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1664 1152v-1280 q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h384v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h128q52 0 90 -38t38 -90z" />
-<glyph unicode="&#xf134;" horiz-adv-x="1408" d="M512 1344q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 1376v-320q0 -16 -12 -25q-8 -7 -20 -7q-4 0 -7 1l-448 96q-11 2 -18 11t-7 20h-256v-102q111 -23 183.5 -111t72.5 -203v-800q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v800 q0 106 62.5 190.5t161.5 114.5v111h-32q-59 0 -115 -23.5t-91.5 -53t-66 -66.5t-40.5 -53.5t-14 -24.5q-17 -35 -57 -35q-16 0 -29 7q-23 12 -31.5 37t3.5 49q5 10 14.5 26t37.5 53.5t60.5 70t85 67t108.5 52.5q-25 42 -25 86q0 66 47 113t113 47t113 -47t47 -113 q0 -33 -14 -64h302q0 11 7 20t18 11l448 96q3 1 7 1q12 0 20 -7q12 -9 12 -25z" />
-<glyph unicode="&#xf135;" horiz-adv-x="1664" d="M1440 1088q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM1664 1376q0 -249 -75.5 -430.5t-253.5 -360.5q-81 -80 -195 -176l-20 -379q-2 -16 -16 -26l-384 -224q-7 -4 -16 -4q-12 0 -23 9l-64 64q-13 14 -8 32l85 276l-281 281l-276 -85q-3 -1 -9 -1 q-14 0 -23 9l-64 64q-17 19 -5 39l224 384q10 14 26 16l379 20q96 114 176 195q188 187 358 258t431 71q14 0 24 -9.5t10 -22.5z" />
-<glyph unicode="&#xf136;" horiz-adv-x="1792" d="M1745 763l-164 -763h-334l178 832q13 56 -15 88q-27 33 -83 33h-169l-204 -953h-334l204 953h-286l-204 -953h-334l204 953l-153 327h1276q101 0 189.5 -40.5t147.5 -113.5q60 -73 81 -168.5t0 -194.5z" />
-<glyph unicode="&#xf137;" d="M909 141l102 102q19 19 19 45t-19 45l-307 307l307 307q19 19 19 45t-19 45l-102 102q-19 19 -45 19t-45 -19l-454 -454q-19 -19 -19 -45t19 -45l454 -454q19 -19 45 -19t45 19zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5 t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
-<glyph unicode="&#xf138;" d="M717 141l454 454q19 19 19 45t-19 45l-454 454q-19 19 -45 19t-45 -19l-102 -102q-19 -19 -19 -45t19 -45l307 -307l-307 -307q-19 -19 -19 -45t19 -45l102 -102q19 -19 45 -19t45 19zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5 t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
-<glyph unicode="&#xf139;" d="M1165 397l102 102q19 19 19 45t-19 45l-454 454q-19 19 -45 19t-45 -19l-454 -454q-19 -19 -19 -45t19 -45l102 -102q19 -19 45 -19t45 19l307 307l307 -307q19 -19 45 -19t45 19zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5 t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
-<glyph unicode="&#xf13a;" d="M813 237l454 454q19 19 19 45t-19 45l-102 102q-19 19 -45 19t-45 -19l-307 -307l-307 307q-19 19 -45 19t-45 -19l-102 -102q-19 -19 -19 -45t19 -45l454 -454q19 -19 45 -19t45 19zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5 t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
-<glyph unicode="&#xf13b;" horiz-adv-x="1408" d="M1130 939l16 175h-884l47 -534h612l-22 -228l-197 -53l-196 53l-13 140h-175l22 -278l362 -100h4v1l359 99l50 544h-644l-15 181h674zM0 1408h1408l-128 -1438l-578 -162l-574 162z" />
-<glyph unicode="&#xf13c;" horiz-adv-x="1792" d="M275 1408h1505l-266 -1333l-804 -267l-698 267l71 356h297l-29 -147l422 -161l486 161l68 339h-1208l58 297h1209l38 191h-1208z" />
-<glyph unicode="&#xf13d;" horiz-adv-x="1792" d="M960 1280q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1792 352v-352q0 -22 -20 -30q-8 -2 -12 -2q-13 0 -23 9l-93 93q-119 -143 -318.5 -226.5t-429.5 -83.5t-429.5 83.5t-318.5 226.5l-93 -93q-9 -9 -23 -9q-4 0 -12 2q-20 8 -20 30v352 q0 14 9 23t23 9h352q22 0 30 -20q8 -19 -7 -35l-100 -100q67 -91 189.5 -153.5t271.5 -82.5v647h-192q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h192v163q-58 34 -93 92.5t-35 128.5q0 106 75 181t181 75t181 -75t75 -181q0 -70 -35 -128.5t-93 -92.5v-163h192q26 0 45 -19 t19 -45v-128q0 -26 -19 -45t-45 -19h-192v-647q149 20 271.5 82.5t189.5 153.5l-100 100q-15 16 -7 35q8 20 30 20h352q14 0 23 -9t9 -23z" />
-<glyph unicode="&#xf13e;" horiz-adv-x="1152" d="M1056 768q40 0 68 -28t28 -68v-576q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v576q0 40 28 68t68 28h32v320q0 185 131.5 316.5t316.5 131.5t316.5 -131.5t131.5 -316.5q0 -26 -19 -45t-45 -19h-64q-26 0 -45 19t-19 45q0 106 -75 181t-181 75t-181 -75t-75 -181 v-320h736z" />
-<glyph unicode="&#xf140;" d="M1024 640q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75t75 -181zM1152 640q0 159 -112.5 271.5t-271.5 112.5t-271.5 -112.5t-112.5 -271.5t112.5 -271.5t271.5 -112.5t271.5 112.5t112.5 271.5zM1280 640q0 -212 -150 -362t-362 -150t-362 150 t-150 362t150 362t362 150t362 -150t150 -362zM1408 640q0 130 -51 248.5t-136.5 204t-204 136.5t-248.5 51t-248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
-<glyph unicode="&#xf141;" horiz-adv-x="1408" d="M384 800v-192q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68zM896 800v-192q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68zM1408 800v-192q0 -40 -28 -68t-68 -28h-192 q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68z" />
-<glyph unicode="&#xf142;" horiz-adv-x="384" d="M384 288v-192q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68zM384 800v-192q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68zM384 1312v-192q0 -40 -28 -68t-68 -28h-192 q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68z" />
-<glyph unicode="&#xf143;" d="M512 256q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM863 162q-13 232 -177 396t-396 177q-14 1 -24 -9t-10 -23v-128q0 -13 8.5 -22t21.5 -10q154 -11 264 -121t121 -264q1 -13 10 -21.5t22 -8.5h128q13 0 23 10 t9 24zM1247 161q-5 154 -56 297.5t-139.5 260t-205 205t-260 139.5t-297.5 56q-14 1 -23 -9q-10 -10 -10 -23v-128q0 -13 9 -22t22 -10q204 -7 378 -111.5t278.5 -278.5t111.5 -378q1 -13 10 -22t22 -9h128q13 0 23 10q11 9 9 23zM1536 1120v-960q0 -119 -84.5 -203.5 t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
-<glyph unicode="&#xf144;" d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM1152 585q32 18 32 55t-32 55l-544 320q-31 19 -64 1q-32 -19 -32 -56v-640q0 -37 32 -56 q16 -8 32 -8q17 0 32 9z" />
-<glyph unicode="&#xf145;" horiz-adv-x="1792" d="M1024 1084l316 -316l-572 -572l-316 316zM813 105l618 618q19 19 19 45t-19 45l-362 362q-18 18 -45 18t-45 -18l-618 -618q-19 -19 -19 -45t19 -45l362 -362q18 -18 45 -18t45 18zM1702 742l-907 -908q-37 -37 -90.5 -37t-90.5 37l-126 126q56 56 56 136t-56 136 t-136 56t-136 -56l-125 126q-37 37 -37 90.5t37 90.5l907 906q37 37 90.5 37t90.5 -37l125 -125q-56 -56 -56 -136t56 -136t136 -56t136 56l126 -125q37 -37 37 -90.5t-37 -90.5z" />
-<glyph unicode="&#xf146;" d="M1280 576v128q0 26 -19 45t-45 19h-896q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h896q26 0 45 19t19 45zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5 t84.5 -203.5z" />
-<glyph unicode="&#xf147;" horiz-adv-x="1408" d="M1152 736v-64q0 -14 -9 -23t-23 -9h-832q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h832q14 0 23 -9t9 -23zM1280 288v832q0 66 -47 113t-113 47h-832q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113zM1408 1120v-832q0 -119 -84.5 -203.5 t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832q119 0 203.5 -84.5t84.5 -203.5z" />
-<glyph unicode="&#xf148;" horiz-adv-x="1024" d="M1018 933q-18 -37 -58 -37h-192v-864q0 -14 -9 -23t-23 -9h-704q-21 0 -29 18q-8 20 4 35l160 192q9 11 25 11h320v640h-192q-40 0 -58 37q-17 37 9 68l320 384q18 22 49 22t49 -22l320 -384q27 -32 9 -68z" />
-<glyph unicode="&#xf149;" horiz-adv-x="1024" d="M32 1280h704q13 0 22.5 -9.5t9.5 -23.5v-863h192q40 0 58 -37t-9 -69l-320 -384q-18 -22 -49 -22t-49 22l-320 384q-26 31 -9 69q18 37 58 37h192v640h-320q-14 0 -25 11l-160 192q-13 14 -4 34q9 19 29 19z" />
-<glyph unicode="&#xf14a;" d="M685 237l614 614q19 19 19 45t-19 45l-102 102q-19 19 -45 19t-45 -19l-467 -467l-211 211q-19 19 -45 19t-45 -19l-102 -102q-19 -19 -19 -45t19 -45l358 -358q19 -19 45 -19t45 19zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5 t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
-<glyph unicode="&#xf14b;" d="M404 428l152 -152l-52 -52h-56v96h-96v56zM818 818q14 -13 -3 -30l-291 -291q-17 -17 -30 -3q-14 13 3 30l291 291q17 17 30 3zM544 128l544 544l-288 288l-544 -544v-288h288zM1152 736l92 92q28 28 28 68t-28 68l-152 152q-28 28 -68 28t-68 -28l-92 -92zM1536 1120 v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
-<glyph unicode="&#xf14c;" d="M1280 608v480q0 26 -19 45t-45 19h-480q-42 0 -59 -39q-17 -41 14 -70l144 -144l-534 -534q-19 -19 -19 -45t19 -45l102 -102q19 -19 45 -19t45 19l534 534l144 -144q18 -19 45 -19q12 0 25 5q39 17 39 59zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960 q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
-<glyph unicode="&#xf14d;" d="M1005 435l352 352q19 19 19 45t-19 45l-352 352q-30 31 -69 14q-40 -17 -40 -59v-160q-119 0 -216 -19.5t-162.5 -51t-114 -79t-76.5 -95.5t-44.5 -109t-21.5 -111.5t-5 -110.5q0 -181 167 -404q10 -12 25 -12q7 0 13 3q22 9 19 33q-44 354 62 473q46 52 130 75.5 t224 23.5v-160q0 -42 40 -59q12 -5 24 -5q26 0 45 19zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
-<glyph unicode="&#xf14e;" d="M640 448l256 128l-256 128v-256zM1024 1039v-542l-512 -256v542zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103 t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
-<glyph unicode="&#xf150;" d="M1145 861q18 -35 -5 -66l-320 -448q-19 -27 -52 -27t-52 27l-320 448q-23 31 -5 66q17 35 57 35h640q40 0 57 -35zM1280 160v960q0 13 -9.5 22.5t-22.5 9.5h-960q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h960q13 0 22.5 9.5t9.5 22.5zM1536 1120 v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
-<glyph unicode="&#xf151;" d="M1145 419q-17 -35 -57 -35h-640q-40 0 -57 35q-18 35 5 66l320 448q19 27 52 27t52 -27l320 -448q23 -31 5 -66zM1280 160v960q0 13 -9.5 22.5t-22.5 9.5h-960q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h960q13 0 22.5 9.5t9.5 22.5zM1536 1120v-960 q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
-<glyph unicode="&#xf152;" d="M1088 640q0 -33 -27 -52l-448 -320q-31 -23 -66 -5q-35 17 -35 57v640q0 40 35 57q35 18 66 -5l448 -320q27 -19 27 -52zM1280 160v960q0 14 -9 23t-23 9h-960q-14 0 -23 -9t-9 -23v-960q0 -14 9 -23t23 -9h960q14 0 23 9t9 23zM1536 1120v-960q0 -119 -84.5 -203.5 t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
-<glyph unicode="&#xf153;" horiz-adv-x="1024" d="M976 229l35 -159q3 -12 -3 -22.5t-17 -14.5l-5 -1q-4 -2 -10.5 -3.5t-16 -4.5t-21.5 -5.5t-25.5 -5t-30 -5t-33.5 -4.5t-36.5 -3t-38.5 -1q-234 0 -409 130.5t-238 351.5h-95q-13 0 -22.5 9.5t-9.5 22.5v113q0 13 9.5 22.5t22.5 9.5h66q-2 57 1 105h-67q-14 0 -23 9 t-9 23v114q0 14 9 23t23 9h98q67 210 243.5 338t400.5 128q102 0 194 -23q11 -3 20 -15q6 -11 3 -24l-43 -159q-3 -13 -14 -19.5t-24 -2.5l-4 1q-4 1 -11.5 2.5l-17.5 3.5t-22.5 3.5t-26 3t-29 2.5t-29.5 1q-126 0 -226 -64t-150 -176h468q16 0 25 -12q10 -12 7 -26 l-24 -114q-5 -26 -32 -26h-488q-3 -37 0 -105h459q15 0 25 -12q9 -12 6 -27l-24 -112q-2 -11 -11 -18.5t-20 -7.5h-387q48 -117 149.5 -185.5t228.5 -68.5q18 0 36 1.5t33.5 3.5t29.5 4.5t24.5 5t18.5 4.5l12 3l5 2q13 5 26 -2q12 -7 15 -21z" />
-<glyph unicode="&#xf154;" horiz-adv-x="1024" d="M1020 399v-367q0 -14 -9 -23t-23 -9h-956q-14 0 -23 9t-9 23v150q0 13 9.5 22.5t22.5 9.5h97v383h-95q-14 0 -23 9.5t-9 22.5v131q0 14 9 23t23 9h95v223q0 171 123.5 282t314.5 111q185 0 335 -125q9 -8 10 -20.5t-7 -22.5l-103 -127q-9 -11 -22 -12q-13 -2 -23 7 q-5 5 -26 19t-69 32t-93 18q-85 0 -137 -47t-52 -123v-215h305q13 0 22.5 -9t9.5 -23v-131q0 -13 -9.5 -22.5t-22.5 -9.5h-305v-379h414v181q0 13 9 22.5t23 9.5h162q14 0 23 -9.5t9 -22.5z" />
-<glyph unicode="&#xf155;" horiz-adv-x="1024" d="M978 351q0 -153 -99.5 -263.5t-258.5 -136.5v-175q0 -14 -9 -23t-23 -9h-135q-13 0 -22.5 9.5t-9.5 22.5v175q-66 9 -127.5 31t-101.5 44.5t-74 48t-46.5 37.5t-17.5 18q-17 21 -2 41l103 135q7 10 23 12q15 2 24 -9l2 -2q113 -99 243 -125q37 -8 74 -8q81 0 142.5 43 t61.5 122q0 28 -15 53t-33.5 42t-58.5 37.5t-66 32t-80 32.5q-39 16 -61.5 25t-61.5 26.5t-62.5 31t-56.5 35.5t-53.5 42.5t-43.5 49t-35.5 58t-21 66.5t-8.5 78q0 138 98 242t255 134v180q0 13 9.5 22.5t22.5 9.5h135q14 0 23 -9t9 -23v-176q57 -6 110.5 -23t87 -33.5 t63.5 -37.5t39 -29t15 -14q17 -18 5 -38l-81 -146q-8 -15 -23 -16q-14 -3 -27 7q-3 3 -14.5 12t-39 26.5t-58.5 32t-74.5 26t-85.5 11.5q-95 0 -155 -43t-60 -111q0 -26 8.5 -48t29.5 -41.5t39.5 -33t56 -31t60.5 -27t70 -27.5q53 -20 81 -31.5t76 -35t75.5 -42.5t62 -50 t53 -63.5t31.5 -76.5t13 -94z" />
-<glyph unicode="&#xf156;" horiz-adv-x="898" d="M898 1066v-102q0 -14 -9 -23t-23 -9h-168q-23 -144 -129 -234t-276 -110q167 -178 459 -536q14 -16 4 -34q-8 -18 -29 -18h-195q-16 0 -25 12q-306 367 -498 571q-9 9 -9 22v127q0 13 9.5 22.5t22.5 9.5h112q132 0 212.5 43t102.5 125h-427q-14 0 -23 9t-9 23v102 q0 14 9 23t23 9h413q-57 113 -268 113h-145q-13 0 -22.5 9.5t-9.5 22.5v133q0 14 9 23t23 9h832q14 0 23 -9t9 -23v-102q0 -14 -9 -23t-23 -9h-233q47 -61 64 -144h171q14 0 23 -9t9 -23z" />
-<glyph unicode="&#xf157;" horiz-adv-x="1027" d="M603 0h-172q-13 0 -22.5 9t-9.5 23v330h-288q-13 0 -22.5 9t-9.5 23v103q0 13 9.5 22.5t22.5 9.5h288v85h-288q-13 0 -22.5 9t-9.5 23v104q0 13 9.5 22.5t22.5 9.5h214l-321 578q-8 16 0 32q10 16 28 16h194q19 0 29 -18l215 -425q19 -38 56 -125q10 24 30.5 68t27.5 61 l191 420q8 19 29 19h191q17 0 27 -16q9 -14 1 -31l-313 -579h215q13 0 22.5 -9.5t9.5 -22.5v-104q0 -14 -9.5 -23t-22.5 -9h-290v-85h290q13 0 22.5 -9.5t9.5 -22.5v-103q0 -14 -9.5 -23t-22.5 -9h-290v-330q0 -13 -9.5 -22.5t-22.5 -9.5z" />
-<glyph unicode="&#xf158;" horiz-adv-x="1280" d="M1043 971q0 100 -65 162t-171 62h-320v-448h320q106 0 171 62t65 162zM1280 971q0 -193 -126.5 -315t-326.5 -122h-340v-118h505q14 0 23 -9t9 -23v-128q0 -14 -9 -23t-23 -9h-505v-192q0 -14 -9.5 -23t-22.5 -9h-167q-14 0 -23 9t-9 23v192h-224q-14 0 -23 9t-9 23v128 q0 14 9 23t23 9h224v118h-224q-14 0 -23 9t-9 23v149q0 13 9 22.5t23 9.5h224v629q0 14 9 23t23 9h539q200 0 326.5 -122t126.5 -315z" />
-<glyph unicode="&#xf159;" horiz-adv-x="1792" d="M514 341l81 299h-159l75 -300q1 -1 1 -3t1 -3q0 1 0.5 3.5t0.5 3.5zM630 768l35 128h-292l32 -128h225zM822 768h139l-35 128h-70zM1271 340l78 300h-162l81 -299q0 -1 0.5 -3.5t1.5 -3.5q0 1 0.5 3t0.5 3zM1382 768l33 128h-297l34 -128h230zM1792 736v-64q0 -14 -9 -23 t-23 -9h-213l-164 -616q-7 -24 -31 -24h-159q-24 0 -31 24l-166 616h-209l-167 -616q-7 -24 -31 -24h-159q-11 0 -19.5 7t-10.5 17l-160 616h-208q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h175l-33 128h-142q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h109l-89 344q-5 15 5 28 q10 12 26 12h137q26 0 31 -24l90 -360h359l97 360q7 24 31 24h126q24 0 31 -24l98 -360h365l93 360q5 24 31 24h137q16 0 26 -12q10 -13 5 -28l-91 -344h111q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-145l-34 -128h179q14 0 23 -9t9 -23z" />
-<glyph unicode="&#xf15a;" horiz-adv-x="1280" d="M1167 896q18 -182 -131 -258q117 -28 175 -103t45 -214q-7 -71 -32.5 -125t-64.5 -89t-97 -58.5t-121.5 -34.5t-145.5 -15v-255h-154v251q-80 0 -122 1v-252h-154v255q-18 0 -54 0.5t-55 0.5h-200l31 183h111q50 0 58 51v402h16q-6 1 -16 1v287q-13 68 -89 68h-111v164 l212 -1q64 0 97 1v252h154v-247q82 2 122 2v245h154v-252q79 -7 140 -22.5t113 -45t82.5 -78t36.5 -114.5zM952 351q0 36 -15 64t-37 46t-57.5 30.5t-65.5 18.5t-74 9t-69 3t-64.5 -1t-47.5 -1v-338q8 0 37 -0.5t48 -0.5t53 1.5t58.5 4t57 8.5t55.5 14t47.5 21t39.5 30 t24.5 40t9.5 51zM881 827q0 33 -12.5 58.5t-30.5 42t-48 28t-55 16.5t-61.5 8t-58 2.5t-54 -1t-39.5 -0.5v-307q5 0 34.5 -0.5t46.5 0t50 2t55 5.5t51.5 11t48.5 18.5t37 27t27 38.5t9 51z" />
-<glyph unicode="&#xf15b;" d="M1024 1024v472q22 -14 36 -28l408 -408q14 -14 28 -36h-472zM896 992q0 -40 28 -68t68 -28h544v-1056q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h800v-544z" />
-<glyph unicode="&#xf15c;" d="M1468 1060q14 -14 28 -36h-472v472q22 -14 36 -28zM992 896h544v-1056q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h800v-544q0 -40 28 -68t68 -28zM1152 160v64q0 14 -9 23t-23 9h-704q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h704 q14 0 23 9t9 23zM1152 416v64q0 14 -9 23t-23 9h-704q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h704q14 0 23 9t9 23zM1152 672v64q0 14 -9 23t-23 9h-704q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h704q14 0 23 9t9 23z" />
-<glyph unicode="&#xf15d;" horiz-adv-x="1664" d="M1191 1128h177l-72 218l-12 47q-2 16 -2 20h-4l-3 -20q0 -1 -3.5 -18t-7.5 -29zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9t9 -23zM1572 -23 v-233h-584v90l369 529q12 18 21 27l11 9v3q-2 0 -6.5 -0.5t-7.5 -0.5q-12 -3 -30 -3h-232v-115h-120v229h567v-89l-369 -530q-6 -8 -21 -26l-11 -11v-2l14 2q9 2 30 2h248v119h121zM1661 874v-106h-288v106h75l-47 144h-243l-47 -144h75v-106h-287v106h70l230 662h162 l230 -662h70z" />
-<glyph unicode="&#xf15e;" horiz-adv-x="1664" d="M1191 104h177l-72 218l-12 47q-2 16 -2 20h-4l-3 -20q0 -1 -3.5 -18t-7.5 -29zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9t9 -23zM1661 -150 v-106h-288v106h75l-47 144h-243l-47 -144h75v-106h-287v106h70l230 662h162l230 -662h70zM1572 1001v-233h-584v90l369 529q12 18 21 27l11 9v3q-2 0 -6.5 -0.5t-7.5 -0.5q-12 -3 -30 -3h-232v-115h-120v229h567v-89l-369 -530q-6 -8 -21 -26l-11 -10v-3l14 3q9 1 30 1h248 v119h121z" />
-<glyph unicode="&#xf160;" horiz-adv-x="1792" d="M736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9t9 -23zM1792 -32v-192q0 -14 -9 -23t-23 -9h-832q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h832 q14 0 23 -9t9 -23zM1600 480v-192q0 -14 -9 -23t-23 -9h-640q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h640q14 0 23 -9t9 -23zM1408 992v-192q0 -14 -9 -23t-23 -9h-448q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h448q14 0 23 -9t9 -23zM1216 1504v-192q0 -14 -9 -23t-23 -9h-256 q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h256q14 0 23 -9t9 -23z" />
-<glyph unicode="&#xf161;" horiz-adv-x="1792" d="M1216 -32v-192q0 -14 -9 -23t-23 -9h-256q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h256q14 0 23 -9t9 -23zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192 q14 0 23 -9t9 -23zM1408 480v-192q0 -14 -9 -23t-23 -9h-448q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h448q14 0 23 -9t9 -23zM1600 992v-192q0 -14 -9 -23t-23 -9h-640q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h640q14 0 23 -9t9 -23zM1792 1504v-192q0 -14 -9 -23t-23 -9h-832 q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h832q14 0 23 -9t9 -23z" />
-<glyph unicode="&#xf162;" d="M1346 223q0 63 -44 116t-103 53q-52 0 -83 -37t-31 -94t36.5 -95t104.5 -38q50 0 85 27t35 68zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9t9 -23 zM1486 165q0 -62 -13 -121.5t-41 -114t-68 -95.5t-98.5 -65.5t-127.5 -24.5q-62 0 -108 16q-24 8 -42 15l39 113q15 -7 31 -11q37 -13 75 -13q84 0 134.5 58.5t66.5 145.5h-2q-21 -23 -61.5 -37t-84.5 -14q-106 0 -173 71.5t-67 172.5q0 105 72 178t181 73q123 0 205 -94.5 t82 -252.5zM1456 882v-114h-469v114h167v432q0 7 0.5 19t0.5 17v16h-2l-7 -12q-8 -13 -26 -31l-62 -58l-82 86l192 185h123v-654h165z" />
-<glyph unicode="&#xf163;" d="M1346 1247q0 63 -44 116t-103 53q-52 0 -83 -37t-31 -94t36.5 -95t104.5 -38q50 0 85 27t35 68zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9 t9 -23zM1456 -142v-114h-469v114h167v432q0 7 0.5 19t0.5 17v16h-2l-7 -12q-8 -13 -26 -31l-62 -58l-82 86l192 185h123v-654h165zM1486 1189q0 -62 -13 -121.5t-41 -114t-68 -95.5t-98.5 -65.5t-127.5 -24.5q-62 0 -108 16q-24 8 -42 15l39 113q15 -7 31 -11q37 -13 75 -13 q84 0 134.5 58.5t66.5 145.5h-2q-21 -23 -61.5 -37t-84.5 -14q-106 0 -173 71.5t-67 172.5q0 105 72 178t181 73q123 0 205 -94.5t82 -252.5z" />
-<glyph unicode="&#xf164;" horiz-adv-x="1664" d="M256 192q0 26 -19 45t-45 19q-27 0 -45.5 -19t-18.5 -45q0 -27 18.5 -45.5t45.5 -18.5q26 0 45 18.5t19 45.5zM416 704v-640q0 -26 -19 -45t-45 -19h-288q-26 0 -45 19t-19 45v640q0 26 19 45t45 19h288q26 0 45 -19t19 -45zM1600 704q0 -86 -55 -149q15 -44 15 -76 q3 -76 -43 -137q17 -56 0 -117q-15 -57 -54 -94q9 -112 -49 -181q-64 -76 -197 -78h-36h-76h-17q-66 0 -144 15.5t-121.5 29t-120.5 39.5q-123 43 -158 44q-26 1 -45 19.5t-19 44.5v641q0 25 18 43.5t43 20.5q24 2 76 59t101 121q68 87 101 120q18 18 31 48t17.5 48.5 t13.5 60.5q7 39 12.5 61t19.5 52t34 50q19 19 45 19q46 0 82.5 -10.5t60 -26t40 -40.5t24 -45t12 -50t5 -45t0.5 -39q0 -38 -9.5 -76t-19 -60t-27.5 -56q-3 -6 -10 -18t-11 -22t-8 -24h277q78 0 135 -57t57 -135z" />
-<glyph unicode="&#xf165;" horiz-adv-x="1664" d="M256 960q0 -26 -19 -45t-45 -19q-27 0 -45.5 19t-18.5 45q0 27 18.5 45.5t45.5 18.5q26 0 45 -18.5t19 -45.5zM416 448v640q0 26 -19 45t-45 19h-288q-26 0 -45 -19t-19 -45v-640q0 -26 19 -45t45 -19h288q26 0 45 19t19 45zM1545 597q55 -61 55 -149q-1 -78 -57.5 -135 t-134.5 -57h-277q4 -14 8 -24t11 -22t10 -18q18 -37 27 -57t19 -58.5t10 -76.5q0 -24 -0.5 -39t-5 -45t-12 -50t-24 -45t-40 -40.5t-60 -26t-82.5 -10.5q-26 0 -45 19q-20 20 -34 50t-19.5 52t-12.5 61q-9 42 -13.5 60.5t-17.5 48.5t-31 48q-33 33 -101 120q-49 64 -101 121 t-76 59q-25 2 -43 20.5t-18 43.5v641q0 26 19 44.5t45 19.5q35 1 158 44q77 26 120.5 39.5t121.5 29t144 15.5h17h76h36q133 -2 197 -78q58 -69 49 -181q39 -37 54 -94q17 -61 0 -117q46 -61 43 -137q0 -32 -15 -76z" />
-<glyph unicode="&#xf166;" d="M919 233v157q0 50 -29 50q-17 0 -33 -16v-224q16 -16 33 -16q29 0 29 49zM1103 355h66v34q0 51 -33 51t-33 -51v-34zM532 621v-70h-80v-423h-74v423h-78v70h232zM733 495v-367h-67v40q-39 -45 -76 -45q-33 0 -42 28q-6 16 -6 54v290h66v-270q0 -24 1 -26q1 -15 15 -15 q20 0 42 31v280h67zM985 384v-146q0 -52 -7 -73q-12 -42 -53 -42q-35 0 -68 41v-36h-67v493h67v-161q32 40 68 40q41 0 53 -42q7 -21 7 -74zM1236 255v-9q0 -29 -2 -43q-3 -22 -15 -40q-27 -40 -80 -40q-52 0 -81 38q-21 27 -21 86v129q0 59 20 86q29 38 80 38t78 -38 q21 -28 21 -86v-76h-133v-65q0 -51 34 -51q24 0 30 26q0 1 0.5 7t0.5 16.5v21.5h68zM785 1079v-156q0 -51 -32 -51t-32 51v156q0 52 32 52t32 -52zM1318 366q0 177 -19 260q-10 44 -43 73.5t-76 34.5q-136 15 -412 15q-275 0 -411 -15q-44 -5 -76.5 -34.5t-42.5 -73.5 q-20 -87 -20 -260q0 -176 20 -260q10 -43 42.5 -73t75.5 -35q137 -15 412 -15t412 15q43 5 75.5 35t42.5 73q20 84 20 260zM563 1017l90 296h-75l-51 -195l-53 195h-78l24 -69t23 -69q35 -103 46 -158v-201h74v201zM852 936v130q0 58 -21 87q-29 38 -78 38q-51 0 -78 -38 q-21 -29 -21 -87v-130q0 -58 21 -87q27 -38 78 -38q49 0 78 38q21 27 21 87zM1033 816h67v370h-67v-283q-22 -31 -42 -31q-15 0 -16 16q-1 2 -1 26v272h-67v-293q0 -37 6 -55q11 -27 43 -27q36 0 77 45v-40zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960 q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
-<glyph unicode="&#xf167;" d="M971 292v-211q0 -67 -39 -67q-23 0 -45 22v301q22 22 45 22q39 0 39 -67zM1309 291v-46h-90v46q0 68 45 68t45 -68zM343 509h107v94h-312v-94h105v-569h100v569zM631 -60h89v494h-89v-378q-30 -42 -57 -42q-18 0 -21 21q-1 3 -1 35v364h-89v-391q0 -49 8 -73 q12 -37 58 -37q48 0 102 61v-54zM1060 88v197q0 73 -9 99q-17 56 -71 56q-50 0 -93 -54v217h-89v-663h89v48q45 -55 93 -55q54 0 71 55q9 27 9 100zM1398 98v13h-91q0 -51 -2 -61q-7 -36 -40 -36q-46 0 -46 69v87h179v103q0 79 -27 116q-39 51 -106 51q-68 0 -107 -51 q-28 -37 -28 -116v-173q0 -79 29 -116q39 -51 108 -51q72 0 108 53q18 27 21 54q2 9 2 58zM790 1011v210q0 69 -43 69t-43 -69v-210q0 -70 43 -70t43 70zM1509 260q0 -234 -26 -350q-14 -59 -58 -99t-102 -46q-184 -21 -555 -21t-555 21q-58 6 -102.5 46t-57.5 99 q-26 112 -26 350q0 234 26 350q14 59 58 99t103 47q183 20 554 20t555 -20q58 -7 102.5 -47t57.5 -99q26 -112 26 -350zM511 1536h102l-121 -399v-271h-100v271q-14 74 -61 212q-37 103 -65 187h106l71 -263zM881 1203v-175q0 -81 -28 -118q-37 -51 -106 -51q-67 0 -105 51 q-28 38 -28 118v175q0 80 28 117q38 51 105 51q69 0 106 -51q28 -37 28 -117zM1216 1365v-499h-91v55q-53 -62 -103 -62q-46 0 -59 37q-8 24 -8 75v394h91v-367q0 -33 1 -35q3 -22 21 -22q27 0 57 43v381h91z" />
-<glyph unicode="&#xf168;" horiz-adv-x="1408" d="M597 869q-10 -18 -257 -456q-27 -46 -65 -46h-239q-21 0 -31 17t0 36l253 448q1 0 0 1l-161 279q-12 22 -1 37q9 15 32 15h239q40 0 66 -45zM1403 1511q11 -16 0 -37l-528 -934v-1l336 -615q11 -20 1 -37q-10 -15 -32 -15h-239q-42 0 -66 45l-339 622q18 32 531 942 q25 45 64 45h241q22 0 31 -15z" />
-<glyph unicode="&#xf169;" d="M685 771q0 1 -126 222q-21 34 -52 34h-184q-18 0 -26 -11q-7 -12 1 -29l125 -216v-1l-196 -346q-9 -14 0 -28q8 -13 24 -13h185q31 0 50 36zM1309 1268q-7 12 -24 12h-187q-30 0 -49 -35l-411 -729q1 -2 262 -481q20 -35 52 -35h184q18 0 25 12q8 13 -1 28l-260 476v1 l409 723q8 16 0 28zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
-<glyph unicode="&#xf16a;" horiz-adv-x="1792" d="M1280 640q0 37 -30 54l-512 320q-31 20 -65 2q-33 -18 -33 -56v-640q0 -38 33 -56q16 -8 31 -8q20 0 34 10l512 320q30 17 30 54zM1792 640q0 -96 -1 -150t-8.5 -136.5t-22.5 -147.5q-16 -73 -69 -123t-124 -58q-222 -25 -671 -25t-671 25q-71 8 -124.5 58t-69.5 123 q-14 65 -21.5 147.5t-8.5 136.5t-1 150t1 150t8.5 136.5t22.5 147.5q16 73 69 123t124 58q222 25 671 25t671 -25q71 -8 124.5 -58t69.5 -123q14 -65 21.5 -147.5t8.5 -136.5t1 -150z" />
-<glyph unicode="&#xf16b;" horiz-adv-x="1792" d="M402 829l494 -305l-342 -285l-490 319zM1388 274v-108l-490 -293v-1l-1 1l-1 -1v1l-489 293v108l147 -96l342 284v2l1 -1l1 1v-2l343 -284zM554 1418l342 -285l-494 -304l-338 270zM1390 829l338 -271l-489 -319l-343 285zM1239 1418l489 -319l-338 -270l-494 304z" />
-<glyph unicode="&#xf16c;" d="M1289 -96h-1118v480h-160v-640h1438v640h-160v-480zM347 428l33 157l783 -165l-33 -156zM450 802l67 146l725 -339l-67 -145zM651 1158l102 123l614 -513l-102 -123zM1048 1536l477 -641l-128 -96l-477 641zM330 65v159h800v-159h-800z" />
-<glyph unicode="&#xf16d;" d="M1024 640q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM1162 640q0 -164 -115 -279t-279 -115t-279 115t-115 279t115 279t279 115t279 -115t115 -279zM1270 1050q0 -38 -27 -65t-65 -27t-65 27t-27 65t27 65t65 27t65 -27t27 -65zM768 1270 q-7 0 -76.5 0.5t-105.5 0t-96.5 -3t-103 -10t-71.5 -18.5q-50 -20 -88 -58t-58 -88q-11 -29 -18.5 -71.5t-10 -103t-3 -96.5t0 -105.5t0.5 -76.5t-0.5 -76.5t0 -105.5t3 -96.5t10 -103t18.5 -71.5q20 -50 58 -88t88 -58q29 -11 71.5 -18.5t103 -10t96.5 -3t105.5 0t76.5 0.5 t76.5 -0.5t105.5 0t96.5 3t103 10t71.5 18.5q50 20 88 58t58 88q11 29 18.5 71.5t10 103t3 96.5t0 105.5t-0.5 76.5t0.5 76.5t0 105.5t-3 96.5t-10 103t-18.5 71.5q-20 50 -58 88t-88 58q-29 11 -71.5 18.5t-103 10t-96.5 3t-105.5 0t-76.5 -0.5zM1536 640q0 -229 -5 -317 q-10 -208 -124 -322t-322 -124q-88 -5 -317 -5t-317 5q-208 10 -322 124t-124 322q-5 88 -5 317t5 317q10 208 124 322t322 124q88 5 317 5t317 -5q208 -10 322 -124t124 -322q5 -88 5 -317z" />
-<glyph unicode="&#xf16e;" d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960zM698 640q0 88 -62 150t-150 62t-150 -62t-62 -150t62 -150t150 -62t150 62t62 150zM1262 640q0 88 -62 150 t-150 62t-150 -62t-62 -150t62 -150t150 -62t150 62t62 150z" />
-<glyph unicode="&#xf170;" d="M768 914l201 -306h-402zM1133 384h94l-459 691l-459 -691h94l104 160h522zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
-<glyph unicode="&#xf171;" horiz-adv-x="1408" d="M815 677q8 -63 -50.5 -101t-111.5 -6q-39 17 -53.5 58t-0.5 82t52 58q36 18 72.5 12t64 -35.5t27.5 -67.5zM926 698q-14 107 -113 164t-197 13q-63 -28 -100.5 -88.5t-34.5 -129.5q4 -91 77.5 -155t165.5 -56q91 8 152 84t50 168zM1165 1240q-20 27 -56 44.5t-58 22 t-71 12.5q-291 47 -566 -2q-43 -7 -66 -12t-55 -22t-50 -43q30 -28 76 -45.5t73.5 -22t87.5 -11.5q228 -29 448 -1q63 8 89.5 12t72.5 21.5t75 46.5zM1222 205q-8 -26 -15.5 -76.5t-14 -84t-28.5 -70t-58 -56.5q-86 -48 -189.5 -71.5t-202 -22t-201.5 18.5q-46 8 -81.5 18 t-76.5 27t-73 43.5t-52 61.5q-25 96 -57 292l6 16l18 9q223 -148 506.5 -148t507.5 148q21 -6 24 -23t-5 -45t-8 -37zM1403 1166q-26 -167 -111 -655q-5 -30 -27 -56t-43.5 -40t-54.5 -31q-252 -126 -610 -88q-248 27 -394 139q-15 12 -25.5 26.5t-17 35t-9 34t-6 39.5 t-5.5 35q-9 50 -26.5 150t-28 161.5t-23.5 147.5t-22 158q3 26 17.5 48.5t31.5 37.5t45 30t46 22.5t48 18.5q125 46 313 64q379 37 676 -50q155 -46 215 -122q16 -20 16.5 -51t-5.5 -54z" />
-<glyph unicode="&#xf172;" d="M848 666q0 43 -41 66t-77 1q-43 -20 -42.5 -72.5t43.5 -70.5q39 -23 81 4t36 72zM928 682q8 -66 -36 -121t-110 -61t-119 40t-56 113q-2 49 25.5 93t72.5 64q70 31 141.5 -10t81.5 -118zM1100 1073q-20 -21 -53.5 -34t-53 -16t-63.5 -8q-155 -20 -324 0q-44 6 -63 9.5 t-52.5 16t-54.5 32.5q13 19 36 31t40 15.5t47 8.5q198 35 408 1q33 -5 51 -8.5t43 -16t39 -31.5zM1142 327q0 7 5.5 26.5t3 32t-17.5 16.5q-161 -106 -365 -106t-366 106l-12 -6l-5 -12q26 -154 41 -210q47 -81 204 -108q249 -46 428 53q34 19 49 51.5t22.5 85.5t12.5 71z M1272 1020q9 53 -8 75q-43 55 -155 88q-216 63 -487 36q-132 -12 -226 -46q-38 -15 -59.5 -25t-47 -34t-29.5 -54q8 -68 19 -138t29 -171t24 -137q1 -5 5 -31t7 -36t12 -27t22 -28q105 -80 284 -100q259 -28 440 63q24 13 39.5 23t31 29t19.5 40q48 267 80 473zM1536 1120 v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
-<glyph unicode="&#xf173;" horiz-adv-x="1024" d="M944 207l80 -237q-23 -35 -111 -66t-177 -32q-104 -2 -190.5 26t-142.5 74t-95 106t-55.5 120t-16.5 118v544h-168v215q72 26 129 69.5t91 90t58 102t34 99t15 88.5q1 5 4.5 8.5t7.5 3.5h244v-424h333v-252h-334v-518q0 -30 6.5 -56t22.5 -52.5t49.5 -41.5t81.5 -14 q78 2 134 29z" />
-<glyph unicode="&#xf174;" d="M1136 75l-62 183q-44 -22 -103 -22q-36 -1 -62 10.5t-38.5 31.5t-17.5 40.5t-5 43.5v398h257v194h-256v326h-188q-8 0 -9 -10q-5 -44 -17.5 -87t-39 -95t-77 -95t-118.5 -68v-165h130v-418q0 -57 21.5 -115t65 -111t121 -85.5t176.5 -30.5q69 1 136.5 25t85.5 50z M1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
-<glyph unicode="&#xf175;" horiz-adv-x="768" d="M765 237q8 -19 -5 -35l-350 -384q-10 -10 -23 -10q-14 0 -24 10l-355 384q-13 16 -5 35q9 19 29 19h224v1248q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1248h224q21 0 29 -19z" />
-<glyph unicode="&#xf176;" horiz-adv-x="768" d="M765 1043q-9 -19 -29 -19h-224v-1248q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v1248h-224q-21 0 -29 19t5 35l350 384q10 10 23 10q14 0 24 -10l355 -384q13 -16 5 -35z" />
-<glyph unicode="&#xf177;" horiz-adv-x="1792" d="M1792 736v-192q0 -14 -9 -23t-23 -9h-1248v-224q0 -21 -19 -29t-35 5l-384 350q-10 10 -10 23q0 14 10 24l384 354q16 14 35 6q19 -9 19 -29v-224h1248q14 0 23 -9t9 -23z" />
-<glyph unicode="&#xf178;" horiz-adv-x="1792" d="M1728 643q0 -14 -10 -24l-384 -354q-16 -14 -35 -6q-19 9 -19 29v224h-1248q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h1248v224q0 21 19 29t35 -5l384 -350q10 -10 10 -23z" />
-<glyph unicode="&#xf179;" horiz-adv-x="1408" d="M1393 321q-39 -125 -123 -250q-129 -196 -257 -196q-49 0 -140 32q-86 32 -151 32q-61 0 -142 -33q-81 -34 -132 -34q-152 0 -301 259q-147 261 -147 503q0 228 113 374q112 144 284 144q72 0 177 -30q104 -30 138 -30q45 0 143 34q102 34 173 34q119 0 213 -65 q52 -36 104 -100q-79 -67 -114 -118q-65 -94 -65 -207q0 -124 69 -223t158 -126zM1017 1494q0 -61 -29 -136q-30 -75 -93 -138q-54 -54 -108 -72q-37 -11 -104 -17q3 149 78 257q74 107 250 148q1 -3 2.5 -11t2.5 -11q0 -4 0.5 -10t0.5 -10z" />
-<glyph unicode="&#xf17a;" horiz-adv-x="1664" d="M682 530v-651l-682 94v557h682zM682 1273v-659h-682v565zM1664 530v-786l-907 125v661h907zM1664 1408v-794h-907v669z" />
-<glyph unicode="&#xf17b;" horiz-adv-x="1408" d="M493 1053q16 0 27.5 11.5t11.5 27.5t-11.5 27.5t-27.5 11.5t-27 -11.5t-11 -27.5t11 -27.5t27 -11.5zM915 1053q16 0 27 11.5t11 27.5t-11 27.5t-27 11.5t-27.5 -11.5t-11.5 -27.5t11.5 -27.5t27.5 -11.5zM103 869q42 0 72 -30t30 -72v-430q0 -43 -29.5 -73t-72.5 -30 t-73 30t-30 73v430q0 42 30 72t73 30zM1163 850v-666q0 -46 -32 -78t-77 -32h-75v-227q0 -43 -30 -73t-73 -30t-73 30t-30 73v227h-138v-227q0 -43 -30 -73t-73 -30q-42 0 -72 30t-30 73l-1 227h-74q-46 0 -78 32t-32 78v666h918zM931 1255q107 -55 171 -153.5t64 -215.5 h-925q0 117 64 215.5t172 153.5l-71 131q-7 13 5 20q13 6 20 -6l72 -132q95 42 201 42t201 -42l72 132q7 12 20 6q12 -7 5 -20zM1408 767v-430q0 -43 -30 -73t-73 -30q-42 0 -72 30t-30 73v430q0 43 30 72.5t72 29.5q43 0 73 -29.5t30 -72.5z" />
-<glyph unicode="&#xf17c;" d="M663 1125q-11 -1 -15.5 -10.5t-8.5 -9.5q-5 -1 -5 5q0 12 19 15h10zM750 1111q-4 -1 -11.5 6.5t-17.5 4.5q24 11 32 -2q3 -6 -3 -9zM399 684q-4 1 -6 -3t-4.5 -12.5t-5.5 -13.5t-10 -13q-7 -10 -1 -12q4 -1 12.5 7t12.5 18q1 3 2 7t2 6t1.5 4.5t0.5 4v3t-1 2.5t-3 2z M1254 325q0 18 -55 42q4 15 7.5 27.5t5 26t3 21.5t0.5 22.5t-1 19.5t-3.5 22t-4 20.5t-5 25t-5.5 26.5q-10 48 -47 103t-72 75q24 -20 57 -83q87 -162 54 -278q-11 -40 -50 -42q-31 -4 -38.5 18.5t-8 83.5t-11.5 107q-9 39 -19.5 69t-19.5 45.5t-15.5 24.5t-13 15t-7.5 7 q-14 62 -31 103t-29.5 56t-23.5 33t-15 40q-4 21 6 53.5t4.5 49.5t-44.5 25q-15 3 -44.5 18t-35.5 16q-8 1 -11 26t8 51t36 27q37 3 51 -30t4 -58q-11 -19 -2 -26.5t30 -0.5q13 4 13 36v37q-5 30 -13.5 50t-21 30.5t-23.5 15t-27 7.5q-107 -8 -89 -134q0 -15 -1 -15 q-9 9 -29.5 10.5t-33 -0.5t-15.5 5q1 57 -16 90t-45 34q-27 1 -41.5 -27.5t-16.5 -59.5q-1 -15 3.5 -37t13 -37.5t15.5 -13.5q10 3 16 14q4 9 -7 8q-7 0 -15.5 14.5t-9.5 33.5q-1 22 9 37t34 14q17 0 27 -21t9.5 -39t-1.5 -22q-22 -15 -31 -29q-8 -12 -27.5 -23.5 t-20.5 -12.5q-13 -14 -15.5 -27t7.5 -18q14 -8 25 -19.5t16 -19t18.5 -13t35.5 -6.5q47 -2 102 15q2 1 23 7t34.5 10.5t29.5 13t21 17.5q9 14 20 8q5 -3 6.5 -8.5t-3 -12t-16.5 -9.5q-20 -6 -56.5 -21.5t-45.5 -19.5q-44 -19 -70 -23q-25 -5 -79 2q-10 2 -9 -2t17 -19 q25 -23 67 -22q17 1 36 7t36 14t33.5 17.5t30 17t24.5 12t17.5 2.5t8.5 -11q0 -2 -1 -4.5t-4 -5t-6 -4.5t-8.5 -5t-9 -4.5t-10 -5t-9.5 -4.5q-28 -14 -67.5 -44t-66.5 -43t-49 -1q-21 11 -63 73q-22 31 -25 22q-1 -3 -1 -10q0 -25 -15 -56.5t-29.5 -55.5t-21 -58t11.5 -63 q-23 -6 -62.5 -90t-47.5 -141q-2 -18 -1.5 -69t-5.5 -59q-8 -24 -29 -3q-32 31 -36 94q-2 28 4 56q4 19 -1 18l-4 -5q-36 -65 10 -166q5 -12 25 -28t24 -20q20 -23 104 -90.5t93 -76.5q16 -15 17.5 -38t-14 -43t-45.5 -23q8 -15 29 -44.5t28 -54t7 -70.5q46 24 7 92 q-4 8 -10.5 16t-9.5 12t-2 6q3 5 13 9.5t20 -2.5q46 -52 166 -36q133 15 177 87q23 38 34 30q12 -6 10 -52q-1 -25 -23 -92q-9 -23 -6 -37.5t24 -15.5q3 19 14.5 77t13.5 90q2 21 -6.5 73.5t-7.5 97t23 70.5q15 18 51 18q1 37 34.5 53t72.5 10.5t60 -22.5zM626 1152 q3 17 -2.5 30t-11.5 15q-9 2 -9 -7q2 -5 5 -6q10 0 7 -15q-3 -20 8 -20q3 0 3 3zM1045 955q-2 8 -6.5 11.5t-13 5t-14.5 5.5q-5 3 -9.5 8t-7 8t-5.5 6.5t-4 4t-4 -1.5q-14 -16 7 -43.5t39 -31.5q9 -1 14.5 8t3.5 20zM867 1168q0 11 -5 19.5t-11 12.5t-9 3q-14 -1 -7 -7l4 -2 q14 -4 18 -31q0 -3 8 2zM921 1401q0 2 -2.5 5t-9 7t-9.5 6q-15 15 -24 15q-9 -1 -11.5 -7.5t-1 -13t-0.5 -12.5q-1 -4 -6 -10.5t-6 -9t3 -8.5q4 -3 8 0t11 9t15 9q1 1 9 1t15 2t9 7zM1486 60q20 -12 31 -24.5t12 -24t-2.5 -22.5t-15.5 -22t-23.5 -19.5t-30 -18.5 t-31.5 -16.5t-32 -15.5t-27 -13q-38 -19 -85.5 -56t-75.5 -64q-17 -16 -68 -19.5t-89 14.5q-18 9 -29.5 23.5t-16.5 25.5t-22 19.5t-47 9.5q-44 1 -130 1q-19 0 -57 -1.5t-58 -2.5q-44 -1 -79.5 -15t-53.5 -30t-43.5 -28.5t-53.5 -11.5q-29 1 -111 31t-146 43q-19 4 -51 9.5 t-50 9t-39.5 9.5t-33.5 14.5t-17 19.5q-10 23 7 66.5t18 54.5q1 16 -4 40t-10 42.5t-4.5 36.5t10.5 27q14 12 57 14t60 12q30 18 42 35t12 51q21 -73 -32 -106q-32 -20 -83 -15q-34 3 -43 -10q-13 -15 5 -57q2 -6 8 -18t8.5 -18t4.5 -17t1 -22q0 -15 -17 -49t-14 -48 q3 -17 37 -26q20 -6 84.5 -18.5t99.5 -20.5q24 -6 74 -22t82.5 -23t55.5 -4q43 6 64.5 28t23 48t-7.5 58.5t-19 52t-20 36.5q-121 190 -169 242q-68 74 -113 40q-11 -9 -15 15q-3 16 -2 38q1 29 10 52t24 47t22 42q8 21 26.5 72t29.5 78t30 61t39 54q110 143 124 195 q-12 112 -16 310q-2 90 24 151.5t106 104.5q39 21 104 21q53 1 106 -13.5t89 -41.5q57 -42 91.5 -121.5t29.5 -147.5q-5 -95 30 -214q34 -113 133 -218q55 -59 99.5 -163t59.5 -191q8 -49 5 -84.5t-12 -55.5t-20 -22q-10 -2 -23.5 -19t-27 -35.5t-40.5 -33.5t-61 -14 q-18 1 -31.5 5t-22.5 13.5t-13.5 15.5t-11.5 20.5t-9 19.5q-22 37 -41 30t-28 -49t7 -97q20 -70 1 -195q-10 -65 18 -100.5t73 -33t85 35.5q59 49 89.5 66.5t103.5 42.5q53 18 77 36.5t18.5 34.5t-25 28.5t-51.5 23.5q-33 11 -49.5 48t-15 72.5t15.5 47.5q1 -31 8 -56.5 t14.5 -40.5t20.5 -28.5t21 -19t21.5 -13t16.5 -9.5z" />
-<glyph unicode="&#xf17d;" d="M1024 36q-42 241 -140 498h-2l-2 -1q-16 -6 -43 -16.5t-101 -49t-137 -82t-131 -114.5t-103 -148l-15 11q184 -150 418 -150q132 0 256 52zM839 643q-21 49 -53 111q-311 -93 -673 -93q-1 -7 -1 -21q0 -124 44 -236.5t124 -201.5q50 89 123.5 166.5t142.5 124.5t130.5 81 t99.5 48l37 13q4 1 13 3.5t13 4.5zM732 855q-120 213 -244 378q-138 -65 -234 -186t-128 -272q302 0 606 80zM1416 536q-210 60 -409 29q87 -239 128 -469q111 75 185 189.5t96 250.5zM611 1277q-1 0 -2 -1q1 1 2 1zM1201 1132q-185 164 -433 164q-76 0 -155 -19 q131 -170 246 -382q69 26 130 60.5t96.5 61.5t65.5 57t37.5 40.5zM1424 647q-3 232 -149 410l-1 -1q-9 -12 -19 -24.5t-43.5 -44.5t-71 -60.5t-100 -65t-131.5 -64.5q25 -53 44 -95q2 -6 6.5 -17.5t7.5 -16.5q36 5 74.5 7t73.5 2t69 -1.5t64 -4t56.5 -5.5t48 -6.5t36.5 -6 t25 -4.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
-<glyph unicode="&#xf17e;" d="M1173 473q0 50 -19.5 91.5t-48.5 68.5t-73 49t-82.5 34t-87.5 23l-104 24q-30 7 -44 10.5t-35 11.5t-30 16t-16.5 21t-7.5 30q0 77 144 77q43 0 77 -12t54 -28.5t38 -33.5t40 -29t48 -12q47 0 75.5 32t28.5 77q0 55 -56 99.5t-142 67.5t-182 23q-68 0 -132 -15.5 t-119.5 -47t-89 -87t-33.5 -128.5q0 -61 19 -106.5t56 -75.5t80 -48.5t103 -32.5l146 -36q90 -22 112 -36q32 -20 32 -60q0 -39 -40 -64.5t-105 -25.5q-51 0 -91.5 16t-65 38.5t-45.5 45t-46 38.5t-54 16q-50 0 -75.5 -30t-25.5 -75q0 -92 122 -157.5t291 -65.5 q73 0 140 18.5t122.5 53.5t88.5 93.5t33 131.5zM1536 256q0 -159 -112.5 -271.5t-271.5 -112.5q-130 0 -234 80q-77 -16 -150 -16q-143 0 -273.5 55.5t-225 150t-150 225t-55.5 273.5q0 73 16 150q-80 104 -80 234q0 159 112.5 271.5t271.5 112.5q130 0 234 -80 q77 16 150 16q143 0 273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -73 -16 -150q80 -104 80 -234z" />
-<glyph unicode="&#xf180;" horiz-adv-x="1280" d="M1000 1102l37 194q5 23 -9 40t-35 17h-712q-23 0 -38.5 -17t-15.5 -37v-1101q0 -7 6 -1l291 352q23 26 38 33.5t48 7.5h239q22 0 37 14.5t18 29.5q24 130 37 191q4 21 -11.5 40t-36.5 19h-294q-29 0 -48 19t-19 48v42q0 29 19 47.5t48 18.5h346q18 0 35 13.5t20 29.5z M1227 1324q-15 -73 -53.5 -266.5t-69.5 -350t-35 -173.5q-6 -22 -9 -32.5t-14 -32.5t-24.5 -33t-38.5 -21t-58 -10h-271q-13 0 -22 -10q-8 -9 -426 -494q-22 -25 -58.5 -28.5t-48.5 5.5q-55 22 -55 98v1410q0 55 38 102.5t120 47.5h888q95 0 127 -53t10 -159zM1227 1324 l-158 -790q4 17 35 173.5t69.5 350t53.5 266.5z" />
-<glyph unicode="&#xf181;" d="M704 192v1024q0 14 -9 23t-23 9h-480q-14 0 -23 -9t-9 -23v-1024q0 -14 9 -23t23 -9h480q14 0 23 9t9 23zM1376 576v640q0 14 -9 23t-23 9h-480q-14 0 -23 -9t-9 -23v-640q0 -14 9 -23t23 -9h480q14 0 23 9t9 23zM1536 1344v-1408q0 -26 -19 -45t-45 -19h-1408 q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h1408q26 0 45 -19t19 -45z" />
-<glyph unicode="&#xf182;" horiz-adv-x="1280" d="M1280 480q0 -40 -28 -68t-68 -28q-51 0 -80 43l-227 341h-45v-132l247 -411q9 -15 9 -33q0 -26 -19 -45t-45 -19h-192v-272q0 -46 -33 -79t-79 -33h-160q-46 0 -79 33t-33 79v272h-192q-26 0 -45 19t-19 45q0 18 9 33l247 411v132h-45l-227 -341q-29 -43 -80 -43 q-40 0 -68 28t-28 68q0 29 16 53l256 384q73 107 176 107h384q103 0 176 -107l256 -384q16 -24 16 -53zM864 1280q0 -93 -65.5 -158.5t-158.5 -65.5t-158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5t158.5 -65.5t65.5 -158.5z" />
-<glyph unicode="&#xf183;" horiz-adv-x="1024" d="M1024 832v-416q0 -40 -28 -68t-68 -28t-68 28t-28 68v352h-64v-912q0 -46 -33 -79t-79 -33t-79 33t-33 79v464h-64v-464q0 -46 -33 -79t-79 -33t-79 33t-33 79v912h-64v-352q0 -40 -28 -68t-68 -28t-68 28t-28 68v416q0 80 56 136t136 56h640q80 0 136 -56t56 -136z M736 1280q0 -93 -65.5 -158.5t-158.5 -65.5t-158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5t158.5 -65.5t65.5 -158.5z" />
-<glyph unicode="&#xf184;" d="M773 234l350 473q16 22 24.5 59t-6 85t-61.5 79q-40 26 -83 25.5t-73.5 -17.5t-54.5 -45q-36 -40 -96 -40q-59 0 -95 40q-24 28 -54.5 45t-73.5 17.5t-84 -25.5q-46 -31 -60.5 -79t-6 -85t24.5 -59zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103 t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
-<glyph unicode="&#xf185;" horiz-adv-x="1792" d="M1472 640q0 117 -45.5 223.5t-123 184t-184 123t-223.5 45.5t-223.5 -45.5t-184 -123t-123 -184t-45.5 -223.5t45.5 -223.5t123 -184t184 -123t223.5 -45.5t223.5 45.5t184 123t123 184t45.5 223.5zM1748 363q-4 -15 -20 -20l-292 -96v-306q0 -16 -13 -26q-15 -10 -29 -4 l-292 94l-180 -248q-10 -13 -26 -13t-26 13l-180 248l-292 -94q-14 -6 -29 4q-13 10 -13 26v306l-292 96q-16 5 -20 20q-5 17 4 29l180 248l-180 248q-9 13 -4 29q4 15 20 20l292 96v306q0 16 13 26q15 10 29 4l292 -94l180 248q9 12 26 12t26 -12l180 -248l292 94 q14 6 29 -4q13 -10 13 -26v-306l292 -96q16 -5 20 -20q5 -16 -4 -29l-180 -248l180 -248q9 -12 4 -29z" />
-<glyph unicode="&#xf186;" d="M1262 233q-54 -9 -110 -9q-182 0 -337 90t-245 245t-90 337q0 192 104 357q-201 -60 -328.5 -229t-127.5 -384q0 -130 51 -248.5t136.5 -204t204 -136.5t248.5 -51q144 0 273.5 61.5t220.5 171.5zM1465 318q-94 -203 -283.5 -324.5t-413.5 -121.5q-156 0 -298 61 t-245 164t-164 245t-61 298q0 153 57.5 292.5t156 241.5t235.5 164.5t290 68.5q44 2 61 -39q18 -41 -15 -72q-86 -78 -131.5 -181.5t-45.5 -218.5q0 -148 73 -273t198 -198t273 -73q118 0 228 51q41 18 72 -13q14 -14 17.5 -34t-4.5 -38z" />
-<glyph unicode="&#xf187;" horiz-adv-x="1792" d="M1088 704q0 26 -19 45t-45 19h-256q-26 0 -45 -19t-19 -45t19 -45t45 -19h256q26 0 45 19t19 45zM1664 896v-960q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v960q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1728 1344v-256q0 -26 -19 -45t-45 -19h-1536 q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1536q26 0 45 -19t19 -45z" />
-<glyph unicode="&#xf188;" horiz-adv-x="1664" d="M1632 576q0 -26 -19 -45t-45 -19h-224q0 -171 -67 -290l208 -209q19 -19 19 -45t-19 -45q-18 -19 -45 -19t-45 19l-198 197q-5 -5 -15 -13t-42 -28.5t-65 -36.5t-82 -29t-97 -13v896h-128v-896q-51 0 -101.5 13.5t-87 33t-66 39t-43.5 32.5l-15 14l-183 -207 q-20 -21 -48 -21q-24 0 -43 16q-19 18 -20.5 44.5t15.5 46.5l202 227q-58 114 -58 274h-224q-26 0 -45 19t-19 45t19 45t45 19h224v294l-173 173q-19 19 -19 45t19 45t45 19t45 -19l173 -173h844l173 173q19 19 45 19t45 -19t19 -45t-19 -45l-173 -173v-294h224q26 0 45 -19 t19 -45zM1152 1152h-640q0 133 93.5 226.5t226.5 93.5t226.5 -93.5t93.5 -226.5z" />
-<glyph unicode="&#xf189;" horiz-adv-x="1920" d="M1917 1016q23 -64 -150 -294q-24 -32 -65 -85q-78 -100 -90 -131q-17 -41 14 -81q17 -21 81 -82h1l1 -1l1 -1l2 -2q141 -131 191 -221q3 -5 6.5 -12.5t7 -26.5t-0.5 -34t-25 -27.5t-59 -12.5l-256 -4q-24 -5 -56 5t-52 22l-20 12q-30 21 -70 64t-68.5 77.5t-61 58 t-56.5 15.5q-3 -1 -8 -3.5t-17 -14.5t-21.5 -29.5t-17 -52t-6.5 -77.5q0 -15 -3.5 -27.5t-7.5 -18.5l-4 -5q-18 -19 -53 -22h-115q-71 -4 -146 16.5t-131.5 53t-103 66t-70.5 57.5l-25 24q-10 10 -27.5 30t-71.5 91t-106 151t-122.5 211t-130.5 272q-6 16 -6 27t3 16l4 6 q15 19 57 19l274 2q12 -2 23 -6.5t16 -8.5l5 -3q16 -11 24 -32q20 -50 46 -103.5t41 -81.5l16 -29q29 -60 56 -104t48.5 -68.5t41.5 -38.5t34 -14t27 5q2 1 5 5t12 22t13.5 47t9.5 81t0 125q-2 40 -9 73t-14 46l-6 12q-25 34 -85 43q-13 2 5 24q17 19 38 30q53 26 239 24 q82 -1 135 -13q20 -5 33.5 -13.5t20.5 -24t10.5 -32t3.5 -45.5t-1 -55t-2.5 -70.5t-1.5 -82.5q0 -11 -1 -42t-0.5 -48t3.5 -40.5t11.5 -39t22.5 -24.5q8 -2 17 -4t26 11t38 34.5t52 67t68 107.5q60 104 107 225q4 10 10 17.5t11 10.5l4 3l5 2.5t13 3t20 0.5l288 2 q39 5 64 -2.5t31 -16.5z" />
-<glyph unicode="&#xf18a;" horiz-adv-x="1792" d="M675 252q21 34 11 69t-45 50q-34 14 -73 1t-60 -46q-22 -34 -13 -68.5t43 -50.5t74.5 -2.5t62.5 47.5zM769 373q8 13 3.5 26.5t-17.5 18.5q-14 5 -28.5 -0.5t-21.5 -18.5q-17 -31 13 -45q14 -5 29 0.5t22 18.5zM943 266q-45 -102 -158 -150t-224 -12 q-107 34 -147.5 126.5t6.5 187.5q47 93 151.5 139t210.5 19q111 -29 158.5 -119.5t2.5 -190.5zM1255 426q-9 96 -89 170t-208.5 109t-274.5 21q-223 -23 -369.5 -141.5t-132.5 -264.5q9 -96 89 -170t208.5 -109t274.5 -21q223 23 369.5 141.5t132.5 264.5zM1563 422 q0 -68 -37 -139.5t-109 -137t-168.5 -117.5t-226 -83t-270.5 -31t-275 33.5t-240.5 93t-171.5 151t-65 199.5q0 115 69.5 245t197.5 258q169 169 341.5 236t246.5 -7q65 -64 20 -209q-4 -14 -1 -20t10 -7t14.5 0.5t13.5 3.5l6 2q139 59 246 59t153 -61q45 -63 0 -178 q-2 -13 -4.5 -20t4.5 -12.5t12 -7.5t17 -6q57 -18 103 -47t80 -81.5t34 -116.5zM1489 1046q42 -47 54.5 -108.5t-6.5 -117.5q-8 -23 -29.5 -34t-44.5 -4q-23 8 -34 29.5t-4 44.5q20 63 -24 111t-107 35q-24 -5 -45 8t-25 37q-5 24 8 44.5t37 25.5q60 13 119 -5.5t101 -65.5z M1670 1209q87 -96 112.5 -222.5t-13.5 -241.5q-9 -27 -34 -40t-52 -4t-40 34t-5 52q28 82 10 172t-80 158q-62 69 -148 95.5t-173 8.5q-28 -6 -52 9.5t-30 43.5t9.5 51.5t43.5 29.5q123 26 244 -11.5t208 -134.5z" />
-<glyph unicode="&#xf18b;" d="M1133 -34q-171 -94 -368 -94q-196 0 -367 94q138 87 235.5 211t131.5 268q35 -144 132.5 -268t235.5 -211zM638 1394v-485q0 -252 -126.5 -459.5t-330.5 -306.5q-181 215 -181 495q0 187 83.5 349.5t229.5 269.5t325 137zM1536 638q0 -280 -181 -495 q-204 99 -330.5 306.5t-126.5 459.5v485q179 -30 325 -137t229.5 -269.5t83.5 -349.5z" />
-<glyph unicode="&#xf18c;" horiz-adv-x="1408" d="M1402 433q-32 -80 -76 -138t-91 -88.5t-99 -46.5t-101.5 -14.5t-96.5 8.5t-86.5 22t-69.5 27.5t-46 22.5l-17 10q-113 -228 -289.5 -359.5t-384.5 -132.5q-19 0 -32 13t-13 32t13 31.5t32 12.5q173 1 322.5 107.5t251.5 294.5q-36 -14 -72 -23t-83 -13t-91 2.5t-93 28.5 t-92 59t-84.5 100t-74.5 146q114 47 214 57t167.5 -7.5t124.5 -56.5t88.5 -77t56.5 -82q53 131 79 291q-7 -1 -18 -2.5t-46.5 -2.5t-69.5 0.5t-81.5 10t-88.5 23t-84 42.5t-75 65t-54.5 94.5t-28.5 127.5q70 28 133.5 36.5t112.5 -1t92 -30t73.5 -50t56 -61t42 -63t27.5 -56 t16 -39.5l4 -16q12 122 12 195q-8 6 -21.5 16t-49 44.5t-63.5 71.5t-54 93t-33 112.5t12 127t70 138.5q73 -25 127.5 -61.5t84.5 -76.5t48 -85t20.5 -89t-0.5 -85.5t-13 -76.5t-19 -62t-17 -42l-7 -15q1 -5 1 -50.5t-1 -71.5q3 7 10 18.5t30.5 43t50.5 58t71 55.5t91.5 44.5 t112 14.5t132.5 -24q-2 -78 -21.5 -141.5t-50 -104.5t-69.5 -71.5t-81.5 -45.5t-84.5 -24t-80 -9.5t-67.5 1t-46.5 4.5l-17 3q-23 -147 -73 -283q6 7 18 18.5t49.5 41t77.5 52.5t99.5 42t117.5 20t129 -23.5t137 -77.5z" />
-<glyph unicode="&#xf18d;" horiz-adv-x="1280" d="M1259 283v-66q0 -85 -57.5 -144.5t-138.5 -59.5h-57l-260 -269v269h-529q-81 0 -138.5 59.5t-57.5 144.5v66h1238zM1259 609v-255h-1238v255h1238zM1259 937v-255h-1238v255h1238zM1259 1077v-67h-1238v67q0 84 57.5 143.5t138.5 59.5h846q81 0 138.5 -59.5t57.5 -143.5z " />
-<glyph unicode="&#xf18e;" d="M1152 640q0 -14 -9 -23l-320 -320q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5v192h-352q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h352v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198 t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
-<glyph unicode="&#xf190;" d="M1152 736v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-352v-192q0 -14 -9 -23t-23 -9q-12 0 -24 10l-319 319q-9 9 -9 23t9 23l320 320q9 9 23 9q13 0 22.5 -9.5t9.5 -22.5v-192h352q13 0 22.5 -9.5t9.5 -22.5zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198 t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
-<glyph unicode="&#xf191;" d="M1024 960v-640q0 -26 -19 -45t-45 -19q-20 0 -37 12l-448 320q-27 19 -27 52t27 52l448 320q17 12 37 12q26 0 45 -19t19 -45zM1280 160v960q0 13 -9.5 22.5t-22.5 9.5h-960q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h960q13 0 22.5 9.5t9.5 22.5z M1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
-<glyph unicode="&#xf192;" d="M1024 640q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75t75 -181zM768 1184q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273t-73 273t-198 198t-273 73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5 t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
-<glyph unicode="&#xf193;" horiz-adv-x="1664" d="M1023 349l102 -204q-58 -179 -210 -290t-339 -111q-156 0 -288.5 77.5t-210 210t-77.5 288.5q0 181 104.5 330t274.5 211l17 -131q-122 -54 -195 -165.5t-73 -244.5q0 -185 131.5 -316.5t316.5 -131.5q126 0 232.5 65t165 175.5t49.5 236.5zM1571 249l58 -114l-256 -128 q-13 -7 -29 -7q-40 0 -57 35l-239 477h-472q-24 0 -42.5 16.5t-21.5 40.5l-96 779q-2 16 6 42q14 51 57 82.5t97 31.5q66 0 113 -47t47 -113q0 -69 -52 -117.5t-120 -41.5l37 -289h423v-128h-407l16 -128h455q40 0 57 -35l228 -455z" />
-<glyph unicode="&#xf194;" d="M1292 898q10 216 -161 222q-231 8 -312 -261q44 19 82 19q85 0 74 -96q-4 -57 -74 -167t-105 -110q-43 0 -82 169q-13 54 -45 255q-30 189 -160 177q-59 -7 -164 -100l-81 -72l-81 -72l52 -67q76 52 87 52q57 0 107 -179q15 -55 45 -164.5t45 -164.5q68 -179 164 -179 q157 0 383 294q220 283 226 444zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
-<glyph unicode="&#xf195;" horiz-adv-x="1152" d="M1152 704q0 -191 -94.5 -353t-256.5 -256.5t-353 -94.5h-160q-14 0 -23 9t-9 23v611l-215 -66q-3 -1 -9 -1q-10 0 -19 6q-13 10 -13 26v128q0 23 23 31l233 71v93l-215 -66q-3 -1 -9 -1q-10 0 -19 6q-13 10 -13 26v128q0 23 23 31l233 71v250q0 14 9 23t23 9h160 q14 0 23 -9t9 -23v-181l375 116q15 5 28 -5t13 -26v-128q0 -23 -23 -31l-393 -121v-93l375 116q15 5 28 -5t13 -26v-128q0 -23 -23 -31l-393 -121v-487q188 13 318 151t130 328q0 14 9 23t23 9h160q14 0 23 -9t9 -23z" />
-<glyph unicode="&#xf196;" horiz-adv-x="1408" d="M1152 736v-64q0 -14 -9 -23t-23 -9h-352v-352q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v352h-352q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h352v352q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-352h352q14 0 23 -9t9 -23zM1280 288v832q0 66 -47 113t-113 47h-832 q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113zM1408 1120v-832q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832q119 0 203.5 -84.5t84.5 -203.5z" />
-<glyph unicode="&#xf197;" horiz-adv-x="2176" d="M620 416q-110 -64 -268 -64h-128v64h-64q-13 0 -22.5 23.5t-9.5 56.5q0 24 7 49q-58 2 -96.5 10.5t-38.5 20.5t38.5 20.5t96.5 10.5q-7 25 -7 49q0 33 9.5 56.5t22.5 23.5h64v64h128q158 0 268 -64h1113q42 -7 106.5 -18t80.5 -14q89 -15 150 -40.5t83.5 -47.5t22.5 -40 t-22.5 -40t-83.5 -47.5t-150 -40.5q-16 -3 -80.5 -14t-106.5 -18h-1113zM1739 668q53 -36 53 -92t-53 -92l81 -30q68 48 68 122t-68 122zM625 400h1015q-217 -38 -456 -80q-57 0 -113 -24t-83 -48l-28 -24l-288 -288q-26 -26 -70.5 -45t-89.5 -19h-96l-93 464h29 q157 0 273 64zM352 816h-29l93 464h96q46 0 90 -19t70 -45l288 -288q4 -4 11 -10.5t30.5 -23t48.5 -29t61.5 -23t72.5 -10.5l456 -80h-1015q-116 64 -273 64z" />
-<glyph unicode="&#xf198;" horiz-adv-x="1664" d="M1519 760q62 0 103.5 -40.5t41.5 -101.5q0 -97 -93 -130l-172 -59l56 -167q7 -21 7 -47q0 -59 -42 -102t-101 -43q-47 0 -85.5 27t-53.5 72l-55 165l-310 -106l55 -164q8 -24 8 -47q0 -59 -42 -102t-102 -43q-47 0 -85 27t-53 72l-55 163l-153 -53q-29 -9 -50 -9 q-61 0 -101.5 40t-40.5 101q0 47 27.5 85t71.5 53l156 53l-105 313l-156 -54q-26 -8 -48 -8q-60 0 -101 40.5t-41 100.5q0 47 27.5 85t71.5 53l157 53l-53 159q-8 24 -8 47q0 60 42 102.5t102 42.5q47 0 85 -27t53 -72l54 -160l310 105l-54 160q-8 24 -8 47q0 59 42.5 102 t101.5 43q47 0 85.5 -27.5t53.5 -71.5l53 -161l162 55q21 6 43 6q60 0 102.5 -39.5t42.5 -98.5q0 -45 -30 -81.5t-74 -51.5l-157 -54l105 -316l164 56q24 8 46 8zM725 498l310 105l-105 315l-310 -107z" />
-<glyph unicode="&#xf199;" d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960zM1280 352v436q-31 -35 -64 -55q-34 -22 -132.5 -85t-151.5 -99q-98 -69 -164 -69v0v0q-66 0 -164 69 q-46 32 -141.5 92.5t-142.5 92.5q-12 8 -33 27t-31 27v-436q0 -40 28 -68t68 -28h832q40 0 68 28t28 68zM1280 925q0 41 -27.5 70t-68.5 29h-832q-40 0 -68 -28t-28 -68q0 -37 30.5 -76.5t67.5 -64.5q47 -32 137.5 -89t129.5 -83q3 -2 17 -11.5t21 -14t21 -13t23.5 -13 t21.5 -9.5t22.5 -7.5t20.5 -2.5t20.5 2.5t22.5 7.5t21.5 9.5t23.5 13t21 13t21 14t17 11.5l267 174q35 23 66.5 62.5t31.5 73.5z" />
-<glyph unicode="&#xf19a;" horiz-adv-x="1792" d="M127 640q0 163 67 313l367 -1005q-196 95 -315 281t-119 411zM1415 679q0 -19 -2.5 -38.5t-10 -49.5t-11.5 -44t-17.5 -59t-17.5 -58l-76 -256l-278 826q46 3 88 8q19 2 26 18.5t-2.5 31t-28.5 13.5l-205 -10q-75 1 -202 10q-12 1 -20.5 -5t-11.5 -15t-1.5 -18.5t9 -16.5 t19.5 -8l80 -8l120 -328l-168 -504l-280 832q46 3 88 8q19 2 26 18.5t-2.5 31t-28.5 13.5l-205 -10q-7 0 -23 0.5t-26 0.5q105 160 274.5 253.5t367.5 93.5q147 0 280.5 -53t238.5 -149h-10q-55 0 -92 -40.5t-37 -95.5q0 -12 2 -24t4 -21.5t8 -23t9 -21t12 -22.5t12.5 -21 t14.5 -24t14 -23q63 -107 63 -212zM909 573l237 -647q1 -6 5 -11q-126 -44 -255 -44q-112 0 -217 32zM1570 1009q95 -174 95 -369q0 -209 -104 -385.5t-279 -278.5l235 678q59 169 59 276q0 42 -6 79zM896 1536q182 0 348 -71t286 -191t191 -286t71 -348t-71 -348t-191 -286 t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71zM896 -215q173 0 331.5 68t273 182.5t182.5 273t68 331.5t-68 331.5t-182.5 273t-273 182.5t-331.5 68t-331.5 -68t-273 -182.5t-182.5 -273t-68 -331.5t68 -331.5t182.5 -273 t273 -182.5t331.5 -68z" />
-<glyph unicode="&#xf19b;" horiz-adv-x="1792" d="M1086 1536v-1536l-272 -128q-228 20 -414 102t-293 208.5t-107 272.5q0 140 100.5 263.5t275 205.5t391.5 108v-172q-217 -38 -356.5 -150t-139.5 -255q0 -152 154.5 -267t388.5 -145v1360zM1755 954l37 -390l-525 114l147 83q-119 70 -280 99v172q277 -33 481 -157z" />
-<glyph unicode="&#xf19c;" horiz-adv-x="2048" d="M960 1536l960 -384v-128h-128q0 -26 -20.5 -45t-48.5 -19h-1526q-28 0 -48.5 19t-20.5 45h-128v128zM256 896h256v-768h128v768h256v-768h128v768h256v-768h128v768h256v-768h59q28 0 48.5 -19t20.5 -45v-64h-1664v64q0 26 20.5 45t48.5 19h59v768zM1851 -64 q28 0 48.5 -19t20.5 -45v-128h-1920v128q0 26 20.5 45t48.5 19h1782z" />
-<glyph unicode="&#xf19d;" horiz-adv-x="2304" d="M1774 700l18 -316q4 -69 -82 -128t-235 -93.5t-323 -34.5t-323 34.5t-235 93.5t-82 128l18 316l574 -181q22 -7 48 -7t48 7zM2304 1024q0 -23 -22 -31l-1120 -352q-4 -1 -10 -1t-10 1l-652 206q-43 -34 -71 -111.5t-34 -178.5q63 -36 63 -109q0 -69 -58 -107l58 -433 q2 -14 -8 -25q-9 -11 -24 -11h-192q-15 0 -24 11q-10 11 -8 25l58 433q-58 38 -58 107q0 73 65 111q11 207 98 330l-333 104q-22 8 -22 31t22 31l1120 352q4 1 10 1t10 -1l1120 -352q22 -8 22 -31z" />
-<glyph unicode="&#xf19e;" d="M859 579l13 -707q-62 11 -105 11q-41 0 -105 -11l13 707q-40 69 -168.5 295.5t-216.5 374.5t-181 287q58 -15 108 -15q43 0 111 15q63 -111 133.5 -229.5t167 -276.5t138.5 -227q37 61 109.5 177.5t117.5 190t105 176t107 189.5q54 -14 107 -14q56 0 114 14v0 q-28 -39 -60 -88.5t-49.5 -78.5t-56.5 -96t-49 -84q-146 -248 -353 -610z" />
-<glyph unicode="&#xf1a0;" d="M768 750h725q12 -67 12 -128q0 -217 -91 -387.5t-259.5 -266.5t-386.5 -96q-157 0 -299 60.5t-245 163.5t-163.5 245t-60.5 299t60.5 299t163.5 245t245 163.5t299 60.5q300 0 515 -201l-209 -201q-123 119 -306 119q-129 0 -238.5 -65t-173.5 -176.5t-64 -243.5 t64 -243.5t173.5 -176.5t238.5 -65q87 0 160 24t120 60t82 82t51.5 87t22.5 78h-436v264z" />
-<glyph unicode="&#xf1a1;" horiz-adv-x="1792" d="M1095 369q16 -16 0 -31q-62 -62 -199 -62t-199 62q-16 15 0 31q6 6 15 6t15 -6q48 -49 169 -49q120 0 169 49q6 6 15 6t15 -6zM788 550q0 -37 -26 -63t-63 -26t-63.5 26t-26.5 63q0 38 26.5 64t63.5 26t63 -26.5t26 -63.5zM1183 550q0 -37 -26.5 -63t-63.5 -26t-63 26 t-26 63t26 63.5t63 26.5t63.5 -26t26.5 -64zM1434 670q0 49 -35 84t-85 35t-86 -36q-130 90 -311 96l63 283l200 -45q0 -37 26 -63t63 -26t63.5 26.5t26.5 63.5t-26.5 63.5t-63.5 26.5q-54 0 -80 -50l-221 49q-19 5 -25 -16l-69 -312q-180 -7 -309 -97q-35 37 -87 37 q-50 0 -85 -35t-35 -84q0 -35 18.5 -64t49.5 -44q-6 -27 -6 -56q0 -142 140 -243t337 -101q198 0 338 101t140 243q0 32 -7 57q30 15 48 43.5t18 63.5zM1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191 t348 71t348 -71t286 -191t191 -286t71 -348z" />
-<glyph unicode="&#xf1a2;" d="M939 407q13 -13 0 -26q-53 -53 -171 -53t-171 53q-13 13 0 26q5 6 13 6t13 -6q42 -42 145 -42t145 42q5 6 13 6t13 -6zM676 563q0 -31 -23 -54t-54 -23t-54 23t-23 54q0 32 22.5 54.5t54.5 22.5t54.5 -22.5t22.5 -54.5zM1014 563q0 -31 -23 -54t-54 -23t-54 23t-23 54 q0 32 22.5 54.5t54.5 22.5t54.5 -22.5t22.5 -54.5zM1229 666q0 42 -30 72t-73 30q-42 0 -73 -31q-113 78 -267 82l54 243l171 -39q1 -32 23.5 -54t53.5 -22q32 0 54.5 22.5t22.5 54.5t-22.5 54.5t-54.5 22.5q-48 0 -69 -43l-189 42q-17 5 -21 -13l-60 -268q-154 -6 -265 -83 q-30 32 -74 32q-43 0 -73 -30t-30 -72q0 -30 16 -55t42 -38q-5 -25 -5 -48q0 -122 120 -208.5t289 -86.5q170 0 290 86.5t120 208.5q0 25 -6 49q25 13 40.5 37.5t15.5 54.5zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960 q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
-<glyph unicode="&#xf1a3;" d="M866 697l90 27v62q0 79 -58 135t-138 56t-138 -55.5t-58 -134.5v-283q0 -20 -14 -33.5t-33 -13.5t-32.5 13.5t-13.5 33.5v120h-151v-122q0 -82 57.5 -139t139.5 -57q81 0 138.5 56.5t57.5 136.5v280q0 19 13.5 33t33.5 14q19 0 32.5 -14t13.5 -33v-54zM1199 502v122h-150 v-126q0 -20 -13.5 -33.5t-33.5 -13.5q-19 0 -32.5 14t-13.5 33v123l-90 -26l-60 28v-123q0 -80 58 -137t139 -57t138.5 57t57.5 139zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103 t385.5 -103t279.5 -279.5t103 -385.5z" />
-<glyph unicode="&#xf1a4;" horiz-adv-x="1920" d="M1062 824v118q0 42 -30 72t-72 30t-72 -30t-30 -72v-612q0 -175 -126 -299t-303 -124q-178 0 -303.5 125.5t-125.5 303.5v266h328v-262q0 -43 30 -72.5t72 -29.5t72 29.5t30 72.5v620q0 171 126.5 292t301.5 121q176 0 302 -122t126 -294v-136l-195 -58zM1592 602h328 v-266q0 -178 -125.5 -303.5t-303.5 -125.5q-177 0 -303 124.5t-126 300.5v268l131 -61l195 58v-270q0 -42 30 -71.5t72 -29.5t72 29.5t30 71.5v275z" />
-<glyph unicode="&#xf1a5;" d="M1472 160v480h-704v704h-480q-93 0 -158.5 -65.5t-65.5 -158.5v-480h704v-704h480q93 0 158.5 65.5t65.5 158.5zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5 t84.5 -203.5z" />
-<glyph unicode="&#xf1a6;" horiz-adv-x="2048" d="M328 1254h204v-983h-532v697h328v286zM328 435v369h-123v-369h123zM614 968v-697h205v697h-205zM614 1254v-204h205v204h-205zM901 968h533v-942h-533v163h328v82h-328v697zM1229 435v369h-123v-369h123zM1516 968h532v-942h-532v163h327v82h-327v697zM1843 435v369h-123 v-369h123z" />
-<glyph unicode="&#xf1a7;" d="M1046 516q0 -64 -38 -109t-91 -45q-43 0 -70 15v277q28 17 70 17q53 0 91 -45.5t38 -109.5zM703 944q0 -64 -38 -109.5t-91 -45.5q-43 0 -70 15v277q28 17 70 17q53 0 91 -45t38 -109zM1265 513q0 134 -88 229t-213 95q-20 0 -39 -3q-23 -78 -78 -136q-87 -95 -211 -101 v-636l211 41v206q51 -19 117 -19q125 0 213 95t88 229zM922 940q0 134 -88.5 229t-213.5 95q-74 0 -141 -36h-186v-840l211 41v206q55 -19 116 -19q125 0 213.5 95t88.5 229zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960 q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
-<glyph unicode="&#xf1a8;" horiz-adv-x="2038" d="M1222 607q75 3 143.5 -20.5t118 -58.5t101 -94.5t84 -108t75.5 -120.5q33 -56 78.5 -109t75.5 -80.5t99 -88.5q-48 -30 -108.5 -57.5t-138.5 -59t-114 -47.5q-44 37 -74 115t-43.5 164.5t-33 180.5t-42.5 168.5t-72.5 123t-122.5 48.5l-10 -2l-6 -4q4 -5 13 -14 q6 -5 28 -23.5t25.5 -22t19 -18t18 -20.5t11.5 -21t10.5 -27.5t4.5 -31t4 -40.5l1 -33q1 -26 -2.5 -57.5t-7.5 -52t-12.5 -58.5t-11.5 -53q-35 1 -101 -9.5t-98 -10.5q-39 0 -72 10q-2 16 -2 47q0 74 3 96q2 13 31.5 41.5t57 59t26.5 51.5q-24 2 -43 -24 q-36 -53 -111.5 -99.5t-136.5 -46.5q-25 0 -75.5 63t-106.5 139.5t-84 96.5q-6 4 -27 30q-482 -112 -513 -112q-16 0 -28 11t-12 27q0 15 8.5 26.5t22.5 14.5l486 106q-8 14 -8 25t5.5 17.5t16 11.5t20 7t23 4.5t18.5 4.5q4 1 15.5 7.5t17.5 6.5q15 0 28 -16t20 -33 q163 37 172 37q17 0 29.5 -11t12.5 -28q0 -15 -8.5 -26t-23.5 -14l-182 -40l-1 -16q-1 -26 81.5 -117.5t104.5 -91.5q47 0 119 80t72 129q0 36 -23.5 53t-51 18.5t-51 11.5t-23.5 34q0 16 10 34l-68 19q43 44 43 117q0 26 -5 58q82 16 144 16q44 0 71.5 -1.5t48.5 -8.5 t31 -13.5t20.5 -24.5t15.5 -33.5t17 -47.5t24 -60l50 25q-3 -40 -23 -60t-42.5 -21t-40 -6.5t-16.5 -20.5zM1282 842q-5 5 -13.5 15.5t-12 14.5t-10.5 11.5t-10 10.5l-8 8t-8.5 7.5t-8 5t-8.5 4.5q-7 3 -14.5 5t-20.5 2.5t-22 0.5h-32.5h-37.5q-126 0 -217 -43 q16 30 36 46.5t54 29.5t65.5 36t46 36.5t50 55t43.5 50.5q12 -9 28 -31.5t32 -36.5t38 -13l12 1v-76l22 -1q247 95 371 190q28 21 50 39t42.5 37.5t33 31t29.5 34t24 31t24.5 37t23 38t27 47.5t29.5 53l7 9q-2 -53 -43 -139q-79 -165 -205 -264t-306 -142q-14 -3 -42 -7.5 t-50 -9.5t-39 -14q3 -19 24.5 -46t21.5 -34q0 -11 -26 -30zM1061 -79q39 26 131.5 47.5t146.5 21.5q9 0 22.5 -15.5t28 -42.5t26 -50t24 -51t14.5 -33q-121 -45 -244 -45q-61 0 -125 11zM822 568l48 12l109 -177l-73 -48zM1323 51q3 -15 3 -16q0 -7 -17.5 -14.5t-46 -13 t-54 -9.5t-53.5 -7.5t-32 -4.5l-7 43q21 2 60.5 8.5t72 10t60.5 3.5h14zM866 679l-96 -20l-6 17q10 1 32.5 7t34.5 6q19 0 35 -10zM1061 45h31l10 -83l-41 -12v95zM1950 1535v1v-1zM1950 1535l-1 -5l-2 -2l1 3zM1950 1535l1 1z" />
-<glyph unicode="&#xf1a9;" d="M1167 -50q-5 19 -24 5q-30 -22 -87 -39t-131 -17q-129 0 -193 49q-5 4 -13 4q-11 0 -26 -12q-7 -6 -7.5 -16t7.5 -20q34 -32 87.5 -46t102.5 -12.5t99 4.5q41 4 84.5 20.5t65 30t28.5 20.5q12 12 7 29zM1128 65q-19 47 -39 61q-23 15 -76 15q-47 0 -71 -10 q-29 -12 -78 -56q-26 -24 -12 -44q9 -8 17.5 -4.5t31.5 23.5q3 2 10.5 8.5t10.5 8.5t10 7t11.5 7t12.5 5t15 4.5t16.5 2.5t20.5 1q27 0 44.5 -7.5t23 -14.5t13.5 -22q10 -17 12.5 -20t12.5 1q23 12 14 34zM1483 346q0 22 -5 44.5t-16.5 45t-34 36.5t-52.5 14 q-33 0 -97 -41.5t-129 -83.5t-101 -42q-27 -1 -63.5 19t-76 49t-83.5 58t-100 49t-111 19q-115 -1 -197 -78.5t-84 -178.5q-2 -112 74 -164q29 -20 62.5 -28.5t103.5 -8.5q57 0 132 32.5t134 71t120 70.5t93 31q26 -1 65 -31.5t71.5 -67t68 -67.5t55.5 -32q35 -3 58.5 14 t55.5 63q28 41 42.5 101t14.5 106zM1536 506q0 -164 -62 -304.5t-166 -236t-242.5 -149.5t-290.5 -54t-293 57.5t-247.5 157t-170.5 241.5t-64 302q0 89 19.5 172.5t49 145.5t70.5 118.5t78.5 94t78.5 69.5t64.5 46.5t42.5 24.5q14 8 51 26.5t54.5 28.5t48 30t60.5 44 q36 28 58 72.5t30 125.5q129 -155 186 -193q44 -29 130 -68t129 -66q21 -13 39 -25t60.5 -46.5t76 -70.5t75 -95t69 -122t47 -148.5t19.5 -177.5z" />
-<glyph unicode="&#xf1aa;" d="M1070 463l-160 -160l-151 -152l-30 -30q-65 -64 -151.5 -87t-171.5 -2q-16 -70 -72 -115t-129 -45q-85 0 -145 60.5t-60 145.5q0 72 44.5 128t113.5 72q-22 86 1 173t88 152l12 12l151 -152l-11 -11q-37 -37 -37 -89t37 -90q37 -37 89 -37t89 37l30 30l151 152l161 160z M729 1145l12 -12l-152 -152l-12 12q-37 37 -89 37t-89 -37t-37 -89.5t37 -89.5l29 -29l152 -152l160 -160l-151 -152l-161 160l-151 152l-30 30q-68 67 -90 159.5t5 179.5q-70 15 -115 71t-45 129q0 85 60 145.5t145 60.5q76 0 133.5 -49t69.5 -123q84 20 169.5 -3.5 t149.5 -87.5zM1536 78q0 -85 -60 -145.5t-145 -60.5q-74 0 -131 47t-71 118q-86 -28 -179.5 -6t-161.5 90l-11 12l151 152l12 -12q37 -37 89 -37t89 37t37 89t-37 89l-30 30l-152 152l-160 160l152 152l160 -160l152 -152l29 -30q64 -64 87.5 -150.5t2.5 -171.5 q76 -11 126.5 -68.5t50.5 -134.5zM1534 1202q0 -77 -51 -135t-127 -69q26 -85 3 -176.5t-90 -158.5l-12 -12l-151 152l12 12q37 37 37 89t-37 89t-89 37t-89 -37l-30 -30l-152 -152l-160 -160l-152 152l161 160l152 152l29 30q67 67 159 89.5t178 -3.5q11 75 68.5 126 t135.5 51q85 0 145 -60.5t60 -145.5z" />
-<glyph unicode="&#xf1ab;" d="M654 458q-1 -3 -12.5 0.5t-31.5 11.5l-20 9q-44 20 -87 49q-7 5 -41 31.5t-38 28.5q-67 -103 -134 -181q-81 -95 -105 -110q-4 -2 -19.5 -4t-18.5 0q6 4 82 92q21 24 85.5 115t78.5 118q17 30 51 98.5t36 77.5q-8 1 -110 -33q-8 -2 -27.5 -7.5t-34.5 -9.5t-17 -5 q-2 -2 -2 -10.5t-1 -9.5q-5 -10 -31 -15q-23 -7 -47 0q-18 4 -28 21q-4 6 -5 23q6 2 24.5 5t29.5 6q58 16 105 32q100 35 102 35q10 2 43 19.5t44 21.5q9 3 21.5 8t14.5 5.5t6 -0.5q2 -12 -1 -33q0 -2 -12.5 -27t-26.5 -53.5t-17 -33.5q-25 -50 -77 -131l64 -28 q12 -6 74.5 -32t67.5 -28q4 -1 10.5 -25.5t4.5 -30.5zM449 944q3 -15 -4 -28q-12 -23 -50 -38q-30 -12 -60 -12q-26 3 -49 26q-14 15 -18 41l1 3q3 -3 19.5 -5t26.5 0t58 16q36 12 55 14q17 0 21 -17zM1147 815l63 -227l-139 42zM39 15l694 232v1032l-694 -233v-1031z M1280 332l102 -31l-181 657l-100 31l-216 -536l102 -31l45 110l211 -65zM777 1294l573 -184v380zM1088 -29l158 -13l-54 -160l-40 66q-130 -83 -276 -108q-58 -12 -91 -12h-84q-79 0 -199.5 39t-183.5 85q-8 7 -8 16q0 8 5 13.5t13 5.5q4 0 18 -7.5t30.5 -16.5t20.5 -11 q73 -37 159.5 -61.5t157.5 -24.5q95 0 167 14.5t157 50.5q15 7 30.5 15.5t34 19t28.5 16.5zM1536 1050v-1079l-774 246q-14 -6 -375 -127.5t-368 -121.5q-13 0 -18 13q0 1 -1 3v1078q3 9 4 10q5 6 20 11q106 35 149 50v384l558 -198q2 0 160.5 55t316 108.5t161.5 53.5 q20 0 20 -21v-418z" />
-<glyph unicode="&#xf1ac;" horiz-adv-x="1792" d="M288 1152q66 0 113 -47t47 -113v-1088q0 -66 -47 -113t-113 -47h-128q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h128zM1664 989q58 -34 93 -93t35 -128v-768q0 -106 -75 -181t-181 -75h-864q-66 0 -113 47t-47 113v1536q0 40 28 68t68 28h672q40 0 88 -20t76 -48 l152 -152q28 -28 48 -76t20 -88v-163zM928 0v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM928 256v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM928 512v128q0 14 -9 23 t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM1184 0v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM1184 256v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128 q14 0 23 9t9 23zM1184 512v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM1440 0v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM1440 256v128q0 14 -9 23t-23 9h-128 q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM1440 512v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM1536 896v256h-160q-40 0 -68 28t-28 68v160h-640v-512h896z" />
-<glyph unicode="&#xf1ad;" d="M1344 1536q26 0 45 -19t19 -45v-1664q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v1664q0 26 19 45t45 19h1280zM512 1248v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23zM512 992v-64q0 -14 9 -23t23 -9h64q14 0 23 9 t9 23v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23zM512 736v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23zM512 480v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23zM384 160v64 q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM384 416v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM384 672v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64 q14 0 23 9t9 23zM384 928v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM384 1184v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM896 -96v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9 t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM896 416v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM896 672v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM896 928v64 q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM896 1184v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1152 160v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64 q14 0 23 9t9 23zM1152 416v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1152 672v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1152 928v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9 t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1152 1184v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23z" />
-<glyph unicode="&#xf1ae;" horiz-adv-x="1280" d="M1188 988l-292 -292v-824q0 -46 -33 -79t-79 -33t-79 33t-33 79v384h-64v-384q0 -46 -33 -79t-79 -33t-79 33t-33 79v824l-292 292q-28 28 -28 68t28 68t68 28t68 -28l228 -228h368l228 228q28 28 68 28t68 -28t28 -68t-28 -68zM864 1152q0 -93 -65.5 -158.5 t-158.5 -65.5t-158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5t158.5 -65.5t65.5 -158.5z" />
-<glyph unicode="&#xf1b0;" horiz-adv-x="1664" d="M780 1064q0 -60 -19 -113.5t-63 -92.5t-105 -39q-76 0 -138 57.5t-92 135.5t-30 151q0 60 19 113.5t63 92.5t105 39q77 0 138.5 -57.5t91.5 -135t30 -151.5zM438 581q0 -80 -42 -139t-119 -59q-76 0 -141.5 55.5t-100.5 133.5t-35 152q0 80 42 139.5t119 59.5 q76 0 141.5 -55.5t100.5 -134t35 -152.5zM832 608q118 0 255 -97.5t229 -237t92 -254.5q0 -46 -17 -76.5t-48.5 -45t-64.5 -20t-76 -5.5q-68 0 -187.5 45t-182.5 45q-66 0 -192.5 -44.5t-200.5 -44.5q-183 0 -183 146q0 86 56 191.5t139.5 192.5t187.5 146t193 59zM1071 819 q-61 0 -105 39t-63 92.5t-19 113.5q0 74 30 151.5t91.5 135t138.5 57.5q61 0 105 -39t63 -92.5t19 -113.5q0 -73 -30 -151t-92 -135.5t-138 -57.5zM1503 923q77 0 119 -59.5t42 -139.5q0 -74 -35 -152t-100.5 -133.5t-141.5 -55.5q-77 0 -119 59t-42 139q0 74 35 152.5 t100.5 134t141.5 55.5z" />
-<glyph unicode="&#xf1b1;" horiz-adv-x="768" d="M704 1008q0 -145 -57 -243.5t-152 -135.5l45 -821q2 -26 -16 -45t-44 -19h-192q-26 0 -44 19t-16 45l45 821q-95 37 -152 135.5t-57 243.5q0 128 42.5 249.5t117.5 200t160 78.5t160 -78.5t117.5 -200t42.5 -249.5z" />
-<glyph unicode="&#xf1b2;" horiz-adv-x="1792" d="M896 -93l640 349v636l-640 -233v-752zM832 772l698 254l-698 254l-698 -254zM1664 1024v-768q0 -35 -18 -65t-49 -47l-704 -384q-28 -16 -61 -16t-61 16l-704 384q-31 17 -49 47t-18 65v768q0 40 23 73t61 47l704 256q22 8 44 8t44 -8l704 -256q38 -14 61 -47t23 -73z " />
-<glyph unicode="&#xf1b3;" horiz-adv-x="2304" d="M640 -96l384 192v314l-384 -164v-342zM576 358l404 173l-404 173l-404 -173zM1664 -96l384 192v314l-384 -164v-342zM1600 358l404 173l-404 173l-404 -173zM1152 651l384 165v266l-384 -164v-267zM1088 1030l441 189l-441 189l-441 -189zM2176 512v-416q0 -36 -19 -67 t-52 -47l-448 -224q-25 -14 -57 -14t-57 14l-448 224q-5 2 -7 4q-2 -2 -7 -4l-448 -224q-25 -14 -57 -14t-57 14l-448 224q-33 16 -52 47t-19 67v416q0 38 21.5 70t56.5 48l434 186v400q0 38 21.5 70t56.5 48l448 192q23 10 50 10t50 -10l448 -192q35 -16 56.5 -48t21.5 -70 v-400l434 -186q36 -16 57 -48t21 -70z" />
-<glyph unicode="&#xf1b4;" horiz-adv-x="2048" d="M1848 1197h-511v-124h511v124zM1596 771q-90 0 -146 -52.5t-62 -142.5h408q-18 195 -200 195zM1612 186q63 0 122 32t76 87h221q-100 -307 -427 -307q-214 0 -340.5 132t-126.5 347q0 208 130.5 345.5t336.5 137.5q138 0 240.5 -68t153 -179t50.5 -248q0 -17 -2 -47h-658 q0 -111 57.5 -171.5t166.5 -60.5zM277 236h296q205 0 205 167q0 180 -199 180h-302v-347zM277 773h281q78 0 123.5 36.5t45.5 113.5q0 144 -190 144h-260v-294zM0 1282h594q87 0 155 -14t126.5 -47.5t90 -96.5t31.5 -154q0 -181 -172 -263q114 -32 172 -115t58 -204 q0 -75 -24.5 -136.5t-66 -103.5t-98.5 -71t-121 -42t-134 -13h-611v1260z" />
-<glyph unicode="&#xf1b5;" d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960zM499 1041h-371v-787h382q117 0 197 57.5t80 170.5q0 158 -143 200q107 52 107 164q0 57 -19.5 96.5 t-56.5 60.5t-79 29.5t-97 8.5zM477 723h-176v184h163q119 0 119 -90q0 -94 -106 -94zM486 388h-185v217h189q124 0 124 -113q0 -104 -128 -104zM1136 356q-68 0 -104 38t-36 107h411q1 10 1 30q0 132 -74.5 220.5t-203.5 88.5q-128 0 -210 -86t-82 -216q0 -135 79 -217 t213 -82q205 0 267 191h-138q-11 -34 -47.5 -54t-75.5 -20zM1126 722q113 0 124 -122h-254q4 56 39 89t91 33zM964 988h319v-77h-319v77z" />
-<glyph unicode="&#xf1b6;" horiz-adv-x="1792" d="M1582 954q0 -101 -71.5 -172.5t-172.5 -71.5t-172.5 71.5t-71.5 172.5t71.5 172.5t172.5 71.5t172.5 -71.5t71.5 -172.5zM812 212q0 104 -73 177t-177 73q-27 0 -54 -6l104 -42q77 -31 109.5 -106.5t1.5 -151.5q-31 -77 -107 -109t-152 -1q-21 8 -62 24.5t-61 24.5 q32 -60 91 -96.5t130 -36.5q104 0 177 73t73 177zM1642 953q0 126 -89.5 215.5t-215.5 89.5q-127 0 -216.5 -89.5t-89.5 -215.5q0 -127 89.5 -216t216.5 -89q126 0 215.5 89t89.5 216zM1792 953q0 -189 -133.5 -322t-321.5 -133l-437 -319q-12 -129 -109 -218t-229 -89 q-121 0 -214 76t-118 192l-230 92v429l389 -157q79 48 173 48q13 0 35 -2l284 407q2 187 135.5 319t320.5 132q188 0 321.5 -133.5t133.5 -321.5z" />
-<glyph unicode="&#xf1b7;" d="M1242 889q0 80 -57 136.5t-137 56.5t-136.5 -57t-56.5 -136q0 -80 56.5 -136.5t136.5 -56.5t137 56.5t57 136.5zM632 301q0 -83 -58 -140.5t-140 -57.5q-56 0 -103 29t-72 77q52 -20 98 -40q60 -24 120 1.5t85 86.5q24 60 -1.5 120t-86.5 84l-82 33q22 5 42 5 q82 0 140 -57.5t58 -140.5zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v153l172 -69q20 -92 93.5 -152t168.5 -60q104 0 181 70t87 173l345 252q150 0 255.5 105.5t105.5 254.5q0 150 -105.5 255.5t-255.5 105.5 q-148 0 -253 -104.5t-107 -252.5l-225 -322q-9 1 -28 1q-75 0 -137 -37l-297 119v468q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5zM1289 887q0 -100 -71 -170.5t-171 -70.5t-170.5 70.5t-70.5 170.5t70.5 171t170.5 71q101 0 171.5 -70.5t70.5 -171.5z " />
-<glyph unicode="&#xf1b8;" horiz-adv-x="1792" d="M836 367l-15 -368l-2 -22l-420 29q-36 3 -67 31.5t-47 65.5q-11 27 -14.5 55t4 65t12 55t21.5 64t19 53q78 -12 509 -28zM449 953l180 -379l-147 92q-63 -72 -111.5 -144.5t-72.5 -125t-39.5 -94.5t-18.5 -63l-4 -21l-190 357q-17 26 -18 56t6 47l8 18q35 63 114 188 l-140 86zM1680 436l-188 -359q-12 -29 -36.5 -46.5t-43.5 -20.5l-18 -4q-71 -7 -219 -12l8 -164l-230 367l211 362l7 -173q170 -16 283 -5t170 33zM895 1360q-47 -63 -265 -435l-317 187l-19 12l225 356q20 31 60 45t80 10q24 -2 48.5 -12t42 -21t41.5 -33t36 -34.5 t36 -39.5t32 -35zM1550 1053l212 -363q18 -37 12.5 -76t-27.5 -74q-13 -20 -33 -37t-38 -28t-48.5 -22t-47 -16t-51.5 -14t-46 -12q-34 72 -265 436l313 195zM1407 1279l142 83l-220 -373l-419 20l151 86q-34 89 -75 166t-75.5 123.5t-64.5 80t-47 46.5l-17 13l405 -1 q31 3 58 -10.5t39 -28.5l11 -15q39 -61 112 -190z" />
-<glyph unicode="&#xf1b9;" horiz-adv-x="2048" d="M480 448q0 66 -47 113t-113 47t-113 -47t-47 -113t47 -113t113 -47t113 47t47 113zM516 768h1016l-89 357q-2 8 -14 17.5t-21 9.5h-768q-9 0 -21 -9.5t-14 -17.5zM1888 448q0 66 -47 113t-113 47t-113 -47t-47 -113t47 -113t113 -47t113 47t47 113zM2048 544v-384 q0 -14 -9 -23t-23 -9h-96v-128q0 -80 -56 -136t-136 -56t-136 56t-56 136v128h-1024v-128q0 -80 -56 -136t-136 -56t-136 56t-56 136v128h-96q-14 0 -23 9t-9 23v384q0 93 65.5 158.5t158.5 65.5h28l105 419q23 94 104 157.5t179 63.5h768q98 0 179 -63.5t104 -157.5 l105 -419h28q93 0 158.5 -65.5t65.5 -158.5z" />
-<glyph unicode="&#xf1ba;" horiz-adv-x="2048" d="M1824 640q93 0 158.5 -65.5t65.5 -158.5v-384q0 -14 -9 -23t-23 -9h-96v-64q0 -80 -56 -136t-136 -56t-136 56t-56 136v64h-1024v-64q0 -80 -56 -136t-136 -56t-136 56t-56 136v64h-96q-14 0 -23 9t-9 23v384q0 93 65.5 158.5t158.5 65.5h28l105 419q23 94 104 157.5 t179 63.5h128v224q0 14 9 23t23 9h448q14 0 23 -9t9 -23v-224h128q98 0 179 -63.5t104 -157.5l105 -419h28zM320 160q66 0 113 47t47 113t-47 113t-113 47t-113 -47t-47 -113t47 -113t113 -47zM516 640h1016l-89 357q-2 8 -14 17.5t-21 9.5h-768q-9 0 -21 -9.5t-14 -17.5z M1728 160q66 0 113 47t47 113t-47 113t-113 47t-113 -47t-47 -113t47 -113t113 -47z" />
-<glyph unicode="&#xf1bb;" d="M1504 64q0 -26 -19 -45t-45 -19h-462q1 -17 6 -87.5t5 -108.5q0 -25 -18 -42.5t-43 -17.5h-320q-25 0 -43 17.5t-18 42.5q0 38 5 108.5t6 87.5h-462q-26 0 -45 19t-19 45t19 45l402 403h-229q-26 0 -45 19t-19 45t19 45l402 403h-197q-26 0 -45 19t-19 45t19 45l384 384 q19 19 45 19t45 -19l384 -384q19 -19 19 -45t-19 -45t-45 -19h-197l402 -403q19 -19 19 -45t-19 -45t-45 -19h-229l402 -403q19 -19 19 -45z" />
-<glyph unicode="&#xf1bc;" d="M1127 326q0 32 -30 51q-193 115 -447 115q-133 0 -287 -34q-42 -9 -42 -52q0 -20 13.5 -34.5t35.5 -14.5q5 0 37 8q132 27 243 27q226 0 397 -103q19 -11 33 -11q19 0 33 13.5t14 34.5zM1223 541q0 40 -35 61q-237 141 -548 141q-153 0 -303 -42q-48 -13 -48 -64 q0 -25 17.5 -42.5t42.5 -17.5q7 0 37 8q122 33 251 33q279 0 488 -124q24 -13 38 -13q25 0 42.5 17.5t17.5 42.5zM1331 789q0 47 -40 70q-126 73 -293 110.5t-343 37.5q-204 0 -364 -47q-23 -7 -38.5 -25.5t-15.5 -48.5q0 -31 20.5 -52t51.5 -21q11 0 40 8q133 37 307 37 q159 0 309.5 -34t253.5 -95q21 -12 40 -12q29 0 50.5 20.5t21.5 51.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
-<glyph unicode="&#xf1bd;" horiz-adv-x="1024" d="M1024 1233l-303 -582l24 -31h279v-415h-507l-44 -30l-142 -273l-30 -30h-301v303l303 583l-24 30h-279v415h507l44 30l142 273l30 30h301v-303z" />
-<glyph unicode="&#xf1be;" horiz-adv-x="2304" d="M784 164l16 241l-16 523q-1 10 -7.5 17t-16.5 7q-9 0 -16 -7t-7 -17l-14 -523l14 -241q1 -10 7.5 -16.5t15.5 -6.5q22 0 24 23zM1080 193l11 211l-12 586q0 16 -13 24q-8 5 -16 5t-16 -5q-13 -8 -13 -24l-1 -6l-10 -579q0 -1 11 -236v-1q0 -10 6 -17q9 -11 23 -11 q11 0 20 9q9 7 9 20zM35 533l20 -128l-20 -126q-2 -9 -9 -9t-9 9l-17 126l17 128q2 9 9 9t9 -9zM121 612l26 -207l-26 -203q-2 -9 -10 -9q-9 0 -9 10l-23 202l23 207q0 9 9 9q8 0 10 -9zM401 159zM213 650l25 -245l-25 -237q0 -11 -11 -11q-10 0 -12 11l-21 237l21 245 q2 12 12 12q11 0 11 -12zM307 657l23 -252l-23 -244q-2 -13 -14 -13q-13 0 -13 13l-21 244l21 252q0 13 13 13q12 0 14 -13zM401 639l21 -234l-21 -246q-2 -16 -16 -16q-6 0 -10.5 4.5t-4.5 11.5l-20 246l20 234q0 6 4.5 10.5t10.5 4.5q14 0 16 -15zM784 164zM495 785 l21 -380l-21 -246q0 -7 -5 -12.5t-12 -5.5q-16 0 -18 18l-18 246l18 380q2 18 18 18q7 0 12 -5.5t5 -12.5zM589 871l19 -468l-19 -244q0 -8 -5.5 -13.5t-13.5 -5.5q-18 0 -20 19l-16 244l16 468q2 19 20 19q8 0 13.5 -5.5t5.5 -13.5zM687 911l18 -506l-18 -242 q-2 -21 -22 -21q-19 0 -21 21l-16 242l16 506q0 9 6.5 15.5t14.5 6.5q9 0 15 -6.5t7 -15.5zM1079 169v0v0zM881 915l15 -510l-15 -239q0 -10 -7.5 -17.5t-17.5 -7.5t-17 7t-8 18l-14 239l14 510q0 11 7.5 18t17.5 7t17.5 -7t7.5 -18zM980 896l14 -492l-14 -236q0 -11 -8 -19 t-19 -8t-19 8t-9 19l-12 236l12 492q1 12 9 20t19 8t18.5 -8t8.5 -20zM1192 404l-14 -231v0q0 -13 -9 -22t-22 -9t-22 9t-10 22l-6 114l-6 117l12 636v3q2 15 12 24q9 7 20 7q8 0 15 -5q14 -8 16 -26zM2304 423q0 -117 -83 -199.5t-200 -82.5h-786q-13 2 -22 11t-9 22v899 q0 23 28 33q85 34 181 34q195 0 338 -131.5t160 -323.5q53 22 110 22q117 0 200 -83t83 -201z" />
-<glyph unicode="&#xf1c0;" d="M768 768q237 0 443 43t325 127v-170q0 -69 -103 -128t-280 -93.5t-385 -34.5t-385 34.5t-280 93.5t-103 128v170q119 -84 325 -127t443 -43zM768 0q237 0 443 43t325 127v-170q0 -69 -103 -128t-280 -93.5t-385 -34.5t-385 34.5t-280 93.5t-103 128v170q119 -84 325 -127 t443 -43zM768 384q237 0 443 43t325 127v-170q0 -69 -103 -128t-280 -93.5t-385 -34.5t-385 34.5t-280 93.5t-103 128v170q119 -84 325 -127t443 -43zM768 1536q208 0 385 -34.5t280 -93.5t103 -128v-128q0 -69 -103 -128t-280 -93.5t-385 -34.5t-385 34.5t-280 93.5 t-103 128v128q0 69 103 128t280 93.5t385 34.5z" />
-<glyph unicode="&#xf1c1;" d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z M894 465q33 -26 84 -56q59 7 117 7q147 0 177 -49q16 -22 2 -52q0 -1 -1 -2l-2 -2v-1q-6 -38 -71 -38q-48 0 -115 20t-130 53q-221 -24 -392 -83q-153 -262 -242 -262q-15 0 -28 7l-24 12q-1 1 -6 5q-10 10 -6 36q9 40 56 91.5t132 96.5q14 9 23 -6q2 -2 2 -4q52 85 107 197 q68 136 104 262q-24 82 -30.5 159.5t6.5 127.5q11 40 42 40h21h1q23 0 35 -15q18 -21 9 -68q-2 -6 -4 -8q1 -3 1 -8v-30q-2 -123 -14 -192q55 -164 146 -238zM318 54q52 24 137 158q-51 -40 -87.5 -84t-49.5 -74zM716 974q-15 -42 -2 -132q1 7 7 44q0 3 7 43q1 4 4 8 q-1 1 -1 2t-0.5 1.5t-0.5 1.5q-1 22 -13 36q0 -1 -1 -2v-2zM592 313q135 54 284 81q-2 1 -13 9.5t-16 13.5q-76 67 -127 176q-27 -86 -83 -197q-30 -56 -45 -83zM1238 329q-24 24 -140 24q76 -28 124 -28q14 0 18 1q0 1 -2 3z" />
-<glyph unicode="&#xf1c2;" d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z M233 768v-107h70l164 -661h159l128 485q7 20 10 46q2 16 2 24h4l3 -24q1 -3 3.5 -20t5.5 -26l128 -485h159l164 661h70v107h-300v-107h90l-99 -438q-5 -20 -7 -46l-2 -21h-4l-3 21q-1 5 -4 21t-5 25l-144 545h-114l-144 -545q-2 -9 -4.5 -24.5t-3.5 -21.5l-4 -21h-4l-2 21 q-2 26 -7 46l-99 438h90v107h-300z" />
-<glyph unicode="&#xf1c3;" d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z M429 106v-106h281v106h-75l103 161q5 7 10 16.5t7.5 13.5t3.5 4h2q1 -4 5 -10q2 -4 4.5 -7.5t6 -8t6.5 -8.5l107 -161h-76v-106h291v106h-68l-192 273l195 282h67v107h-279v-107h74l-103 -159q-4 -7 -10 -16.5t-9 -13.5l-2 -3h-2q-1 4 -5 10q-6 11 -17 23l-106 159h76v107 h-290v-107h68l189 -272l-194 -283h-68z" />
-<glyph unicode="&#xf1c4;" d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z M416 106v-106h327v106h-93v167h137q76 0 118 15q67 23 106.5 87t39.5 146q0 81 -37 141t-100 87q-48 19 -130 19h-368v-107h92v-555h-92zM769 386h-119v268h120q52 0 83 -18q56 -33 56 -115q0 -89 -62 -120q-31 -15 -78 -15z" />
-<glyph unicode="&#xf1c5;" d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z M1280 320v-320h-1024v192l192 192l128 -128l384 384zM448 512q-80 0 -136 56t-56 136t56 136t136 56t136 -56t56 -136t-56 -136t-136 -56z" />
-<glyph unicode="&#xf1c6;" d="M640 1152v128h-128v-128h128zM768 1024v128h-128v-128h128zM640 896v128h-128v-128h128zM768 768v128h-128v-128h128zM1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400 v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-128v-128h-128v128h-512v-1536h1280zM781 593l107 -349q8 -27 8 -52q0 -83 -72.5 -137.5t-183.5 -54.5t-183.5 54.5t-72.5 137.5q0 25 8 52q21 63 120 396v128h128v-128h79 q22 0 39 -13t23 -34zM640 128q53 0 90.5 19t37.5 45t-37.5 45t-90.5 19t-90.5 -19t-37.5 -45t37.5 -45t90.5 -19z" />
-<glyph unicode="&#xf1c7;" d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z M620 686q20 -8 20 -30v-544q0 -22 -20 -30q-8 -2 -12 -2q-12 0 -23 9l-166 167h-131q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h131l166 167q16 15 35 7zM1037 -3q31 0 50 24q129 159 129 363t-129 363q-16 21 -43 24t-47 -14q-21 -17 -23.5 -43.5t14.5 -47.5 q100 -123 100 -282t-100 -282q-17 -21 -14.5 -47.5t23.5 -42.5q18 -15 40 -15zM826 145q27 0 47 20q87 93 87 219t-87 219q-18 19 -45 20t-46 -17t-20 -44.5t18 -46.5q52 -57 52 -131t-52 -131q-19 -20 -18 -46.5t20 -44.5q20 -17 44 -17z" />
-<glyph unicode="&#xf1c8;" d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z M768 768q52 0 90 -38t38 -90v-384q0 -52 -38 -90t-90 -38h-384q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h384zM1260 766q20 -8 20 -30v-576q0 -22 -20 -30q-8 -2 -12 -2q-14 0 -23 9l-265 266v90l265 266q9 9 23 9q4 0 12 -2z" />
-<glyph unicode="&#xf1c9;" d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z M480 768q8 11 21 12.5t24 -6.5l51 -38q11 -8 12.5 -21t-6.5 -24l-182 -243l182 -243q8 -11 6.5 -24t-12.5 -21l-51 -38q-11 -8 -24 -6.5t-21 12.5l-226 301q-14 19 0 38zM1282 467q14 -19 0 -38l-226 -301q-8 -11 -21 -12.5t-24 6.5l-51 38q-11 8 -12.5 21t6.5 24l182 243 l-182 243q-8 11 -6.5 24t12.5 21l51 38q11 8 24 6.5t21 -12.5zM662 6q-13 2 -20.5 13t-5.5 24l138 831q2 13 13 20.5t24 5.5l63 -10q13 -2 20.5 -13t5.5 -24l-138 -831q-2 -13 -13 -20.5t-24 -5.5z" />
-<glyph unicode="&#xf1ca;" d="M1497 709v-198q-101 -23 -198 -23q-65 -136 -165.5 -271t-181.5 -215.5t-128 -106.5q-80 -45 -162 3q-28 17 -60.5 43.5t-85 83.5t-102.5 128.5t-107.5 184t-105.5 244t-91.5 314.5t-70.5 390h283q26 -218 70 -398.5t104.5 -317t121.5 -235.5t140 -195q169 169 287 406 q-142 72 -223 220t-81 333q0 192 104 314.5t284 122.5q178 0 273 -105.5t95 -297.5q0 -159 -58 -286q-7 -1 -19.5 -3t-46 -2t-63 6t-62 25.5t-50.5 51.5q31 103 31 184q0 87 -29 132t-79 45q-53 0 -85 -49.5t-32 -140.5q0 -186 105 -293.5t267 -107.5q62 0 121 14z" />
-<glyph unicode="&#xf1cb;" horiz-adv-x="1792" d="M216 367l603 -402v359l-334 223zM154 511l193 129l-193 129v-258zM973 -35l603 402l-269 180l-334 -223v-359zM896 458l272 182l-272 182l-272 -182zM485 733l334 223v359l-603 -402zM1445 640l193 -129v258zM1307 733l269 180l-603 402v-359zM1792 913v-546 q0 -41 -34 -64l-819 -546q-21 -13 -43 -13t-43 13l-819 546q-34 23 -34 64v546q0 41 34 64l819 546q21 13 43 13t43 -13l819 -546q34 -23 34 -64z" />
-<glyph unicode="&#xf1cc;" horiz-adv-x="2048" d="M1800 764q111 -46 179.5 -145.5t68.5 -221.5q0 -164 -118 -280.5t-285 -116.5q-4 0 -11.5 0.5t-10.5 0.5h-1209h-1h-2h-5q-170 10 -288 125.5t-118 280.5q0 110 55 203t147 147q-12 39 -12 82q0 115 82 196t199 81q95 0 172 -58q75 154 222.5 248t326.5 94 q166 0 306 -80.5t221.5 -218.5t81.5 -301q0 -6 -0.5 -18t-0.5 -18zM468 498q0 -122 84 -193t208 -71q137 0 240 99q-16 20 -47.5 56.5t-43.5 50.5q-67 -65 -144 -65q-55 0 -93.5 33.5t-38.5 87.5q0 53 38.5 87t91.5 34q44 0 84.5 -21t73 -55t65 -75t69 -82t77 -75t97 -55 t121.5 -21q121 0 204.5 71.5t83.5 190.5q0 121 -84 192t-207 71q-143 0 -241 -97q14 -16 29.5 -34t34.5 -40t29 -34q66 64 142 64q52 0 92 -33t40 -84q0 -57 -37 -91.5t-94 -34.5q-43 0 -82.5 21t-72 55t-65.5 75t-69.5 82t-77.5 75t-96.5 55t-118.5 21q-122 0 -207 -70.5 t-85 -189.5z" />
-<glyph unicode="&#xf1cd;" horiz-adv-x="1792" d="M896 1536q182 0 348 -71t286 -191t191 -286t71 -348t-71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71zM896 1408q-190 0 -361 -90l194 -194q82 28 167 28t167 -28l194 194q-171 90 -361 90zM218 279l194 194 q-28 82 -28 167t28 167l-194 194q-90 -171 -90 -361t90 -361zM896 -128q190 0 361 90l-194 194q-82 -28 -167 -28t-167 28l-194 -194q171 -90 361 -90zM896 256q159 0 271.5 112.5t112.5 271.5t-112.5 271.5t-271.5 112.5t-271.5 -112.5t-112.5 -271.5t112.5 -271.5 t271.5 -112.5zM1380 473l194 -194q90 171 90 361t-90 361l-194 -194q28 -82 28 -167t-28 -167z" />
-<glyph unicode="&#xf1ce;" horiz-adv-x="1792" d="M1760 640q0 -176 -68.5 -336t-184 -275.5t-275.5 -184t-336 -68.5t-336 68.5t-275.5 184t-184 275.5t-68.5 336q0 213 97 398.5t265 305.5t374 151v-228q-221 -45 -366.5 -221t-145.5 -406q0 -130 51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5 t136.5 204t51 248.5q0 230 -145.5 406t-366.5 221v228q206 -31 374 -151t265 -305.5t97 -398.5z" />
-<glyph unicode="&#xf1d0;" horiz-adv-x="1792" d="M19 662q8 217 116 406t305 318h5q0 -1 -1 -3q-8 -8 -28 -33.5t-52 -76.5t-60 -110.5t-44.5 -135.5t-14 -150.5t39 -157.5t108.5 -154q50 -50 102 -69.5t90.5 -11.5t69.5 23.5t47 32.5l16 16q39 51 53 116.5t6.5 122.5t-21 107t-26.5 80l-14 29q-10 25 -30.5 49.5t-43 41 t-43.5 29.5t-35 19l-13 6l104 115q39 -17 78 -52t59 -61l19 -27q1 48 -18.5 103.5t-40.5 87.5l-20 31l161 183l160 -181q-33 -46 -52.5 -102.5t-22.5 -90.5l-4 -33q22 37 61.5 72.5t67.5 52.5l28 17l103 -115q-44 -14 -85 -50t-60 -65l-19 -29q-31 -56 -48 -133.5t-7 -170 t57 -156.5q33 -45 77.5 -60.5t85 -5.5t76 26.5t57.5 33.5l21 16q60 53 96.5 115t48.5 121.5t10 121.5t-18 118t-37 107.5t-45.5 93t-45 72t-34.5 47.5l-13 17q-14 13 -7 13l10 -3q40 -29 62.5 -46t62 -50t64 -58t58.5 -65t55.5 -77t45.5 -88t38 -103t23.5 -117t10.5 -136 q3 -259 -108 -465t-312 -321t-456 -115q-185 0 -351 74t-283.5 198t-184 293t-60.5 353z" />
-<glyph unicode="&#xf1d1;" horiz-adv-x="1792" d="M874 -102v-66q-208 6 -385 109.5t-283 275.5l58 34q29 -49 73 -99l65 57q148 -168 368 -212l-17 -86q65 -12 121 -13zM276 428l-83 -28q22 -60 49 -112l-57 -33q-98 180 -98 385t98 385l57 -33q-30 -56 -49 -112l82 -28q-35 -100 -35 -212q0 -109 36 -212zM1528 251 l58 -34q-106 -172 -283 -275.5t-385 -109.5v66q56 1 121 13l-17 86q220 44 368 212l65 -57q44 50 73 99zM1377 805l-233 -80q14 -42 14 -85t-14 -85l232 -80q-31 -92 -98 -169l-185 162q-57 -67 -147 -85l48 -241q-52 -10 -98 -10t-98 10l48 241q-90 18 -147 85l-185 -162 q-67 77 -98 169l232 80q-14 42 -14 85t14 85l-233 80q33 93 99 169l185 -162q59 68 147 86l-48 240q44 10 98 10t98 -10l-48 -240q88 -18 147 -86l185 162q66 -76 99 -169zM874 1448v-66q-65 -2 -121 -13l17 -86q-220 -42 -368 -211l-65 56q-38 -42 -73 -98l-57 33 q106 172 282 275.5t385 109.5zM1705 640q0 -205 -98 -385l-57 33q27 52 49 112l-83 28q36 103 36 212q0 112 -35 212l82 28q-19 56 -49 112l57 33q98 -180 98 -385zM1585 1063l-57 -33q-35 56 -73 98l-65 -56q-148 169 -368 211l17 86q-56 11 -121 13v66q209 -6 385 -109.5 t282 -275.5zM1748 640q0 173 -67.5 331t-181.5 272t-272 181.5t-331 67.5t-331 -67.5t-272 -181.5t-181.5 -272t-67.5 -331t67.5 -331t181.5 -272t272 -181.5t331 -67.5t331 67.5t272 181.5t181.5 272t67.5 331zM1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71 t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
-<glyph unicode="&#xf1d2;" d="M582 228q0 -66 -93 -66q-107 0 -107 63q0 64 98 64q102 0 102 -61zM546 694q0 -85 -74 -85q-77 0 -77 84q0 90 77 90q36 0 55 -25.5t19 -63.5zM712 769v125q-78 -29 -135 -29q-50 29 -110 29q-86 0 -145 -57t-59 -143q0 -50 29.5 -102t73.5 -67v-3q-38 -17 -38 -85 q0 -53 41 -77v-3q-113 -37 -113 -139q0 -45 20 -78.5t54 -51t72 -25.5t81 -8q224 0 224 188q0 67 -48 99t-126 46q-27 5 -51.5 20.5t-24.5 39.5q0 44 49 52q77 15 122 70t45 134q0 24 -10 52q37 9 49 13zM771 350h137q-2 27 -2 82v387q0 46 2 69h-137q3 -23 3 -71v-392 q0 -50 -3 -75zM1280 366v121q-30 -21 -68 -21q-53 0 -53 82v225h52q9 0 26.5 -1t26.5 -1v117h-105q0 82 3 102h-140q4 -24 4 -55v-47h-60v-117q36 3 37 3q3 0 11 -0.5t12 -0.5v-2h-2v-217q0 -37 2.5 -64t11.5 -56.5t24.5 -48.5t43.5 -31t66 -12q64 0 108 24zM924 1072 q0 36 -24 63.5t-60 27.5t-60.5 -27t-24.5 -64q0 -36 25 -62.5t60 -26.5t59.5 27t24.5 62zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
-<glyph unicode="&#xf1d3;" horiz-adv-x="1792" d="M595 22q0 100 -165 100q-158 0 -158 -104q0 -101 172 -101q151 0 151 105zM536 777q0 61 -30 102t-89 41q-124 0 -124 -145q0 -135 124 -135q119 0 119 137zM805 1101v-202q-36 -12 -79 -22q16 -43 16 -84q0 -127 -73 -216.5t-197 -112.5q-40 -8 -59.5 -27t-19.5 -58 q0 -31 22.5 -51.5t58 -32t78.5 -22t86 -25.5t78.5 -37.5t58 -64t22.5 -98.5q0 -304 -363 -304q-69 0 -130 12.5t-116 41t-87.5 82t-32.5 127.5q0 165 182 225v4q-67 41 -67 126q0 109 63 137v4q-72 24 -119.5 108.5t-47.5 165.5q0 139 95 231.5t235 92.5q96 0 178 -47 q98 0 218 47zM1123 220h-222q4 45 4 134v609q0 94 -4 128h222q-4 -33 -4 -124v-613q0 -89 4 -134zM1724 442v-196q-71 -39 -174 -39q-62 0 -107 20t-70 50t-39.5 78t-18.5 92t-4 103v351h2v4q-7 0 -19 1t-18 1q-21 0 -59 -6v190h96v76q0 54 -6 89h227q-6 -41 -6 -165h171 v-190q-15 0 -43.5 2t-42.5 2h-85v-365q0 -131 87 -131q61 0 109 33zM1148 1389q0 -58 -39 -101.5t-96 -43.5q-58 0 -98 43.5t-40 101.5q0 59 39.5 103t98.5 44q58 0 96.5 -44.5t38.5 -102.5z" />
-<glyph unicode="&#xf1d4;" d="M809 532l266 499h-112l-157 -312q-24 -48 -44 -92l-42 92l-155 312h-120l263 -493v-324h101v318zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
-<glyph unicode="&#xf1d5;" horiz-adv-x="1280" d="M842 964q0 -80 -57 -136.5t-136 -56.5q-60 0 -111 35q-62 -67 -115 -146q-247 -371 -202 -859q1 -22 -12.5 -38.5t-34.5 -18.5h-5q-20 0 -35 13.5t-17 33.5q-14 126 -3.5 247.5t29.5 217t54 186t69 155.5t74 125q61 90 132 165q-16 35 -16 77q0 80 56.5 136.5t136.5 56.5 t136.5 -56.5t56.5 -136.5zM1223 953q0 -158 -78 -292t-212.5 -212t-292.5 -78q-64 0 -131 14q-21 5 -32.5 23.5t-6.5 39.5q5 20 23 31.5t39 7.5q51 -13 108 -13q97 0 186 38t153 102t102 153t38 186t-38 186t-102 153t-153 102t-186 38t-186 -38t-153 -102t-102 -153 t-38 -186q0 -114 52 -218q10 -20 3.5 -40t-25.5 -30t-39.5 -3t-30.5 26q-64 123 -64 265q0 119 46.5 227t124.5 186t186 124t226 46q158 0 292.5 -78t212.5 -212.5t78 -292.5z" />
-<glyph unicode="&#xf1d6;" horiz-adv-x="1792" d="M270 730q-8 19 -8 52q0 20 11 49t24 45q-1 22 7.5 53t22.5 43q0 139 92.5 288.5t217.5 209.5q139 66 324 66q133 0 266 -55q49 -21 90 -48t71 -56t55 -68t42 -74t32.5 -84.5t25.5 -89.5t22 -98l1 -5q55 -83 55 -150q0 -14 -9 -40t-9 -38q0 -1 1.5 -3.5t3.5 -5t2 -3.5 q77 -114 120.5 -214.5t43.5 -208.5q0 -43 -19.5 -100t-55.5 -57q-9 0 -19.5 7.5t-19 17.5t-19 26t-16 26.5t-13.5 26t-9 17.5q-1 1 -3 1l-5 -4q-59 -154 -132 -223q20 -20 61.5 -38.5t69 -41.5t35.5 -65q-2 -4 -4 -16t-7 -18q-64 -97 -302 -97q-53 0 -110.5 9t-98 20 t-104.5 30q-15 5 -23 7q-14 4 -46 4.5t-40 1.5q-41 -45 -127.5 -65t-168.5 -20q-35 0 -69 1.5t-93 9t-101 20.5t-74.5 40t-32.5 64q0 40 10 59.5t41 48.5q11 2 40.5 13t49.5 12q4 0 14 2q2 2 2 4l-2 3q-48 11 -108 105.5t-73 156.5l-5 3q-4 0 -12 -20q-18 -41 -54.5 -74.5 t-77.5 -37.5h-1q-4 0 -6 4.5t-5 5.5q-23 54 -23 100q0 275 252 466z" />
-<glyph unicode="&#xf1d7;" horiz-adv-x="2048" d="M580 1075q0 41 -25 66t-66 25q-43 0 -76 -25.5t-33 -65.5q0 -39 33 -64.5t76 -25.5q41 0 66 24.5t25 65.5zM1323 568q0 28 -25.5 50t-65.5 22q-27 0 -49.5 -22.5t-22.5 -49.5q0 -28 22.5 -50.5t49.5 -22.5q40 0 65.5 22t25.5 51zM1087 1075q0 41 -24.5 66t-65.5 25 q-43 0 -76 -25.5t-33 -65.5q0 -39 33 -64.5t76 -25.5q41 0 65.5 24.5t24.5 65.5zM1722 568q0 28 -26 50t-65 22q-27 0 -49.5 -22.5t-22.5 -49.5q0 -28 22.5 -50.5t49.5 -22.5q39 0 65 22t26 51zM1456 965q-31 4 -70 4q-169 0 -311 -77t-223.5 -208.5t-81.5 -287.5 q0 -78 23 -152q-35 -3 -68 -3q-26 0 -50 1.5t-55 6.5t-44.5 7t-54.5 10.5t-50 10.5l-253 -127l72 218q-290 203 -290 490q0 169 97.5 311t264 223.5t363.5 81.5q176 0 332.5 -66t262 -182.5t136.5 -260.5zM2048 404q0 -117 -68.5 -223.5t-185.5 -193.5l55 -181l-199 109 q-150 -37 -218 -37q-169 0 -311 70.5t-223.5 191.5t-81.5 264t81.5 264t223.5 191.5t311 70.5q161 0 303 -70.5t227.5 -192t85.5 -263.5z" />
-<glyph unicode="&#xf1d8;" horiz-adv-x="1792" d="M1764 1525q33 -24 27 -64l-256 -1536q-5 -29 -32 -45q-14 -8 -31 -8q-11 0 -24 5l-453 185l-242 -295q-18 -23 -49 -23q-13 0 -22 4q-19 7 -30.5 23.5t-11.5 36.5v349l864 1059l-1069 -925l-395 162q-37 14 -40 55q-2 40 32 59l1664 960q15 9 32 9q20 0 36 -11z" />
-<glyph unicode="&#xf1d9;" horiz-adv-x="1792" d="M1764 1525q33 -24 27 -64l-256 -1536q-5 -29 -32 -45q-14 -8 -31 -8q-11 0 -24 5l-527 215l-298 -327q-18 -21 -47 -21q-14 0 -23 4q-19 7 -30 23.5t-11 36.5v452l-472 193q-37 14 -40 55q-3 39 32 59l1664 960q35 21 68 -2zM1422 26l221 1323l-1434 -827l336 -137 l863 639l-478 -797z" />
-<glyph unicode="&#xf1da;" d="M1536 640q0 -156 -61 -298t-164 -245t-245 -164t-298 -61q-172 0 -327 72.5t-264 204.5q-7 10 -6.5 22.5t8.5 20.5l137 138q10 9 25 9q16 -2 23 -12q73 -95 179 -147t225 -52q104 0 198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5t-40.5 198.5t-109.5 163.5 t-163.5 109.5t-198.5 40.5q-98 0 -188 -35.5t-160 -101.5l137 -138q31 -30 14 -69q-17 -40 -59 -40h-448q-26 0 -45 19t-19 45v448q0 42 40 59q39 17 69 -14l130 -129q107 101 244.5 156.5t284.5 55.5q156 0 298 -61t245 -164t164 -245t61 -298zM896 928v-448q0 -14 -9 -23 t-23 -9h-320q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h224v352q0 14 9 23t23 9h64q14 0 23 -9t9 -23z" />
-<glyph unicode="&#xf1db;" d="M768 1280q-130 0 -248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5t-51 248.5t-136.5 204t-204 136.5t-248.5 51zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103 t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
-<glyph unicode="&#xf1dc;" horiz-adv-x="1792" d="M1682 -128q-44 0 -132.5 3.5t-133.5 3.5q-44 0 -132 -3.5t-132 -3.5q-24 0 -37 20.5t-13 45.5q0 31 17 46t39 17t51 7t45 15q33 21 33 140l-1 391q0 21 -1 31q-13 4 -50 4h-675q-38 0 -51 -4q-1 -10 -1 -31l-1 -371q0 -142 37 -164q16 -10 48 -13t57 -3.5t45 -15 t20 -45.5q0 -26 -12.5 -48t-36.5 -22q-47 0 -139.5 3.5t-138.5 3.5q-43 0 -128 -3.5t-127 -3.5q-23 0 -35.5 21t-12.5 45q0 30 15.5 45t36 17.5t47.5 7.5t42 15q33 23 33 143l-1 57v813q0 3 0.5 26t0 36.5t-1.5 38.5t-3.5 42t-6.5 36.5t-11 31.5t-16 18q-15 10 -45 12t-53 2 t-41 14t-18 45q0 26 12 48t36 22q46 0 138.5 -3.5t138.5 -3.5q42 0 126.5 3.5t126.5 3.5q25 0 37.5 -22t12.5 -48q0 -30 -17 -43.5t-38.5 -14.5t-49.5 -4t-43 -13q-35 -21 -35 -160l1 -320q0 -21 1 -32q13 -3 39 -3h699q25 0 38 3q1 11 1 32l1 320q0 139 -35 160 q-18 11 -58.5 12.5t-66 13t-25.5 49.5q0 26 12.5 48t37.5 22q44 0 132 -3.5t132 -3.5q43 0 129 3.5t129 3.5q25 0 37.5 -22t12.5 -48q0 -30 -17.5 -44t-40 -14.5t-51.5 -3t-44 -12.5q-35 -23 -35 -161l1 -943q0 -119 34 -140q16 -10 46 -13.5t53.5 -4.5t41.5 -15.5t18 -44.5 q0 -26 -12 -48t-36 -22z" />
-<glyph unicode="&#xf1dd;" horiz-adv-x="1280" d="M1278 1347v-73q0 -29 -18.5 -61t-42.5 -32q-50 0 -54 -1q-26 -6 -32 -31q-3 -11 -3 -64v-1152q0 -25 -18 -43t-43 -18h-108q-25 0 -43 18t-18 43v1218h-143v-1218q0 -25 -17.5 -43t-43.5 -18h-108q-26 0 -43.5 18t-17.5 43v496q-147 12 -245 59q-126 58 -192 179 q-64 117 -64 259q0 166 88 286q88 118 209 159q111 37 417 37h479q25 0 43 -18t18 -43z" />
-<glyph unicode="&#xf1de;" d="M352 128v-128h-352v128h352zM704 256q26 0 45 -19t19 -45v-256q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h256zM864 640v-128h-864v128h864zM224 1152v-128h-224v128h224zM1536 128v-128h-736v128h736zM576 1280q26 0 45 -19t19 -45v-256 q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h256zM1216 768q26 0 45 -19t19 -45v-256q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h256zM1536 640v-128h-224v128h224zM1536 1152v-128h-864v128h864z" />
-<glyph unicode="&#xf1e0;" d="M1216 512q133 0 226.5 -93.5t93.5 -226.5t-93.5 -226.5t-226.5 -93.5t-226.5 93.5t-93.5 226.5q0 12 2 34l-360 180q-92 -86 -218 -86q-133 0 -226.5 93.5t-93.5 226.5t93.5 226.5t226.5 93.5q126 0 218 -86l360 180q-2 22 -2 34q0 133 93.5 226.5t226.5 93.5 t226.5 -93.5t93.5 -226.5t-93.5 -226.5t-226.5 -93.5q-126 0 -218 86l-360 -180q2 -22 2 -34t-2 -34l360 -180q92 86 218 86z" />
-<glyph unicode="&#xf1e1;" d="M1280 341q0 88 -62.5 151t-150.5 63q-84 0 -145 -58l-241 120q2 16 2 23t-2 23l241 120q61 -58 145 -58q88 0 150.5 63t62.5 151t-62.5 150.5t-150.5 62.5t-151 -62.5t-63 -150.5q0 -7 2 -23l-241 -120q-62 57 -145 57q-88 0 -150.5 -62.5t-62.5 -150.5t62.5 -150.5 t150.5 -62.5q83 0 145 57l241 -120q-2 -16 -2 -23q0 -88 63 -150.5t151 -62.5t150.5 62.5t62.5 150.5zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
-<glyph unicode="&#xf1e2;" horiz-adv-x="1792" d="M571 947q-10 25 -34 35t-49 0q-108 -44 -191 -127t-127 -191q-10 -25 0 -49t35 -34q13 -5 24 -5q42 0 60 40q34 84 98.5 148.5t148.5 98.5q25 11 35 35t0 49zM1513 1303l46 -46l-244 -243l68 -68q19 -19 19 -45.5t-19 -45.5l-64 -64q89 -161 89 -343q0 -143 -55.5 -273.5 t-150 -225t-225 -150t-273.5 -55.5t-273.5 55.5t-225 150t-150 225t-55.5 273.5t55.5 273.5t150 225t225 150t273.5 55.5q182 0 343 -89l64 64q19 19 45.5 19t45.5 -19l68 -68zM1521 1359q-10 -10 -22 -10q-13 0 -23 10l-91 90q-9 10 -9 23t9 23q10 9 23 9t23 -9l90 -91 q10 -9 10 -22.5t-10 -22.5zM1751 1129q-11 -9 -23 -9t-23 9l-90 91q-10 9 -10 22.5t10 22.5q9 10 22.5 10t22.5 -10l91 -90q9 -10 9 -23t-9 -23zM1792 1312q0 -14 -9 -23t-23 -9h-96q-14 0 -23 9t-9 23t9 23t23 9h96q14 0 23 -9t9 -23zM1600 1504v-96q0 -14 -9 -23t-23 -9 t-23 9t-9 23v96q0 14 9 23t23 9t23 -9t9 -23zM1751 1449l-91 -90q-10 -10 -22 -10q-13 0 -23 10q-10 9 -10 22.5t10 22.5l90 91q10 9 23 9t23 -9q9 -10 9 -23t-9 -23z" />
-<glyph unicode="&#xf1e3;" horiz-adv-x="1792" d="M609 720l287 208l287 -208l-109 -336h-355zM896 1536q182 0 348 -71t286 -191t191 -286t71 -348t-71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71zM1515 186q149 203 149 454v3l-102 -89l-240 224l63 323 l134 -12q-150 206 -389 282l53 -124l-287 -159l-287 159l53 124q-239 -76 -389 -282l135 12l62 -323l-240 -224l-102 89v-3q0 -251 149 -454l30 132l326 -40l139 -298l-116 -69q117 -39 240 -39t240 39l-116 69l139 298l326 40z" />
-<glyph unicode="&#xf1e4;" horiz-adv-x="1792" d="M448 224v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM256 608v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM832 224v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23 v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM640 608v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM66 768q-28 0 -47 19t-19 46v129h514v-129q0 -27 -19 -46t-46 -19h-383zM1216 224v-192q0 -14 -9 -23t-23 -9h-192 q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1024 608v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1600 224v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23 zM1408 608v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1792 1016v-13h-514v10q0 104 -382 102q-382 -1 -382 -102v-10h-514v13q0 17 8.5 43t34 64t65.5 75.5t110.5 76t160 67.5t224 47.5t293.5 18.5t293 -18.5t224 -47.5 t160.5 -67.5t110.5 -76t65.5 -75.5t34 -64t8.5 -43zM1792 608v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1792 962v-129q0 -27 -19 -46t-46 -19h-384q-27 0 -46 19t-19 46v129h514z" />
-<glyph unicode="&#xf1e5;" horiz-adv-x="1792" d="M704 1216v-768q0 -26 -19 -45t-45 -19v-576q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v512l249 873q7 23 31 23h424zM1024 1216v-704h-256v704h256zM1792 320v-512q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v576q-26 0 -45 19t-19 45v768h424q24 0 31 -23z M736 1504v-224h-352v224q0 14 9 23t23 9h288q14 0 23 -9t9 -23zM1408 1504v-224h-352v224q0 14 9 23t23 9h288q14 0 23 -9t9 -23z" />
-<glyph unicode="&#xf1e6;" horiz-adv-x="1792" d="M1755 1083q37 -37 37 -90t-37 -91l-401 -400l150 -150l-160 -160q-163 -163 -389.5 -186.5t-411.5 100.5l-362 -362h-181v181l362 362q-124 185 -100.5 411.5t186.5 389.5l160 160l150 -150l400 401q38 37 91 37t90 -37t37 -90.5t-37 -90.5l-400 -401l234 -234l401 400 q38 37 91 37t90 -37z" />
-<glyph unicode="&#xf1e7;" horiz-adv-x="1792" d="M873 796q0 -83 -63.5 -142.5t-152.5 -59.5t-152.5 59.5t-63.5 142.5q0 84 63.5 143t152.5 59t152.5 -59t63.5 -143zM1375 796q0 -83 -63 -142.5t-153 -59.5q-89 0 -152.5 59.5t-63.5 142.5q0 84 63.5 143t152.5 59q90 0 153 -59t63 -143zM1600 616v667q0 87 -32 123.5 t-111 36.5h-1112q-83 0 -112.5 -34t-29.5 -126v-673q43 -23 88.5 -40t81 -28t81 -18.5t71 -11t70 -4t58.5 -0.5t56.5 2t44.5 2q68 1 95 -27q6 -6 10 -9q26 -25 61 -51q7 91 118 87q5 0 36.5 -1.5t43 -2t45.5 -1t53 1t54.5 4.5t61 8.5t62 13.5t67 19.5t67.5 27t72 34.5z M1763 621q-121 -149 -372 -252q84 -285 -23 -465q-66 -113 -183 -148q-104 -32 -182 15q-86 51 -82 164l-1 326v1q-8 2 -24.5 6t-23.5 5l-1 -338q4 -114 -83 -164q-79 -47 -183 -15q-117 36 -182 150q-105 180 -22 463q-251 103 -372 252q-25 37 -4 63t60 -1q3 -2 11 -7 t11 -8v694q0 72 47 123t114 51h1257q67 0 114 -51t47 -123v-694l21 15q39 27 60 1t-4 -63z" />
-<glyph unicode="&#xf1e8;" horiz-adv-x="1792" d="M896 1102v-434h-145v434h145zM1294 1102v-434h-145v434h145zM1294 342l253 254v795h-1194v-1049h326v-217l217 217h398zM1692 1536v-1013l-434 -434h-326l-217 -217h-217v217h-398v1158l109 289h1483z" />
-<glyph unicode="&#xf1e9;" d="M773 217v-127q-1 -292 -6 -305q-12 -32 -51 -40q-54 -9 -181.5 38t-162.5 89q-13 15 -17 36q-1 12 4 26q4 10 34 47t181 216q1 0 60 70q15 19 39.5 24.5t49.5 -3.5q24 -10 37.5 -29t12.5 -42zM624 468q-3 -55 -52 -70l-120 -39q-275 -88 -292 -88q-35 2 -54 36 q-12 25 -17 75q-8 76 1 166.5t30 124.5t56 32q13 0 202 -77q70 -29 115 -47l84 -34q23 -9 35.5 -30.5t11.5 -48.5zM1450 171q-7 -54 -91.5 -161t-135.5 -127q-37 -14 -63 7q-14 10 -184 287l-47 77q-14 21 -11.5 46t19.5 46q35 43 83 26q1 -1 119 -40q203 -66 242 -79.5 t47 -20.5q28 -22 22 -61zM778 803q5 -102 -54 -122q-58 -17 -114 71l-378 598q-8 35 19 62q41 43 207.5 89.5t224.5 31.5q40 -10 49 -45q3 -18 22 -305.5t24 -379.5zM1440 695q3 -39 -26 -59q-15 -10 -329 -86q-67 -15 -91 -23l1 2q-23 -6 -46 4t-37 32q-30 47 0 87 q1 1 75 102q125 171 150 204t34 39q28 19 65 2q48 -23 123 -133.5t81 -167.5v-3z" />
-<glyph unicode="&#xf1ea;" horiz-adv-x="2048" d="M1024 1024h-384v-384h384v384zM1152 384v-128h-640v128h640zM1152 1152v-640h-640v640h640zM1792 384v-128h-512v128h512zM1792 640v-128h-512v128h512zM1792 896v-128h-512v128h512zM1792 1152v-128h-512v128h512zM256 192v960h-128v-960q0 -26 19 -45t45 -19t45 19 t19 45zM1920 192v1088h-1536v-1088q0 -33 -11 -64h1483q26 0 45 19t19 45zM2048 1408v-1216q0 -80 -56 -136t-136 -56h-1664q-80 0 -136 56t-56 136v1088h256v128h1792z" />
-<glyph unicode="&#xf1eb;" horiz-adv-x="2048" d="M1024 13q-20 0 -93 73.5t-73 93.5q0 32 62.5 54t103.5 22t103.5 -22t62.5 -54q0 -20 -73 -93.5t-93 -73.5zM1294 284q-2 0 -40 25t-101.5 50t-128.5 25t-128.5 -25t-101 -50t-40.5 -25q-18 0 -93.5 75t-75.5 93q0 13 10 23q78 77 196 121t233 44t233 -44t196 -121 q10 -10 10 -23q0 -18 -75.5 -93t-93.5 -75zM1567 556q-11 0 -23 8q-136 105 -252 154.5t-268 49.5q-85 0 -170.5 -22t-149 -53t-113.5 -62t-79 -53t-31 -22q-17 0 -92 75t-75 93q0 12 10 22q132 132 320 205t380 73t380 -73t320 -205q10 -10 10 -22q0 -18 -75 -93t-92 -75z M1838 827q-11 0 -22 9q-179 157 -371.5 236.5t-420.5 79.5t-420.5 -79.5t-371.5 -236.5q-11 -9 -22 -9q-17 0 -92.5 75t-75.5 93q0 13 10 23q187 186 445 288t527 102t527 -102t445 -288q10 -10 10 -23q0 -18 -75.5 -93t-92.5 -75z" />
-<glyph unicode="&#xf1ec;" horiz-adv-x="1792" d="M384 0q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM768 0q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM384 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5 t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1152 0q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM768 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5 t37.5 90.5zM384 768q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1152 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM768 768q0 53 -37.5 90.5t-90.5 37.5 t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1536 0v384q0 52 -38 90t-90 38t-90 -38t-38 -90v-384q0 -52 38 -90t90 -38t90 38t38 90zM1152 768q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5z M1536 1088v256q0 26 -19 45t-45 19h-1280q-26 0 -45 -19t-19 -45v-256q0 -26 19 -45t45 -19h1280q26 0 45 19t19 45zM1536 768q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1664 1408v-1536q0 -52 -38 -90t-90 -38 h-1408q-52 0 -90 38t-38 90v1536q0 52 38 90t90 38h1408q52 0 90 -38t38 -90z" />
-<glyph unicode="&#xf1ed;" d="M1519 890q18 -84 -4 -204q-87 -444 -565 -444h-44q-25 0 -44 -16.5t-24 -42.5l-4 -19l-55 -346l-2 -15q-5 -26 -24.5 -42.5t-44.5 -16.5h-251q-21 0 -33 15t-9 36q9 56 26.5 168t26.5 168t27 167.5t27 167.5q5 37 43 37h131q133 -2 236 21q175 39 287 144q102 95 155 246 q24 70 35 133q1 6 2.5 7.5t3.5 1t6 -3.5q79 -59 98 -162zM1347 1172q0 -107 -46 -236q-80 -233 -302 -315q-113 -40 -252 -42q0 -1 -90 -1l-90 1q-100 0 -118 -96q-2 -8 -85 -530q-1 -10 -12 -10h-295q-22 0 -36.5 16.5t-11.5 38.5l232 1471q5 29 27.5 48t51.5 19h598 q34 0 97.5 -13t111.5 -32q107 -41 163.5 -123t56.5 -196z" />
-<glyph unicode="&#xf1ee;" horiz-adv-x="1792" d="M441 864q32 0 52 -26q266 -364 362 -774h-446q-127 441 -367 749q-12 16 -3 33.5t29 17.5h373zM1000 507q-49 -199 -125 -393q-79 310 -256 594q40 221 44 449q211 -340 337 -650zM1099 1216q235 -324 384.5 -698.5t184.5 -773.5h-451q-41 665 -553 1472h435zM1792 640 q0 -424 -101 -812q-67 560 -359 1083q-25 301 -106 584q-4 16 5.5 28.5t25.5 12.5h359q21 0 38.5 -13t22.5 -33q115 -409 115 -850z" />
-<glyph unicode="&#xf1f0;" horiz-adv-x="2304" d="M1975 546h-138q14 37 66 179l3 9q4 10 10 26t9 26l12 -55zM531 611l-58 295q-11 54 -75 54h-268l-2 -13q311 -79 403 -336zM710 960l-162 -438l-17 89q-26 70 -85 129.5t-131 88.5l135 -510h175l261 641h-176zM849 318h166l104 642h-166zM1617 944q-69 27 -149 27 q-123 0 -201 -59t-79 -153q-1 -102 145 -174q48 -23 67 -41t19 -39q0 -30 -30 -46t-69 -16q-86 0 -156 33l-22 11l-23 -144q74 -34 185 -34q130 -1 208.5 59t80.5 160q0 106 -140 174q-49 25 -71 42t-22 38q0 22 24.5 38.5t70.5 16.5q70 1 124 -24l15 -8zM2042 960h-128 q-65 0 -87 -54l-246 -588h174l35 96h212q5 -22 20 -96h154zM2304 1280v-1280q0 -52 -38 -90t-90 -38h-2048q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h2048q52 0 90 -38t38 -90z" />
-<glyph unicode="&#xf1f1;" horiz-adv-x="2304" d="M671 603h-13q-47 0 -47 -32q0 -22 20 -22q17 0 28 15t12 39zM1066 639h62v3q1 4 0.5 6.5t-1 7t-2 8t-4.5 6.5t-7.5 5t-11.5 2q-28 0 -36 -38zM1606 603h-12q-48 0 -48 -32q0 -22 20 -22q17 0 28 15t12 39zM1925 629q0 41 -30 41q-19 0 -31 -20t-12 -51q0 -42 28 -42 q20 0 32.5 20t12.5 52zM480 770h87l-44 -262h-56l32 201l-71 -201h-39l-4 200l-34 -200h-53l44 262h81l2 -163zM733 663q0 -6 -4 -42q-16 -101 -17 -113h-47l1 22q-20 -26 -58 -26q-23 0 -37.5 16t-14.5 42q0 39 26 60.5t73 21.5q14 0 23 -1q0 3 0.5 5.5t1 4.5t0.5 3 q0 20 -36 20q-29 0 -59 -10q0 4 7 48q38 11 67 11q74 0 74 -62zM889 721l-8 -49q-22 3 -41 3q-27 0 -27 -17q0 -8 4.5 -12t21.5 -11q40 -19 40 -60q0 -72 -87 -71q-34 0 -58 6q0 2 7 49q29 -8 51 -8q32 0 32 19q0 7 -4.5 11.5t-21.5 12.5q-43 20 -43 59q0 72 84 72 q30 0 50 -4zM977 721h28l-7 -52h-29q-2 -17 -6.5 -40.5t-7 -38.5t-2.5 -18q0 -16 19 -16q8 0 16 2l-8 -47q-21 -7 -40 -7q-43 0 -45 47q0 12 8 56q3 20 25 146h55zM1180 648q0 -23 -7 -52h-111q-3 -22 10 -33t38 -11q30 0 58 14l-9 -54q-30 -8 -57 -8q-95 0 -95 95 q0 55 27.5 90.5t69.5 35.5q35 0 55.5 -21t20.5 -56zM1319 722q-13 -23 -22 -62q-22 2 -31 -24t-25 -128h-56l3 14q22 130 29 199h51l-3 -33q14 21 25.5 29.5t28.5 4.5zM1506 763l-9 -57q-28 14 -50 14q-31 0 -51 -27.5t-20 -70.5q0 -30 13.5 -47t38.5 -17q21 0 48 13 l-10 -59q-28 -8 -50 -8q-45 0 -71.5 30.5t-26.5 82.5q0 70 35.5 114.5t91.5 44.5q26 0 61 -13zM1668 663q0 -18 -4 -42q-13 -79 -17 -113h-46l1 22q-20 -26 -59 -26q-23 0 -37 16t-14 42q0 39 25.5 60.5t72.5 21.5q15 0 23 -1q2 7 2 13q0 20 -36 20q-29 0 -59 -10q0 4 8 48 q38 11 67 11q73 0 73 -62zM1809 722q-14 -24 -21 -62q-23 2 -31.5 -23t-25.5 -129h-56l3 14q19 104 29 199h52q0 -11 -4 -33q15 21 26.5 29.5t27.5 4.5zM1950 770h56l-43 -262h-53l3 19q-23 -23 -52 -23q-31 0 -49.5 24t-18.5 64q0 53 27.5 92t64.5 39q31 0 53 -29z M2061 640q0 148 -72.5 273t-198 198t-273.5 73q-181 0 -328 -110q127 -116 171 -284h-50q-44 150 -158 253q-114 -103 -158 -253h-50q44 168 171 284q-147 110 -328 110q-148 0 -273.5 -73t-198 -198t-72.5 -273t72.5 -273t198 -198t273.5 -73q181 0 328 110 q-120 111 -165 264h50q46 -138 152 -233q106 95 152 233h50q-45 -153 -165 -264q147 -110 328 -110q148 0 273.5 73t198 198t72.5 273zM2304 1280v-1280q0 -52 -38 -90t-90 -38h-2048q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h2048q52 0 90 -38t38 -90z" />
-<glyph unicode="&#xf1f2;" horiz-adv-x="2304" d="M313 759q0 -51 -36 -84q-29 -26 -89 -26h-17v220h17q61 0 89 -27q36 -31 36 -83zM2089 824q0 -52 -64 -52h-19v101h20q63 0 63 -49zM380 759q0 74 -50 120.5t-129 46.5h-95v-333h95q74 0 119 38q60 51 60 128zM410 593h65v333h-65v-333zM730 694q0 40 -20.5 62t-75.5 42 q-29 10 -39.5 19t-10.5 23q0 16 13.5 26.5t34.5 10.5q29 0 53 -27l34 44q-41 37 -98 37q-44 0 -74 -27.5t-30 -67.5q0 -35 18 -55.5t64 -36.5q37 -13 45 -19q19 -12 19 -34q0 -20 -14 -33.5t-36 -13.5q-48 0 -71 44l-42 -40q44 -64 115 -64q51 0 83 30.5t32 79.5zM1008 604 v77q-37 -37 -78 -37q-49 0 -80.5 32.5t-31.5 82.5q0 48 31.5 81.5t77.5 33.5q43 0 81 -38v77q-40 20 -80 20q-74 0 -125.5 -50.5t-51.5 -123.5t51 -123.5t125 -50.5q42 0 81 19zM2240 0v527q-65 -40 -144.5 -84t-237.5 -117t-329.5 -137.5t-417.5 -134.5t-504 -118h1569 q26 0 45 19t19 45zM1389 757q0 75 -53 128t-128 53t-128 -53t-53 -128t53 -128t128 -53t128 53t53 128zM1541 584l144 342h-71l-90 -224l-89 224h-71l142 -342h35zM1714 593h184v56h-119v90h115v56h-115v74h119v57h-184v-333zM2105 593h80l-105 140q76 16 76 94q0 47 -31 73 t-87 26h-97v-333h65v133h9zM2304 1274v-1268q0 -56 -38.5 -95t-93.5 -39h-2040q-55 0 -93.5 39t-38.5 95v1268q0 56 38.5 95t93.5 39h2040q55 0 93.5 -39t38.5 -95z" />
-<glyph unicode="&#xf1f3;" horiz-adv-x="2304" d="M119 854h89l-45 108zM740 328l74 79l-70 79h-163v-49h142v-55h-142v-54h159zM898 406l99 -110v217zM1186 453q0 33 -40 33h-84v-69h83q41 0 41 36zM1475 457q0 29 -42 29h-82v-61h81q43 0 43 32zM1197 923q0 29 -42 29h-82v-60h81q43 0 43 31zM1656 854h89l-44 108z M699 1009v-271h-66v212l-94 -212h-57l-94 212v-212h-132l-25 60h-135l-25 -60h-70l116 271h96l110 -257v257h106l85 -184l77 184h108zM1255 453q0 -20 -5.5 -35t-14 -25t-22.5 -16.5t-26 -10t-31.5 -4.5t-31.5 -1t-32.5 0.5t-29.5 0.5v-91h-126l-80 90l-83 -90h-256v271h260 l80 -89l82 89h207q109 0 109 -89zM964 794v-56h-217v271h217v-57h-152v-49h148v-55h-148v-54h152zM2304 235v-229q0 -55 -38.5 -94.5t-93.5 -39.5h-2040q-55 0 -93.5 39.5t-38.5 94.5v678h111l25 61h55l25 -61h218v46l19 -46h113l20 47v-47h541v99l10 1q10 0 10 -14v-86h279 v23q23 -12 55 -18t52.5 -6.5t63 0.5t51.5 1l25 61h56l25 -61h227v58l34 -58h182v378h-180v-44l-25 44h-185v-44l-23 44h-249q-69 0 -109 -22v22h-172v-22q-24 22 -73 22h-628l-43 -97l-43 97h-198v-44l-22 44h-169l-78 -179v391q0 55 38.5 94.5t93.5 39.5h2040 q55 0 93.5 -39.5t38.5 -94.5v-678h-120q-51 0 -81 -22v22h-177q-55 0 -78 -22v22h-316v-22q-31 22 -87 22h-209v-22q-23 22 -91 22h-234l-54 -58l-50 58h-349v-378h343l55 59l52 -59h211v89h21q59 0 90 13v-102h174v99h8q8 0 10 -2t2 -10v-87h529q57 0 88 24v-24h168 q60 0 95 17zM1546 469q0 -23 -12 -43t-34 -29q25 -9 34 -26t9 -46v-54h-65v45q0 33 -12 43.5t-46 10.5h-69v-99h-65v271h154q48 0 77 -15t29 -58zM1269 936q0 -24 -12.5 -44t-33.5 -29q26 -9 34.5 -25.5t8.5 -46.5v-53h-65q0 9 0.5 26.5t0 25t-3 18.5t-8.5 16t-17.5 8.5 t-29.5 3.5h-70v-98h-64v271l153 -1q49 0 78 -14.5t29 -57.5zM1798 327v-56h-216v271h216v-56h-151v-49h148v-55h-148v-54zM1372 1009v-271h-66v271h66zM2065 357q0 -86 -102 -86h-126v58h126q34 0 34 25q0 16 -17 21t-41.5 5t-49.5 3.5t-42 22.5t-17 55q0 39 26 60t66 21 h130v-57h-119q-36 0 -36 -25q0 -16 17.5 -20.5t42 -4t49 -2.5t42 -21.5t17.5 -54.5zM2304 407v-101q-24 -35 -88 -35h-125v58h125q33 0 33 25q0 13 -12.5 19t-31 5.5t-40 2t-40 8t-31 24t-12.5 48.5q0 39 26.5 60t66.5 21h129v-57h-118q-36 0 -36 -25q0 -20 29 -22t68.5 -5 t56.5 -26zM2139 1008v-270h-92l-122 203v-203h-132l-26 60h-134l-25 -60h-75q-129 0 -129 133q0 138 133 138h63v-59q-7 0 -28 1t-28.5 0.5t-23 -2t-21.5 -6.5t-14.5 -13.5t-11.5 -23t-3 -33.5q0 -38 13.5 -58t49.5 -20h29l92 213h97l109 -256v256h99l114 -188v188h66z" />
-<glyph unicode="&#xf1f4;" horiz-adv-x="2304" d="M745 630q0 -37 -25.5 -61.5t-62.5 -24.5q-29 0 -46.5 16t-17.5 44q0 37 25 62.5t62 25.5q28 0 46.5 -16.5t18.5 -45.5zM1530 779q0 -42 -22 -57t-66 -15l-32 -1l17 107q2 11 13 11h18q22 0 35 -2t25 -12.5t12 -30.5zM1881 630q0 -36 -25.5 -61t-61.5 -25q-29 0 -47 16 t-18 44q0 37 25 62.5t62 25.5q28 0 46.5 -16.5t18.5 -45.5zM513 801q0 59 -38.5 85.5t-100.5 26.5h-160q-19 0 -21 -19l-65 -408q-1 -6 3 -11t10 -5h76q20 0 22 19l18 110q1 8 7 13t15 6.5t17 1.5t19 -1t14 -1q86 0 135 48.5t49 134.5zM822 489l41 261q1 6 -3 11t-10 5h-76 q-14 0 -17 -33q-27 40 -95 40q-72 0 -122.5 -54t-50.5 -127q0 -59 34.5 -94t92.5 -35q28 0 58 12t48 32q-4 -12 -4 -21q0 -16 13 -16h69q19 0 22 19zM1269 752q0 5 -4 9.5t-9 4.5h-77q-11 0 -18 -10l-106 -156l-44 150q-5 16 -22 16h-75q-5 0 -9 -4.5t-4 -9.5q0 -2 19.5 -59 t42 -123t23.5 -70q-82 -112 -82 -120q0 -13 13 -13h77q11 0 18 10l255 368q2 2 2 7zM1649 801q0 59 -38.5 85.5t-100.5 26.5h-159q-20 0 -22 -19l-65 -408q-1 -6 3 -11t10 -5h82q12 0 16 13l18 116q1 8 7 13t15 6.5t17 1.5t19 -1t14 -1q86 0 135 48.5t49 134.5zM1958 489 l41 261q1 6 -3 11t-10 5h-76q-14 0 -17 -33q-26 40 -95 40q-72 0 -122.5 -54t-50.5 -127q0 -59 34.5 -94t92.5 -35q29 0 59 12t47 32q0 -1 -2 -9t-2 -12q0 -16 13 -16h69q19 0 22 19zM2176 898v1q0 14 -13 14h-74q-11 0 -13 -11l-65 -416l-1 -2q0 -5 4 -9.5t10 -4.5h66 q19 0 21 19zM392 764q-5 -35 -26 -46t-60 -11l-33 -1l17 107q2 11 13 11h19q40 0 58 -11.5t12 -48.5zM2304 1280v-1280q0 -52 -38 -90t-90 -38h-2048q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h2048q52 0 90 -38t38 -90z" />
-<glyph unicode="&#xf1f5;" horiz-adv-x="2304" d="M1597 633q0 -69 -21 -106q-19 -35 -52 -35q-23 0 -41 9v224q29 30 57 30q57 0 57 -122zM2035 669h-110q6 98 56 98q51 0 54 -98zM476 534q0 59 -33 91.5t-101 57.5q-36 13 -52 24t-16 25q0 26 38 26q58 0 124 -33l18 112q-67 32 -149 32q-77 0 -123 -38q-48 -39 -48 -109 q0 -58 32.5 -90.5t99.5 -56.5q39 -14 54.5 -25.5t15.5 -27.5q0 -31 -48 -31q-29 0 -70 12.5t-72 30.5l-18 -113q72 -41 168 -41q81 0 129 37q51 41 51 117zM771 749l19 111h-96v135l-129 -21l-18 -114l-46 -8l-17 -103h62v-219q0 -84 44 -120q38 -30 111 -30q32 0 79 11v118 q-32 -7 -44 -7q-42 0 -42 50v197h77zM1087 724v139q-15 3 -28 3q-32 0 -55.5 -16t-33.5 -46l-10 56h-131v-471h150v306q26 31 82 31q16 0 26 -2zM1124 389h150v471h-150v-471zM1746 638q0 122 -45 179q-40 52 -111 52q-64 0 -117 -56l-8 47h-132v-645l150 25v151 q36 -11 68 -11q83 0 134 56q61 65 61 202zM1278 986q0 33 -23 56t-56 23t-56 -23t-23 -56t23 -56.5t56 -23.5t56 23.5t23 56.5zM2176 629q0 113 -48 176q-50 64 -144 64q-96 0 -151.5 -66t-55.5 -180q0 -128 63 -188q55 -55 161 -55q101 0 160 40l-16 103q-57 -31 -128 -31 q-43 0 -63 19q-23 19 -28 66h248q2 14 2 52zM2304 1280v-1280q0 -52 -38 -90t-90 -38h-2048q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h2048q52 0 90 -38t38 -90z" />
-<glyph unicode="&#xf1f6;" horiz-adv-x="2048" d="M1558 684q61 -356 298 -556q0 -52 -38 -90t-90 -38h-448q0 -106 -75 -181t-181 -75t-180.5 74.5t-75.5 180.5zM1024 -176q16 0 16 16t-16 16q-59 0 -101.5 42.5t-42.5 101.5q0 16 -16 16t-16 -16q0 -73 51.5 -124.5t124.5 -51.5zM2026 1424q8 -10 7.5 -23.5t-10.5 -22.5 l-1872 -1622q-10 -8 -23.5 -7t-21.5 11l-84 96q-8 10 -7.5 23.5t10.5 21.5l186 161q-19 32 -19 66q50 42 91 88t85 119.5t74.5 158.5t50 206t19.5 260q0 152 117 282.5t307 158.5q-8 19 -8 39q0 40 28 68t68 28t68 -28t28 -68q0 -20 -8 -39q124 -18 219 -82.5t148 -157.5 l418 363q10 8 23.5 7t21.5 -11z" />
-<glyph unicode="&#xf1f7;" horiz-adv-x="2048" d="M1040 -160q0 16 -16 16q-59 0 -101.5 42.5t-42.5 101.5q0 16 -16 16t-16 -16q0 -73 51.5 -124.5t124.5 -51.5q16 0 16 16zM503 315l877 760q-42 88 -132.5 146.5t-223.5 58.5q-93 0 -169.5 -31.5t-121.5 -80.5t-69 -103t-24 -105q0 -384 -137 -645zM1856 128 q0 -52 -38 -90t-90 -38h-448q0 -106 -75 -181t-181 -75t-180.5 74.5t-75.5 180.5l149 129h757q-166 187 -227 459l111 97q61 -356 298 -556zM1942 1520l84 -96q8 -10 7.5 -23.5t-10.5 -22.5l-1872 -1622q-10 -8 -23.5 -7t-21.5 11l-84 96q-8 10 -7.5 23.5t10.5 21.5l186 161 q-19 32 -19 66q50 42 91 88t85 119.5t74.5 158.5t50 206t19.5 260q0 152 117 282.5t307 158.5q-8 19 -8 39q0 40 28 68t68 28t68 -28t28 -68q0 -20 -8 -39q124 -18 219 -82.5t148 -157.5l418 363q10 8 23.5 7t21.5 -11z" />
-<glyph unicode="&#xf1f8;" horiz-adv-x="1408" d="M512 160v704q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-704q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM768 160v704q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-704q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1024 160v704q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-704 q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM480 1152h448l-48 117q-7 9 -17 11h-317q-10 -2 -17 -11zM1408 1120v-64q0 -14 -9 -23t-23 -9h-96v-948q0 -83 -47 -143.5t-113 -60.5h-832q-66 0 -113 58.5t-47 141.5v952h-96q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h309l70 167 q15 37 54 63t79 26h320q40 0 79 -26t54 -63l70 -167h309q14 0 23 -9t9 -23z" />
-<glyph unicode="&#xf1f9;" d="M1150 462v-109q0 -50 -36.5 -89t-94 -60.5t-118 -32.5t-117.5 -11q-205 0 -342.5 139t-137.5 346q0 203 136 339t339 136q34 0 75.5 -4.5t93 -18t92.5 -34t69 -56.5t28 -81v-109q0 -16 -16 -16h-118q-16 0 -16 16v70q0 43 -65.5 67.5t-137.5 24.5q-140 0 -228.5 -91.5 t-88.5 -237.5q0 -151 91.5 -249.5t233.5 -98.5q68 0 138 24t70 66v70q0 7 4.5 11.5t10.5 4.5h119q6 0 11 -4.5t5 -11.5zM768 1280q-130 0 -248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5 t-51 248.5t-136.5 204t-204 136.5t-248.5 51zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
-<glyph unicode="&#xf1fa;" d="M972 761q0 108 -53.5 169t-147.5 61q-63 0 -124 -30.5t-110 -84.5t-79.5 -137t-30.5 -180q0 -112 53.5 -173t150.5 -61q96 0 176 66.5t122.5 166t42.5 203.5zM1536 640q0 -111 -37 -197t-98.5 -135t-131.5 -74.5t-145 -27.5q-6 0 -15.5 -0.5t-16.5 -0.5q-95 0 -142 53 q-28 33 -33 83q-52 -66 -131.5 -110t-173.5 -44q-161 0 -249.5 95.5t-88.5 269.5q0 157 66 290t179 210.5t246 77.5q87 0 155 -35.5t106 -99.5l2 19l11 56q1 6 5.5 12t9.5 6h118q5 0 13 -11q5 -5 3 -16l-120 -614q-5 -24 -5 -48q0 -39 12.5 -52t44.5 -13q28 1 57 5.5t73 24 t77 50t57 89.5t24 137q0 292 -174 466t-466 174q-130 0 -248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51q228 0 405 144q11 9 24 8t21 -12l41 -49q8 -12 7 -24q-2 -13 -12 -22q-102 -83 -227.5 -128t-258.5 -45q-156 0 -298 61 t-245 164t-164 245t-61 298t61 298t164 245t245 164t298 61q344 0 556 -212t212 -556z" />
-<glyph unicode="&#xf1fb;" horiz-adv-x="1792" d="M1698 1442q94 -94 94 -226.5t-94 -225.5l-225 -223l104 -104q10 -10 10 -23t-10 -23l-210 -210q-10 -10 -23 -10t-23 10l-105 105l-603 -603q-37 -37 -90 -37h-203l-256 -128l-64 64l128 256v203q0 53 37 90l603 603l-105 105q-10 10 -10 23t10 23l210 210q10 10 23 10 t23 -10l104 -104l223 225q93 94 225.5 94t226.5 -94zM512 64l576 576l-192 192l-576 -576v-192h192z" />
-<glyph unicode="&#xf1fc;" horiz-adv-x="1792" d="M1615 1536q70 0 122.5 -46.5t52.5 -116.5q0 -63 -45 -151q-332 -629 -465 -752q-97 -91 -218 -91q-126 0 -216.5 92.5t-90.5 219.5q0 128 92 212l638 579q59 54 130 54zM706 502q39 -76 106.5 -130t150.5 -76l1 -71q4 -213 -129.5 -347t-348.5 -134q-123 0 -218 46.5 t-152.5 127.5t-86.5 183t-29 220q7 -5 41 -30t62 -44.5t59 -36.5t46 -17q41 0 55 37q25 66 57.5 112.5t69.5 76t88 47.5t103 25.5t125 10.5z" />
-<glyph unicode="&#xf1fd;" horiz-adv-x="1792" d="M1792 128v-384h-1792v384q45 0 85 14t59 27.5t47 37.5q30 27 51.5 38t56.5 11t55.5 -11t52.5 -38q29 -25 47 -38t58 -27t86 -14q45 0 85 14.5t58 27t48 37.5q21 19 32.5 27t31 15t43.5 7q35 0 56.5 -11t51.5 -38q28 -24 47 -37.5t59 -27.5t85 -14t85 14t59 27.5t47 37.5 q30 27 51.5 38t56.5 11q34 0 55.5 -11t51.5 -38q28 -24 47 -37.5t59 -27.5t85 -14zM1792 448v-192q-35 0 -55.5 11t-52.5 38q-29 25 -47 38t-58 27t-85 14q-46 0 -86 -14t-58 -27t-47 -38q-22 -19 -33 -27t-31 -15t-44 -7q-35 0 -56.5 11t-51.5 38q-29 25 -47 38t-58 27 t-86 14q-45 0 -85 -14.5t-58 -27t-48 -37.5q-21 -19 -32.5 -27t-31 -15t-43.5 -7q-35 0 -56.5 11t-51.5 38q-28 24 -47 37.5t-59 27.5t-85 14q-46 0 -86 -14t-58 -27t-47 -38q-30 -27 -51.5 -38t-56.5 -11v192q0 80 56 136t136 56h64v448h256v-448h256v448h256v-448h256v448 h256v-448h64q80 0 136 -56t56 -136zM512 1312q0 -77 -36 -118.5t-92 -41.5q-53 0 -90.5 37.5t-37.5 90.5q0 29 9.5 51t23.5 34t31 28t31 31.5t23.5 44.5t9.5 67q38 0 83 -74t45 -150zM1024 1312q0 -77 -36 -118.5t-92 -41.5q-53 0 -90.5 37.5t-37.5 90.5q0 29 9.5 51 t23.5 34t31 28t31 31.5t23.5 44.5t9.5 67q38 0 83 -74t45 -150zM1536 1312q0 -77 -36 -118.5t-92 -41.5q-53 0 -90.5 37.5t-37.5 90.5q0 29 9.5 51t23.5 34t31 28t31 31.5t23.5 44.5t9.5 67q38 0 83 -74t45 -150z" />
-<glyph unicode="&#xf1fe;" horiz-adv-x="2048" d="M2048 0v-128h-2048v1536h128v-1408h1920zM1664 1024l256 -896h-1664v576l448 576l576 -576z" />
-<glyph unicode="&#xf200;" horiz-adv-x="1792" d="M768 646l546 -546q-106 -108 -247.5 -168t-298.5 -60q-209 0 -385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103v-762zM955 640h773q0 -157 -60 -298.5t-168 -247.5zM1664 768h-768v768q209 0 385.5 -103t279.5 -279.5t103 -385.5z" />
-<glyph unicode="&#xf201;" horiz-adv-x="2048" d="M2048 0v-128h-2048v1536h128v-1408h1920zM1920 1248v-435q0 -21 -19.5 -29.5t-35.5 7.5l-121 121l-633 -633q-10 -10 -23 -10t-23 10l-233 233l-416 -416l-192 192l585 585q10 10 23 10t23 -10l233 -233l464 464l-121 121q-16 16 -7.5 35.5t29.5 19.5h435q14 0 23 -9 t9 -23z" />
-<glyph unicode="&#xf202;" horiz-adv-x="1792" d="M1292 832q0 -6 10 -41q10 -29 25 -49.5t41 -34t44 -20t55 -16.5q325 -91 325 -332q0 -146 -105.5 -242.5t-254.5 -96.5q-59 0 -111.5 18.5t-91.5 45.5t-77 74.5t-63 87.5t-53.5 103.5t-43.5 103t-39.5 106.5t-35.5 95q-32 81 -61.5 133.5t-73.5 96.5t-104 64t-142 20 q-96 0 -183 -55.5t-138 -144.5t-51 -185q0 -160 106.5 -279.5t263.5 -119.5q177 0 258 95q56 63 83 116l84 -152q-15 -34 -44 -70l1 -1q-131 -152 -388 -152q-147 0 -269.5 79t-190.5 207.5t-68 274.5q0 105 43.5 206t116 176.5t172 121.5t204.5 46q87 0 159 -19t123.5 -50 t95 -80t72.5 -99t58.5 -117t50.5 -124.5t50 -130.5t55 -127q96 -200 233 -200q81 0 138.5 48.5t57.5 128.5q0 42 -19 72t-50.5 46t-72.5 31.5t-84.5 27t-87.5 34t-81 52t-65 82t-39 122.5q-3 16 -3 33q0 110 87.5 192t198.5 78q78 -3 120.5 -14.5t90.5 -53.5h-1 q12 -11 23 -24.5t26 -36t19 -27.5l-129 -99q-26 49 -54 70v1q-23 21 -97 21q-49 0 -84 -33t-35 -83z" />
-<glyph unicode="&#xf203;" d="M1432 484q0 173 -234 239q-35 10 -53 16.5t-38 25t-29 46.5q0 2 -2 8.5t-3 12t-1 7.5q0 36 24.5 59.5t60.5 23.5q54 0 71 -15h-1q20 -15 39 -51l93 71q-39 54 -49 64q-33 29 -67.5 39t-85.5 10q-80 0 -142 -57.5t-62 -137.5q0 -7 2 -23q16 -96 64.5 -140t148.5 -73 q29 -8 49 -15.5t45 -21.5t38.5 -34.5t13.5 -46.5v-5q1 -58 -40.5 -93t-100.5 -35q-97 0 -167 144q-23 47 -51.5 121.5t-48 125.5t-54 110.5t-74 95.5t-103.5 60.5t-147 24.5q-101 0 -192 -56t-144 -148t-50 -192v-1q4 -108 50.5 -199t133.5 -147.5t196 -56.5q186 0 279 110 q20 27 31 51l-60 109q-42 -80 -99 -116t-146 -36q-115 0 -191 87t-76 204q0 105 82 189t186 84q112 0 170 -53.5t104 -172.5q8 -21 25.5 -68.5t28.5 -76.5t31.5 -74.5t38.5 -74t45.5 -62.5t55.5 -53.5t66 -33t80 -13.5q107 0 183 69.5t76 174.5zM1536 1120v-960 q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
-<glyph unicode="&#xf204;" horiz-adv-x="2048" d="M1152 640q0 104 -40.5 198.5t-109.5 163.5t-163.5 109.5t-198.5 40.5t-198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5t198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5zM1920 640q0 104 -40.5 198.5 t-109.5 163.5t-163.5 109.5t-198.5 40.5h-386q119 -90 188.5 -224t69.5 -288t-69.5 -288t-188.5 -224h386q104 0 198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5zM2048 640q0 -130 -51 -248.5t-136.5 -204t-204 -136.5t-248.5 -51h-768q-130 0 -248.5 51t-204 136.5 t-136.5 204t-51 248.5t51 248.5t136.5 204t204 136.5t248.5 51h768q130 0 248.5 -51t204 -136.5t136.5 -204t51 -248.5z" />
-<glyph unicode="&#xf205;" horiz-adv-x="2048" d="M0 640q0 130 51 248.5t136.5 204t204 136.5t248.5 51h768q130 0 248.5 -51t204 -136.5t136.5 -204t51 -248.5t-51 -248.5t-136.5 -204t-204 -136.5t-248.5 -51h-768q-130 0 -248.5 51t-204 136.5t-136.5 204t-51 248.5zM1408 128q104 0 198.5 40.5t163.5 109.5 t109.5 163.5t40.5 198.5t-40.5 198.5t-109.5 163.5t-163.5 109.5t-198.5 40.5t-198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5z" />
-<glyph unicode="&#xf206;" horiz-adv-x="2304" d="M762 384h-314q-40 0 -57.5 35t6.5 67l188 251q-65 31 -137 31q-132 0 -226 -94t-94 -226t94 -226t226 -94q115 0 203 72.5t111 183.5zM576 512h186q-18 85 -75 148zM1056 512l288 384h-480l-99 -132q105 -103 126 -252h165zM2176 448q0 132 -94 226t-226 94 q-60 0 -121 -24l174 -260q15 -23 10 -49t-27 -40q-15 -11 -36 -11q-35 0 -53 29l-174 260q-93 -95 -93 -225q0 -132 94 -226t226 -94t226 94t94 226zM2304 448q0 -185 -131.5 -316.5t-316.5 -131.5t-316.5 131.5t-131.5 316.5q0 97 39.5 183.5t109.5 149.5l-65 98l-353 -469 q-18 -26 -51 -26h-197q-23 -164 -149 -274t-294 -110q-185 0 -316.5 131.5t-131.5 316.5t131.5 316.5t316.5 131.5q114 0 215 -55l137 183h-224q-26 0 -45 19t-19 45t19 45t45 19h384v-128h435l-85 128h-222q-26 0 -45 19t-19 45t19 45t45 19h256q33 0 53 -28l267 -400 q91 44 192 44q185 0 316.5 -131.5t131.5 -316.5z" />
-<glyph unicode="&#xf207;" d="M384 320q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1408 320q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1362 716l-72 384q-5 23 -22.5 37.5t-40.5 14.5 h-918q-23 0 -40.5 -14.5t-22.5 -37.5l-72 -384q-5 -30 14 -53t49 -23h1062q30 0 49 23t14 53zM1136 1328q0 20 -14 34t-34 14h-640q-20 0 -34 -14t-14 -34t14 -34t34 -14h640q20 0 34 14t14 34zM1536 603v-603h-128v-128q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5 t-37.5 90.5v128h-768v-128q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5v128h-128v603q0 112 25 223l103 454q9 78 97.5 137t230 89t312.5 30t312.5 -30t230 -89t97.5 -137l105 -454q23 -102 23 -223z" />
-<glyph unicode="&#xf208;" horiz-adv-x="2048" d="M1463 704q0 -35 -25 -60.5t-61 -25.5h-702q-36 0 -61 25.5t-25 60.5t25 60.5t61 25.5h702q36 0 61 -25.5t25 -60.5zM1677 704q0 86 -23 170h-982q-36 0 -61 25t-25 60q0 36 25 61t61 25h908q-88 143 -235 227t-320 84q-177 0 -327.5 -87.5t-238 -237.5t-87.5 -327 q0 -86 23 -170h982q36 0 61 -25t25 -60q0 -36 -25 -61t-61 -25h-908q88 -143 235.5 -227t320.5 -84q132 0 253 51.5t208 139t139 208t52 253.5zM2048 959q0 -35 -25 -60t-61 -25h-131q17 -85 17 -170q0 -167 -65.5 -319.5t-175.5 -263t-262.5 -176t-319.5 -65.5 q-246 0 -448.5 133t-301.5 350h-189q-36 0 -61 25t-25 61q0 35 25 60t61 25h132q-17 85 -17 170q0 167 65.5 319.5t175.5 263t262.5 176t320.5 65.5q245 0 447.5 -133t301.5 -350h188q36 0 61 -25t25 -61z" />
-<glyph unicode="&#xf209;" horiz-adv-x="1280" d="M953 1158l-114 -328l117 -21q165 451 165 518q0 56 -38 56q-57 0 -130 -225zM654 471l33 -88q37 42 71 67l-33 5.5t-38.5 7t-32.5 8.5zM362 1367q0 -98 159 -521q18 10 49 10q15 0 75 -5l-121 351q-75 220 -123 220q-19 0 -29 -17.5t-10 -37.5zM283 608q0 -36 51.5 -119 t117.5 -153t100 -70q14 0 25.5 13t11.5 27q0 24 -32 102q-13 32 -32 72t-47.5 89t-61.5 81t-62 32q-20 0 -45.5 -27t-25.5 -47zM125 273q0 -41 25 -104q59 -145 183.5 -227t281.5 -82q227 0 382 170q152 169 152 427q0 43 -1 67t-11.5 62t-30.5 56q-56 49 -211.5 75.5 t-270.5 26.5q-37 0 -49 -11q-12 -5 -12 -35q0 -34 21.5 -60t55.5 -40t77.5 -23.5t87.5 -11.5t85 -4t70 0h23q24 0 40 -19q15 -19 19 -55q-28 -28 -96 -54q-61 -22 -93 -46q-64 -46 -108.5 -114t-44.5 -137q0 -31 18.5 -88.5t18.5 -87.5l-3 -12q-4 -12 -4 -14 q-137 10 -146 216q-8 -2 -41 -2q2 -7 2 -21q0 -53 -40.5 -89.5t-94.5 -36.5q-82 0 -166.5 78t-84.5 159q0 34 33 67q52 -64 60 -76q77 -104 133 -104q12 0 26.5 8.5t14.5 20.5q0 34 -87.5 145t-116.5 111q-43 0 -70 -44.5t-27 -90.5zM11 264q0 101 42.5 163t136.5 88 q-28 74 -28 104q0 62 61 123t122 61q29 0 70 -15q-163 462 -163 567q0 80 41 130.5t119 50.5q131 0 325 -581q6 -17 8 -23q6 16 29 79.5t43.5 118.5t54 127.5t64.5 123t70.5 86.5t76.5 36q71 0 112 -49t41 -122q0 -108 -159 -550q61 -15 100.5 -46t58.5 -78t26 -93.5 t7 -110.5q0 -150 -47 -280t-132 -225t-211 -150t-278 -55q-111 0 -223 42q-149 57 -258 191.5t-109 286.5z" />
-<glyph unicode="&#xf20a;" horiz-adv-x="2048" d="M785 528h207q-14 -158 -98.5 -248.5t-214.5 -90.5q-162 0 -254.5 116t-92.5 316q0 194 93 311.5t233 117.5q148 0 232 -87t97 -247h-203q-5 64 -35.5 99t-81.5 35q-57 0 -88.5 -60.5t-31.5 -177.5q0 -48 5 -84t18 -69.5t40 -51.5t66 -18q95 0 109 139zM1497 528h206 q-14 -158 -98 -248.5t-214 -90.5q-162 0 -254.5 116t-92.5 316q0 194 93 311.5t233 117.5q148 0 232 -87t97 -247h-204q-4 64 -35 99t-81 35q-57 0 -88.5 -60.5t-31.5 -177.5q0 -48 5 -84t18 -69.5t39.5 -51.5t65.5 -18q49 0 76.5 38t33.5 101zM1856 647q0 207 -15.5 307 t-60.5 161q-6 8 -13.5 14t-21.5 15t-16 11q-86 63 -697 63q-625 0 -710 -63q-5 -4 -17.5 -11.5t-21 -14t-14.5 -14.5q-45 -60 -60 -159.5t-15 -308.5q0 -208 15 -307.5t60 -160.5q6 -8 15 -15t20.5 -14t17.5 -12q44 -33 239.5 -49t470.5 -16q610 0 697 65q5 4 17 11t20.5 14 t13.5 16q46 60 61 159t15 309zM2048 1408v-1536h-2048v1536h2048z" />
-<glyph unicode="&#xf20b;" d="M992 912v-496q0 -14 -9 -23t-23 -9h-160q-14 0 -23 9t-9 23v496q0 112 -80 192t-192 80h-272v-1152q0 -14 -9 -23t-23 -9h-160q-14 0 -23 9t-9 23v1344q0 14 9 23t23 9h464q135 0 249 -66.5t180.5 -180.5t66.5 -249zM1376 1376v-880q0 -135 -66.5 -249t-180.5 -180.5 t-249 -66.5h-464q-14 0 -23 9t-9 23v960q0 14 9 23t23 9h160q14 0 23 -9t9 -23v-768h272q112 0 192 80t80 192v880q0 14 9 23t23 9h160q14 0 23 -9t9 -23z" />
-<glyph unicode="&#xf20c;" d="M1311 694v-114q0 -24 -13.5 -38t-37.5 -14h-202q-24 0 -38 14t-14 38v114q0 24 14 38t38 14h202q24 0 37.5 -14t13.5 -38zM821 464v250q0 53 -32.5 85.5t-85.5 32.5h-133q-68 0 -96 -52q-28 52 -96 52h-130q-53 0 -85.5 -32.5t-32.5 -85.5v-250q0 -22 21 -22h55 q22 0 22 22v230q0 24 13.5 38t38.5 14h94q24 0 38 -14t14 -38v-230q0 -22 21 -22h54q22 0 22 22v230q0 24 14 38t38 14h97q24 0 37.5 -14t13.5 -38v-230q0 -22 22 -22h55q21 0 21 22zM1410 560v154q0 53 -33 85.5t-86 32.5h-264q-53 0 -86 -32.5t-33 -85.5v-410 q0 -21 22 -21h55q21 0 21 21v180q31 -42 94 -42h191q53 0 86 32.5t33 85.5zM1536 1176v-1072q0 -96 -68 -164t-164 -68h-1072q-96 0 -164 68t-68 164v1072q0 96 68 164t164 68h1072q96 0 164 -68t68 -164z" />
-<glyph unicode="&#xf20d;" d="M915 450h-294l147 551zM1001 128h311l-324 1024h-440l-324 -1024h311l383 314zM1536 1120v-960q0 -118 -85 -203t-203 -85h-960q-118 0 -203 85t-85 203v960q0 118 85 203t203 85h960q118 0 203 -85t85 -203z" />
-<glyph unicode="&#xf20e;" horiz-adv-x="2048" d="M2048 641q0 -21 -13 -36.5t-33 -19.5l-205 -356q3 -9 3 -18q0 -20 -12.5 -35.5t-32.5 -19.5l-193 -337q3 -8 3 -16q0 -23 -16.5 -40t-40.5 -17q-25 0 -41 18h-400q-17 -20 -43 -20t-43 20h-399q-17 -20 -43 -20q-23 0 -40 16.5t-17 40.5q0 8 4 20l-193 335 q-20 4 -32.5 19.5t-12.5 35.5q0 9 3 18l-206 356q-20 5 -32.5 20.5t-12.5 35.5q0 21 13.5 36.5t33.5 19.5l199 344q0 1 -0.5 3t-0.5 3q0 36 34 51l209 363q-4 10 -4 18q0 24 17 40.5t40 16.5q26 0 44 -21h396q16 21 43 21t43 -21h398q18 21 44 21q23 0 40 -16.5t17 -40.5 q0 -6 -4 -18l207 -358q23 -1 39 -17.5t16 -38.5q0 -13 -7 -27l187 -324q19 -4 31.5 -19.5t12.5 -35.5zM1063 -158h389l-342 354h-143l-342 -354h360q18 16 39 16t39 -16zM112 654q1 -4 1 -13q0 -10 -2 -15l208 -360q2 0 4.5 -1t5.5 -2.5l5 -2.5l188 199v347l-187 194 q-13 -8 -29 -10zM986 1438h-388l190 -200l554 200h-280q-16 -16 -38 -16t-38 16zM1689 226q1 6 5 11l-64 68l-17 -79h76zM1583 226l22 105l-252 266l-296 -307l63 -64h463zM1495 -142l16 28l65 310h-427l333 -343q8 4 13 5zM578 -158h5l342 354h-373v-335l4 -6q14 -5 22 -13 zM552 226h402l64 66l-309 321l-157 -166v-221zM359 226h163v189l-168 -177q4 -8 5 -12zM358 1051q0 -1 0.5 -2t0.5 -2q0 -16 -8 -29l171 -177v269zM552 1121v-311l153 -157l297 314l-223 236zM556 1425l-4 -8v-264l205 74l-191 201q-6 -2 -10 -3zM1447 1438h-16l-621 -224 l213 -225zM1023 946l-297 -315l311 -319l296 307zM688 634l-136 141v-284zM1038 270l-42 -44h85zM1374 618l238 -251l132 624l-3 5l-1 1zM1718 1018q-8 13 -8 29v2l-216 376q-5 1 -13 5l-437 -463l310 -327zM522 1142v223l-163 -282zM522 196h-163l163 -283v283zM1607 196 l-48 -227l130 227h-82zM1729 266l207 361q-2 10 -2 14q0 1 3 16l-171 296l-129 -612l77 -82q5 3 15 7z" />
-<glyph unicode="&#xf210;" d="M0 856q0 131 91.5 226.5t222.5 95.5h742l352 358v-1470q0 -132 -91.5 -227t-222.5 -95h-780q-131 0 -222.5 95t-91.5 227v790zM1232 102l-176 180v425q0 46 -32 79t-78 33h-484q-46 0 -78 -33t-32 -79v-492q0 -46 32.5 -79.5t77.5 -33.5h770z" />
-<glyph unicode="&#xf211;" d="M934 1386q-317 -121 -556 -362.5t-358 -560.5q-20 89 -20 176q0 208 102.5 384.5t278.5 279t384 102.5q82 0 169 -19zM1203 1267q93 -65 164 -155q-389 -113 -674.5 -400.5t-396.5 -676.5q-93 72 -155 162q112 386 395 671t667 399zM470 -67q115 356 379.5 622t619.5 384 q40 -92 54 -195q-292 -120 -516 -345t-343 -518q-103 14 -194 52zM1536 -125q-193 50 -367 115q-135 -84 -290 -107q109 205 274 370.5t369 275.5q-21 -152 -101 -284q65 -175 115 -370z" />
-<glyph unicode="&#xf212;" horiz-adv-x="2048" d="M1893 1144l155 -1272q-131 0 -257 57q-200 91 -393 91q-226 0 -374 -148q-148 148 -374 148q-193 0 -393 -91q-128 -57 -252 -57h-5l155 1272q224 127 482 127q233 0 387 -106q154 106 387 106q258 0 482 -127zM1398 157q129 0 232 -28.5t260 -93.5l-124 1021 q-171 78 -368 78q-224 0 -374 -141q-150 141 -374 141q-197 0 -368 -78l-124 -1021q105 43 165.5 65t148.5 39.5t178 17.5q202 0 374 -108q172 108 374 108zM1438 191l-55 907q-211 -4 -359 -155q-152 155 -374 155q-176 0 -336 -66l-114 -941q124 51 228.5 76t221.5 25 q209 0 374 -102q172 107 374 102z" />
-<glyph unicode="&#xf213;" horiz-adv-x="2048" d="M1500 165v733q0 21 -15 36t-35 15h-93q-20 0 -35 -15t-15 -36v-733q0 -20 15 -35t35 -15h93q20 0 35 15t15 35zM1216 165v531q0 20 -15 35t-35 15h-101q-20 0 -35 -15t-15 -35v-531q0 -20 15 -35t35 -15h101q20 0 35 15t15 35zM924 165v429q0 20 -15 35t-35 15h-101 q-20 0 -35 -15t-15 -35v-429q0 -20 15 -35t35 -15h101q20 0 35 15t15 35zM632 165v362q0 20 -15 35t-35 15h-101q-20 0 -35 -15t-15 -35v-362q0 -20 15 -35t35 -15h101q20 0 35 15t15 35zM2048 311q0 -166 -118 -284t-284 -118h-1244q-166 0 -284 118t-118 284 q0 116 63 214.5t168 148.5q-10 34 -10 73q0 113 80.5 193.5t193.5 80.5q102 0 180 -67q45 183 194 300t338 117q149 0 275 -73.5t199.5 -199.5t73.5 -275q0 -66 -14 -122q135 -33 221 -142.5t86 -247.5z" />
-<glyph unicode="&#xf214;" d="M0 1536h1536v-1392l-776 -338l-760 338v1392zM1436 209v926h-1336v-926l661 -294zM1436 1235v201h-1336v-201h1336zM181 937v-115h-37v115h37zM181 789v-115h-37v115h37zM181 641v-115h-37v115h37zM181 493v-115h-37v115h37zM181 345v-115h-37v115h37zM207 202l15 34 l105 -47l-15 -33zM343 142l15 34l105 -46l-15 -34zM478 82l15 34l105 -46l-15 -34zM614 23l15 33l104 -46l-15 -34zM797 10l105 46l15 -33l-105 -47zM932 70l105 46l15 -34l-105 -46zM1068 130l105 46l15 -34l-105 -46zM1203 189l105 47l15 -34l-105 -46zM259 1389v-36h-114 v36h114zM421 1389v-36h-115v36h115zM583 1389v-36h-115v36h115zM744 1389v-36h-114v36h114zM906 1389v-36h-114v36h114zM1068 1389v-36h-115v36h115zM1230 1389v-36h-115v36h115zM1391 1389v-36h-114v36h114zM181 1049v-79h-37v115h115v-36h-78zM421 1085v-36h-115v36h115z M583 1085v-36h-115v36h115zM744 1085v-36h-114v36h114zM906 1085v-36h-114v36h114zM1068 1085v-36h-115v36h115zM1230 1085v-36h-115v36h115zM1355 970v79h-78v36h115v-115h-37zM1355 822v115h37v-115h-37zM1355 674v115h37v-115h-37zM1355 526v115h37v-115h-37zM1355 378 v115h37v-115h-37zM1355 230v115h37v-115h-37zM760 265q-129 0 -221 91.5t-92 221.5q0 129 92 221t221 92q130 0 221.5 -92t91.5 -221q0 -130 -91.5 -221.5t-221.5 -91.5zM595 646q0 -36 19.5 -56.5t49.5 -25t64 -7t64 -2t49.5 -9t19.5 -30.5q0 -49 -112 -49q-97 0 -123 51 h-3l-31 -63q67 -42 162 -42q29 0 56.5 5t55.5 16t45.5 33t17.5 53q0 46 -27.5 69.5t-67.5 27t-79.5 3t-67 5t-27.5 25.5q0 21 20.5 33t40.5 15t41 3q34 0 70.5 -11t51.5 -34h3l30 58q-3 1 -21 8.5t-22.5 9t-19.5 7t-22 7t-20 4.5t-24 4t-23 1q-29 0 -56.5 -5t-54 -16.5 t-43 -34t-16.5 -53.5z" />
-<glyph unicode="&#xf215;" horiz-adv-x="2048" d="M863 504q0 112 -79.5 191.5t-191.5 79.5t-191 -79.5t-79 -191.5t79 -191t191 -79t191.5 79t79.5 191zM1726 505q0 112 -79 191t-191 79t-191.5 -79t-79.5 -191q0 -113 79.5 -192t191.5 -79t191 79.5t79 191.5zM2048 1314v-1348q0 -44 -31.5 -75.5t-76.5 -31.5h-1832 q-45 0 -76.5 31.5t-31.5 75.5v1348q0 44 31.5 75.5t76.5 31.5h431q44 0 76 -31.5t32 -75.5v-161h754v161q0 44 32 75.5t76 31.5h431q45 0 76.5 -31.5t31.5 -75.5z" />
-<glyph unicode="&#xf216;" horiz-adv-x="2048" d="M1430 953zM1690 749q148 0 253 -98.5t105 -244.5q0 -157 -109 -261.5t-267 -104.5q-85 0 -162 27.5t-138 73.5t-118 106t-109 126.5t-103.5 132.5t-108.5 126t-117 106t-136 73.5t-159 27.5q-154 0 -251.5 -91.5t-97.5 -244.5q0 -157 104 -250t263 -93q100 0 208 37.5 t193 98.5q5 4 21 18.5t30 24t22 9.5q14 0 24.5 -10.5t10.5 -24.5q0 -24 -60 -77q-101 -88 -234.5 -142t-260.5 -54q-133 0 -245.5 58t-180 165t-67.5 241q0 205 141.5 341t347.5 136q120 0 226.5 -43.5t185.5 -113t151.5 -153t139 -167.5t133.5 -153.5t149.5 -113 t172.5 -43.5q102 0 168.5 61.5t66.5 162.5q0 95 -64.5 159t-159.5 64q-30 0 -81.5 -18.5t-68.5 -18.5q-20 0 -35.5 15t-15.5 35q0 18 8.5 57t8.5 59q0 159 -107.5 263t-266.5 104q-58 0 -111.5 -18.5t-84 -40.5t-55.5 -40.5t-33 -18.5q-15 0 -25.5 10.5t-10.5 25.5 q0 19 25 46q59 67 147 103.5t182 36.5q191 0 318 -125.5t127 -315.5q0 -37 -4 -66q57 15 115 15z" />
-<glyph unicode="&#xf217;" horiz-adv-x="1664" d="M1216 832q0 26 -19 45t-45 19h-128v128q0 26 -19 45t-45 19t-45 -19t-19 -45v-128h-128q-26 0 -45 -19t-19 -45t19 -45t45 -19h128v-128q0 -26 19 -45t45 -19t45 19t19 45v128h128q26 0 45 19t19 45zM640 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5 t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1536 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1664 1088v-512q0 -24 -16 -42.5t-41 -21.5l-1044 -122q1 -7 4.5 -21.5t6 -26.5t2.5 -22q0 -16 -24 -64h920 q26 0 45 -19t19 -45t-19 -45t-45 -19h-1024q-26 0 -45 19t-19 45q0 14 11 39.5t29.5 59.5t20.5 38l-177 823h-204q-26 0 -45 19t-19 45t19 45t45 19h256q16 0 28.5 -6.5t20 -15.5t13 -24.5t7.5 -26.5t5.5 -29.5t4.5 -25.5h1201q26 0 45 -19t19 -45z" />
-<glyph unicode="&#xf218;" horiz-adv-x="1664" d="M1280 832q0 26 -19 45t-45 19t-45 -19l-147 -146v293q0 26 -19 45t-45 19t-45 -19t-19 -45v-293l-147 146q-19 19 -45 19t-45 -19t-19 -45t19 -45l256 -256q19 -19 45 -19t45 19l256 256q19 19 19 45zM640 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5 t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1536 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1664 1088v-512q0 -24 -16 -42.5t-41 -21.5l-1044 -122q1 -7 4.5 -21.5t6 -26.5t2.5 -22q0 -16 -24 -64h920 q26 0 45 -19t19 -45t-19 -45t-45 -19h-1024q-26 0 -45 19t-19 45q0 14 11 39.5t29.5 59.5t20.5 38l-177 823h-204q-26 0 -45 19t-19 45t19 45t45 19h256q16 0 28.5 -6.5t20 -15.5t13 -24.5t7.5 -26.5t5.5 -29.5t4.5 -25.5h1201q26 0 45 -19t19 -45z" />
-<glyph unicode="&#xf219;" horiz-adv-x="2048" d="M212 768l623 -665l-300 665h-323zM1024 -4l349 772h-698zM538 896l204 384h-262l-288 -384h346zM1213 103l623 665h-323zM683 896h682l-204 384h-274zM1510 896h346l-288 384h-262zM1651 1382l384 -512q14 -18 13 -41.5t-17 -40.5l-960 -1024q-18 -20 -47 -20t-47 20 l-960 1024q-16 17 -17 40.5t13 41.5l384 512q18 26 51 26h1152q33 0 51 -26z" />
-<glyph unicode="&#xf21a;" horiz-adv-x="2048" d="M1811 -19q19 19 45 19t45 -19l128 -128l-90 -90l-83 83l-83 -83q-18 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-83 83l-83 -83 q-19 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-128 128l90 90l83 -83l83 83q19 19 45 19t45 -19l83 -83l83 83q19 19 45 19t45 -19l83 -83l83 83q19 19 45 19t45 -19l83 -83l83 83q19 19 45 19t45 -19l83 -83l83 83q19 19 45 19t45 -19l83 -83l83 83 q19 19 45 19t45 -19l83 -83zM237 19q-19 -19 -45 -19t-45 19l-128 128l90 90l83 -82l83 82q19 19 45 19t45 -19l83 -82l64 64v293l-210 314q-17 26 -7 56.5t40 40.5l177 58v299h128v128h256v128h256v-128h256v-128h128v-299l177 -58q30 -10 40 -40.5t-7 -56.5l-210 -314 v-293l19 18q19 19 45 19t45 -19l83 -82l83 82q19 19 45 19t45 -19l128 -128l-90 -90l-83 83l-83 -83q-18 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-83 83l-83 -83 q-19 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-83 83zM640 1152v-128l384 128l384 -128v128h-128v128h-512v-128h-128z" />
-<glyph unicode="&#xf21b;" d="M576 0l96 448l-96 128l-128 64zM832 0l128 640l-128 -64l-96 -128zM992 1010q-2 4 -4 6q-10 8 -96 8q-70 0 -167 -19q-7 -2 -21 -2t-21 2q-97 19 -167 19q-86 0 -96 -8q-2 -2 -4 -6q2 -18 4 -27q2 -3 7.5 -6.5t7.5 -10.5q2 -4 7.5 -20.5t7 -20.5t7.5 -17t8.5 -17t9 -14 t12 -13.5t14 -9.5t17.5 -8t20.5 -4t24.5 -2q36 0 59 12.5t32.5 30t14.5 34.5t11.5 29.5t17.5 12.5h12q11 0 17.5 -12.5t11.5 -29.5t14.5 -34.5t32.5 -30t59 -12.5q13 0 24.5 2t20.5 4t17.5 8t14 9.5t12 13.5t9 14t8.5 17t7.5 17t7 20.5t7.5 20.5q2 7 7.5 10.5t7.5 6.5 q2 9 4 27zM1408 131q0 -121 -73 -190t-194 -69h-874q-121 0 -194 69t-73 190q0 61 4.5 118t19 125.5t37.5 123.5t63.5 103.5t93.5 74.5l-90 220h214q-22 64 -22 128q0 12 2 32q-194 40 -194 96q0 57 210 99q17 62 51.5 134t70.5 114q32 37 76 37q30 0 84 -31t84 -31t84 31 t84 31q44 0 76 -37q36 -42 70.5 -114t51.5 -134q210 -42 210 -99q0 -56 -194 -96q7 -81 -20 -160h214l-82 -225q63 -33 107.5 -96.5t65.5 -143.5t29 -151.5t8 -148.5z" />
-<glyph unicode="&#xf21c;" horiz-adv-x="2304" d="M2301 500q12 -103 -22 -198.5t-99 -163.5t-158.5 -106t-196.5 -31q-161 11 -279.5 125t-134.5 274q-12 111 27.5 210.5t118.5 170.5l-71 107q-96 -80 -151 -194t-55 -244q0 -27 -18.5 -46.5t-45.5 -19.5h-256h-69q-23 -164 -149 -274t-294 -110q-185 0 -316.5 131.5 t-131.5 316.5t131.5 316.5t316.5 131.5q76 0 152 -27l24 45q-123 110 -304 110h-64q-26 0 -45 19t-19 45t19 45t45 19h128q78 0 145 -13.5t116.5 -38.5t71.5 -39.5t51 -36.5h512h115l-85 128h-222q-30 0 -49 22.5t-14 52.5q4 23 23 38t43 15h253q33 0 53 -28l70 -105 l114 114q19 19 46 19h101q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-179l115 -172q131 63 275 36q143 -26 244 -134.5t118 -253.5zM448 128q115 0 203 72.5t111 183.5h-314q-35 0 -55 31q-18 32 -1 63l147 277q-47 13 -91 13q-132 0 -226 -94t-94 -226t94 -226 t226 -94zM1856 128q132 0 226 94t94 226t-94 226t-226 94q-60 0 -121 -24l174 -260q15 -23 10 -49t-27 -40q-15 -11 -36 -11q-35 0 -53 29l-174 260q-93 -95 -93 -225q0 -132 94 -226t226 -94z" />
-<glyph unicode="&#xf21d;" d="M1408 0q0 -63 -61.5 -113.5t-164 -81t-225 -46t-253.5 -15.5t-253.5 15.5t-225 46t-164 81t-61.5 113.5q0 49 33 88.5t91 66.5t118 44.5t131 29.5q26 5 48 -10.5t26 -41.5q5 -26 -10.5 -48t-41.5 -26q-58 -10 -106 -23.5t-76.5 -25.5t-48.5 -23.5t-27.5 -19.5t-8.5 -12 q3 -11 27 -26.5t73 -33t114 -32.5t160.5 -25t201.5 -10t201.5 10t160.5 25t114 33t73 33.5t27 27.5q-1 4 -8.5 11t-27.5 19t-48.5 23.5t-76.5 25t-106 23.5q-26 4 -41.5 26t-10.5 48q4 26 26 41.5t48 10.5q71 -12 131 -29.5t118 -44.5t91 -66.5t33 -88.5zM1024 896v-384 q0 -26 -19 -45t-45 -19h-64v-384q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v384h-64q-26 0 -45 19t-19 45v384q0 53 37.5 90.5t90.5 37.5h384q53 0 90.5 -37.5t37.5 -90.5zM928 1280q0 -93 -65.5 -158.5t-158.5 -65.5t-158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5 t158.5 -65.5t65.5 -158.5z" />
-<glyph unicode="&#xf21e;" horiz-adv-x="1792" d="M1280 512h305q-5 -6 -10 -10.5t-9 -7.5l-3 -4l-623 -600q-18 -18 -44 -18t-44 18l-624 602q-5 2 -21 20h369q22 0 39.5 13.5t22.5 34.5l70 281l190 -667q6 -20 23 -33t39 -13q21 0 38 13t23 33l146 485l56 -112q18 -35 57 -35zM1792 940q0 -145 -103 -300h-369l-111 221 q-8 17 -25.5 27t-36.5 8q-45 -5 -56 -46l-129 -430l-196 686q-6 20 -23.5 33t-39.5 13t-39 -13.5t-22 -34.5l-116 -464h-423q-103 155 -103 300q0 220 127 344t351 124q62 0 126.5 -21.5t120 -58t95.5 -68.5t76 -68q36 36 76 68t95.5 68.5t120 58t126.5 21.5q224 0 351 -124 t127 -344z" />
-<glyph unicode="&#xf221;" horiz-adv-x="1280" d="M1152 960q0 -221 -147.5 -384.5t-364.5 -187.5v-260h224q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-224v-224q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v224h-224q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h224v260q-150 16 -271.5 103t-186 224t-52.5 292 q11 134 80.5 249t182 188t245.5 88q170 19 319 -54t236 -212t87 -306zM128 960q0 -185 131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5z" />
-<glyph unicode="&#xf222;" d="M1472 1408q26 0 45 -19t19 -45v-416q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v262l-382 -383q126 -156 126 -359q0 -117 -45.5 -223.5t-123 -184t-184 -123t-223.5 -45.5t-223.5 45.5t-184 123t-123 184t-45.5 223.5t45.5 223.5t123 184t184 123t223.5 45.5 q203 0 359 -126l382 382h-261q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h416zM576 0q185 0 316.5 131.5t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
-<glyph unicode="&#xf223;" horiz-adv-x="1280" d="M830 1220q145 -72 233.5 -210.5t88.5 -305.5q0 -221 -147.5 -384.5t-364.5 -187.5v-132h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-96v-96q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v96h-96q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96v132q-217 24 -364.5 187.5 t-147.5 384.5q0 167 88.5 305.5t233.5 210.5q-165 96 -228 273q-6 16 3.5 29.5t26.5 13.5h69q21 0 29 -20q44 -106 140 -171t214 -65t214 65t140 171q8 20 37 20h61q17 0 26.5 -13.5t3.5 -29.5q-63 -177 -228 -273zM576 256q185 0 316.5 131.5t131.5 316.5t-131.5 316.5 t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
-<glyph unicode="&#xf224;" d="M1024 1504q0 14 9 23t23 9h288q26 0 45 -19t19 -45v-288q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v134l-254 -255q126 -158 126 -359q0 -221 -147.5 -384.5t-364.5 -187.5v-132h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-96v-96q0 -14 -9 -23t-23 -9h-64 q-14 0 -23 9t-9 23v96h-96q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96v132q-149 16 -270.5 103t-186.5 223.5t-53 291.5q16 204 160 353.5t347 172.5q118 14 228 -19t198 -103l255 254h-134q-14 0 -23 9t-9 23v64zM576 256q185 0 316.5 131.5t131.5 316.5t-131.5 316.5 t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
-<glyph unicode="&#xf225;" horiz-adv-x="1792" d="M1280 1504q0 14 9 23t23 9h288q26 0 45 -19t19 -45v-288q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v134l-254 -255q126 -158 126 -359q0 -221 -147.5 -384.5t-364.5 -187.5v-132h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-96v-96q0 -14 -9 -23t-23 -9h-64 q-14 0 -23 9t-9 23v96h-96q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96v132q-217 24 -364.5 187.5t-147.5 384.5q0 201 126 359l-52 53l-101 -111q-9 -10 -22 -10.5t-23 7.5l-48 44q-10 8 -10.5 21.5t8.5 23.5l105 115l-111 112v-134q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9 t-9 23v288q0 26 19 45t45 19h288q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-133l106 -107l86 94q9 10 22 10.5t23 -7.5l48 -44q10 -8 10.5 -21.5t-8.5 -23.5l-90 -99l57 -56q158 126 359 126t359 -126l255 254h-134q-14 0 -23 9t-9 23v64zM832 256q185 0 316.5 131.5 t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
-<glyph unicode="&#xf226;" horiz-adv-x="1792" d="M1790 1007q12 -155 -52.5 -292t-186 -224t-271.5 -103v-260h224q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-224v-224q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v224h-512v-224q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v224h-224q-14 0 -23 9t-9 23v64q0 14 9 23 t23 9h224v260q-150 16 -271.5 103t-186 224t-52.5 292q17 206 164.5 356.5t352.5 169.5q206 21 377 -94q171 115 377 94q205 -19 352.5 -169.5t164.5 -356.5zM896 647q128 131 128 313t-128 313q-128 -131 -128 -313t128 -313zM576 512q115 0 218 57q-154 165 -154 391 q0 224 154 391q-103 57 -218 57q-185 0 -316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5zM1152 128v260q-137 15 -256 94q-119 -79 -256 -94v-260h512zM1216 512q185 0 316.5 131.5t131.5 316.5t-131.5 316.5t-316.5 131.5q-115 0 -218 -57q154 -167 154 -391 q0 -226 -154 -391q103 -57 218 -57z" />
-<glyph unicode="&#xf227;" horiz-adv-x="1920" d="M1536 1120q0 14 9 23t23 9h288q26 0 45 -19t19 -45v-288q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v134l-254 -255q76 -95 107.5 -214t9.5 -247q-31 -182 -166 -312t-318 -156q-210 -29 -384.5 80t-241.5 300q-117 6 -221 57.5t-177.5 133t-113.5 192.5t-32 230 q9 135 78 252t182 191.5t248 89.5q118 14 227.5 -19t198.5 -103l255 254h-134q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h288q26 0 45 -19t19 -45v-288q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v134l-254 -255q59 -74 93 -169q182 -9 328 -124l255 254h-134q-14 0 -23 9 t-9 23v64zM1024 704q0 20 -4 58q-162 -25 -271 -150t-109 -292q0 -20 4 -58q162 25 271 150t109 292zM128 704q0 -168 111 -294t276 -149q-3 29 -3 59q0 210 135 369.5t338 196.5q-53 120 -163.5 193t-245.5 73q-185 0 -316.5 -131.5t-131.5 -316.5zM1088 -128 q185 0 316.5 131.5t131.5 316.5q0 168 -111 294t-276 149q3 -29 3 -59q0 -210 -135 -369.5t-338 -196.5q53 -120 163.5 -193t245.5 -73z" />
-<glyph unicode="&#xf228;" horiz-adv-x="2048" d="M1664 1504q0 14 9 23t23 9h288q26 0 45 -19t19 -45v-288q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v134l-254 -255q76 -95 107.5 -214t9.5 -247q-32 -180 -164.5 -310t-313.5 -157q-223 -34 -409 90q-117 -78 -256 -93v-132h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23 t-23 -9h-96v-96q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v96h-96q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96v132q-155 17 -279.5 109.5t-187 237.5t-39.5 307q25 187 159.5 322.5t320.5 164.5q224 34 410 -90q146 97 320 97q201 0 359 -126l255 254h-134q-14 0 -23 9 t-9 23v64zM896 391q128 131 128 313t-128 313q-128 -131 -128 -313t128 -313zM128 704q0 -185 131.5 -316.5t316.5 -131.5q117 0 218 57q-154 167 -154 391t154 391q-101 57 -218 57q-185 0 -316.5 -131.5t-131.5 -316.5zM1216 256q185 0 316.5 131.5t131.5 316.5 t-131.5 316.5t-316.5 131.5q-117 0 -218 -57q154 -167 154 -391t-154 -391q101 -57 218 -57z" />
-<glyph unicode="&#xf229;" d="M1472 1408q26 0 45 -19t19 -45v-416q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v262l-213 -214l140 -140q9 -10 9 -23t-9 -22l-46 -46q-9 -9 -22 -9t-23 9l-140 141l-78 -79q126 -156 126 -359q0 -117 -45.5 -223.5t-123 -184t-184 -123t-223.5 -45.5t-223.5 45.5 t-184 123t-123 184t-45.5 223.5t45.5 223.5t123 184t184 123t223.5 45.5q203 0 359 -126l78 78l-172 172q-9 10 -9 23t9 22l46 46q9 9 22 9t23 -9l172 -172l213 213h-261q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h416zM576 0q185 0 316.5 131.5t131.5 316.5t-131.5 316.5 t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
-<glyph unicode="&#xf22a;" horiz-adv-x="1280" d="M640 892q217 -24 364.5 -187.5t147.5 -384.5q0 -167 -87 -306t-236 -212t-319 -54q-133 15 -245.5 88t-182 188t-80.5 249q-12 155 52.5 292t186 224t271.5 103v132h-160q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h160v165l-92 -92q-10 -9 -23 -9t-22 9l-46 46q-9 9 -9 22 t9 23l202 201q19 19 45 19t45 -19l202 -201q9 -10 9 -23t-9 -22l-46 -46q-9 -9 -22 -9t-23 9l-92 92v-165h160q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-160v-132zM576 -128q185 0 316.5 131.5t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5 t131.5 -316.5t316.5 -131.5z" />
-<glyph unicode="&#xf22b;" horiz-adv-x="2048" d="M1901 621q19 -19 19 -45t-19 -45l-294 -294q-9 -10 -22.5 -10t-22.5 10l-45 45q-10 9 -10 22.5t10 22.5l185 185h-294v-224q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v224h-132q-24 -217 -187.5 -364.5t-384.5 -147.5q-167 0 -306 87t-212 236t-54 319q15 133 88 245.5 t188 182t249 80.5q155 12 292 -52.5t224 -186t103 -271.5h132v224q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-224h294l-185 185q-10 9 -10 22.5t10 22.5l45 45q9 10 22.5 10t22.5 -10zM576 128q185 0 316.5 131.5t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5 t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
-<glyph unicode="&#xf22c;" horiz-adv-x="1280" d="M1152 960q0 -221 -147.5 -384.5t-364.5 -187.5v-612q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v612q-217 24 -364.5 187.5t-147.5 384.5q0 117 45.5 223.5t123 184t184 123t223.5 45.5t223.5 -45.5t184 -123t123 -184t45.5 -223.5zM576 512q185 0 316.5 131.5 t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
-<glyph unicode="&#xf22d;" horiz-adv-x="1280" d="M1024 576q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5zM1152 576q0 -117 -45.5 -223.5t-123 -184t-184 -123t-223.5 -45.5t-223.5 45.5t-184 123t-123 184t-45.5 223.5t45.5 223.5t123 184t184 123 t223.5 45.5t223.5 -45.5t184 -123t123 -184t45.5 -223.5z" />
-<glyph unicode="&#xf22e;" horiz-adv-x="1792" />
-<glyph unicode="&#xf22f;" horiz-adv-x="1792" />
-<glyph unicode="&#xf230;" d="M1451 1408q35 0 60 -25t25 -60v-1366q0 -35 -25 -60t-60 -25h-391v595h199l30 232h-229v148q0 56 23.5 84t91.5 28l122 1v207q-63 9 -178 9q-136 0 -217.5 -80t-81.5 -226v-171h-200v-232h200v-595h-735q-35 0 -60 25t-25 60v1366q0 35 25 60t60 25h1366z" />
-<glyph unicode="&#xf231;" horiz-adv-x="1280" d="M0 939q0 108 37.5 203.5t103.5 166.5t152 123t185 78t202 26q158 0 294 -66.5t221 -193.5t85 -287q0 -96 -19 -188t-60 -177t-100 -149.5t-145 -103t-189 -38.5q-68 0 -135 32t-96 88q-10 -39 -28 -112.5t-23.5 -95t-20.5 -71t-26 -71t-32 -62.5t-46 -77.5t-62 -86.5 l-14 -5l-9 10q-15 157 -15 188q0 92 21.5 206.5t66.5 287.5t52 203q-32 65 -32 169q0 83 52 156t132 73q61 0 95 -40.5t34 -102.5q0 -66 -44 -191t-44 -187q0 -63 45 -104.5t109 -41.5q55 0 102 25t78.5 68t56 95t38 110.5t20 111t6.5 99.5q0 173 -109.5 269.5t-285.5 96.5 q-200 0 -334 -129.5t-134 -328.5q0 -44 12.5 -85t27 -65t27 -45.5t12.5 -30.5q0 -28 -15 -73t-37 -45q-2 0 -17 3q-51 15 -90.5 56t-61 94.5t-32.5 108t-11 106.5z" />
-<glyph unicode="&#xf232;" d="M985 562q13 0 97.5 -44t89.5 -53q2 -5 2 -15q0 -33 -17 -76q-16 -39 -71 -65.5t-102 -26.5q-57 0 -190 62q-98 45 -170 118t-148 185q-72 107 -71 194v8q3 91 74 158q24 22 52 22q6 0 18 -1.5t19 -1.5q19 0 26.5 -6.5t15.5 -27.5q8 -20 33 -88t25 -75q0 -21 -34.5 -57.5 t-34.5 -46.5q0 -7 5 -15q34 -73 102 -137q56 -53 151 -101q12 -7 22 -7q15 0 54 48.5t52 48.5zM782 32q127 0 243.5 50t200.5 134t134 200.5t50 243.5t-50 243.5t-134 200.5t-200.5 134t-243.5 50t-243.5 -50t-200.5 -134t-134 -200.5t-50 -243.5q0 -203 120 -368l-79 -233 l242 77q158 -104 345 -104zM782 1414q153 0 292.5 -60t240.5 -161t161 -240.5t60 -292.5t-60 -292.5t-161 -240.5t-240.5 -161t-292.5 -60q-195 0 -365 94l-417 -134l136 405q-108 178 -108 389q0 153 60 292.5t161 240.5t240.5 161t292.5 60z" />
-<glyph unicode="&#xf233;" horiz-adv-x="1792" d="M128 128h1024v128h-1024v-128zM128 640h1024v128h-1024v-128zM1696 192q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM128 1152h1024v128h-1024v-128zM1696 704q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM1696 1216 q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM1792 384v-384h-1792v384h1792zM1792 896v-384h-1792v384h1792zM1792 1408v-384h-1792v384h1792z" />
-<glyph unicode="&#xf234;" horiz-adv-x="2048" d="M704 640q-159 0 -271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5t-112.5 -271.5t-271.5 -112.5zM1664 512h352q13 0 22.5 -9.5t9.5 -22.5v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-352v-352q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5 t-9.5 22.5v352h-352q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h352v352q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5v-352zM928 288q0 -52 38 -90t90 -38h256v-238q-68 -50 -171 -50h-874q-121 0 -194 69t-73 190q0 53 3.5 103.5t14 109t26.5 108.5 t43 97.5t62 81t85.5 53.5t111.5 20q19 0 39 -17q79 -61 154.5 -91.5t164.5 -30.5t164.5 30.5t154.5 91.5q20 17 39 17q132 0 217 -96h-223q-52 0 -90 -38t-38 -90v-192z" />
-<glyph unicode="&#xf235;" horiz-adv-x="2048" d="M704 640q-159 0 -271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5t-112.5 -271.5t-271.5 -112.5zM1781 320l249 -249q9 -9 9 -23q0 -13 -9 -22l-136 -136q-9 -9 -22 -9q-14 0 -23 9l-249 249l-249 -249q-9 -9 -23 -9q-13 0 -22 9l-136 136 q-9 9 -9 22q0 14 9 23l249 249l-249 249q-9 9 -9 23q0 13 9 22l136 136q9 9 22 9q14 0 23 -9l249 -249l249 249q9 9 23 9q13 0 22 -9l136 -136q9 -9 9 -22q0 -14 -9 -23zM1283 320l-181 -181q-37 -37 -37 -91q0 -53 37 -90l83 -83q-21 -3 -44 -3h-874q-121 0 -194 69 t-73 190q0 53 3.5 103.5t14 109t26.5 108.5t43 97.5t62 81t85.5 53.5t111.5 20q19 0 39 -17q154 -122 319 -122t319 122q20 17 39 17q28 0 57 -6q-28 -27 -41 -50t-13 -56q0 -54 37 -91z" />
-<glyph unicode="&#xf236;" horiz-adv-x="2048" d="M256 512h1728q26 0 45 -19t19 -45v-448h-256v256h-1536v-256h-256v1216q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-704zM832 832q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM2048 576v64q0 159 -112.5 271.5t-271.5 112.5h-704 q-26 0 -45 -19t-19 -45v-384h1152z" />
-<glyph unicode="&#xf237;" d="M1536 1536l-192 -448h192v-192h-274l-55 -128h329v-192h-411l-357 -832l-357 832h-411v192h329l-55 128h-274v192h192l-192 448h256l323 -768h378l323 768h256zM768 320l108 256h-216z" />
-<glyph unicode="&#xf238;" d="M1088 1536q185 0 316.5 -93.5t131.5 -226.5v-896q0 -130 -125.5 -222t-305.5 -97l213 -202q16 -15 8 -35t-30 -20h-1056q-22 0 -30 20t8 35l213 202q-180 5 -305.5 97t-125.5 222v896q0 133 131.5 226.5t316.5 93.5h640zM768 192q80 0 136 56t56 136t-56 136t-136 56 t-136 -56t-56 -136t56 -136t136 -56zM1344 768v512h-1152v-512h1152z" />
-<glyph unicode="&#xf239;" d="M1088 1536q185 0 316.5 -93.5t131.5 -226.5v-896q0 -130 -125.5 -222t-305.5 -97l213 -202q16 -15 8 -35t-30 -20h-1056q-22 0 -30 20t8 35l213 202q-180 5 -305.5 97t-125.5 222v896q0 133 131.5 226.5t316.5 93.5h640zM288 224q66 0 113 47t47 113t-47 113t-113 47 t-113 -47t-47 -113t47 -113t113 -47zM704 768v512h-544v-512h544zM1248 224q66 0 113 47t47 113t-47 113t-113 47t-113 -47t-47 -113t47 -113t113 -47zM1408 768v512h-576v-512h576z" />
-<glyph unicode="&#xf23a;" horiz-adv-x="1792" d="M597 1115v-1173q0 -25 -12.5 -42.5t-36.5 -17.5q-17 0 -33 8l-465 233q-21 10 -35.5 33.5t-14.5 46.5v1140q0 20 10 34t29 14q14 0 44 -15l511 -256q3 -3 3 -5zM661 1014l534 -866l-534 266v600zM1792 996v-1054q0 -25 -14 -40.5t-38 -15.5t-47 13l-441 220zM1789 1116 q0 -3 -256.5 -419.5t-300.5 -487.5l-390 634l324 527q17 28 52 28q14 0 26 -6l541 -270q4 -2 4 -6z" />
-<glyph unicode="&#xf23b;" d="M809 532l266 499h-112l-157 -312q-24 -48 -44 -92l-42 92l-155 312h-120l263 -493v-324h101v318zM1536 1408v-1536h-1536v1536h1536z" />
-<glyph unicode="&#xf23c;" horiz-adv-x="2296" d="M478 -139q-8 -16 -27 -34.5t-37 -25.5q-25 -9 -51.5 3.5t-28.5 31.5q-1 22 40 55t68 38q23 4 34 -21.5t2 -46.5zM1819 -139q7 -16 26 -34.5t38 -25.5q25 -9 51.5 3.5t27.5 31.5q2 22 -39.5 55t-68.5 38q-22 4 -33 -21.5t-2 -46.5zM1867 -30q13 -27 56.5 -59.5t77.5 -41.5 q45 -13 82 4.5t37 50.5q0 46 -67.5 100.5t-115.5 59.5q-40 5 -63.5 -37.5t-6.5 -76.5zM428 -30q-13 -27 -56 -59.5t-77 -41.5q-45 -13 -82 4.5t-37 50.5q0 46 67.5 100.5t115.5 59.5q40 5 63 -37.5t6 -76.5zM1158 1094h1q-41 0 -76 -15q27 -8 44 -30.5t17 -49.5 q0 -35 -27 -60t-65 -25q-52 0 -80 43q-5 -23 -5 -42q0 -74 56 -126.5t135 -52.5q80 0 136 52.5t56 126.5t-56 126.5t-136 52.5zM1462 1312q-99 109 -220.5 131.5t-245.5 -44.5q27 60 82.5 96.5t118 39.5t121.5 -17t99.5 -74.5t44.5 -131.5zM2212 73q8 -11 -11 -42 q7 -23 7 -40q1 -56 -44.5 -112.5t-109.5 -91.5t-118 -37q-48 -2 -92 21.5t-66 65.5q-687 -25 -1259 0q-23 -41 -66.5 -65t-92.5 -22q-86 3 -179.5 80.5t-92.5 160.5q2 22 7 40q-19 31 -11 42q6 10 31 1q14 22 41 51q-7 29 2 38q11 10 39 -4q29 20 59 34q0 29 13 37 q23 12 51 -16q35 5 61 -2q18 -4 38 -19v73q-11 0 -18 2q-53 10 -97 44.5t-55 87.5q-9 38 0 81q15 62 93 95q2 17 19 35.5t36 23.5t33 -7.5t19 -30.5h13q46 -5 60 -23q3 -3 5 -7q10 1 30.5 3.5t30.5 3.5q-15 11 -30 17q-23 40 -91 43q0 6 1 10q-62 2 -118.5 18.5t-84.5 47.5 q-32 36 -42.5 92t-2.5 112q16 126 90 179q23 16 52 4.5t32 -40.5q0 -1 1.5 -14t2.5 -21t3 -20t5.5 -19t8.5 -10q27 -14 76 -12q48 46 98 74q-40 4 -162 -14l47 46q61 58 163 111q145 73 282 86q-20 8 -41 15.5t-47 14t-42.5 10.5t-47.5 11t-43 10q595 126 904 -139 q98 -84 158 -222q85 -10 121 9h1q5 3 8.5 10t5.5 19t3 19.5t3 21.5l1 14q3 28 32 40t52 -5q73 -52 91 -178q7 -57 -3.5 -113t-42.5 -91q-28 -32 -83.5 -48.5t-115.5 -18.5v-10q-71 -2 -95 -43q-14 -5 -31 -17q11 -1 32 -3.5t30 -3.5q1 4 5 8q16 18 60 23h13q5 18 19 30t33 8 t36 -23t19 -36q79 -32 93 -95q9 -40 1 -81q-12 -53 -56 -88t-97 -44q-10 -2 -17 -2q0 -49 -1 -73q20 15 38 19q26 7 61 2q28 28 51 16q14 -9 14 -37q33 -16 59 -34q27 13 38 4q10 -10 2 -38q28 -30 41 -51q23 8 31 -1zM1937 1025q0 -29 -9 -54q82 -32 112 -132 q4 37 -9.5 98.5t-41.5 90.5q-20 19 -36 17t-16 -20zM1859 925q35 -42 47.5 -108.5t-0.5 -124.5q67 13 97 45q13 14 18 28q-3 64 -31 114.5t-79 66.5q-15 -15 -52 -21zM1822 921q-30 0 -44 1q42 -115 53 -239q21 0 43 3q16 68 1 135t-53 100zM258 839q30 100 112 132 q-9 25 -9 54q0 18 -16.5 20t-35.5 -17q-28 -29 -41.5 -90.5t-9.5 -98.5zM294 737q29 -31 97 -45q-13 58 -0.5 124.5t47.5 108.5v0q-37 6 -52 21q-51 -16 -78.5 -66t-31.5 -115q9 -17 18 -28zM471 683q14 124 73 235q-19 -4 -55 -18l-45 -19v1q-46 -89 -20 -196q25 -3 47 -3z M1434 644q8 -38 16.5 -108.5t11.5 -89.5q3 -18 9.5 -21.5t23.5 4.5q40 20 62 85.5t23 125.5q-24 2 -146 4zM1152 1285q-116 0 -199 -82.5t-83 -198.5q0 -117 83 -199.5t199 -82.5t199 82.5t83 199.5q0 116 -83 198.5t-199 82.5zM1380 646q-106 2 -211 0v1q-1 -27 2.5 -86 t13.5 -66q29 -14 93.5 -14.5t95.5 10.5q9 3 11 39t-0.5 69.5t-4.5 46.5zM1112 447q8 4 9.5 48t-0.5 88t-4 63v1q-212 -3 -214 -3q-4 -20 -7 -62t0 -83t14 -46q34 -15 101 -16t101 10zM718 636q-16 -59 4.5 -118.5t77.5 -84.5q15 -8 24 -5t12 21q3 16 8 90t10 103 q-69 -2 -136 -6zM591 510q3 -23 -34 -36q132 -141 271.5 -240t305.5 -154q172 49 310.5 146t293.5 250q-33 13 -30 34l3 9v1v-1q-17 2 -50 5.5t-48 4.5q-26 -90 -82 -132q-51 -38 -82 1q-5 6 -9 14q-7 13 -17 62q-2 -5 -5 -9t-7.5 -7t-8 -5.5t-9.5 -4l-10 -2.5t-12 -2 l-12 -1.5t-13.5 -1t-13.5 -0.5q-106 -9 -163 11q-4 -17 -10 -26.5t-21 -15t-23 -7t-36 -3.5q-2 0 -3 -0.5t-3 -0.5h-3q-179 -17 -203 40q-2 -63 -56 -54q-47 8 -91 54q-12 13 -20 26q-17 29 -26 65q-58 -6 -87 -10q1 -2 4 -10zM507 -118q3 14 3 30q-17 71 -51 130t-73 70 q-41 12 -101.5 -14.5t-104.5 -80t-39 -107.5q35 -53 100 -93t119 -42q51 -2 94 28t53 79zM510 53q23 -63 27 -119q195 113 392 174q-98 52 -180.5 120t-179.5 165q-6 -4 -29 -13q0 -2 -1 -5t-1 -4q31 -18 22 -37q-12 -23 -56 -34q-10 -13 -29 -24h-1q-2 -83 1 -150 q19 -34 35 -73zM579 -113q532 -21 1145 0q-254 147 -428 196q-76 -35 -156 -57q-8 -3 -16 0q-65 21 -129 49q-208 -60 -416 -188h-1v-1q1 0 1 1zM1763 -67q4 54 28 120q14 38 33 71l-1 -1q3 77 3 153q-15 8 -30 25q-42 9 -56 33q-9 20 22 38q-2 4 -2 9q-16 4 -28 12 q-204 -190 -383 -284q198 -59 414 -176zM2155 -90q5 54 -39 107.5t-104 80t-102 14.5q-38 -11 -72.5 -70.5t-51.5 -129.5q0 -16 3 -30q10 -49 53 -79t94 -28q54 2 119 42t100 93z" />
-<glyph unicode="&#xf23d;" horiz-adv-x="2304" d="M1524 -25q0 -68 -48 -116t-116 -48t-116.5 48t-48.5 116t48.5 116.5t116.5 48.5t116 -48.5t48 -116.5zM775 -25q0 -68 -48.5 -116t-116.5 -48t-116 48t-48 116t48 116.5t116 48.5t116.5 -48.5t48.5 -116.5zM0 1469q57 -60 110.5 -104.5t121 -82t136 -63t166 -45.5 t200 -31.5t250 -18.5t304 -9.5t372.5 -2.5q139 0 244.5 -5t181 -16.5t124 -27.5t71 -39.5t24 -51.5t-19.5 -64t-56.5 -76.5t-89.5 -91t-116 -104.5t-139 -119q-185 -157 -286 -247q29 51 76.5 109t94 105.5t94.5 98.5t83 91.5t54 80.5t13 70t-45.5 55.5t-116.5 41t-204 23.5 t-304 5q-168 -2 -314 6t-256 23t-204.5 41t-159.5 51.5t-122.5 62.5t-91.5 66.5t-68 71.5t-50.5 69.5t-40 68t-36.5 59.5z" />
-<glyph unicode="&#xf23e;" horiz-adv-x="1792" d="M896 1472q-169 0 -323 -66t-265.5 -177.5t-177.5 -265.5t-66 -323t66 -323t177.5 -265.5t265.5 -177.5t323 -66t323 66t265.5 177.5t177.5 265.5t66 323t-66 323t-177.5 265.5t-265.5 177.5t-323 66zM896 1536q182 0 348 -71t286 -191t191 -286t71 -348t-71 -348 t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71zM496 704q16 0 16 -16v-480q0 -16 -16 -16h-32q-16 0 -16 16v480q0 16 16 16h32zM896 640q53 0 90.5 -37.5t37.5 -90.5q0 -35 -17.5 -64t-46.5 -46v-114q0 -14 -9 -23 t-23 -9h-64q-14 0 -23 9t-9 23v114q-29 17 -46.5 46t-17.5 64q0 53 37.5 90.5t90.5 37.5zM896 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM544 928v-96 q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v96q0 93 65.5 158.5t158.5 65.5t158.5 -65.5t65.5 -158.5v-96q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v96q0 146 -103 249t-249 103t-249 -103t-103 -249zM1408 192v512q0 26 -19 45t-45 19h-896q-26 0 -45 -19t-19 -45v-512 q0 -26 19 -45t45 -19h896q26 0 45 19t19 45z" />
-<glyph unicode="&#xf240;" horiz-adv-x="2304" d="M1920 1024v-768h-1664v768h1664zM2048 448h128v384h-128v288q0 14 -9 23t-23 9h-1856q-14 0 -23 -9t-9 -23v-960q0 -14 9 -23t23 -9h1856q14 0 23 9t9 23v288zM2304 832v-384q0 -53 -37.5 -90.5t-90.5 -37.5v-160q0 -66 -47 -113t-113 -47h-1856q-66 0 -113 47t-47 113 v960q0 66 47 113t113 47h1856q66 0 113 -47t47 -113v-160q53 0 90.5 -37.5t37.5 -90.5z" />
-<glyph unicode="&#xf241;" horiz-adv-x="2304" d="M256 256v768h1280v-768h-1280zM2176 960q53 0 90.5 -37.5t37.5 -90.5v-384q0 -53 -37.5 -90.5t-90.5 -37.5v-160q0 -66 -47 -113t-113 -47h-1856q-66 0 -113 47t-47 113v960q0 66 47 113t113 47h1856q66 0 113 -47t47 -113v-160zM2176 448v384h-128v288q0 14 -9 23t-23 9 h-1856q-14 0 -23 -9t-9 -23v-960q0 -14 9 -23t23 -9h1856q14 0 23 9t9 23v288h128z" />
-<glyph unicode="&#xf242;" horiz-adv-x="2304" d="M256 256v768h896v-768h-896zM2176 960q53 0 90.5 -37.5t37.5 -90.5v-384q0 -53 -37.5 -90.5t-90.5 -37.5v-160q0 -66 -47 -113t-113 -47h-1856q-66 0 -113 47t-47 113v960q0 66 47 113t113 47h1856q66 0 113 -47t47 -113v-160zM2176 448v384h-128v288q0 14 -9 23t-23 9 h-1856q-14 0 -23 -9t-9 -23v-960q0 -14 9 -23t23 -9h1856q14 0 23 9t9 23v288h128z" />
-<glyph unicode="&#xf243;" horiz-adv-x="2304" d="M256 256v768h512v-768h-512zM2176 960q53 0 90.5 -37.5t37.5 -90.5v-384q0 -53 -37.5 -90.5t-90.5 -37.5v-160q0 -66 -47 -113t-113 -47h-1856q-66 0 -113 47t-47 113v960q0 66 47 113t113 47h1856q66 0 113 -47t47 -113v-160zM2176 448v384h-128v288q0 14 -9 23t-23 9 h-1856q-14 0 -23 -9t-9 -23v-960q0 -14 9 -23t23 -9h1856q14 0 23 9t9 23v288h128z" />
-<glyph unicode="&#xf244;" horiz-adv-x="2304" d="M2176 960q53 0 90.5 -37.5t37.5 -90.5v-384q0 -53 -37.5 -90.5t-90.5 -37.5v-160q0 -66 -47 -113t-113 -47h-1856q-66 0 -113 47t-47 113v960q0 66 47 113t113 47h1856q66 0 113 -47t47 -113v-160zM2176 448v384h-128v288q0 14 -9 23t-23 9h-1856q-14 0 -23 -9t-9 -23 v-960q0 -14 9 -23t23 -9h1856q14 0 23 9t9 23v288h128z" />
-<glyph unicode="&#xf245;" horiz-adv-x="1280" d="M1133 493q31 -30 14 -69q-17 -40 -59 -40h-382l201 -476q10 -25 0 -49t-34 -35l-177 -75q-25 -10 -49 0t-35 34l-191 452l-312 -312q-19 -19 -45 -19q-12 0 -24 5q-40 17 -40 59v1504q0 42 40 59q12 5 24 5q27 0 45 -19z" />
-<glyph unicode="&#xf246;" horiz-adv-x="1024" d="M832 1408q-320 0 -320 -224v-416h128v-128h-128v-544q0 -224 320 -224h64v-128h-64q-272 0 -384 146q-112 -146 -384 -146h-64v128h64q320 0 320 224v544h-128v128h128v416q0 224 -320 224h-64v128h64q272 0 384 -146q112 146 384 146h64v-128h-64z" />
-<glyph unicode="&#xf247;" horiz-adv-x="2048" d="M2048 1152h-128v-1024h128v-384h-384v128h-1280v-128h-384v384h128v1024h-128v384h384v-128h1280v128h384v-384zM1792 1408v-128h128v128h-128zM128 1408v-128h128v128h-128zM256 -128v128h-128v-128h128zM1664 0v128h128v1024h-128v128h-1280v-128h-128v-1024h128v-128 h1280zM1920 -128v128h-128v-128h128zM1280 896h384v-768h-896v256h-384v768h896v-256zM512 512h640v512h-640v-512zM1536 256v512h-256v-384h-384v-128h640z" />
-<glyph unicode="&#xf248;" horiz-adv-x="2304" d="M2304 768h-128v-640h128v-384h-384v128h-896v-128h-384v384h128v128h-384v-128h-384v384h128v640h-128v384h384v-128h896v128h384v-384h-128v-128h384v128h384v-384zM2048 1024v-128h128v128h-128zM1408 1408v-128h128v128h-128zM128 1408v-128h128v128h-128zM256 256 v128h-128v-128h128zM1536 384h-128v-128h128v128zM384 384h896v128h128v640h-128v128h-896v-128h-128v-640h128v-128zM896 -128v128h-128v-128h128zM2176 -128v128h-128v-128h128zM2048 128v640h-128v128h-384v-384h128v-384h-384v128h-384v-128h128v-128h896v128h128z" />
-<glyph unicode="&#xf249;" d="M1024 288v-416h-928q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h1344q40 0 68 -28t28 -68v-928h-416q-40 0 -68 -28t-28 -68zM1152 256h381q-15 -82 -65 -132l-184 -184q-50 -50 -132 -65v381z" />
-<glyph unicode="&#xf24a;" d="M1400 256h-248v-248q29 10 41 22l185 185q12 12 22 41zM1120 384h288v896h-1280v-1280h896v288q0 40 28 68t68 28zM1536 1312v-1024q0 -40 -20 -88t-48 -76l-184 -184q-28 -28 -76 -48t-88 -20h-1024q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h1344q40 0 68 -28t28 -68 z" />
-<glyph unicode="&#xf24b;" horiz-adv-x="2304" d="M1951 538q0 -26 -15.5 -44.5t-38.5 -23.5q-8 -2 -18 -2h-153v140h153q10 0 18 -2q23 -5 38.5 -23.5t15.5 -44.5zM1933 751q0 -25 -15 -42t-38 -21q-3 -1 -15 -1h-139v129h139q3 0 8.5 -0.5t6.5 -0.5q23 -4 38 -21.5t15 -42.5zM728 587v308h-228v-308q0 -58 -38 -94.5 t-105 -36.5q-108 0 -229 59v-112q53 -15 121 -23t109 -9l42 -1q328 0 328 217zM1442 403v113q-99 -52 -200 -59q-108 -8 -169 41t-61 142t61 142t169 41q101 -7 200 -58v112q-48 12 -100 19.5t-80 9.5l-28 2q-127 6 -218.5 -14t-140.5 -60t-71 -88t-22 -106t22 -106t71 -88 t140.5 -60t218.5 -14q101 4 208 31zM2176 518q0 54 -43 88.5t-109 39.5v3q57 8 89 41.5t32 79.5q0 55 -41 88t-107 36q-3 0 -12 0.5t-14 0.5h-455v-510h491q74 0 121.5 36.5t47.5 96.5zM2304 1280v-1280q0 -52 -38 -90t-90 -38h-2048q-52 0 -90 38t-38 90v1280q0 52 38 90 t90 38h2048q52 0 90 -38t38 -90z" />
-<glyph unicode="&#xf24c;" horiz-adv-x="2304" d="M858 295v693q-106 -41 -172 -135.5t-66 -211.5t66 -211.5t172 -134.5zM1362 641q0 117 -66 211.5t-172 135.5v-694q106 41 172 135.5t66 211.5zM1577 641q0 -159 -78.5 -294t-213.5 -213.5t-294 -78.5q-119 0 -227.5 46.5t-187 125t-125 187t-46.5 227.5q0 159 78.5 294 t213.5 213.5t294 78.5t294 -78.5t213.5 -213.5t78.5 -294zM1960 634q0 139 -55.5 261.5t-147.5 205.5t-213.5 131t-252.5 48h-301q-176 0 -323.5 -81t-235 -230t-87.5 -335q0 -171 87 -317.5t236 -231.5t323 -85h301q129 0 251.5 50.5t214.5 135t147.5 202.5t55.5 246z M2304 1280v-1280q0 -52 -38 -90t-90 -38h-2048q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h2048q52 0 90 -38t38 -90z" />
-<glyph unicode="&#xf24d;" horiz-adv-x="1792" d="M1664 -96v1088q0 13 -9.5 22.5t-22.5 9.5h-1088q-13 0 -22.5 -9.5t-9.5 -22.5v-1088q0 -13 9.5 -22.5t22.5 -9.5h1088q13 0 22.5 9.5t9.5 22.5zM1792 992v-1088q0 -66 -47 -113t-113 -47h-1088q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1088q66 0 113 -47t47 -113 zM1408 1376v-160h-128v160q0 13 -9.5 22.5t-22.5 9.5h-1088q-13 0 -22.5 -9.5t-9.5 -22.5v-1088q0 -13 9.5 -22.5t22.5 -9.5h160v-128h-160q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1088q66 0 113 -47t47 -113z" />
-<glyph unicode="&#xf24e;" horiz-adv-x="2304" d="M1728 1088l-384 -704h768zM448 1088l-384 -704h768zM1269 1280q-14 -40 -45.5 -71.5t-71.5 -45.5v-1291h608q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-1344q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h608v1291q-40 14 -71.5 45.5t-45.5 71.5h-491q-14 0 -23 9t-9 23v64 q0 14 9 23t23 9h491q21 57 70 92.5t111 35.5t111 -35.5t70 -92.5h491q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-491zM1088 1264q33 0 56.5 23.5t23.5 56.5t-23.5 56.5t-56.5 23.5t-56.5 -23.5t-23.5 -56.5t23.5 -56.5t56.5 -23.5zM2176 384q0 -73 -46.5 -131t-117.5 -91 t-144.5 -49.5t-139.5 -16.5t-139.5 16.5t-144.5 49.5t-117.5 91t-46.5 131q0 11 35 81t92 174.5t107 195.5t102 184t56 100q18 33 56 33t56 -33q4 -7 56 -100t102 -184t107 -195.5t92 -174.5t35 -81zM896 384q0 -73 -46.5 -131t-117.5 -91t-144.5 -49.5t-139.5 -16.5 t-139.5 16.5t-144.5 49.5t-117.5 91t-46.5 131q0 11 35 81t92 174.5t107 195.5t102 184t56 100q18 33 56 33t56 -33q4 -7 56 -100t102 -184t107 -195.5t92 -174.5t35 -81z" />
-<glyph unicode="&#xf250;" d="M1408 1408q0 -261 -106.5 -461.5t-266.5 -306.5q160 -106 266.5 -306.5t106.5 -461.5h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-1472q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96q0 261 106.5 461.5t266.5 306.5q-160 106 -266.5 306.5t-106.5 461.5h-96q-14 0 -23 9 t-9 23v64q0 14 9 23t23 9h1472q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-96zM874 700q77 29 149 92.5t129.5 152.5t92.5 210t35 253h-1024q0 -132 35 -253t92.5 -210t129.5 -152.5t149 -92.5q19 -7 30.5 -23.5t11.5 -36.5t-11.5 -36.5t-30.5 -23.5q-77 -29 -149 -92.5 t-129.5 -152.5t-92.5 -210t-35 -253h1024q0 132 -35 253t-92.5 210t-129.5 152.5t-149 92.5q-19 7 -30.5 23.5t-11.5 36.5t11.5 36.5t30.5 23.5z" />
-<glyph unicode="&#xf251;" d="M1408 1408q0 -261 -106.5 -461.5t-266.5 -306.5q160 -106 266.5 -306.5t106.5 -461.5h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-1472q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96q0 261 106.5 461.5t266.5 306.5q-160 106 -266.5 306.5t-106.5 461.5h-96q-14 0 -23 9 t-9 23v64q0 14 9 23t23 9h1472q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-96zM1280 1408h-1024q0 -66 9 -128h1006q9 61 9 128zM1280 -128q0 130 -34 249.5t-90.5 208t-126.5 152t-146 94.5h-230q-76 -31 -146 -94.5t-126.5 -152t-90.5 -208t-34 -249.5h1024z" />
-<glyph unicode="&#xf252;" d="M1408 1408q0 -261 -106.5 -461.5t-266.5 -306.5q160 -106 266.5 -306.5t106.5 -461.5h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-1472q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96q0 261 106.5 461.5t266.5 306.5q-160 106 -266.5 306.5t-106.5 461.5h-96q-14 0 -23 9 t-9 23v64q0 14 9 23t23 9h1472q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-96zM1280 1408h-1024q0 -206 85 -384h854q85 178 85 384zM1223 192q-54 141 -145.5 241.5t-194.5 142.5h-230q-103 -42 -194.5 -142.5t-145.5 -241.5h910z" />
-<glyph unicode="&#xf253;" d="M1408 1408q0 -261 -106.5 -461.5t-266.5 -306.5q160 -106 266.5 -306.5t106.5 -461.5h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-1472q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96q0 261 106.5 461.5t266.5 306.5q-160 106 -266.5 306.5t-106.5 461.5h-96q-14 0 -23 9 t-9 23v64q0 14 9 23t23 9h1472q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-96zM874 700q77 29 149 92.5t129.5 152.5t92.5 210t35 253h-1024q0 -132 35 -253t92.5 -210t129.5 -152.5t149 -92.5q19 -7 30.5 -23.5t11.5 -36.5t-11.5 -36.5t-30.5 -23.5q-137 -51 -244 -196 h700q-107 145 -244 196q-19 7 -30.5 23.5t-11.5 36.5t11.5 36.5t30.5 23.5z" />
-<glyph unicode="&#xf254;" d="M1504 -64q14 0 23 -9t9 -23v-128q0 -14 -9 -23t-23 -9h-1472q-14 0 -23 9t-9 23v128q0 14 9 23t23 9h1472zM130 0q3 55 16 107t30 95t46 87t53.5 76t64.5 69.5t66 60t70.5 55t66.5 47.5t65 43q-43 28 -65 43t-66.5 47.5t-70.5 55t-66 60t-64.5 69.5t-53.5 76t-46 87 t-30 95t-16 107h1276q-3 -55 -16 -107t-30 -95t-46 -87t-53.5 -76t-64.5 -69.5t-66 -60t-70.5 -55t-66.5 -47.5t-65 -43q43 -28 65 -43t66.5 -47.5t70.5 -55t66 -60t64.5 -69.5t53.5 -76t46 -87t30 -95t16 -107h-1276zM1504 1536q14 0 23 -9t9 -23v-128q0 -14 -9 -23t-23 -9 h-1472q-14 0 -23 9t-9 23v128q0 14 9 23t23 9h1472z" />
-<glyph unicode="&#xf255;" d="M768 1152q-53 0 -90.5 -37.5t-37.5 -90.5v-128h-32v93q0 48 -32 81.5t-80 33.5q-46 0 -79 -33t-33 -79v-429l-32 30v172q0 48 -32 81.5t-80 33.5q-46 0 -79 -33t-33 -79v-224q0 -47 35 -82l310 -296q39 -39 39 -102q0 -26 19 -45t45 -19h640q26 0 45 19t19 45v25 q0 41 10 77l108 436q10 36 10 77v246q0 48 -32 81.5t-80 33.5q-46 0 -79 -33t-33 -79v-32h-32v125q0 40 -25 72.5t-64 40.5q-14 2 -23 2q-46 0 -79 -33t-33 -79v-128h-32v122q0 51 -32.5 89.5t-82.5 43.5q-5 1 -13 1zM768 1280q84 0 149 -50q57 34 123 34q59 0 111 -27 t86 -76q27 7 59 7q100 0 170 -71.5t70 -171.5v-246q0 -51 -13 -108l-109 -436q-6 -24 -6 -71q0 -80 -56 -136t-136 -56h-640q-84 0 -138 58.5t-54 142.5l-308 296q-76 73 -76 175v224q0 99 70.5 169.5t169.5 70.5q11 0 16 -1q6 95 75.5 160t164.5 65q52 0 98 -21 q72 69 174 69z" />
-<glyph unicode="&#xf256;" horiz-adv-x="1792" d="M880 1408q-46 0 -79 -33t-33 -79v-656h-32v528q0 46 -33 79t-79 33t-79 -33t-33 -79v-528v-256l-154 205q-38 51 -102 51q-53 0 -90.5 -37.5t-37.5 -90.5q0 -43 26 -77l384 -512q38 -51 102 -51h688q34 0 61 22t34 56l76 405q5 32 5 59v498q0 46 -33 79t-79 33t-79 -33 t-33 -79v-272h-32v528q0 46 -33 79t-79 33t-79 -33t-33 -79v-528h-32v656q0 46 -33 79t-79 33zM880 1536q68 0 125.5 -35.5t88.5 -96.5q19 4 42 4q99 0 169.5 -70.5t70.5 -169.5v-17q105 6 180.5 -64t75.5 -175v-498q0 -40 -8 -83l-76 -404q-14 -79 -76.5 -131t-143.5 -52 h-688q-60 0 -114.5 27.5t-90.5 74.5l-384 512q-51 68 -51 154q0 106 75 181t181 75q78 0 128 -34v434q0 99 70.5 169.5t169.5 70.5q23 0 42 -4q31 61 88.5 96.5t125.5 35.5z" />
-<glyph unicode="&#xf257;" horiz-adv-x="1792" d="M1073 -128h-177q-163 0 -226 141q-23 49 -23 102v5q-62 30 -98.5 88.5t-36.5 127.5q0 38 5 48h-261q-106 0 -181 75t-75 181t75 181t181 75h113l-44 17q-74 28 -119.5 93.5t-45.5 145.5q0 106 75 181t181 75q46 0 91 -17l628 -239h401q106 0 181 -75t75 -181v-668 q0 -88 -54 -157.5t-140 -90.5l-339 -85q-92 -23 -186 -23zM1024 583l-155 -71l-163 -74q-30 -14 -48 -41.5t-18 -60.5q0 -46 33 -79t79 -33q26 0 46 10l338 154q-49 10 -80.5 50t-31.5 90v55zM1344 272q0 46 -33 79t-79 33q-26 0 -46 -10l-290 -132q-28 -13 -37 -17 t-30.5 -17t-29.5 -23.5t-16 -29t-8 -40.5q0 -50 31.5 -82t81.5 -32q20 0 38 9l352 160q30 14 48 41.5t18 60.5zM1112 1024l-650 248q-24 8 -46 8q-53 0 -90.5 -37.5t-37.5 -90.5q0 -40 22.5 -73t59.5 -47l526 -200v-64h-640q-53 0 -90.5 -37.5t-37.5 -90.5t37.5 -90.5 t90.5 -37.5h535l233 106v198q0 63 46 106l111 102h-69zM1073 0q82 0 155 19l339 85q43 11 70 45.5t27 78.5v668q0 53 -37.5 90.5t-90.5 37.5h-308l-136 -126q-36 -33 -36 -82v-296q0 -46 33 -77t79 -31t79 35t33 81v208h32v-208q0 -70 -57 -114q52 -8 86.5 -48.5t34.5 -93.5 q0 -42 -23 -78t-61 -53l-310 -141h91z" />
-<glyph unicode="&#xf258;" horiz-adv-x="2048" d="M1151 1536q61 0 116 -28t91 -77l572 -781q118 -159 118 -359v-355q0 -80 -56 -136t-136 -56h-384q-80 0 -136 56t-56 136v177l-286 143h-546q-80 0 -136 56t-56 136v32q0 119 84.5 203.5t203.5 84.5h420l42 128h-686q-100 0 -173.5 67.5t-81.5 166.5q-65 79 -65 182v32 q0 80 56 136t136 56h959zM1920 -64v355q0 157 -93 284l-573 781q-39 52 -103 52h-959q-26 0 -45 -19t-19 -45q0 -32 1.5 -49.5t9.5 -40.5t25 -43q10 31 35.5 50t56.5 19h832v-32h-832q-26 0 -45 -19t-19 -45q0 -44 3 -58q8 -44 44 -73t81 -29h640h91q40 0 68 -28t28 -68 q0 -15 -5 -30l-64 -192q-10 -29 -35 -47.5t-56 -18.5h-443q-66 0 -113 -47t-47 -113v-32q0 -26 19 -45t45 -19h561q16 0 29 -7l317 -158q24 -13 38.5 -36t14.5 -50v-197q0 -26 19 -45t45 -19h384q26 0 45 19t19 45z" />
-<glyph unicode="&#xf259;" horiz-adv-x="2048" d="M816 1408q-48 0 -79.5 -34t-31.5 -82q0 -14 3 -28l150 -624h-26l-116 482q-9 38 -39.5 62t-69.5 24q-47 0 -79 -34t-32 -81q0 -11 4 -29q3 -13 39 -161t68 -282t32 -138v-227l-307 230q-34 26 -77 26q-52 0 -89.5 -36.5t-37.5 -88.5q0 -67 56 -110l507 -379 q34 -26 76 -26h694q33 0 59 20.5t34 52.5l100 401q8 30 10 88t9 86l116 478q3 12 3 26q0 46 -33 79t-80 33q-38 0 -69 -25.5t-40 -62.5l-99 -408h-26l132 547q3 14 3 28q0 47 -32 80t-80 33q-38 0 -68.5 -24t-39.5 -62l-145 -602h-127l-164 682q-9 38 -39.5 62t-68.5 24z M1461 -256h-694q-85 0 -153 51l-507 380q-50 38 -78.5 94t-28.5 118q0 105 75 179t180 74q25 0 49.5 -5.5t41.5 -11t41 -20.5t35 -23t38.5 -29.5t37.5 -28.5l-123 512q-7 35 -7 59q0 93 60 162t152 79q14 87 80.5 144.5t155.5 57.5q83 0 148 -51.5t85 -132.5l103 -428 l83 348q20 81 85 132.5t148 51.5q87 0 152.5 -54t82.5 -139q93 -10 155 -78t62 -161q0 -30 -7 -57l-116 -477q-5 -22 -5 -67q0 -51 -13 -108l-101 -401q-19 -75 -79.5 -122.5t-137.5 -47.5z" />
-<glyph unicode="&#xf25a;" horiz-adv-x="1792" d="M640 1408q-53 0 -90.5 -37.5t-37.5 -90.5v-512v-384l-151 202q-41 54 -107 54q-52 0 -89 -38t-37 -90q0 -43 26 -77l384 -512q38 -51 102 -51h718q22 0 39.5 13.5t22.5 34.5l92 368q24 96 24 194v217q0 41 -28 71t-68 30t-68 -28t-28 -68h-32v61q0 48 -32 81.5t-80 33.5 q-46 0 -79 -33t-33 -79v-64h-32v90q0 55 -37 94.5t-91 39.5q-53 0 -90.5 -37.5t-37.5 -90.5v-96h-32v570q0 55 -37 94.5t-91 39.5zM640 1536q107 0 181.5 -77.5t74.5 -184.5v-220q22 2 32 2q99 0 173 -69q47 21 99 21q113 0 184 -87q27 7 56 7q94 0 159 -67.5t65 -161.5 v-217q0 -116 -28 -225l-92 -368q-16 -64 -68 -104.5t-118 -40.5h-718q-60 0 -114.5 27.5t-90.5 74.5l-384 512q-51 68 -51 154q0 105 74.5 180.5t179.5 75.5q71 0 130 -35v547q0 106 75 181t181 75zM768 128v384h-32v-384h32zM1024 128v384h-32v-384h32zM1280 128v384h-32 v-384h32z" />
-<glyph unicode="&#xf25b;" d="M1288 889q60 0 107 -23q141 -63 141 -226v-177q0 -94 -23 -186l-85 -339q-21 -86 -90.5 -140t-157.5 -54h-668q-106 0 -181 75t-75 181v401l-239 628q-17 45 -17 91q0 106 75 181t181 75q80 0 145.5 -45.5t93.5 -119.5l17 -44v113q0 106 75 181t181 75t181 -75t75 -181 v-261q27 5 48 5q69 0 127.5 -36.5t88.5 -98.5zM1072 896q-33 0 -60.5 -18t-41.5 -48l-74 -163l-71 -155h55q50 0 90 -31.5t50 -80.5l154 338q10 20 10 46q0 46 -33 79t-79 33zM1293 761q-22 0 -40.5 -8t-29 -16t-23.5 -29.5t-17 -30.5t-17 -37l-132 -290q-10 -20 -10 -46 q0 -46 33 -79t79 -33q33 0 60.5 18t41.5 48l160 352q9 18 9 38q0 50 -32 81.5t-82 31.5zM128 1120q0 -22 8 -46l248 -650v-69l102 111q43 46 106 46h198l106 233v535q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5v-640h-64l-200 526q-14 37 -47 59.5t-73 22.5 q-53 0 -90.5 -37.5t-37.5 -90.5zM1180 -128q44 0 78.5 27t45.5 70l85 339q19 73 19 155v91l-141 -310q-17 -38 -53 -61t-78 -23q-53 0 -93.5 34.5t-48.5 86.5q-44 -57 -114 -57h-208v32h208q46 0 81 33t35 79t-31 79t-77 33h-296q-49 0 -82 -36l-126 -136v-308 q0 -53 37.5 -90.5t90.5 -37.5h668z" />
-<glyph unicode="&#xf25c;" horiz-adv-x="1973" d="M857 992v-117q0 -13 -9.5 -22t-22.5 -9h-298v-812q0 -13 -9 -22.5t-22 -9.5h-135q-13 0 -22.5 9t-9.5 23v812h-297q-13 0 -22.5 9t-9.5 22v117q0 14 9 23t23 9h793q13 0 22.5 -9.5t9.5 -22.5zM1895 995l77 -961q1 -13 -8 -24q-10 -10 -23 -10h-134q-12 0 -21 8.5 t-10 20.5l-46 588l-189 -425q-8 -19 -29 -19h-120q-20 0 -29 19l-188 427l-45 -590q-1 -12 -10 -20.5t-21 -8.5h-135q-13 0 -23 10q-9 10 -9 24l78 961q1 12 10 20.5t21 8.5h142q20 0 29 -19l220 -520q10 -24 20 -51q3 7 9.5 24.5t10.5 26.5l221 520q9 19 29 19h141 q13 0 22 -8.5t10 -20.5z" />
-<glyph unicode="&#xf25d;" horiz-adv-x="1792" d="M1042 833q0 88 -60 121q-33 18 -117 18h-123v-281h162q66 0 102 37t36 105zM1094 548l205 -373q8 -17 -1 -31q-8 -16 -27 -16h-152q-20 0 -28 17l-194 365h-155v-350q0 -14 -9 -23t-23 -9h-134q-14 0 -23 9t-9 23v960q0 14 9 23t23 9h294q128 0 190 -24q85 -31 134 -109 t49 -180q0 -92 -42.5 -165.5t-115.5 -109.5q6 -10 9 -16zM896 1376q-150 0 -286 -58.5t-234.5 -157t-157 -234.5t-58.5 -286t58.5 -286t157 -234.5t234.5 -157t286 -58.5t286 58.5t234.5 157t157 234.5t58.5 286t-58.5 286t-157 234.5t-234.5 157t-286 58.5zM1792 640 q0 -182 -71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
-<glyph unicode="&#xf25e;" horiz-adv-x="1792" d="M605 303q153 0 257 104q14 18 3 36l-45 82q-6 13 -24 17q-16 2 -27 -11l-4 -3q-4 -4 -11.5 -10t-17.5 -13t-23.5 -14.5t-28.5 -13.5t-33.5 -9.5t-37.5 -3.5q-76 0 -125 50t-49 127q0 76 48 125.5t122 49.5q37 0 71.5 -14t50.5 -28l16 -14q11 -11 26 -10q16 2 24 14l53 78 q13 20 -2 39q-3 4 -11 12t-30 23.5t-48.5 28t-67.5 22.5t-86 10q-148 0 -246 -96.5t-98 -240.5q0 -146 97 -241.5t247 -95.5zM1235 303q153 0 257 104q14 18 4 36l-45 82q-8 14 -25 17q-16 2 -27 -11l-4 -3q-4 -4 -11.5 -10t-17.5 -13t-23.5 -14.5t-28.5 -13.5t-33.5 -9.5 t-37.5 -3.5q-76 0 -125 50t-49 127q0 76 48 125.5t122 49.5q37 0 71.5 -14t50.5 -28l16 -14q11 -11 26 -10q16 2 24 14l53 78q13 20 -2 39q-3 4 -11 12t-30 23.5t-48.5 28t-67.5 22.5t-86 10q-147 0 -245.5 -96.5t-98.5 -240.5q0 -146 97 -241.5t247 -95.5zM896 1376 q-150 0 -286 -58.5t-234.5 -157t-157 -234.5t-58.5 -286t58.5 -286t157 -234.5t234.5 -157t286 -58.5t286 58.5t234.5 157t157 234.5t58.5 286t-58.5 286t-157 234.5t-234.5 157t-286 58.5zM896 1536q182 0 348 -71t286 -191t191 -286t71 -348t-71 -348t-191 -286t-286 -191 t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71z" />
-<glyph unicode="&#xf260;" horiz-adv-x="2048" d="M736 736l384 -384l-384 -384l-672 672l672 672l168 -168l-96 -96l-72 72l-480 -480l480 -480l193 193l-289 287zM1312 1312l672 -672l-672 -672l-168 168l96 96l72 -72l480 480l-480 480l-193 -193l289 -287l-96 -96l-384 384z" />
-<glyph unicode="&#xf261;" horiz-adv-x="1792" d="M717 182l271 271l-279 279l-88 -88l192 -191l-96 -96l-279 279l279 279l40 -40l87 87l-127 128l-454 -454zM1075 190l454 454l-454 454l-271 -271l279 -279l88 88l-192 191l96 96l279 -279l-279 -279l-40 40l-87 -88zM1792 640q0 -182 -71 -348t-191 -286t-286 -191 t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
-<glyph unicode="&#xf262;" horiz-adv-x="2304" d="M651 539q0 -39 -27.5 -66.5t-65.5 -27.5q-39 0 -66.5 27.5t-27.5 66.5q0 38 27.5 65.5t66.5 27.5q38 0 65.5 -27.5t27.5 -65.5zM1805 540q0 -39 -27.5 -66.5t-66.5 -27.5t-66.5 27.5t-27.5 66.5t27.5 66t66.5 27t66.5 -27t27.5 -66zM765 539q0 79 -56.5 136t-136.5 57 t-136.5 -56.5t-56.5 -136.5t56.5 -136.5t136.5 -56.5t136.5 56.5t56.5 136.5zM1918 540q0 80 -56.5 136.5t-136.5 56.5q-79 0 -136 -56.5t-57 -136.5t56.5 -136.5t136.5 -56.5t136.5 56.5t56.5 136.5zM850 539q0 -116 -81.5 -197.5t-196.5 -81.5q-116 0 -197.5 82t-81.5 197 t82 196.5t197 81.5t196.5 -81.5t81.5 -196.5zM2004 540q0 -115 -81.5 -196.5t-197.5 -81.5q-115 0 -196.5 81.5t-81.5 196.5t81.5 196.5t196.5 81.5q116 0 197.5 -81.5t81.5 -196.5zM1040 537q0 191 -135.5 326.5t-326.5 135.5q-125 0 -231 -62t-168 -168.5t-62 -231.5 t62 -231.5t168 -168.5t231 -62q191 0 326.5 135.5t135.5 326.5zM1708 1110q-254 111 -556 111q-319 0 -573 -110q117 0 223 -45.5t182.5 -122.5t122 -183t45.5 -223q0 115 43.5 219.5t118 180.5t177.5 123t217 50zM2187 537q0 191 -135 326.5t-326 135.5t-326.5 -135.5 t-135.5 -326.5t135.5 -326.5t326.5 -135.5t326 135.5t135 326.5zM1921 1103h383q-44 -51 -75 -114.5t-40 -114.5q110 -151 110 -337q0 -156 -77 -288t-209 -208.5t-287 -76.5q-133 0 -249 56t-196 155q-47 -56 -129 -179q-11 22 -53.5 82.5t-74.5 97.5 q-80 -99 -196.5 -155.5t-249.5 -56.5q-155 0 -287 76.5t-209 208.5t-77 288q0 186 110 337q-9 51 -40 114.5t-75 114.5h365q149 100 355 156.5t432 56.5q224 0 421 -56t348 -157z" />
-<glyph unicode="&#xf263;" horiz-adv-x="1280" d="M640 629q-188 0 -321 133t-133 320q0 188 133 321t321 133t321 -133t133 -321q0 -187 -133 -320t-321 -133zM640 1306q-92 0 -157.5 -65.5t-65.5 -158.5q0 -92 65.5 -157.5t157.5 -65.5t157.5 65.5t65.5 157.5q0 93 -65.5 158.5t-157.5 65.5zM1163 574q13 -27 15 -49.5 t-4.5 -40.5t-26.5 -38.5t-42.5 -37t-61.5 -41.5q-115 -73 -315 -94l73 -72l267 -267q30 -31 30 -74t-30 -73l-12 -13q-31 -30 -74 -30t-74 30q-67 68 -267 268l-267 -268q-31 -30 -74 -30t-73 30l-12 13q-31 30 -31 73t31 74l267 267l72 72q-203 21 -317 94 q-39 25 -61.5 41.5t-42.5 37t-26.5 38.5t-4.5 40.5t15 49.5q10 20 28 35t42 22t56 -2t65 -35q5 -4 15 -11t43 -24.5t69 -30.5t92 -24t113 -11q91 0 174 25.5t120 50.5l38 25q33 26 65 35t56 2t42 -22t28 -35z" />
-<glyph unicode="&#xf264;" d="M927 956q0 -66 -46.5 -112.5t-112.5 -46.5t-112.5 46.5t-46.5 112.5t46.5 112.5t112.5 46.5t112.5 -46.5t46.5 -112.5zM1141 593q-10 20 -28 32t-47.5 9.5t-60.5 -27.5q-10 -8 -29 -20t-81 -32t-127 -20t-124 18t-86 36l-27 18q-31 25 -60.5 27.5t-47.5 -9.5t-28 -32 q-22 -45 -2 -74.5t87 -73.5q83 -53 226 -67l-51 -52q-142 -142 -191 -190q-22 -22 -22 -52.5t22 -52.5l9 -9q22 -22 52.5 -22t52.5 22l191 191q114 -115 191 -191q22 -22 52.5 -22t52.5 22l9 9q22 22 22 52.5t-22 52.5l-191 190l-52 52q141 14 225 67q67 44 87 73.5t-2 74.5 zM1092 956q0 134 -95 229t-229 95t-229 -95t-95 -229t95 -229t229 -95t229 95t95 229zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
-<glyph unicode="&#xf265;" horiz-adv-x="1720" d="M1565 1408q65 0 110 -45.5t45 -110.5v-519q0 -176 -68 -336t-182.5 -275t-274 -182.5t-334.5 -67.5q-176 0 -335.5 67.5t-274.5 182.5t-183 275t-68 336v519q0 64 46 110t110 46h1409zM861 344q47 0 82 33l404 388q37 35 37 85q0 49 -34.5 83.5t-83.5 34.5q-47 0 -82 -33 l-323 -310l-323 310q-35 33 -81 33q-49 0 -83.5 -34.5t-34.5 -83.5q0 -51 36 -85l405 -388q33 -33 81 -33z" />
-<glyph unicode="&#xf266;" horiz-adv-x="2304" d="M1494 -103l-295 695q-25 -49 -158.5 -305.5t-198.5 -389.5q-1 -1 -27.5 -0.5t-26.5 1.5q-82 193 -255.5 587t-259.5 596q-21 50 -66.5 107.5t-103.5 100.5t-102 43q0 5 -0.5 24t-0.5 27h583v-50q-39 -2 -79.5 -16t-66.5 -43t-10 -64q26 -59 216.5 -499t235.5 -540 q31 61 140 266.5t131 247.5q-19 39 -126 281t-136 295q-38 69 -201 71v50l513 -1v-47q-60 -2 -93.5 -25t-12.5 -69q33 -70 87 -189.5t86 -187.5q110 214 173 363q24 55 -10 79.5t-129 26.5q1 7 1 25v24q64 0 170.5 0.5t180 1t92.5 0.5v-49q-62 -2 -119 -33t-90 -81 l-213 -442q13 -33 127.5 -290t121.5 -274l441 1017q-14 38 -49.5 62.5t-65 31.5t-55.5 8v50l460 -4l1 -2l-1 -44q-139 -4 -201 -145q-526 -1216 -559 -1291h-49z" />
-<glyph unicode="&#xf267;" horiz-adv-x="1792" d="M949 643q0 -26 -16.5 -45t-41.5 -19q-26 0 -45 16.5t-19 41.5q0 26 17 45t42 19t44 -16.5t19 -41.5zM964 585l350 581q-9 -8 -67.5 -62.5t-125.5 -116.5t-136.5 -127t-117 -110.5t-50.5 -51.5l-349 -580q7 7 67 62t126 116.5t136 127t117 111t50 50.5zM1611 640 q0 -201 -104 -371q-3 2 -17 11t-26.5 16.5t-16.5 7.5q-13 0 -13 -13q0 -10 59 -44q-74 -112 -184.5 -190.5t-241.5 -110.5l-16 67q-1 10 -15 10q-5 0 -8 -5.5t-2 -9.5l16 -68q-72 -15 -146 -15q-199 0 -372 105q1 2 13 20.5t21.5 33.5t9.5 19q0 13 -13 13q-6 0 -17 -14.5 t-22.5 -34.5t-13.5 -23q-113 75 -192 187.5t-110 244.5l69 15q10 3 10 15q0 5 -5.5 8t-10.5 2l-68 -15q-14 72 -14 139q0 206 109 379q2 -1 18.5 -12t30 -19t17.5 -8q13 0 13 12q0 6 -12.5 15.5t-32.5 21.5l-20 12q77 112 189 189t244 107l15 -67q2 -10 15 -10q5 0 8 5.5 t2 10.5l-15 66q71 13 134 13q204 0 379 -109q-39 -56 -39 -65q0 -13 12 -13q11 0 48 64q111 -75 187.5 -186t107.5 -241l-56 -12q-10 -2 -10 -16q0 -5 5.5 -8t9.5 -2l57 13q14 -72 14 -140zM1696 640q0 163 -63.5 311t-170.5 255t-255 170.5t-311 63.5t-311 -63.5 t-255 -170.5t-170.5 -255t-63.5 -311t63.5 -311t170.5 -255t255 -170.5t311 -63.5t311 63.5t255 170.5t170.5 255t63.5 311zM1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71t348 -71t286 -191 t191 -286t71 -348z" />
-<glyph unicode="&#xf268;" horiz-adv-x="1792" d="M893 1536q240 2 451 -120q232 -134 352 -372l-742 39q-160 9 -294 -74.5t-185 -229.5l-276 424q128 159 311 245.5t383 87.5zM146 1131l337 -663q72 -143 211 -217t293 -45l-230 -451q-212 33 -385 157.5t-272.5 316t-99.5 411.5q0 267 146 491zM1732 962 q58 -150 59.5 -310.5t-48.5 -306t-153 -272t-246 -209.5q-230 -133 -498 -119l405 623q88 131 82.5 290.5t-106.5 277.5zM896 942q125 0 213.5 -88.5t88.5 -213.5t-88.5 -213.5t-213.5 -88.5t-213.5 88.5t-88.5 213.5t88.5 213.5t213.5 88.5z" />
-<glyph unicode="&#xf269;" horiz-adv-x="1792" d="M903 -256q-283 0 -504.5 150.5t-329.5 398.5q-58 131 -67 301t26 332.5t111 312t179 242.5l-11 -281q11 14 68 15.5t70 -15.5q42 81 160.5 138t234.5 59q-54 -45 -119.5 -148.5t-58.5 -163.5q25 -8 62.5 -13.5t63 -7.5t68 -4t50.5 -3q15 -5 9.5 -45.5t-30.5 -75.5 q-5 -7 -16.5 -18.5t-56.5 -35.5t-101 -34l15 -189l-139 67q-18 -43 -7.5 -81.5t36 -66.5t65.5 -41.5t81 -6.5q51 9 98 34.5t83.5 45t73.5 17.5q61 -4 89.5 -33t19.5 -65q-1 -2 -2.5 -5.5t-8.5 -12.5t-18 -15.5t-31.5 -10.5t-46.5 -1q-60 -95 -144.5 -135.5t-209.5 -29.5 q74 -61 162.5 -82.5t168.5 -6t154.5 52t128 87.5t80.5 104q43 91 39 192.5t-37.5 188.5t-78.5 125q87 -38 137 -79.5t77 -112.5q15 170 -57.5 343t-209.5 284q265 -77 412 -279.5t151 -517.5q2 -127 -40.5 -255t-123.5 -238t-189 -196t-247.5 -135.5t-288.5 -49.5z" />
-<glyph unicode="&#xf26a;" horiz-adv-x="1792" d="M1493 1308q-165 110 -359 110q-155 0 -293 -73t-240 -200q-75 -93 -119.5 -218t-48.5 -266v-42q4 -141 48.5 -266t119.5 -218q102 -127 240 -200t293 -73q194 0 359 110q-121 -108 -274.5 -168t-322.5 -60q-29 0 -43 1q-175 8 -333 82t-272 193t-181 281t-67 339 q0 182 71 348t191 286t286 191t348 71h3q168 -1 320.5 -60.5t273.5 -167.5zM1792 640q0 -192 -77 -362.5t-213 -296.5q-104 -63 -222 -63q-137 0 -255 84q154 56 253.5 233t99.5 405q0 227 -99 404t-253 234q119 83 254 83q119 0 226 -65q135 -125 210.5 -295t75.5 -361z " />
-<glyph unicode="&#xf26b;" horiz-adv-x="1792" d="M1792 599q0 -56 -7 -104h-1151q0 -146 109.5 -244.5t257.5 -98.5q99 0 185.5 46.5t136.5 130.5h423q-56 -159 -170.5 -281t-267.5 -188.5t-321 -66.5q-187 0 -356 83q-228 -116 -394 -116q-237 0 -237 263q0 115 45 275q17 60 109 229q199 360 475 606 q-184 -79 -427 -354q63 274 283.5 449.5t501.5 175.5q30 0 45 -1q255 117 433 117q64 0 116 -13t94.5 -40.5t66.5 -76.5t24 -115q0 -116 -75 -286q101 -182 101 -390zM1722 1239q0 83 -53 132t-137 49q-108 0 -254 -70q121 -47 222.5 -131.5t170.5 -195.5q51 135 51 216z M128 2q0 -86 48.5 -132.5t134.5 -46.5q115 0 266 83q-122 72 -213.5 183t-137.5 245q-98 -205 -98 -332zM632 715h728q-5 142 -113 237t-251 95q-144 0 -251.5 -95t-112.5 -237z" />
-<glyph unicode="&#xf26c;" horiz-adv-x="2048" d="M1792 288v960q0 13 -9.5 22.5t-22.5 9.5h-1600q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h1600q13 0 22.5 9.5t9.5 22.5zM1920 1248v-960q0 -66 -47 -113t-113 -47h-736v-128h352q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-832q-14 0 -23 9t-9 23 v64q0 14 9 23t23 9h352v128h-736q-66 0 -113 47t-47 113v960q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" />
-<glyph unicode="&#xf26d;" horiz-adv-x="1792" d="M138 1408h197q-70 -64 -126 -149q-36 -56 -59 -115t-30 -125.5t-8.5 -120t10.5 -132t21 -126t28 -136.5q4 -19 6 -28q51 -238 81 -329q57 -171 152 -275h-272q-48 0 -82 34t-34 82v1304q0 48 34 82t82 34zM1346 1408h308q48 0 82 -34t34 -82v-1304q0 -48 -34 -82t-82 -34 h-178q212 210 196 565l-469 -101q-2 -45 -12 -82t-31 -72t-59.5 -59.5t-93.5 -36.5q-123 -26 -199 40q-32 27 -53 61t-51.5 129t-64.5 258q-35 163 -45.5 263t-5.5 139t23 77q20 41 62.5 73t102.5 45q45 12 83.5 6.5t67 -17t54 -35t43 -48t34.5 -56.5l468 100 q-68 175 -180 287z" />
-<glyph unicode="&#xf26e;" d="M1401 -11l-6 -6q-113 -114 -259 -175q-154 -64 -317 -64q-165 0 -317 64q-148 63 -259 175q-113 112 -175 258q-42 103 -54 189q-4 28 48 36q51 8 56 -20q1 -1 1 -4q18 -90 46 -159q50 -124 152 -226q98 -98 226 -152q132 -56 276 -56q143 0 276 56q128 55 225 152l6 6 q10 10 25 6q12 -3 33 -22q36 -37 17 -58zM929 604l-66 -66l63 -63q21 -21 -7 -49q-17 -17 -32 -17q-10 0 -19 10l-62 61l-66 -66q-5 -5 -15 -5q-15 0 -31 16l-2 2q-18 15 -18 29q0 7 8 17l66 65l-66 66q-16 16 14 45q18 18 31 18q6 0 13 -5l65 -66l65 65q18 17 48 -13 q27 -27 11 -44zM1400 547q0 -118 -46 -228q-45 -105 -126 -186q-80 -80 -187 -126t-228 -46t-228 46t-187 126q-82 82 -125 186q-15 32 -15 40h-1q-9 27 43 44q50 16 60 -12q37 -99 97 -167h1v339v2q3 136 102 232q105 103 253 103q147 0 251 -103t104 -249 q0 -147 -104.5 -251t-250.5 -104q-58 0 -112 16q-28 11 -13 61q16 51 44 43l14 -3q14 -3 32.5 -6t30.5 -3q104 0 176 71.5t72 174.5q0 101 -72 171q-71 71 -175 71q-107 0 -178 -80q-64 -72 -64 -160v-413q110 -67 242 -67q96 0 185 36.5t156 103.5t103.5 155t36.5 183 q0 198 -141 339q-140 140 -339 140q-200 0 -340 -140q-53 -53 -77 -87l-2 -2q-8 -11 -13 -15.5t-21.5 -9.5t-38.5 3q-21 5 -36.5 16.5t-15.5 26.5v680q0 15 10.5 26.5t27.5 11.5h877q30 0 30 -55t-30 -55h-811v-483h1q40 42 102 84t108 61q109 46 231 46q121 0 228 -46 t187 -126q81 -81 126 -186q46 -112 46 -229zM1369 1128q9 -8 9 -18t-5.5 -18t-16.5 -21q-26 -26 -39 -26q-9 0 -16 7q-106 91 -207 133q-128 56 -276 56q-133 0 -262 -49q-27 -10 -45 37q-9 25 -8 38q3 16 16 20q130 57 299 57q164 0 316 -64q137 -58 235 -152z" />
-<glyph unicode="&#xf270;" horiz-adv-x="1792" d="M1551 60q15 6 26 3t11 -17.5t-15 -33.5q-13 -16 -44 -43.5t-95.5 -68t-141 -74t-188 -58t-229.5 -24.5q-119 0 -238 31t-209 76.5t-172.5 104t-132.5 105t-84 87.5q-8 9 -10 16.5t1 12t8 7t11.5 2t11.5 -4.5q192 -117 300 -166q389 -176 799 -90q190 40 391 135z M1758 175q11 -16 2.5 -69.5t-28.5 -102.5q-34 -83 -85 -124q-17 -14 -26 -9t0 24q21 45 44.5 121.5t6.5 98.5q-5 7 -15.5 11.5t-27 6t-29.5 2.5t-35 0t-31.5 -2t-31 -3t-22.5 -2q-6 -1 -13 -1.5t-11 -1t-8.5 -1t-7 -0.5h-5.5h-4.5t-3 0.5t-2 1.5l-1.5 3q-6 16 47 40t103 30 q46 7 108 1t76 -24zM1364 618q0 -31 13.5 -64t32 -58t37.5 -46t33 -32l13 -11l-227 -224q-40 37 -79 75.5t-58 58.5l-19 20q-11 11 -25 33q-38 -59 -97.5 -102.5t-127.5 -63.5t-140 -23t-137.5 21t-117.5 65.5t-83 113t-31 162.5q0 84 28 154t72 116.5t106.5 83t122.5 57 t130 34.5t119.5 18.5t99.5 6.5v127q0 65 -21 97q-34 53 -121 53q-6 0 -16.5 -1t-40.5 -12t-56 -29.5t-56 -59.5t-48 -96l-294 27q0 60 22 119t67 113t108 95t151.5 65.5t190.5 24.5q100 0 181 -25t129.5 -61.5t81 -83t45 -86t12.5 -73.5v-589zM692 597q0 -86 70 -133 q66 -44 139 -22q84 25 114 123q14 45 14 101v162q-59 -2 -111 -12t-106.5 -33.5t-87 -71t-32.5 -114.5z" />
-<glyph unicode="&#xf271;" horiz-adv-x="1792" d="M1536 1280q52 0 90 -38t38 -90v-1280q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h384v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h128zM1152 1376v-288q0 -14 9 -23t23 -9 h64q14 0 23 9t9 23v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23zM384 1376v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23zM1536 -128v1024h-1408v-1024h1408zM896 448h224q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-224 v-224q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v224h-224q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h224v224q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-224z" />
-<glyph unicode="&#xf272;" horiz-adv-x="1792" d="M1152 416v-64q0 -14 -9 -23t-23 -9h-576q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h576q14 0 23 -9t9 -23zM128 -128h1408v1024h-1408v-1024zM512 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1280 1088v288q0 14 -9 23 t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1664 1152v-1280q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h384v96q0 66 47 113t113 47h64q66 0 113 -47 t47 -113v-96h128q52 0 90 -38t38 -90z" />
-<glyph unicode="&#xf273;" horiz-adv-x="1792" d="M1111 151l-46 -46q-9 -9 -22 -9t-23 9l-188 189l-188 -189q-10 -9 -23 -9t-22 9l-46 46q-9 9 -9 22t9 23l189 188l-189 188q-9 10 -9 23t9 22l46 46q9 9 22 9t23 -9l188 -188l188 188q10 9 23 9t22 -9l46 -46q9 -9 9 -22t-9 -23l-188 -188l188 -188q9 -10 9 -23t-9 -22z M128 -128h1408v1024h-1408v-1024zM512 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1280 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1664 1152v-1280 q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h384v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h128q52 0 90 -38t38 -90z" />
-<glyph unicode="&#xf274;" horiz-adv-x="1792" d="M1303 572l-512 -512q-10 -9 -23 -9t-23 9l-288 288q-9 10 -9 23t9 22l46 46q9 9 22 9t23 -9l220 -220l444 444q10 9 23 9t22 -9l46 -46q9 -9 9 -22t-9 -23zM128 -128h1408v1024h-1408v-1024zM512 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23 t23 -9h64q14 0 23 9t9 23zM1280 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1664 1152v-1280q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47 t47 -113v-96h384v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h128q52 0 90 -38t38 -90z" />
-<glyph unicode="&#xf275;" horiz-adv-x="1792" d="M448 1536q26 0 45 -19t19 -45v-891l536 429q17 14 40 14q26 0 45 -19t19 -45v-379l536 429q17 14 40 14q26 0 45 -19t19 -45v-1152q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v1664q0 26 19 45t45 19h384z" />
-<glyph unicode="&#xf276;" horiz-adv-x="1024" d="M512 448q66 0 128 15v-655q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v655q61 -15 128 -15zM512 1536q212 0 362 -150t150 -362t-150 -362t-362 -150t-362 150t-150 362t150 362t362 150zM512 1312q14 0 23 9t9 23t-9 23t-23 9q-146 0 -249 -103t-103 -249 q0 -14 9 -23t23 -9t23 9t9 23q0 119 84.5 203.5t203.5 84.5z" />
-<glyph unicode="&#xf277;" horiz-adv-x="1792" d="M1745 1239q10 -10 10 -23t-10 -23l-141 -141q-28 -28 -68 -28h-1344q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h576v64q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-64h512q40 0 68 -28zM768 320h256v-512q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v512zM1600 768 q26 0 45 -19t19 -45v-256q0 -26 -19 -45t-45 -19h-1344q-40 0 -68 28l-141 141q-10 10 -10 23t10 23l141 141q28 28 68 28h512v192h256v-192h576z" />
-<glyph unicode="&#xf278;" horiz-adv-x="2048" d="M2020 1525q28 -20 28 -53v-1408q0 -20 -11 -36t-29 -23l-640 -256q-24 -11 -48 0l-616 246l-616 -246q-10 -5 -24 -5q-19 0 -36 11q-28 20 -28 53v1408q0 20 11 36t29 23l640 256q24 11 48 0l616 -246l616 246q32 13 60 -6zM736 1390v-1270l576 -230v1270zM128 1173 v-1270l544 217v1270zM1920 107v1270l-544 -217v-1270z" />
-<glyph unicode="&#xf279;" horiz-adv-x="1792" d="M512 1536q13 0 22.5 -9.5t9.5 -22.5v-1472q0 -20 -17 -28l-480 -256q-7 -4 -15 -4q-13 0 -22.5 9.5t-9.5 22.5v1472q0 20 17 28l480 256q7 4 15 4zM1760 1536q13 0 22.5 -9.5t9.5 -22.5v-1472q0 -20 -17 -28l-480 -256q-7 -4 -15 -4q-13 0 -22.5 9.5t-9.5 22.5v1472 q0 20 17 28l480 256q7 4 15 4zM640 1536q8 0 14 -3l512 -256q18 -10 18 -29v-1472q0 -13 -9.5 -22.5t-22.5 -9.5q-8 0 -14 3l-512 256q-18 10 -18 29v1472q0 13 9.5 22.5t22.5 9.5z" />
-<glyph unicode="&#xf27a;" horiz-adv-x="1792" d="M640 640q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1024 640q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1408 640q0 53 -37.5 90.5t-90.5 37.5 t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1792 640q0 -174 -120 -321.5t-326 -233t-450 -85.5q-110 0 -211 18q-173 -173 -435 -229q-52 -10 -86 -13q-12 -1 -22 6t-13 18q-4 15 20 37q5 5 23.5 21.5t25.5 23.5t23.5 25.5t24 31.5t20.5 37 t20 48t14.5 57.5t12.5 72.5q-146 90 -229.5 216.5t-83.5 269.5q0 174 120 321.5t326 233t450 85.5t450 -85.5t326 -233t120 -321.5z" />
-<glyph unicode="&#xf27b;" horiz-adv-x="1792" d="M640 640q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1024 640q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1408 640q0 -53 -37.5 -90.5t-90.5 -37.5 t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM896 1152q-204 0 -381.5 -69.5t-282 -187.5t-104.5 -255q0 -112 71.5 -213.5t201.5 -175.5l87 -50l-27 -96q-24 -91 -70 -172q152 63 275 171l43 38l57 -6q69 -8 130 -8q204 0 381.5 69.5t282 187.5 t104.5 255t-104.5 255t-282 187.5t-381.5 69.5zM1792 640q0 -174 -120 -321.5t-326 -233t-450 -85.5q-70 0 -145 8q-198 -175 -460 -242q-49 -14 -114 -22h-5q-15 0 -27 10.5t-16 27.5v1q-3 4 -0.5 12t2 10t4.5 9.5l6 9t7 8.5t8 9q7 8 31 34.5t34.5 38t31 39.5t32.5 51 t27 59t26 76q-157 89 -247.5 220t-90.5 281q0 130 71 248.5t191 204.5t286 136.5t348 50.5t348 -50.5t286 -136.5t191 -204.5t71 -248.5z" />
-<glyph unicode="&#xf27c;" horiz-adv-x="1024" d="M512 345l512 295v-591l-512 -296v592zM0 640v-591l512 296zM512 1527v-591l-512 -296v591zM512 936l512 295v-591z" />
-<glyph unicode="&#xf27d;" horiz-adv-x="1792" d="M1709 1018q-10 -236 -332 -651q-333 -431 -562 -431q-142 0 -240 263q-44 160 -132 482q-72 262 -157 262q-18 0 -127 -76l-77 98q24 21 108 96.5t130 115.5q156 138 241 146q95 9 153 -55.5t81 -203.5q44 -287 66 -373q55 -249 120 -249q51 0 154 161q101 161 109 246 q13 139 -109 139q-57 0 -121 -26q120 393 459 382q251 -8 236 -326z" />
-<glyph unicode="&#xf27e;" d="M0 1408h1536v-1536h-1536v1536zM1085 293l-221 631l221 297h-634l221 -297l-221 -631l317 -304z" />
-<glyph unicode="&#xf280;" d="M0 1408h1536v-1536h-1536v1536zM908 1088l-12 -33l75 -83l-31 -114l25 -25l107 57l107 -57l25 25l-31 114l75 83l-12 33h-95l-53 96h-32l-53 -96h-95zM641 925q32 0 44.5 -16t11.5 -63l174 21q0 55 -17.5 92.5t-50.5 56t-69 25.5t-85 7q-133 0 -199 -57.5t-66 -182.5v-72 h-96v-128h76q20 0 20 -8v-382q0 -14 -5 -20t-18 -7l-73 -7v-88h448v86l-149 14q-6 1 -8.5 1.5t-3.5 2.5t-0.5 4t1 7t0.5 10v387h191l38 128h-231q-6 0 -2 6t4 9v80q0 27 1.5 40.5t7.5 28t19.5 20t36.5 5.5zM1248 96v86l-54 9q-7 1 -9.5 2.5t-2.5 3t1 7.5t1 12v520h-275 l-23 -101l83 -22q23 -7 23 -27v-370q0 -14 -6 -18.5t-20 -6.5l-70 -9v-86h352z" />
-<glyph unicode="&#xf281;" horiz-adv-x="1792" d="M1792 690q0 -58 -29.5 -105.5t-79.5 -72.5q12 -46 12 -96q0 -155 -106.5 -287t-290.5 -208.5t-400 -76.5t-399.5 76.5t-290 208.5t-106.5 287q0 47 11 94q-51 25 -82 73.5t-31 106.5q0 82 58 140.5t141 58.5q85 0 145 -63q218 152 515 162l116 521q3 13 15 21t26 5 l369 -81q18 37 54 59.5t79 22.5q62 0 106 -43.5t44 -105.5t-44 -106t-106 -44t-105.5 43.5t-43.5 105.5l-334 74l-104 -472q300 -9 519 -160q58 61 143 61q83 0 141 -58.5t58 -140.5zM418 491q0 -62 43.5 -106t105.5 -44t106 44t44 106t-44 105.5t-106 43.5q-61 0 -105 -44 t-44 -105zM1228 136q11 11 11 26t-11 26q-10 10 -25 10t-26 -10q-41 -42 -121 -62t-160 -20t-160 20t-121 62q-11 10 -26 10t-25 -10q-11 -10 -11 -25.5t11 -26.5q43 -43 118.5 -68t122.5 -29.5t91 -4.5t91 4.5t122.5 29.5t118.5 68zM1225 341q62 0 105.5 44t43.5 106 q0 61 -44 105t-105 44q-62 0 -106 -43.5t-44 -105.5t44 -106t106 -44z" />
-<glyph unicode="&#xf282;" horiz-adv-x="1792" d="M69 741h1q16 126 58.5 241.5t115 217t167.5 176t223.5 117.5t276.5 43q231 0 414 -105.5t294 -303.5q104 -187 104 -442v-188h-1125q1 -111 53.5 -192.5t136.5 -122.5t189.5 -57t213 -3t208 46.5t173.5 84.5v-377q-92 -55 -229.5 -92t-312.5 -38t-316 53 q-189 73 -311.5 249t-124.5 372q-3 242 111 412t325 268q-48 -60 -78 -125.5t-46 -159.5h635q8 77 -8 140t-47 101.5t-70.5 66.5t-80.5 41t-75 20.5t-56 8.5l-22 1q-135 -5 -259.5 -44.5t-223.5 -104.5t-176 -140.5t-138 -163.5z" />
-<glyph unicode="&#xf283;" horiz-adv-x="2304" d="M0 32v608h2304v-608q0 -66 -47 -113t-113 -47h-1984q-66 0 -113 47t-47 113zM640 256v-128h384v128h-384zM256 256v-128h256v128h-256zM2144 1408q66 0 113 -47t47 -113v-224h-2304v224q0 66 47 113t113 47h1984z" />
-<glyph unicode="&#xf284;" horiz-adv-x="1792" d="M1549 857q55 0 85.5 -28.5t30.5 -83.5t-34 -82t-91 -27h-136v-177h-25v398h170zM1710 267l-4 -11l-5 -10q-113 -230 -330.5 -366t-474.5 -136q-182 0 -348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71q244 0 454.5 -124t329.5 -338l2 -4l8 -16 q-30 -15 -136.5 -68.5t-163.5 -84.5q-6 -3 -479 -268q384 -183 799 -366zM896 -234q250 0 462.5 132.5t322.5 357.5l-287 129q-72 -140 -206 -222t-292 -82q-151 0 -280 75t-204 204t-75 280t75 280t204 204t280 75t280 -73.5t204 -204.5l280 143q-116 208 -321 329 t-443 121q-119 0 -232.5 -31.5t-209 -87.5t-176.5 -137t-137 -176.5t-87.5 -209t-31.5 -232.5t31.5 -232.5t87.5 -209t137 -176.5t176.5 -137t209 -87.5t232.5 -31.5z" />
-<glyph unicode="&#xf285;" horiz-adv-x="1792" d="M1427 827l-614 386l92 151h855zM405 562l-184 116v858l1183 -743zM1424 697l147 -95v-858l-532 335zM1387 718l-500 -802h-855l356 571z" />
-<glyph unicode="&#xf286;" horiz-adv-x="1792" d="M640 528v224q0 16 -16 16h-96q-16 0 -16 -16v-224q0 -16 16 -16h96q16 0 16 16zM1152 528v224q0 16 -16 16h-96q-16 0 -16 -16v-224q0 -16 16 -16h96q16 0 16 16zM1664 496v-752h-640v320q0 80 -56 136t-136 56t-136 -56t-56 -136v-320h-640v752q0 16 16 16h96 q16 0 16 -16v-112h128v624q0 16 16 16h96q16 0 16 -16v-112h128v112q0 16 16 16h96q16 0 16 -16v-112h128v112q0 6 2.5 9.5t8.5 5t9.5 2t11.5 0t9 -0.5v391q-32 15 -32 50q0 23 16.5 39t38.5 16t38.5 -16t16.5 -39q0 -35 -32 -50v-17q45 10 83 10q21 0 59.5 -7.5t54.5 -7.5 q17 0 47 7.5t37 7.5q16 0 16 -16v-210q0 -15 -35 -21.5t-62 -6.5q-18 0 -54.5 7.5t-55.5 7.5q-40 0 -90 -12v-133q1 0 9 0.5t11.5 0t9.5 -2t8.5 -5t2.5 -9.5v-112h128v112q0 16 16 16h96q16 0 16 -16v-112h128v112q0 16 16 16h96q16 0 16 -16v-624h128v112q0 16 16 16h96 q16 0 16 -16z" />
-<glyph unicode="&#xf287;" horiz-adv-x="2304" d="M2288 731q16 -8 16 -27t-16 -27l-320 -192q-8 -5 -16 -5q-9 0 -16 4q-16 10 -16 28v128h-858q37 -58 83 -165q16 -37 24.5 -55t24 -49t27 -47t27 -34t31.5 -26t33 -8h96v96q0 14 9 23t23 9h320q14 0 23 -9t9 -23v-320q0 -14 -9 -23t-23 -9h-320q-14 0 -23 9t-9 23v96h-96 q-32 0 -61 10t-51 23.5t-45 40.5t-37 46t-33.5 57t-28.5 57.5t-28 60.5q-23 53 -37 81.5t-36 65t-44.5 53.5t-46.5 17h-360q-22 -84 -91 -138t-157 -54q-106 0 -181 75t-75 181t75 181t181 75q88 0 157 -54t91 -138h104q24 0 46.5 17t44.5 53.5t36 65t37 81.5q19 41 28 60.5 t28.5 57.5t33.5 57t37 46t45 40.5t51 23.5t61 10h107q21 57 70 92.5t111 35.5q80 0 136 -56t56 -136t-56 -136t-136 -56q-62 0 -111 35.5t-70 92.5h-107q-17 0 -33 -8t-31.5 -26t-27 -34t-27 -47t-24 -49t-24.5 -55q-46 -107 -83 -165h1114v128q0 18 16 28t32 -1z" />
-<glyph unicode="&#xf288;" horiz-adv-x="1792" d="M1150 774q0 -56 -39.5 -95t-95.5 -39h-253v269h253q56 0 95.5 -39.5t39.5 -95.5zM1329 774q0 130 -91.5 222t-222.5 92h-433v-896h180v269h253q130 0 222 91.5t92 221.5zM1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348 t71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
-<glyph unicode="&#xf289;" horiz-adv-x="2304" d="M1645 438q0 59 -34 106.5t-87 68.5q-7 -45 -23 -92q-7 -24 -27.5 -38t-44.5 -14q-12 0 -24 3q-31 10 -45 38.5t-4 58.5q23 71 23 143q0 123 -61 227.5t-166 165.5t-228 61q-134 0 -247 -73t-167 -194q108 -28 188 -106q22 -23 22 -55t-22 -54t-54 -22t-55 22 q-75 75 -180 75q-106 0 -181 -74.5t-75 -180.5t75 -180.5t181 -74.5h1046q79 0 134.5 55.5t55.5 133.5zM1798 438q0 -142 -100.5 -242t-242.5 -100h-1046q-169 0 -289 119.5t-120 288.5q0 153 100 267t249 136q62 184 221 298t354 114q235 0 408.5 -158.5t196.5 -389.5 q116 -25 192.5 -118.5t76.5 -214.5zM2048 438q0 -175 -97 -319q-23 -33 -64 -33q-24 0 -43 13q-26 17 -32 48.5t12 57.5q71 104 71 233t-71 233q-18 26 -12 57t32 49t57.5 11.5t49.5 -32.5q97 -142 97 -318zM2304 438q0 -244 -134 -443q-23 -34 -64 -34q-23 0 -42 13 q-26 18 -32.5 49t11.5 57q108 164 108 358q0 195 -108 357q-18 26 -11.5 57.5t32.5 48.5q26 18 57 12t49 -33q134 -198 134 -442z" />
-<glyph unicode="&#xf28a;" d="M1500 -13q0 -89 -63 -152.5t-153 -63.5t-153.5 63.5t-63.5 152.5q0 90 63.5 153.5t153.5 63.5t153 -63.5t63 -153.5zM1267 268q-115 -15 -192.5 -102.5t-77.5 -205.5q0 -74 33 -138q-146 -78 -379 -78q-109 0 -201 21t-153.5 54.5t-110.5 76.5t-76 85t-44.5 83 t-23.5 66.5t-6 39.5q0 19 4.5 42.5t18.5 56t36.5 58t64 43.5t94.5 18t94 -17.5t63 -41t35.5 -53t17.5 -49t4 -33.5q0 -34 -23 -81q28 -27 82 -42t93 -17l40 -1q115 0 190 51t75 133q0 26 -9 48.5t-31.5 44.5t-49.5 41t-74 44t-93.5 47.5t-119.5 56.5q-28 13 -43 20 q-116 55 -187 100t-122.5 102t-72 125.5t-20.5 162.5q0 78 20.5 150t66 137.5t112.5 114t166.5 77t221.5 28.5q120 0 220 -26t164.5 -67t109.5 -94t64 -105.5t19 -103.5q0 -46 -15 -82.5t-36.5 -58t-48.5 -36t-49 -19.5t-39 -5h-8h-32t-39 5t-44 14t-41 28t-37 46t-24 70.5 t-10 97.5q-15 16 -59 25.5t-81 10.5l-37 1q-68 0 -117.5 -31t-70.5 -70t-21 -76q0 -24 5 -43t24 -46t53 -51t97 -53.5t150 -58.5q76 -25 138.5 -53.5t109 -55.5t83 -59t60.5 -59.5t41 -62.5t26.5 -62t14.5 -63.5t6 -62t1 -62.5z" />
-<glyph unicode="&#xf28b;" d="M704 352v576q0 14 -9 23t-23 9h-256q-14 0 -23 -9t-9 -23v-576q0 -14 9 -23t23 -9h256q14 0 23 9t9 23zM1152 352v576q0 14 -9 23t-23 9h-256q-14 0 -23 -9t-9 -23v-576q0 -14 9 -23t23 -9h256q14 0 23 9t9 23zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103 t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
-<glyph unicode="&#xf28c;" d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM768 96q148 0 273 73t198 198t73 273t-73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273 t73 -273t198 -198t273 -73zM864 320q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-576q0 -14 -9 -23t-23 -9h-192zM480 320q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-576q0 -14 -9 -23t-23 -9h-192z" />
-<glyph unicode="&#xf28d;" d="M1088 352v576q0 14 -9 23t-23 9h-576q-14 0 -23 -9t-9 -23v-576q0 -14 9 -23t23 -9h576q14 0 23 9t9 23zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5 t103 -385.5z" />
-<glyph unicode="&#xf28e;" d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM768 96q148 0 273 73t198 198t73 273t-73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273 t73 -273t198 -198t273 -73zM480 320q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h576q14 0 23 -9t9 -23v-576q0 -14 -9 -23t-23 -9h-576z" />
-<glyph unicode="&#xf290;" horiz-adv-x="1792" d="M1757 128l35 -313q3 -28 -16 -50q-19 -21 -48 -21h-1664q-29 0 -48 21q-19 22 -16 50l35 313h1722zM1664 967l86 -775h-1708l86 775q3 24 21 40.5t43 16.5h256v-128q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5v128h384v-128q0 -53 37.5 -90.5t90.5 -37.5 t90.5 37.5t37.5 90.5v128h256q25 0 43 -16.5t21 -40.5zM1280 1152v-256q0 -26 -19 -45t-45 -19t-45 19t-19 45v256q0 106 -75 181t-181 75t-181 -75t-75 -181v-256q0 -26 -19 -45t-45 -19t-45 19t-19 45v256q0 159 112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5z" />
-<glyph unicode="&#xf291;" horiz-adv-x="2048" d="M1920 768q53 0 90.5 -37.5t37.5 -90.5t-37.5 -90.5t-90.5 -37.5h-15l-115 -662q-8 -46 -44 -76t-82 -30h-1280q-46 0 -82 30t-44 76l-115 662h-15q-53 0 -90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5h1792zM485 -32q26 2 43.5 22.5t15.5 46.5l-32 416q-2 26 -22.5 43.5 t-46.5 15.5t-43.5 -22.5t-15.5 -46.5l32 -416q2 -25 20.5 -42t43.5 -17h5zM896 32v416q0 26 -19 45t-45 19t-45 -19t-19 -45v-416q0 -26 19 -45t45 -19t45 19t19 45zM1280 32v416q0 26 -19 45t-45 19t-45 -19t-19 -45v-416q0 -26 19 -45t45 -19t45 19t19 45zM1632 27l32 416 q2 26 -15.5 46.5t-43.5 22.5t-46.5 -15.5t-22.5 -43.5l-32 -416q-2 -26 15.5 -46.5t43.5 -22.5h5q25 0 43.5 17t20.5 42zM476 1244l-93 -412h-132l101 441q19 88 89 143.5t160 55.5h167q0 26 19 45t45 19h384q26 0 45 -19t19 -45h167q90 0 160 -55.5t89 -143.5l101 -441 h-132l-93 412q-11 44 -45.5 72t-79.5 28h-167q0 -26 -19 -45t-45 -19h-384q-26 0 -45 19t-19 45h-167q-45 0 -79.5 -28t-45.5 -72z" />
-<glyph unicode="&#xf292;" horiz-adv-x="1792" d="M991 512l64 256h-254l-64 -256h254zM1759 1016l-56 -224q-7 -24 -31 -24h-327l-64 -256h311q15 0 25 -12q10 -14 6 -28l-56 -224q-5 -24 -31 -24h-327l-81 -328q-7 -24 -31 -24h-224q-16 0 -26 12q-9 12 -6 28l78 312h-254l-81 -328q-7 -24 -31 -24h-225q-15 0 -25 12 q-9 12 -6 28l78 312h-311q-15 0 -25 12q-9 12 -6 28l56 224q7 24 31 24h327l64 256h-311q-15 0 -25 12q-10 14 -6 28l56 224q5 24 31 24h327l81 328q7 24 32 24h224q15 0 25 -12q9 -12 6 -28l-78 -312h254l81 328q7 24 32 24h224q15 0 25 -12q9 -12 6 -28l-78 -312h311 q15 0 25 -12q9 -12 6 -28z" />
-<glyph unicode="&#xf293;" d="M841 483l148 -148l-149 -149zM840 1094l149 -149l-148 -148zM710 -130l464 464l-306 306l306 306l-464 464v-611l-255 255l-93 -93l320 -321l-320 -321l93 -93l255 255v-611zM1429 640q0 -209 -32 -365.5t-87.5 -257t-140.5 -162.5t-181.5 -86.5t-219.5 -24.5 t-219.5 24.5t-181.5 86.5t-140.5 162.5t-87.5 257t-32 365.5t32 365.5t87.5 257t140.5 162.5t181.5 86.5t219.5 24.5t219.5 -24.5t181.5 -86.5t140.5 -162.5t87.5 -257t32 -365.5z" />
-<glyph unicode="&#xf294;" horiz-adv-x="1024" d="M596 113l173 172l-173 172v-344zM596 823l173 172l-173 172v-344zM628 640l356 -356l-539 -540v711l-297 -296l-108 108l372 373l-372 373l108 108l297 -296v711l539 -540z" />
-<glyph unicode="&#xf295;" d="M1280 256q0 52 -38 90t-90 38t-90 -38t-38 -90t38 -90t90 -38t90 38t38 90zM512 1024q0 52 -38 90t-90 38t-90 -38t-38 -90t38 -90t90 -38t90 38t38 90zM1536 256q0 -159 -112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5t271.5 -112.5 t112.5 -271.5zM1440 1344q0 -20 -13 -38l-1056 -1408q-19 -26 -51 -26h-160q-26 0 -45 19t-19 45q0 20 13 38l1056 1408q19 26 51 26h160q26 0 45 -19t19 -45zM768 1024q0 -159 -112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5 t271.5 -112.5t112.5 -271.5z" />
-<glyph unicode="&#xf296;" horiz-adv-x="1792" d="M104 830l792 -1015l-868 630q-18 13 -25 34.5t0 42.5l101 308v0zM566 830h660l-330 -1015v0zM368 1442l198 -612h-462l198 612q8 23 33 23t33 -23zM1688 830l101 -308q7 -21 0 -42.5t-25 -34.5l-868 -630l792 1015v0zM1688 830h-462l198 612q8 23 33 23t33 -23z" />
-<glyph unicode="&#xf297;" horiz-adv-x="1792" d="M384 704h160v224h-160v-224zM1221 372v92q-104 -36 -243 -38q-135 -1 -259.5 46.5t-220.5 122.5l1 -96q88 -80 212 -128.5t272 -47.5q129 0 238 49zM640 704h640v224h-640v-224zM1792 736q0 -187 -99 -352q89 -102 89 -229q0 -157 -129.5 -268t-313.5 -111 q-122 0 -225 52.5t-161 140.5q-19 -1 -57 -1t-57 1q-58 -88 -161 -140.5t-225 -52.5q-184 0 -313.5 111t-129.5 268q0 127 89 229q-99 165 -99 352q0 209 120 385.5t326.5 279.5t449.5 103t449.5 -103t326.5 -279.5t120 -385.5z" />
-<glyph unicode="&#xf298;" d="M515 625v-128h-252v128h252zM515 880v-127h-252v127h252zM1273 369v-128h-341v128h341zM1273 625v-128h-672v128h672zM1273 880v-127h-672v127h672zM1408 20v1240q0 8 -6 14t-14 6h-32l-378 -256l-210 171l-210 -171l-378 256h-32q-8 0 -14 -6t-6 -14v-1240q0 -8 6 -14 t14 -6h1240q8 0 14 6t6 14zM553 1130l185 150h-406zM983 1130l221 150h-406zM1536 1260v-1240q0 -62 -43 -105t-105 -43h-1240q-62 0 -105 43t-43 105v1240q0 62 43 105t105 43h1240q62 0 105 -43t43 -105z" />
-<glyph unicode="&#xf299;" horiz-adv-x="1792" d="M896 720q-104 196 -160 278q-139 202 -347 318q-34 19 -70 36q-89 40 -94 32t34 -38l39 -31q62 -43 112.5 -93.5t94.5 -116.5t70.5 -113t70.5 -131q9 -17 13 -25q44 -84 84 -153t98 -154t115.5 -150t131 -123.5t148.5 -90.5q153 -66 154 -60q1 3 -49 37q-53 36 -81 57 q-77 58 -179 211t-185 310zM549 177q-76 60 -132.5 125t-98 143.5t-71 154.5t-58.5 186t-52 209t-60.5 252t-76.5 289q273 0 497.5 -36t379 -92t271 -144.5t185.5 -172.5t110 -198.5t56 -199.5t12.5 -198.5t-9.5 -173t-20 -143.5t-13 -107l323 -327h-104l-281 285 q-22 -2 -91.5 -14t-121.5 -19t-138 -6t-160.5 17t-167.5 59t-179 111z" />
-<glyph unicode="&#xf29a;" horiz-adv-x="1792" d="M1374 879q-6 26 -28.5 39.5t-48.5 7.5q-261 -62 -401 -62t-401 62q-26 6 -48.5 -7.5t-28.5 -39.5t7.5 -48.5t39.5 -28.5q194 -46 303 -58q-2 -158 -15.5 -269t-26.5 -155.5t-41 -115.5l-9 -21q-10 -25 1 -49t36 -34q9 -4 23 -4q44 0 60 41l8 20q54 139 71 259h42 q17 -120 71 -259l8 -20q16 -41 60 -41q14 0 23 4q25 10 36 34t1 49l-9 21q-28 71 -41 115.5t-26.5 155.5t-15.5 269q109 12 303 58q26 6 39.5 28.5t7.5 48.5zM1024 1024q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5z M1600 640q0 -143 -55.5 -273.5t-150 -225t-225 -150t-273.5 -55.5t-273.5 55.5t-225 150t-150 225t-55.5 273.5t55.5 273.5t150 225t225 150t273.5 55.5t273.5 -55.5t225 -150t150 -225t55.5 -273.5zM896 1408q-156 0 -298 -61t-245 -164t-164 -245t-61 -298t61 -298 t164 -245t245 -164t298 -61t298 61t245 164t164 245t61 298t-61 298t-164 245t-245 164t-298 61zM1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
-<glyph unicode="&#xf29b;" d="M1438 723q34 -35 29 -82l-44 -551q-4 -42 -34.5 -70t-71.5 -28q-6 0 -9 1q-44 3 -72.5 36.5t-25.5 77.5l35 429l-143 -8q55 -113 55 -240q0 -216 -148 -372l-137 137q91 101 91 235q0 145 -102.5 248t-247.5 103q-134 0 -236 -92l-137 138q120 114 284 141l264 300 l-149 87l-181 -161q-33 -30 -77 -27.5t-73 35.5t-26.5 77t34.5 73l239 213q26 23 60 26.5t64 -14.5l488 -283q36 -21 48 -68q17 -67 -26 -117l-205 -232l371 20q49 3 83 -32zM1240 1180q-74 0 -126 52t-52 126t52 126t126 52t126.5 -52t52.5 -126t-52.5 -126t-126.5 -52z M613 -62q106 0 196 61l139 -139q-146 -116 -335 -116q-148 0 -273.5 73t-198.5 198t-73 273q0 188 116 336l139 -139q-60 -88 -60 -197q0 -145 102.5 -247.5t247.5 -102.5z" />
-<glyph unicode="&#xf29c;" d="M880 336v-160q0 -14 -9 -23t-23 -9h-160q-14 0 -23 9t-9 23v160q0 14 9 23t23 9h160q14 0 23 -9t9 -23zM1136 832q0 -50 -15 -90t-45.5 -69t-52 -44t-59.5 -36q-32 -18 -46.5 -28t-26 -24t-11.5 -29v-32q0 -14 -9 -23t-23 -9h-160q-14 0 -23 9t-9 23v68q0 35 10.5 64.5 t24 47.5t39 35.5t41 25.5t44.5 21q53 25 75 43t22 49q0 42 -43.5 71.5t-95.5 29.5q-56 0 -95 -27q-29 -20 -80 -83q-9 -12 -25 -12q-11 0 -19 6l-108 82q-10 7 -12 20t5 23q122 192 349 192q129 0 238.5 -89.5t109.5 -214.5zM768 1280q-130 0 -248.5 -51t-204 -136.5 t-136.5 -204t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5t-51 248.5t-136.5 204t-204 136.5t-248.5 51zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5 t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
-<glyph unicode="&#xf29d;" horiz-adv-x="1408" d="M366 1225q-64 0 -110 45.5t-46 110.5q0 64 46 109.5t110 45.5t109.5 -45.5t45.5 -109.5q0 -65 -45.5 -110.5t-109.5 -45.5zM917 583q0 -50 -30 -67.5t-63.5 -6.5t-47.5 34l-367 438q-7 12 -14 15.5t-11 1.5l-3 -3q-7 -8 4 -21l122 -139l1 -354l-161 -457 q-67 -192 -92 -234q-16 -26 -28 -32q-50 -26 -103 -1q-29 13 -41.5 43t-9.5 57q2 17 197 618l5 416l-85 -164l35 -222q4 -24 -1 -42t-14 -27.5t-19 -16t-17 -7.5l-7 -2q-19 -3 -34.5 3t-24 16t-14 22t-7.5 19.5t-2 9.5l-46 299l211 381q23 34 113 34q75 0 107 -40l424 -521 q7 -5 14 -17l3 -3l-1 -1q7 -13 7 -29zM514 433q43 -113 88.5 -225t69.5 -168l24 -55q36 -93 42 -125q11 -70 -36 -97q-35 -22 -66 -16t-51 22t-29 35h-1q-6 16 -8 25l-124 351zM1338 -159q31 -49 31 -57q0 -5 -3 -7q-9 -5 -14.5 0.5t-15.5 26t-16 30.5q-114 172 -423 661 q3 -1 7 1t7 4l3 2q11 9 11 17z" />
-<glyph unicode="&#xf29e;" horiz-adv-x="2304" d="M504 542h171l-1 265zM1530 641q0 87 -50.5 140t-146.5 53h-54v-388h52q91 0 145 57t54 138zM956 1018l1 -756q0 -14 -9.5 -24t-23.5 -10h-216q-14 0 -23.5 10t-9.5 24v62h-291l-55 -81q-10 -15 -28 -15h-267q-21 0 -30.5 18t3.5 35l556 757q9 14 27 14h332q14 0 24 -10 t10 -24zM1783 641q0 -193 -125.5 -303t-324.5 -110h-270q-14 0 -24 10t-10 24v756q0 14 10 24t24 10h268q200 0 326 -109t126 -302zM1939 640q0 -11 -0.5 -29t-8 -71.5t-21.5 -102t-44.5 -108t-73.5 -102.5h-51q38 45 66.5 104.5t41.5 112t21 98t9 72.5l1 27q0 8 -0.5 22.5 t-7.5 60t-20 91.5t-41 111.5t-66 124.5h43q41 -47 72 -107t45.5 -111.5t23 -96t10.5 -70.5zM2123 640q0 -11 -0.5 -29t-8 -71.5t-21.5 -102t-45 -108t-74 -102.5h-51q38 45 66.5 104.5t41.5 112t21 98t9 72.5l1 27q0 8 -0.5 22.5t-7.5 60t-19.5 91.5t-40.5 111.5t-66 124.5 h43q41 -47 72 -107t45.5 -111.5t23 -96t10.5 -70.5zM2304 640q0 -11 -0.5 -29t-8 -71.5t-21.5 -102t-44.5 -108t-73.5 -102.5h-51q38 45 66 104.5t41 112t21 98t9 72.5l1 27q0 8 -0.5 22.5t-7.5 60t-19.5 91.5t-40.5 111.5t-66 124.5h43q41 -47 72 -107t45.5 -111.5t23 -96 t9.5 -70.5z" />
-<glyph unicode="&#xf2a0;" horiz-adv-x="1408" d="M617 -153q0 11 -13 58t-31 107t-20 69q-1 4 -5 26.5t-8.5 36t-13.5 21.5q-15 14 -51 14q-23 0 -70 -5.5t-71 -5.5q-34 0 -47 11q-6 5 -11 15.5t-7.5 20t-6.5 24t-5 18.5q-37 128 -37 255t37 255q1 4 5 18.5t6.5 24t7.5 20t11 15.5q13 11 47 11q24 0 71 -5.5t70 -5.5 q36 0 51 14q9 8 13.5 21.5t8.5 36t5 26.5q2 9 20 69t31 107t13 58q0 22 -43.5 52.5t-75.5 42.5q-20 8 -45 8q-34 0 -98 -18q-57 -17 -96.5 -40.5t-71 -66t-46 -70t-45.5 -94.5q-6 -12 -9 -19q-49 -107 -68 -216t-19 -244t19 -244t68 -216q56 -122 83 -161q63 -91 179 -127 l6 -2q64 -18 98 -18q25 0 45 8q32 12 75.5 42.5t43.5 52.5zM776 760q-26 0 -45 19t-19 45.5t19 45.5q37 37 37 90q0 52 -37 91q-19 19 -19 45t19 45t45 19t45 -19q75 -75 75 -181t-75 -181q-21 -19 -45 -19zM957 579q-27 0 -45 19q-19 19 -19 45t19 45q112 114 112 272 t-112 272q-19 19 -19 45t19 45t45 19t45 -19q150 -150 150 -362t-150 -362q-18 -19 -45 -19zM1138 398q-27 0 -45 19q-19 19 -19 45t19 45q90 91 138.5 208t48.5 245t-48.5 245t-138.5 208q-19 19 -19 45t19 45t45 19t45 -19q109 -109 167 -249t58 -294t-58 -294t-167 -249 q-18 -19 -45 -19z" />
-<glyph unicode="&#xf2a1;" horiz-adv-x="2176" d="M192 352q-66 0 -113 -47t-47 -113t47 -113t113 -47t113 47t47 113t-47 113t-113 47zM704 352q-66 0 -113 -47t-47 -113t47 -113t113 -47t113 47t47 113t-47 113t-113 47zM704 864q-66 0 -113 -47t-47 -113t47 -113t113 -47t113 47t47 113t-47 113t-113 47zM1472 352 q-66 0 -113 -47t-47 -113t47 -113t113 -47t113 47t47 113t-47 113t-113 47zM1984 352q-66 0 -113 -47t-47 -113t47 -113t113 -47t113 47t47 113t-47 113t-113 47zM1472 864q-66 0 -113 -47t-47 -113t47 -113t113 -47t113 47t47 113t-47 113t-113 47zM1984 864 q-66 0 -113 -47t-47 -113t47 -113t113 -47t113 47t47 113t-47 113t-113 47zM1984 1376q-66 0 -113 -47t-47 -113t47 -113t113 -47t113 47t47 113t-47 113t-113 47zM384 192q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM896 192q0 -80 -56 -136 t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM384 704q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM896 704q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM384 1216q0 -80 -56 -136t-136 -56 t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1664 192q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM896 1216q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM2176 192q0 -80 -56 -136t-136 -56t-136 56 t-56 136t56 136t136 56t136 -56t56 -136zM1664 704q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM2176 704q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1664 1216q0 -80 -56 -136t-136 -56t-136 56t-56 136 t56 136t136 56t136 -56t56 -136zM2176 1216q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136z" />
-<glyph unicode="&#xf2a2;" horiz-adv-x="1792" d="M128 -192q0 -26 -19 -45t-45 -19t-45 19t-19 45t19 45t45 19t45 -19t19 -45zM320 0q0 -26 -19 -45t-45 -19t-45 19t-19 45t19 45t45 19t45 -19t19 -45zM365 365l256 -256l-90 -90l-256 256zM704 384q0 -26 -19 -45t-45 -19t-45 19t-19 45t19 45t45 19t45 -19t19 -45z M1411 704q0 -59 -11.5 -108.5t-37.5 -93.5t-44 -67.5t-53 -64.5q-31 -35 -45.5 -54t-33.5 -50t-26.5 -64t-7.5 -74q0 -159 -112.5 -271.5t-271.5 -112.5q-26 0 -45 19t-19 45t19 45t45 19q106 0 181 75t75 181q0 57 11.5 105.5t37 91t43.5 66.5t52 63q40 46 59.5 72 t37.5 74.5t18 103.5q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5q0 -26 -19 -45t-45 -19t-45 19t-19 45q0 117 45.5 223.5t123 184t184 123t223.5 45.5t223.5 -45.5t184 -123t123 -184t45.5 -223.5zM896 576q0 -26 -19 -45t-45 -19t-45 19t-19 45t19 45 t45 19t45 -19t19 -45zM1184 704q0 -26 -19 -45t-45 -19t-45 19t-19 45q0 93 -65.5 158.5t-158.5 65.5q-92 0 -158 -65.5t-66 -158.5q0 -26 -19 -45t-45 -19t-45 19t-19 45q0 146 103 249t249 103t249 -103t103 -249zM1578 993q10 -25 -1 -49t-36 -34q-9 -4 -23 -4 q-19 0 -35.5 11t-23.5 30q-68 178 -224 295q-21 16 -25 42t12 47q17 21 43 25t47 -12q183 -137 266 -351zM1788 1074q9 -25 -1.5 -49t-35.5 -34q-11 -4 -23 -4q-44 0 -60 41q-92 238 -297 393q-22 16 -25.5 42t12.5 47q16 22 42 25.5t47 -12.5q235 -175 341 -449z" />
-<glyph unicode="&#xf2a3;" horiz-adv-x="2304" d="M1032 576q-59 2 -84 55q-17 34 -48 53.5t-68 19.5q-53 0 -90.5 -37.5t-37.5 -90.5q0 -56 36 -89l10 -8q34 -31 82 -31q37 0 68 19.5t48 53.5q25 53 84 55zM1600 704q0 56 -36 89l-10 8q-34 31 -82 31q-37 0 -68 -19.5t-48 -53.5q-25 -53 -84 -55q59 -2 84 -55 q17 -34 48 -53.5t68 -19.5q53 0 90.5 37.5t37.5 90.5zM1174 925q-17 -35 -55 -48t-73 4q-62 31 -134 31q-51 0 -99 -17q3 0 9.5 0.5t9.5 0.5q92 0 170.5 -50t118.5 -133q17 -36 3.5 -73.5t-49.5 -54.5q-18 -9 -39 -9q21 0 39 -9q36 -17 49.5 -54.5t-3.5 -73.5 q-40 -83 -118.5 -133t-170.5 -50h-6q-16 2 -44 4l-290 27l-239 -120q-14 -7 -29 -7q-40 0 -57 35l-160 320q-11 23 -4 47.5t29 37.5l209 119l148 267q17 155 91.5 291.5t195.5 236.5q31 25 70.5 21.5t64.5 -34.5t21.5 -70t-34.5 -65q-70 -59 -117 -128q123 84 267 101 q40 5 71.5 -19t35.5 -64q5 -40 -19 -71.5t-64 -35.5q-84 -10 -159 -55q46 10 99 10q115 0 218 -50q36 -18 49 -55.5t-5 -73.5zM2137 1085l160 -320q11 -23 4 -47.5t-29 -37.5l-209 -119l-148 -267q-17 -155 -91.5 -291.5t-195.5 -236.5q-26 -22 -61 -22q-45 0 -74 35 q-25 31 -21.5 70t34.5 65q70 59 117 128q-123 -84 -267 -101q-4 -1 -12 -1q-36 0 -63.5 24t-31.5 60q-5 40 19 71.5t64 35.5q84 10 159 55q-46 -10 -99 -10q-115 0 -218 50q-36 18 -49 55.5t5 73.5q17 35 55 48t73 -4q62 -31 134 -31q51 0 99 17q-3 0 -9.5 -0.5t-9.5 -0.5 q-92 0 -170.5 50t-118.5 133q-17 36 -3.5 73.5t49.5 54.5q18 9 39 9q-21 0 -39 9q-36 17 -49.5 54.5t3.5 73.5q40 83 118.5 133t170.5 50h6h1q14 -2 42 -4l291 -27l239 120q14 7 29 7q40 0 57 -35z" />
-<glyph unicode="&#xf2a4;" horiz-adv-x="1792" d="M1056 704q0 -26 19 -45t45 -19t45 19t19 45q0 146 -103 249t-249 103t-249 -103t-103 -249q0 -26 19 -45t45 -19t45 19t19 45q0 93 66 158.5t158 65.5t158 -65.5t66 -158.5zM835 1280q-117 0 -223.5 -45.5t-184 -123t-123 -184t-45.5 -223.5q0 -26 19 -45t45 -19t45 19 t19 45q0 185 131.5 316.5t316.5 131.5t316.5 -131.5t131.5 -316.5q0 -55 -18 -103.5t-37.5 -74.5t-59.5 -72q-34 -39 -52 -63t-43.5 -66.5t-37 -91t-11.5 -105.5q0 -106 -75 -181t-181 -75q-26 0 -45 -19t-19 -45t19 -45t45 -19q159 0 271.5 112.5t112.5 271.5q0 41 7.5 74 t26.5 64t33.5 50t45.5 54q35 41 53 64.5t44 67.5t37.5 93.5t11.5 108.5q0 117 -45.5 223.5t-123 184t-184 123t-223.5 45.5zM591 561l226 -226l-579 -579q-12 -12 -29 -12t-29 12l-168 168q-12 12 -12 29t12 29zM1612 1524l168 -168q12 -12 12 -29t-12 -30l-233 -233 l-26 -25l-71 -71q-66 153 -195 258l91 91l207 207q13 12 30 12t29 -12z" />
-<glyph unicode="&#xf2a5;" d="M866 1021q0 -27 -13 -94q-11 -50 -31.5 -150t-30.5 -150q-2 -11 -4.5 -12.5t-13.5 -2.5q-20 -2 -31 -2q-58 0 -84 49.5t-26 113.5q0 88 35 174t103 124q28 14 51 14q28 0 36.5 -16.5t8.5 -47.5zM1352 597q0 14 -39 75.5t-52 66.5q-21 8 -34 8q-91 0 -226 -77l-2 2 q3 22 27.5 135t24.5 178q0 233 -242 233q-24 0 -68 -6q-94 -17 -168.5 -89.5t-111.5 -166.5t-37 -189q0 -146 80.5 -225t227.5 -79q25 0 25 -3t-1 -5q-4 -34 -26 -117q-14 -52 -51.5 -101t-82.5 -49q-42 0 -42 47q0 24 10.5 47.5t25 39.5t29.5 28.5t26 20t11 8.5q0 3 -7 10 q-24 22 -58.5 36.5t-65.5 14.5q-35 0 -63.5 -34t-41 -75t-12.5 -75q0 -88 51.5 -142t138.5 -54q82 0 155 53t117.5 126t65.5 153q6 22 15.5 66.5t14.5 66.5q3 12 14 18q118 60 227 60q48 0 127 -18q1 -1 4 -1q5 0 9.5 4.5t4.5 8.5zM1536 1120v-960q0 -119 -84.5 -203.5 t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
-<glyph unicode="&#xf2a6;" horiz-adv-x="1535" d="M744 1231q0 24 -2 38.5t-8.5 30t-21 23t-37.5 7.5q-39 0 -78 -23q-105 -58 -159 -190.5t-54 -269.5q0 -44 8.5 -85.5t26.5 -80.5t52.5 -62.5t81.5 -23.5q4 0 18 -0.5t20 0t16 3t15 8.5t7 16q16 77 48 231.5t48 231.5q19 91 19 146zM1498 575q0 -7 -7.5 -13.5t-15.5 -6.5 l-6 1q-22 3 -62 11t-72 12.5t-63 4.5q-167 0 -351 -93q-15 -8 -21 -27q-10 -36 -24.5 -105.5t-22.5 -100.5q-23 -91 -70 -179.5t-112.5 -164.5t-154.5 -123t-185 -47q-135 0 -214.5 83.5t-79.5 219.5q0 53 19.5 117t63 116.5t97.5 52.5q38 0 120 -33.5t83 -61.5 q0 -1 -16.5 -12.5t-39.5 -31t-46 -44.5t-39 -61t-16 -74q0 -33 16.5 -53t48.5 -20q45 0 85 31.5t66.5 78t48 105.5t32.5 107t16 90v9q0 2 -3.5 3.5t-8.5 1.5h-10t-10 -0.5t-6 -0.5q-227 0 -352 122.5t-125 348.5q0 108 34.5 221t96 210t156 167.5t204.5 89.5q52 9 106 9 q374 0 374 -360q0 -98 -38 -273t-43 -211l3 -3q101 57 182.5 88t167.5 31q22 0 53 -13q19 -7 80 -102.5t61 -116.5z" />
-<glyph unicode="&#xf2a7;" horiz-adv-x="1664" d="M831 863q32 0 59 -18l222 -148q61 -40 110 -97l146 -170q40 -46 29 -106l-72 -413q-6 -32 -29.5 -53.5t-55.5 -25.5l-527 -56l-352 -32h-9q-39 0 -67.5 28t-28.5 68q0 37 27 64t65 32l260 32h-448q-41 0 -69.5 30t-26.5 71q2 39 32 65t69 26l442 1l-521 64q-41 5 -66 37 t-19 73q6 35 34.5 57.5t65.5 22.5h10l481 -60l-351 94q-38 10 -62 41.5t-18 68.5q6 36 33 58.5t62 22.5q6 0 20 -2l448 -96l217 -37q1 0 3 -0.5t3 -0.5q23 0 30.5 23t-12.5 36l-186 125q-35 23 -42 63.5t18 73.5q27 38 76 38zM761 661l186 -125l-218 37l-5 2l-36 38 l-238 262q-1 1 -2.5 3.5t-2.5 3.5q-24 31 -18.5 70t37.5 64q31 23 68 17.5t64 -33.5l142 -147l-4 -4t-5 -4q-32 -45 -23 -99t55 -85zM1648 1115l15 -266q4 -73 -11 -147l-48 -219q-12 -59 -67 -87l-106 -54q2 62 -39 109l-146 170q-53 61 -117 103l-222 148q-34 23 -76 23 q-51 0 -88 -37l-235 312q-25 33 -18 73.5t41 63.5q33 22 71.5 14t62.5 -40l266 -352l-262 455q-21 35 -10.5 75t47.5 59q35 18 72.5 6t57.5 -46l241 -420l-136 337q-15 35 -4.5 74t44.5 56q37 19 76 6t56 -51l193 -415l101 -196q8 -15 23 -17.5t27 7.5t11 26l-12 224 q-2 41 26 71t69 31q39 0 67 -28.5t30 -67.5z" />
-<glyph unicode="&#xf2a8;" horiz-adv-x="1792" d="M335 180q-2 0 -6 2q-86 57 -168.5 145t-139.5 180q-21 30 -21 69q0 9 2 19t4 18t7 18t8.5 16t10.5 17t10 15t12 15.5t11 14.5q184 251 452 365q-110 198 -110 211q0 19 17 29q116 64 128 64q18 0 28 -16l124 -229q92 19 192 19q266 0 497.5 -137.5t378.5 -369.5 q20 -31 20 -69t-20 -69q-91 -142 -218.5 -253.5t-278.5 -175.5q110 -198 110 -211q0 -20 -17 -29q-116 -64 -127 -64q-19 0 -29 16l-124 229l-64 119l-444 820l7 7q-58 -24 -99 -47q3 -5 127 -234t243 -449t119 -223q0 -7 -9 -9q-13 -3 -72 -3q-57 0 -60 7l-456 841 q-39 -28 -82 -68q24 -43 214 -393.5t190 -354.5q0 -10 -11 -10q-14 0 -82.5 22t-72.5 28l-106 197l-224 413q-44 -53 -78 -106q2 -3 18 -25t23 -34l176 -327q0 -10 -10 -10zM1165 282l49 -91q273 111 450 385q-180 277 -459 389q67 -64 103 -148.5t36 -176.5 q0 -106 -47 -200.5t-132 -157.5zM848 896q0 -20 14 -34t34 -14q86 0 147 -61t61 -147q0 -20 14 -34t34 -14t34 14t14 34q0 126 -89 215t-215 89q-20 0 -34 -14t-14 -34zM1214 961l-9 4l7 -7z" />
-<glyph unicode="&#xf2a9;" horiz-adv-x="1280" d="M1050 430q0 -215 -147 -374q-148 -161 -378 -161q-232 0 -378 161q-147 159 -147 374q0 147 68 270.5t189 196.5t268 73q96 0 182 -31q-32 -62 -39 -126q-66 28 -143 28q-167 0 -280.5 -123t-113.5 -291q0 -170 112.5 -288.5t281.5 -118.5t281 118.5t112 288.5 q0 89 -32 166q66 13 123 49q41 -98 41 -212zM846 619q0 -192 -79.5 -345t-238.5 -253l-14 -1q-29 0 -62 5q83 32 146.5 102.5t99.5 154.5t58.5 189t30 192.5t7.5 178.5q0 69 -3 103q55 -160 55 -326zM791 947v-2q-73 214 -206 440q88 -59 142.5 -186.5t63.5 -251.5z M1035 744q-83 0 -160 75q218 120 290 247q19 37 21 56q-42 -94 -139.5 -166.5t-204.5 -97.5q-35 54 -35 113q0 37 17 79t43 68q46 44 157 74q59 16 106 58.5t74 100.5q74 -105 74 -253q0 -109 -24 -170q-32 -77 -88.5 -130.5t-130.5 -53.5z" />
-<glyph unicode="&#xf2aa;" d="M1050 495q0 78 -28 147q-41 -25 -85 -34q22 -50 22 -114q0 -117 -77 -198.5t-193 -81.5t-193.5 81.5t-77.5 198.5q0 115 78 199.5t193 84.5q53 0 98 -19q4 43 27 87q-60 21 -125 21q-154 0 -257.5 -108.5t-103.5 -263.5t103.5 -261t257.5 -106t257.5 106.5t103.5 260.5z M872 850q2 -24 2 -71q0 -63 -5 -123t-20.5 -132.5t-40.5 -130t-68.5 -106t-100.5 -70.5q21 -3 42 -3h10q219 139 219 411q0 116 -38 225zM872 850q-4 80 -44 171.5t-98 130.5q92 -156 142 -302zM1207 955q0 102 -51 174q-41 -86 -124 -109q-69 -19 -109 -53.5t-40 -99.5 q0 -40 24 -77q74 17 140.5 67t95.5 115q-4 -52 -74.5 -111.5t-138.5 -97.5q52 -52 110 -52q51 0 90 37t60 90q17 43 17 117zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5 t84.5 -203.5z" />
-<glyph unicode="&#xf2ab;" d="M1279 388q0 22 -22 27q-67 15 -118 59t-80 108q-7 19 -7 25q0 15 19.5 26t43 17t43 20.5t19.5 36.5q0 19 -18.5 31.5t-38.5 12.5q-12 0 -32 -8t-31 -8q-4 0 -12 2q5 95 5 114q0 79 -17 114q-36 78 -103 121.5t-152 43.5q-199 0 -275 -165q-17 -35 -17 -114q0 -19 5 -114 q-4 -2 -14 -2q-12 0 -32 7.5t-30 7.5q-21 0 -38.5 -12t-17.5 -32q0 -21 19.5 -35.5t43 -20.5t43 -17t19.5 -26q0 -6 -7 -25q-64 -138 -198 -167q-22 -5 -22 -27q0 -46 137 -68q2 -5 6 -26t11.5 -30.5t23.5 -9.5q12 0 37.5 4.5t39.5 4.5q35 0 67 -15t54 -32.5t57.5 -32.5 t76.5 -15q43 0 79 15t57.5 32.5t53.5 32.5t67 15q14 0 39.5 -4t38.5 -4q16 0 23 10t11 30t6 25q137 22 137 68zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5 t103 -385.5z" />
-<glyph unicode="&#xf2ac;" horiz-adv-x="1664" d="M848 1408q134 1 240.5 -68.5t163.5 -192.5q27 -58 27 -179q0 -47 -9 -191q14 -7 28 -7q18 0 51 13.5t51 13.5q29 0 56 -18t27 -46q0 -32 -31.5 -54t-69 -31.5t-69 -29t-31.5 -47.5q0 -15 12 -43q37 -82 102.5 -150t144.5 -101q28 -12 80 -23q28 -6 28 -35 q0 -70 -219 -103q-7 -11 -11 -39t-14 -46.5t-33 -18.5q-20 0 -62 6.5t-64 6.5q-37 0 -62 -5q-32 -5 -63 -22.5t-58 -38t-58 -40.5t-76 -33.5t-99 -13.5q-52 0 -96.5 13.5t-75 33.5t-57.5 40.5t-58 38t-62 22.5q-26 5 -63 5q-24 0 -65.5 -7.5t-58.5 -7.5q-25 0 -35 18.5 t-14 47.5t-11 40q-219 33 -219 103q0 29 28 35q52 11 80 23q78 32 144.5 101t102.5 150q12 28 12 43q0 28 -31.5 47.5t-69.5 29.5t-69.5 31.5t-31.5 52.5q0 27 26 45.5t55 18.5q15 0 48 -13t53 -13q18 0 32 7q-9 142 -9 190q0 122 27 180q64 137 172 198t264 63z" />
-<glyph unicode="&#xf2ad;" d="M1280 388q0 22 -22 27q-67 14 -118 58t-80 109q-7 14 -7 25q0 15 19.5 26t42.5 17t42.5 20.5t19.5 36.5q0 19 -18.5 31.5t-38.5 12.5q-11 0 -31 -8t-32 -8q-4 0 -12 2q5 63 5 115q0 78 -17 114q-36 78 -102.5 121.5t-152.5 43.5q-198 0 -275 -165q-18 -38 -18 -115 q0 -38 6 -114q-10 -2 -15 -2q-11 0 -31.5 8t-30.5 8q-20 0 -37.5 -12.5t-17.5 -32.5q0 -21 19.5 -35.5t42.5 -20.5t42.5 -17t19.5 -26q0 -11 -7 -25q-64 -138 -198 -167q-22 -5 -22 -27q0 -47 138 -69q2 -5 6 -26t11 -30.5t23 -9.5q13 0 38.5 5t38.5 5q35 0 67.5 -15 t54.5 -32.5t57.5 -32.5t76.5 -15q43 0 79 15t57.5 32.5t54 32.5t67.5 15q13 0 39 -4.5t39 -4.5q15 0 22.5 9.5t11.5 31t5 24.5q138 22 138 69zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960 q119 0 203.5 -84.5t84.5 -203.5z" />
-<glyph unicode="&#xf2ae;" horiz-adv-x="2304" d="M2304 1536q-69 -46 -125 -92t-89 -81t-59.5 -71.5t-37.5 -57.5t-22 -44.5t-14 -29.5q-10 -18 -35.5 -136.5t-48.5 -164.5q-15 -29 -50 -60.5t-67.5 -50.5t-72.5 -41t-48 -28q-47 -31 -151 -231q-341 14 -630 -158q-92 -53 -303 -179q47 16 86 31t55 22l15 7 q71 27 163 64.5t133.5 53.5t108 34.5t142.5 31.5q186 31 465 -7q1 0 10 -3q11 -6 14 -17t-3 -22l-194 -345q-15 -29 -47 -22q-128 24 -354 24q-146 0 -402 -44.5t-392 -46.5q-82 -1 -149 13t-107 37t-61 40t-33 34l-1 1v2q0 6 6 6q138 0 371 55q192 366 374.5 524t383.5 158 q5 0 14.5 -0.5t38 -5t55 -12t61.5 -24.5t63 -39.5t54 -59t40 -82.5l102 177q2 4 21 42.5t44.5 86.5t61 109.5t84 133.5t100.5 137q66 82 128 141.5t121.5 96.5t92.5 53.5t88 39.5z" />
-<glyph unicode="&#xf2b0;" d="M1322 640q0 -45 -5 -76l-236 14l224 -78q-19 -73 -58 -141l-214 103l177 -158q-44 -61 -107 -108l-157 178l103 -215q-61 -37 -140 -59l-79 228l14 -240q-38 -6 -76 -6t-76 6l14 238l-78 -226q-74 19 -140 59l103 215l-157 -178q-59 43 -108 108l178 158l-214 -104 q-39 69 -58 141l224 79l-237 -14q-5 42 -5 76q0 35 5 77l238 -14l-225 79q19 73 58 140l214 -104l-177 159q46 61 107 108l158 -178l-103 215q67 39 140 58l77 -224l-13 236q36 6 75 6q38 0 76 -6l-14 -237l78 225q74 -19 140 -59l-103 -214l158 178q61 -47 107 -108 l-177 -159l213 104q37 -62 58 -141l-224 -78l237 14q5 -31 5 -77zM1352 640q0 160 -78.5 295.5t-213 214t-292.5 78.5q-119 0 -227 -46.5t-186.5 -125t-124.5 -187.5t-46 -229q0 -119 46 -228t124.5 -187.5t186.5 -125t227 -46.5q158 0 292.5 78.5t213 214t78.5 294.5z M1425 1023v-766l-657 -383l-657 383v766l657 383zM768 -183l708 412v823l-708 411l-708 -411v-823zM1536 1088v-896l-768 -448l-768 448v896l768 448z" />
-<glyph unicode="&#xf2b1;" horiz-adv-x="1664" d="M339 1318h691l-26 -72h-665q-110 0 -188.5 -79t-78.5 -189v-771q0 -95 60.5 -169.5t153.5 -93.5q23 -5 98 -5v-72h-45q-140 0 -239.5 100t-99.5 240v771q0 140 99.5 240t239.5 100zM1190 1536h247l-482 -1294q-23 -61 -40.5 -103.5t-45 -98t-54 -93.5t-64.5 -78.5 t-79.5 -65t-95.5 -41t-116 -18.5v195q163 26 220 182q20 52 20 105q0 54 -20 106l-285 733h228l187 -585zM1664 978v-1111h-795q37 55 45 73h678v1038q0 85 -49.5 155t-129.5 99l25 67q101 -34 163.5 -123.5t62.5 -197.5z" />
-<glyph unicode="&#xf2b2;" horiz-adv-x="1792" d="M852 1227q0 -29 -17 -52.5t-45 -23.5t-45 23.5t-17 52.5t17 52.5t45 23.5t45 -23.5t17 -52.5zM688 -149v114q0 30 -20.5 51.5t-50.5 21.5t-50 -21.5t-20 -51.5v-114q0 -30 20.5 -52t49.5 -22q30 0 50.5 22t20.5 52zM860 -149v114q0 30 -20 51.5t-50 21.5t-50.5 -21.5 t-20.5 -51.5v-114q0 -30 20.5 -52t50.5 -22q29 0 49.5 22t20.5 52zM1034 -149v114q0 30 -20.5 51.5t-50.5 21.5t-50.5 -21.5t-20.5 -51.5v-114q0 -30 20.5 -52t50.5 -22t50.5 22t20.5 52zM1208 -149v114q0 30 -20.5 51.5t-50.5 21.5t-50.5 -21.5t-20.5 -51.5v-114 q0 -30 20.5 -52t50.5 -22t50.5 22t20.5 52zM1476 535q-84 -160 -232 -259.5t-323 -99.5q-123 0 -229.5 51.5t-178.5 137t-113 197.5t-41 232q0 88 21 174q-104 -175 -104 -390q0 -162 65 -312t185 -251q30 57 91 57q56 0 86 -50q32 50 87 50q56 0 86 -50q32 50 87 50t87 -50 q30 50 86 50q28 0 52.5 -15.5t37.5 -40.5q112 94 177 231.5t73 287.5zM1326 564q0 75 -72 75q-17 0 -47 -6q-95 -19 -149 -19q-226 0 -226 243q0 86 30 204q-83 -127 -83 -275q0 -150 89 -260.5t235 -110.5q111 0 210 70q13 48 13 79zM884 1223q0 50 -32 89.5t-81 39.5 t-81 -39.5t-32 -89.5q0 -51 31.5 -90.5t81.5 -39.5t81.5 39.5t31.5 90.5zM1513 884q0 96 -37.5 179t-113 137t-173.5 54q-77 0 -149 -35t-127 -94q-48 -159 -48 -268q0 -104 45.5 -157t147.5 -53q53 0 142 19q36 6 53 6q51 0 77.5 -28t26.5 -80q0 -26 -4 -46 q75 68 117.5 165.5t42.5 200.5zM1792 667q0 -111 -33.5 -249.5t-93.5 -204.5q-58 -64 -195 -142.5t-228 -104.5l-4 -1v-114q0 -43 -29.5 -75t-72.5 -32q-56 0 -86 50q-32 -50 -87 -50t-87 50q-30 -50 -86 -50q-55 0 -87 50q-30 -50 -86 -50q-47 0 -75 33.5t-28 81.5 q-90 -68 -198 -68q-118 0 -211 80q54 1 106 20q-113 31 -182 127q32 -7 71 -7q89 0 164 46q-192 192 -240 306q-24 56 -24 160q0 57 9 125.5t31.5 146.5t55 141t86.5 105t120 42q59 0 81 -52q19 29 42 54q2 3 12 13t13 16q10 15 23 38t25 42t28 39q87 111 211.5 177 t260.5 66q35 0 62 -4q59 64 146 64q83 0 140 -57q5 -5 5 -12q0 -5 -6 -13.5t-12.5 -16t-16 -17l-10.5 -10.5q17 -6 36 -18t19 -24q0 -6 -16 -25q157 -138 197 -378q25 30 60 30q45 0 100 -49q90 -80 90 -279z" />
-<glyph unicode="&#xf2b3;" d="M917 631q0 33 -6 64h-362v-132h217q-12 -76 -74.5 -120.5t-142.5 -44.5q-99 0 -169 71.5t-70 170.5t70 170.5t169 71.5q93 0 153 -59l104 101q-108 100 -257 100q-160 0 -272 -112.5t-112 -271.5t112 -271.5t272 -112.5q165 0 266.5 105t101.5 270zM1262 585h109v110 h-109v110h-110v-110h-110v-110h110v-110h110v110zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
-<glyph unicode="&#xf2b4;" d="M1536 1024v-839q0 -48 -49 -62q-174 -52 -338 -52q-73 0 -215.5 29.5t-227.5 29.5q-164 0 -370 -48v-338h-160v1368q-63 25 -101 81t-38 124q0 91 64 155t155 64t155 -64t64 -155q0 -68 -38 -124t-101 -81v-68q190 44 343 44q99 0 198 -15q14 -2 111.5 -22.5t149.5 -20.5 q77 0 165 18q11 2 80 21t89 19q26 0 45 -19t19 -45z" />
-<glyph unicode="&#xf2b5;" horiz-adv-x="1792" />
-<glyph unicode="&#xf2b6;" horiz-adv-x="1792" />
-<glyph unicode="&#xf2b7;" horiz-adv-x="1792" />
-<glyph unicode="&#xf2b8;" horiz-adv-x="1792" />
-<glyph unicode="&#xf2b9;" horiz-adv-x="1792" />
-<glyph unicode="&#xf2ba;" horiz-adv-x="1792" />
-<glyph unicode="&#xf2bb;" horiz-adv-x="1792" />
-<glyph unicode="&#xf2bc;" horiz-adv-x="1792" />
-<glyph unicode="&#xf2bd;" horiz-adv-x="1792" />
-<glyph unicode="&#xf2be;" horiz-adv-x="1792" />
-<glyph unicode="&#xf500;" horiz-adv-x="1792" />
-</font>
-</defs></svg> 
\ No newline at end of file
+<font id="FontAwesome" horiz-adv-x="1536" >
+  <font-face 
+    font-family="FontAwesome"
+    font-weight="400"
+    font-stretch="normal"
+    units-per-em="1792"
+    panose-1="0 0 0 0 0 0 0 0 0 0"
+    ascent="1536"
+    descent="-256"
+    bbox="-1.02083 -256.962 2304.6 1537.02"
+    underline-thickness="0"
+    underline-position="0"
+    unicode-range="U+0020-F500"
+  />
+<missing-glyph horiz-adv-x="896" 
+d="M224 112h448v1312h-448v-1312zM112 0v1536h672v-1536h-672z" />
+    <glyph glyph-name=".notdef" horiz-adv-x="896" 
+d="M224 112h448v1312h-448v-1312zM112 0v1536h672v-1536h-672z" />
+    <glyph glyph-name=".null" horiz-adv-x="0" 
+ />
+    <glyph glyph-name="nonmarkingreturn" horiz-adv-x="597" 
+ />
+    <glyph glyph-name="space" unicode=" " horiz-adv-x="448" 
+ />
+    <glyph glyph-name="dieresis" unicode="&#xa8;" horiz-adv-x="1792" 
+ />
+    <glyph glyph-name="copyright" unicode="&#xa9;" horiz-adv-x="1792" 
+ />
+    <glyph glyph-name="registered" unicode="&#xae;" horiz-adv-x="1792" 
+ />
+    <glyph glyph-name="acute" unicode="&#xb4;" horiz-adv-x="1792" 
+ />
+    <glyph glyph-name="AE" unicode="&#xc6;" horiz-adv-x="1792" 
+ />
+    <glyph glyph-name="Oslash" unicode="&#xd8;" horiz-adv-x="1792" 
+ />
+    <glyph glyph-name="trademark" unicode="&#x2122;" horiz-adv-x="1792" 
+ />
+    <glyph glyph-name="infinity" unicode="&#x221e;" horiz-adv-x="1792" 
+ />
+    <glyph glyph-name="notequal" unicode="&#x2260;" horiz-adv-x="1792" 
+ />
+    <glyph glyph-name="glass" unicode="&#xf000;" horiz-adv-x="1792" 
+d="M1699 1350q0 -35 -43 -78l-632 -632v-768h320q26 0 45 -19t19 -45t-19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45t45 19h320v768l-632 632q-43 43 -43 78q0 23 18 36.5t38 17.5t43 4h1408q23 0 43 -4t38 -17.5t18 -36.5z" />
+    <glyph glyph-name="music" unicode="&#xf001;" 
+d="M1536 1312v-1120q0 -50 -34 -89t-86 -60.5t-103.5 -32t-96.5 -10.5t-96.5 10.5t-103.5 32t-86 60.5t-34 89t34 89t86 60.5t103.5 32t96.5 10.5q105 0 192 -39v537l-768 -237v-709q0 -50 -34 -89t-86 -60.5t-103.5 -32t-96.5 -10.5t-96.5 10.5t-103.5 32t-86 60.5t-34 89
+t34 89t86 60.5t103.5 32t96.5 10.5q105 0 192 -39v967q0 31 19 56.5t49 35.5l832 256q12 4 28 4q40 0 68 -28t28 -68z" />
+    <glyph glyph-name="search" unicode="&#xf002;" horiz-adv-x="1664" 
+d="M1152 704q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5zM1664 -128q0 -52 -38 -90t-90 -38q-54 0 -90 38l-343 342q-179 -124 -399 -124q-143 0 -273.5 55.5t-225 150t-150 225t-55.5 273.5
+t55.5 273.5t150 225t225 150t273.5 55.5t273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -220 -124 -399l343 -343q37 -37 37 -90z" />
+    <glyph glyph-name="envelope" unicode="&#xf003;" horiz-adv-x="1792" 
+d="M1664 32v768q-32 -36 -69 -66q-268 -206 -426 -338q-51 -43 -83 -67t-86.5 -48.5t-102.5 -24.5h-1h-1q-48 0 -102.5 24.5t-86.5 48.5t-83 67q-158 132 -426 338q-37 30 -69 66v-768q0 -13 9.5 -22.5t22.5 -9.5h1472q13 0 22.5 9.5t9.5 22.5zM1664 1083v11v13.5t-0.5 13
+t-3 12.5t-5.5 9t-9 7.5t-14 2.5h-1472q-13 0 -22.5 -9.5t-9.5 -22.5q0 -168 147 -284q193 -152 401 -317q6 -5 35 -29.5t46 -37.5t44.5 -31.5t50.5 -27.5t43 -9h1h1q20 0 43 9t50.5 27.5t44.5 31.5t46 37.5t35 29.5q208 165 401 317q54 43 100.5 115.5t46.5 131.5z
+M1792 1120v-1088q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1472q66 0 113 -47t47 -113z" />
+    <glyph glyph-name="heart" unicode="&#xf004;" horiz-adv-x="1792" 
+d="M896 -128q-26 0 -44 18l-624 602q-10 8 -27.5 26t-55.5 65.5t-68 97.5t-53.5 121t-23.5 138q0 220 127 344t351 124q62 0 126.5 -21.5t120 -58t95.5 -68.5t76 -68q36 36 76 68t95.5 68.5t120 58t126.5 21.5q224 0 351 -124t127 -344q0 -221 -229 -450l-623 -600
+q-18 -18 -44 -18z" />
+    <glyph glyph-name="star" unicode="&#xf005;" horiz-adv-x="1664" 
+d="M1664 889q0 -22 -26 -48l-363 -354l86 -500q1 -7 1 -20q0 -21 -10.5 -35.5t-30.5 -14.5q-19 0 -40 12l-449 236l-449 -236q-22 -12 -40 -12q-21 0 -31.5 14.5t-10.5 35.5q0 6 2 20l86 500l-364 354q-25 27 -25 48q0 37 56 46l502 73l225 455q19 41 49 41t49 -41l225 -455
+l502 -73q56 -9 56 -46z" />
+    <glyph glyph-name="star_empty" unicode="&#xf006;" horiz-adv-x="1664" 
+d="M1137 532l306 297l-422 62l-189 382l-189 -382l-422 -62l306 -297l-73 -421l378 199l377 -199zM1664 889q0 -22 -26 -48l-363 -354l86 -500q1 -7 1 -20q0 -50 -41 -50q-19 0 -40 12l-449 236l-449 -236q-22 -12 -40 -12q-21 0 -31.5 14.5t-10.5 35.5q0 6 2 20l86 500
+l-364 354q-25 27 -25 48q0 37 56 46l502 73l225 455q19 41 49 41t49 -41l225 -455l502 -73q56 -9 56 -46z" />
+    <glyph glyph-name="user" unicode="&#xf007;" horiz-adv-x="1280" 
+d="M1280 137q0 -109 -62.5 -187t-150.5 -78h-854q-88 0 -150.5 78t-62.5 187q0 85 8.5 160.5t31.5 152t58.5 131t94 89t134.5 34.5q131 -128 313 -128t313 128q76 0 134.5 -34.5t94 -89t58.5 -131t31.5 -152t8.5 -160.5zM1024 1024q0 -159 -112.5 -271.5t-271.5 -112.5
+t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5z" />
+    <glyph glyph-name="film" unicode="&#xf008;" horiz-adv-x="1920" 
+d="M384 -64v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM384 320v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM384 704v128q0 26 -19 45t-45 19h-128
+q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1408 -64v512q0 26 -19 45t-45 19h-768q-26 0 -45 -19t-19 -45v-512q0 -26 19 -45t45 -19h768q26 0 45 19t19 45zM384 1088v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45
+t45 -19h128q26 0 45 19t19 45zM1792 -64v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1408 704v512q0 26 -19 45t-45 19h-768q-26 0 -45 -19t-19 -45v-512q0 -26 19 -45t45 -19h768q26 0 45 19t19 45zM1792 320v128
+q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1792 704v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1792 1088v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19
+t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1920 1248v-1344q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113v1344q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" />
+    <glyph glyph-name="th_large" unicode="&#xf009;" horiz-adv-x="1664" 
+d="M768 512v-384q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90zM768 1280v-384q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90zM1664 512v-384q0 -52 -38 -90t-90 -38
+h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90zM1664 1280v-384q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90z" />
+    <glyph glyph-name="th" unicode="&#xf00a;" horiz-adv-x="1792" 
+d="M512 288v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM512 800v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1152 288v-192q0 -40 -28 -68t-68 -28h-320
+q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM512 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1152 800v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28
+h320q40 0 68 -28t28 -68zM1792 288v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1152 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 800v-192
+q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68z" />
+    <glyph glyph-name="th_list" unicode="&#xf00b;" horiz-adv-x="1792" 
+d="M512 288v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM512 800v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 288v-192q0 -40 -28 -68t-68 -28h-960
+q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h960q40 0 68 -28t28 -68zM512 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 800v-192q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v192q0 40 28 68t68 28
+h960q40 0 68 -28t28 -68zM1792 1312v-192q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h960q40 0 68 -28t28 -68z" />
+    <glyph glyph-name="ok" unicode="&#xf00c;" horiz-adv-x="1792" 
+d="M1671 970q0 -40 -28 -68l-724 -724l-136 -136q-28 -28 -68 -28t-68 28l-136 136l-362 362q-28 28 -28 68t28 68l136 136q28 28 68 28t68 -28l294 -295l656 657q28 28 68 28t68 -28l136 -136q28 -28 28 -68z" />
+    <glyph glyph-name="remove" unicode="&#xf00d;" horiz-adv-x="1408" 
+d="M1298 214q0 -40 -28 -68l-136 -136q-28 -28 -68 -28t-68 28l-294 294l-294 -294q-28 -28 -68 -28t-68 28l-136 136q-28 28 -28 68t28 68l294 294l-294 294q-28 28 -28 68t28 68l136 136q28 28 68 28t68 -28l294 -294l294 294q28 28 68 28t68 -28l136 -136q28 -28 28 -68
+t-28 -68l-294 -294l294 -294q28 -28 28 -68z" />
+    <glyph glyph-name="zoom_in" unicode="&#xf00e;" horiz-adv-x="1664" 
+d="M1024 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-224v-224q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v224h-224q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h224v224q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5v-224h224
+q13 0 22.5 -9.5t9.5 -22.5zM1152 704q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5zM1664 -128q0 -53 -37.5 -90.5t-90.5 -37.5q-54 0 -90 38l-343 342q-179 -124 -399 -124q-143 0 -273.5 55.5
+t-225 150t-150 225t-55.5 273.5t55.5 273.5t150 225t225 150t273.5 55.5t273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -220 -124 -399l343 -343q37 -37 37 -90z" />
+    <glyph glyph-name="zoom_out" unicode="&#xf010;" horiz-adv-x="1664" 
+d="M1024 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-576q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h576q13 0 22.5 -9.5t9.5 -22.5zM1152 704q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5z
+M1664 -128q0 -53 -37.5 -90.5t-90.5 -37.5q-54 0 -90 38l-343 342q-179 -124 -399 -124q-143 0 -273.5 55.5t-225 150t-150 225t-55.5 273.5t55.5 273.5t150 225t225 150t273.5 55.5t273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -220 -124 -399l343 -343q37 -37 37 -90z
+" />
+    <glyph glyph-name="off" unicode="&#xf011;" 
+d="M1536 640q0 -156 -61 -298t-164 -245t-245 -164t-298 -61t-298 61t-245 164t-164 245t-61 298q0 182 80.5 343t226.5 270q43 32 95.5 25t83.5 -50q32 -42 24.5 -94.5t-49.5 -84.5q-98 -74 -151.5 -181t-53.5 -228q0 -104 40.5 -198.5t109.5 -163.5t163.5 -109.5
+t198.5 -40.5t198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5q0 121 -53.5 228t-151.5 181q-42 32 -49.5 84.5t24.5 94.5q31 43 84 50t95 -25q146 -109 226.5 -270t80.5 -343zM896 1408v-640q0 -52 -38 -90t-90 -38t-90 38t-38 90v640q0 52 38 90t90 38t90 -38t38 -90z" />
+    <glyph glyph-name="signal" unicode="&#xf012;" horiz-adv-x="1792" 
+d="M256 96v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM640 224v-320q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v320q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1024 480v-576q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23
+v576q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1408 864v-960q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v960q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1792 1376v-1472q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v1472q0 14 9 23t23 9h192q14 0 23 -9t9 -23z" />
+    <glyph glyph-name="cog" unicode="&#xf013;" 
+d="M1024 640q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM1536 749v-222q0 -12 -8 -23t-20 -13l-185 -28q-19 -54 -39 -91q35 -50 107 -138q10 -12 10 -25t-9 -23q-27 -37 -99 -108t-94 -71q-12 0 -26 9l-138 108q-44 -23 -91 -38
+q-16 -136 -29 -186q-7 -28 -36 -28h-222q-14 0 -24.5 8.5t-11.5 21.5l-28 184q-49 16 -90 37l-141 -107q-10 -9 -25 -9q-14 0 -25 11q-126 114 -165 168q-7 10 -7 23q0 12 8 23q15 21 51 66.5t54 70.5q-27 50 -41 99l-183 27q-13 2 -21 12.5t-8 23.5v222q0 12 8 23t19 13
+l186 28q14 46 39 92q-40 57 -107 138q-10 12 -10 24q0 10 9 23q26 36 98.5 107.5t94.5 71.5q13 0 26 -10l138 -107q44 23 91 38q16 136 29 186q7 28 36 28h222q14 0 24.5 -8.5t11.5 -21.5l28 -184q49 -16 90 -37l142 107q9 9 24 9q13 0 25 -10q129 -119 165 -170q7 -8 7 -22
+q0 -12 -8 -23q-15 -21 -51 -66.5t-54 -70.5q26 -50 41 -98l183 -28q13 -2 21 -12.5t8 -23.5z" />
+    <glyph glyph-name="trash" unicode="&#xf014;" horiz-adv-x="1408" 
+d="M512 800v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM768 800v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1024 800v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576
+q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1152 76v948h-896v-948q0 -22 7 -40.5t14.5 -27t10.5 -8.5h832q3 0 10.5 8.5t14.5 27t7 40.5zM480 1152h448l-48 117q-7 9 -17 11h-317q-10 -2 -17 -11zM1408 1120v-64q0 -14 -9 -23t-23 -9h-96v-948q0 -83 -47 -143.5t-113 -60.5h-832
+q-66 0 -113 58.5t-47 141.5v952h-96q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h309l70 167q15 37 54 63t79 26h320q40 0 79 -26t54 -63l70 -167h309q14 0 23 -9t9 -23z" />
+    <glyph glyph-name="home" unicode="&#xf015;" horiz-adv-x="1664" 
+d="M1408 544v-480q0 -26 -19 -45t-45 -19h-384v384h-256v-384h-384q-26 0 -45 19t-19 45v480q0 1 0.5 3t0.5 3l575 474l575 -474q1 -2 1 -6zM1631 613l-62 -74q-8 -9 -21 -11h-3q-13 0 -21 7l-692 577l-692 -577q-12 -8 -24 -7q-13 2 -21 11l-62 74q-8 10 -7 23.5t11 21.5
+l719 599q32 26 76 26t76 -26l244 -204v195q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-408l219 -182q10 -8 11 -21.5t-7 -23.5z" />
+    <glyph glyph-name="file_alt" unicode="&#xf016;" 
+d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z
+" />
+    <glyph glyph-name="time" unicode="&#xf017;" 
+d="M896 992v-448q0 -14 -9 -23t-23 -9h-320q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h224v352q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640
+q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="road" unicode="&#xf018;" horiz-adv-x="1920" 
+d="M1111 540v4l-24 320q-1 13 -11 22.5t-23 9.5h-186q-13 0 -23 -9.5t-11 -22.5l-24 -320v-4q-1 -12 8 -20t21 -8h244q12 0 21 8t8 20zM1870 73q0 -73 -46 -73h-704q13 0 22 9.5t8 22.5l-20 256q-1 13 -11 22.5t-23 9.5h-272q-13 0 -23 -9.5t-11 -22.5l-20 -256
+q-1 -13 8 -22.5t22 -9.5h-704q-46 0 -46 73q0 54 26 116l417 1044q8 19 26 33t38 14h339q-13 0 -23 -9.5t-11 -22.5l-15 -192q-1 -14 8 -23t22 -9h166q13 0 22 9t8 23l-15 192q-1 13 -11 22.5t-23 9.5h339q20 0 38 -14t26 -33l417 -1044q26 -62 26 -116z" />
+    <glyph glyph-name="download_alt" unicode="&#xf019;" horiz-adv-x="1664" 
+d="M1280 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1536 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1664 416v-320q0 -40 -28 -68t-68 -28h-1472q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h465l135 -136
+q58 -56 136 -56t136 56l136 136h464q40 0 68 -28t28 -68zM1339 985q17 -41 -14 -70l-448 -448q-18 -19 -45 -19t-45 19l-448 448q-31 29 -14 70q17 39 59 39h256v448q0 26 19 45t45 19h256q26 0 45 -19t19 -45v-448h256q42 0 59 -39z" />
+    <glyph glyph-name="download" unicode="&#xf01a;" 
+d="M1120 608q0 -12 -10 -24l-319 -319q-11 -9 -23 -9t-23 9l-320 320q-15 16 -7 35q8 20 30 20h192v352q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-352h192q14 0 23 -9t9 -23zM768 1184q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273
+t-73 273t-198 198t-273 73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="upload" unicode="&#xf01b;" 
+d="M1118 660q-8 -20 -30 -20h-192v-352q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v352h-192q-14 0 -23 9t-9 23q0 12 10 24l319 319q11 9 23 9t23 -9l320 -320q15 -16 7 -35zM768 1184q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198
+t73 273t-73 273t-198 198t-273 73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="inbox" unicode="&#xf01c;" 
+d="M1023 576h316q-1 3 -2.5 8.5t-2.5 7.5l-212 496h-708l-212 -496q-1 -3 -2.5 -8.5t-2.5 -7.5h316l95 -192h320zM1536 546v-482q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v482q0 62 25 123l238 552q10 25 36.5 42t52.5 17h832q26 0 52.5 -17t36.5 -42l238 -552
+q25 -61 25 -123z" />
+    <glyph glyph-name="play_circle" unicode="&#xf01d;" 
+d="M1184 640q0 -37 -32 -55l-544 -320q-15 -9 -32 -9q-16 0 -32 8q-32 19 -32 56v640q0 37 32 56q33 18 64 -1l544 -320q32 -18 32 -55zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640
+q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="repeat" unicode="&#xf01e;" 
+d="M1536 1280v-448q0 -26 -19 -45t-45 -19h-448q-42 0 -59 40q-17 39 14 69l138 138q-148 137 -349 137q-104 0 -198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5q119 0 225 52t179 147q7 10 23 12q15 0 25 -9
+l137 -138q9 -8 9.5 -20.5t-7.5 -22.5q-109 -132 -264 -204.5t-327 -72.5q-156 0 -298 61t-245 164t-164 245t-61 298t61 298t164 245t245 164t298 61q147 0 284.5 -55.5t244.5 -156.5l130 129q29 31 70 14q39 -17 39 -59z" />
+    <glyph glyph-name="refresh" unicode="&#xf021;" 
+d="M1511 480q0 -5 -1 -7q-64 -268 -268 -434.5t-478 -166.5q-146 0 -282.5 55t-243.5 157l-129 -129q-19 -19 -45 -19t-45 19t-19 45v448q0 26 19 45t45 19h448q26 0 45 -19t19 -45t-19 -45l-137 -137q71 -66 161 -102t187 -36q134 0 250 65t186 179q11 17 53 117
+q8 23 30 23h192q13 0 22.5 -9.5t9.5 -22.5zM1536 1280v-448q0 -26 -19 -45t-45 -19h-448q-26 0 -45 19t-19 45t19 45l138 138q-148 137 -349 137q-134 0 -250 -65t-186 -179q-11 -17 -53 -117q-8 -23 -30 -23h-199q-13 0 -22.5 9.5t-9.5 22.5v7q65 268 270 434.5t480 166.5
+q146 0 284 -55.5t245 -156.5l130 129q19 19 45 19t45 -19t19 -45z" />
+    <glyph glyph-name="list_alt" unicode="&#xf022;" horiz-adv-x="1792" 
+d="M384 352v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 608v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z
+M384 864v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1536 352v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h960q13 0 22.5 -9.5t9.5 -22.5z
+M1536 608v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h960q13 0 22.5 -9.5t9.5 -22.5zM1536 864v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h960q13 0 22.5 -9.5
+t9.5 -22.5zM1664 160v832q0 13 -9.5 22.5t-22.5 9.5h-1472q-13 0 -22.5 -9.5t-9.5 -22.5v-832q0 -13 9.5 -22.5t22.5 -9.5h1472q13 0 22.5 9.5t9.5 22.5zM1792 1248v-1088q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1472q66 0 113 -47
+t47 -113z" />
+    <glyph glyph-name="lock" unicode="&#xf023;" horiz-adv-x="1152" 
+d="M320 768h512v192q0 106 -75 181t-181 75t-181 -75t-75 -181v-192zM1152 672v-576q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v576q0 40 28 68t68 28h32v192q0 184 132 316t316 132t316 -132t132 -316v-192h32q40 0 68 -28t28 -68z" />
+    <glyph glyph-name="flag" unicode="&#xf024;" horiz-adv-x="1792" 
+d="M320 1280q0 -72 -64 -110v-1266q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v1266q-64 38 -64 110q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1792 1216v-763q0 -25 -12.5 -38.5t-39.5 -27.5q-215 -116 -369 -116q-61 0 -123.5 22t-108.5 48
+t-115.5 48t-142.5 22q-192 0 -464 -146q-17 -9 -33 -9q-26 0 -45 19t-19 45v742q0 32 31 55q21 14 79 43q236 120 421 120q107 0 200 -29t219 -88q38 -19 88 -19q54 0 117.5 21t110 47t88 47t54.5 21q26 0 45 -19t19 -45z" />
+    <glyph glyph-name="headphones" unicode="&#xf025;" horiz-adv-x="1664" 
+d="M1664 650q0 -166 -60 -314l-20 -49l-185 -33q-22 -83 -90.5 -136.5t-156.5 -53.5v-32q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-32q71 0 130 -35.5t93 -95.5l68 12q29 95 29 193q0 148 -88 279t-236.5 209t-315.5 78
+t-315.5 -78t-236.5 -209t-88 -279q0 -98 29 -193l68 -12q34 60 93 95.5t130 35.5v32q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v32q-88 0 -156.5 53.5t-90.5 136.5l-185 33l-20 49q-60 148 -60 314q0 151 67 291t179 242.5
+t266 163.5t320 61t320 -61t266 -163.5t179 -242.5t67 -291z" />
+    <glyph glyph-name="volume_off" unicode="&#xf026;" horiz-adv-x="768" 
+d="M768 1184v-1088q0 -26 -19 -45t-45 -19t-45 19l-333 333h-262q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h262l333 333q19 19 45 19t45 -19t19 -45z" />
+    <glyph glyph-name="volume_down" unicode="&#xf027;" horiz-adv-x="1152" 
+d="M768 1184v-1088q0 -26 -19 -45t-45 -19t-45 19l-333 333h-262q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h262l333 333q19 19 45 19t45 -19t19 -45zM1152 640q0 -76 -42.5 -141.5t-112.5 -93.5q-10 -5 -25 -5q-26 0 -45 18.5t-19 45.5q0 21 12 35.5t29 25t34 23t29 36
+t12 56.5t-12 56.5t-29 36t-34 23t-29 25t-12 35.5q0 27 19 45.5t45 18.5q15 0 25 -5q70 -27 112.5 -93t42.5 -142z" />
+    <glyph glyph-name="volume_up" unicode="&#xf028;" horiz-adv-x="1664" 
+d="M768 1184v-1088q0 -26 -19 -45t-45 -19t-45 19l-333 333h-262q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h262l333 333q19 19 45 19t45 -19t19 -45zM1152 640q0 -76 -42.5 -141.5t-112.5 -93.5q-10 -5 -25 -5q-26 0 -45 18.5t-19 45.5q0 21 12 35.5t29 25t34 23t29 36
+t12 56.5t-12 56.5t-29 36t-34 23t-29 25t-12 35.5q0 27 19 45.5t45 18.5q15 0 25 -5q70 -27 112.5 -93t42.5 -142zM1408 640q0 -153 -85 -282.5t-225 -188.5q-13 -5 -25 -5q-27 0 -46 19t-19 45q0 39 39 59q56 29 76 44q74 54 115.5 135.5t41.5 173.5t-41.5 173.5
+t-115.5 135.5q-20 15 -76 44q-39 20 -39 59q0 26 19 45t45 19q13 0 26 -5q140 -59 225 -188.5t85 -282.5zM1664 640q0 -230 -127 -422.5t-338 -283.5q-13 -5 -26 -5q-26 0 -45 19t-19 45q0 36 39 59q7 4 22.5 10.5t22.5 10.5q46 25 82 51q123 91 192 227t69 289t-69 289
+t-192 227q-36 26 -82 51q-7 4 -22.5 10.5t-22.5 10.5q-39 23 -39 59q0 26 19 45t45 19q13 0 26 -5q211 -91 338 -283.5t127 -422.5z" />
+    <glyph glyph-name="qrcode" unicode="&#xf029;" horiz-adv-x="1408" 
+d="M384 384v-128h-128v128h128zM384 1152v-128h-128v128h128zM1152 1152v-128h-128v128h128zM128 129h384v383h-384v-383zM128 896h384v384h-384v-384zM896 896h384v384h-384v-384zM640 640v-640h-640v640h640zM1152 128v-128h-128v128h128zM1408 128v-128h-128v128h128z
+M1408 640v-384h-384v128h-128v-384h-128v640h384v-128h128v128h128zM640 1408v-640h-640v640h640zM1408 1408v-640h-640v640h640z" />
+    <glyph glyph-name="barcode" unicode="&#xf02a;" horiz-adv-x="1792" 
+d="M63 0h-63v1408h63v-1408zM126 1h-32v1407h32v-1407zM220 1h-31v1407h31v-1407zM377 1h-31v1407h31v-1407zM534 1h-62v1407h62v-1407zM660 1h-31v1407h31v-1407zM723 1h-31v1407h31v-1407zM786 1h-31v1407h31v-1407zM943 1h-63v1407h63v-1407zM1100 1h-63v1407h63v-1407z
+M1226 1h-63v1407h63v-1407zM1352 1h-63v1407h63v-1407zM1446 1h-63v1407h63v-1407zM1635 1h-94v1407h94v-1407zM1698 1h-32v1407h32v-1407zM1792 0h-63v1408h63v-1408z" />
+    <glyph glyph-name="tag" unicode="&#xf02b;" 
+d="M448 1088q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1515 512q0 -53 -37 -90l-491 -492q-39 -37 -91 -37q-53 0 -90 37l-715 716q-38 37 -64.5 101t-26.5 117v416q0 52 38 90t90 38h416q53 0 117 -26.5t102 -64.5
+l715 -714q37 -39 37 -91z" />
+    <glyph glyph-name="tags" unicode="&#xf02c;" horiz-adv-x="1920" 
+d="M448 1088q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1515 512q0 -53 -37 -90l-491 -492q-39 -37 -91 -37q-53 0 -90 37l-715 716q-38 37 -64.5 101t-26.5 117v416q0 52 38 90t90 38h416q53 0 117 -26.5t102 -64.5
+l715 -714q37 -39 37 -91zM1899 512q0 -53 -37 -90l-491 -492q-39 -37 -91 -37q-36 0 -59 14t-53 45l470 470q37 37 37 90q0 52 -37 91l-715 714q-38 38 -102 64.5t-117 26.5h224q53 0 117 -26.5t102 -64.5l715 -714q37 -39 37 -91z" />
+    <glyph glyph-name="book" unicode="&#xf02d;" horiz-adv-x="1664" 
+d="M1639 1058q40 -57 18 -129l-275 -906q-19 -64 -76.5 -107.5t-122.5 -43.5h-923q-77 0 -148.5 53.5t-99.5 131.5q-24 67 -2 127q0 4 3 27t4 37q1 8 -3 21.5t-3 19.5q2 11 8 21t16.5 23.5t16.5 23.5q23 38 45 91.5t30 91.5q3 10 0.5 30t-0.5 28q3 11 17 28t17 23
+q21 36 42 92t25 90q1 9 -2.5 32t0.5 28q4 13 22 30.5t22 22.5q19 26 42.5 84.5t27.5 96.5q1 8 -3 25.5t-2 26.5q2 8 9 18t18 23t17 21q8 12 16.5 30.5t15 35t16 36t19.5 32t26.5 23.5t36 11.5t47.5 -5.5l-1 -3q38 9 51 9h761q74 0 114 -56t18 -130l-274 -906
+q-36 -119 -71.5 -153.5t-128.5 -34.5h-869q-27 0 -38 -15q-11 -16 -1 -43q24 -70 144 -70h923q29 0 56 15.5t35 41.5l300 987q7 22 5 57q38 -15 59 -43zM575 1056q-4 -13 2 -22.5t20 -9.5h608q13 0 25.5 9.5t16.5 22.5l21 64q4 13 -2 22.5t-20 9.5h-608q-13 0 -25.5 -9.5
+t-16.5 -22.5zM492 800q-4 -13 2 -22.5t20 -9.5h608q13 0 25.5 9.5t16.5 22.5l21 64q4 13 -2 22.5t-20 9.5h-608q-13 0 -25.5 -9.5t-16.5 -22.5z" />
+    <glyph glyph-name="bookmark" unicode="&#xf02e;" horiz-adv-x="1280" 
+d="M1164 1408q23 0 44 -9q33 -13 52.5 -41t19.5 -62v-1289q0 -34 -19.5 -62t-52.5 -41q-19 -8 -44 -8q-48 0 -83 32l-441 424l-441 -424q-36 -33 -83 -33q-23 0 -44 9q-33 13 -52.5 41t-19.5 62v1289q0 34 19.5 62t52.5 41q21 9 44 9h1048z" />
+    <glyph glyph-name="print" unicode="&#xf02f;" horiz-adv-x="1664" 
+d="M384 0h896v256h-896v-256zM384 640h896v384h-160q-40 0 -68 28t-28 68v160h-640v-640zM1536 576q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1664 576v-416q0 -13 -9.5 -22.5t-22.5 -9.5h-224v-160q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68
+v160h-224q-13 0 -22.5 9.5t-9.5 22.5v416q0 79 56.5 135.5t135.5 56.5h64v544q0 40 28 68t68 28h672q40 0 88 -20t76 -48l152 -152q28 -28 48 -76t20 -88v-256h64q79 0 135.5 -56.5t56.5 -135.5z" />
+    <glyph glyph-name="camera" unicode="&#xf030;" horiz-adv-x="1920" 
+d="M960 864q119 0 203.5 -84.5t84.5 -203.5t-84.5 -203.5t-203.5 -84.5t-203.5 84.5t-84.5 203.5t84.5 203.5t203.5 84.5zM1664 1280q106 0 181 -75t75 -181v-896q0 -106 -75 -181t-181 -75h-1408q-106 0 -181 75t-75 181v896q0 106 75 181t181 75h224l51 136
+q19 49 69.5 84.5t103.5 35.5h512q53 0 103.5 -35.5t69.5 -84.5l51 -136h224zM960 128q185 0 316.5 131.5t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
+    <glyph glyph-name="font" unicode="&#xf031;" horiz-adv-x="1664" 
+d="M725 977l-170 -450q33 0 136.5 -2t160.5 -2q19 0 57 2q-87 253 -184 452zM0 -128l2 79q23 7 56 12.5t57 10.5t49.5 14.5t44.5 29t31 50.5l237 616l280 724h75h53q8 -14 11 -21l205 -480q33 -78 106 -257.5t114 -274.5q15 -34 58 -144.5t72 -168.5q20 -45 35 -57
+q19 -15 88 -29.5t84 -20.5q6 -38 6 -57q0 -5 -0.5 -13.5t-0.5 -12.5q-63 0 -190 8t-191 8q-76 0 -215 -7t-178 -8q0 43 4 78l131 28q1 0 12.5 2.5t15.5 3.5t14.5 4.5t15 6.5t11 8t9 11t2.5 14q0 16 -31 96.5t-72 177.5t-42 100l-450 2q-26 -58 -76.5 -195.5t-50.5 -162.5
+q0 -22 14 -37.5t43.5 -24.5t48.5 -13.5t57 -8.5t41 -4q1 -19 1 -58q0 -9 -2 -27q-58 0 -174.5 10t-174.5 10q-8 0 -26.5 -4t-21.5 -4q-80 -14 -188 -14z" />
+    <glyph glyph-name="bold" unicode="&#xf032;" horiz-adv-x="1408" 
+d="M555 15q74 -32 140 -32q376 0 376 335q0 114 -41 180q-27 44 -61.5 74t-67.5 46.5t-80.5 25t-84 10.5t-94.5 2q-73 0 -101 -10q0 -53 -0.5 -159t-0.5 -158q0 -8 -1 -67.5t-0.5 -96.5t4.5 -83.5t12 -66.5zM541 761q42 -7 109 -7q82 0 143 13t110 44.5t74.5 89.5t25.5 142
+q0 70 -29 122.5t-79 82t-108 43.5t-124 14q-50 0 -130 -13q0 -50 4 -151t4 -152q0 -27 -0.5 -80t-0.5 -79q0 -46 1 -69zM0 -128l2 94q15 4 85 16t106 27q7 12 12.5 27t8.5 33.5t5.5 32.5t3 37.5t0.5 34v35.5v30q0 982 -22 1025q-4 8 -22 14.5t-44.5 11t-49.5 7t-48.5 4.5
+t-30.5 3l-4 83q98 2 340 11.5t373 9.5q23 0 68 -0.5t68 -0.5q70 0 136.5 -13t128.5 -42t108 -71t74 -104.5t28 -137.5q0 -52 -16.5 -95.5t-39 -72t-64.5 -57.5t-73 -45t-84 -40q154 -35 256.5 -134t102.5 -248q0 -100 -35 -179.5t-93.5 -130.5t-138 -85.5t-163.5 -48.5
+t-176 -14q-44 0 -132 3t-132 3q-106 0 -307 -11t-231 -12z" />
+    <glyph glyph-name="italic" unicode="&#xf033;" horiz-adv-x="1024" 
+d="M0 -126l17 85q22 7 61.5 16.5t72 19t59.5 23.5q28 35 41 101q1 7 62 289t114 543.5t52 296.5v25q-24 13 -54.5 18.5t-69.5 8t-58 5.5l19 103q33 -2 120 -6.5t149.5 -7t120.5 -2.5q48 0 98.5 2.5t121 7t98.5 6.5q-5 -39 -19 -89q-30 -10 -101.5 -28.5t-108.5 -33.5
+q-8 -19 -14 -42.5t-9 -40t-7.5 -45.5t-6.5 -42q-27 -148 -87.5 -419.5t-77.5 -355.5q-2 -9 -13 -58t-20 -90t-16 -83.5t-6 -57.5l1 -18q17 -4 185 -31q-3 -44 -16 -99q-11 0 -32.5 -1.5t-32.5 -1.5q-29 0 -87 10t-86 10q-138 2 -206 2q-51 0 -143 -9t-121 -11z" />
+    <glyph glyph-name="text_height" unicode="&#xf034;" horiz-adv-x="1792" 
+d="M1744 128q33 0 42 -18.5t-11 -44.5l-126 -162q-20 -26 -49 -26t-49 26l-126 162q-20 26 -11 44.5t42 18.5h80v1024h-80q-33 0 -42 18.5t11 44.5l126 162q20 26 49 26t49 -26l126 -162q20 -26 11 -44.5t-42 -18.5h-80v-1024h80zM81 1407l54 -27q12 -5 211 -5q44 0 132 2
+t132 2q36 0 107.5 -0.5t107.5 -0.5h293q6 0 21 -0.5t20.5 0t16 3t17.5 9t15 17.5l42 1q4 0 14 -0.5t14 -0.5q2 -112 2 -336q0 -80 -5 -109q-39 -14 -68 -18q-25 44 -54 128q-3 9 -11 48t-14.5 73.5t-7.5 35.5q-6 8 -12 12.5t-15.5 6t-13 2.5t-18 0.5t-16.5 -0.5
+q-17 0 -66.5 0.5t-74.5 0.5t-64 -2t-71 -6q-9 -81 -8 -136q0 -94 2 -388t2 -455q0 -16 -2.5 -71.5t0 -91.5t12.5 -69q40 -21 124 -42.5t120 -37.5q5 -40 5 -50q0 -14 -3 -29l-34 -1q-76 -2 -218 8t-207 10q-50 0 -151 -9t-152 -9q-3 51 -3 52v9q17 27 61.5 43t98.5 29t78 27
+q19 42 19 383q0 101 -3 303t-3 303v117q0 2 0.5 15.5t0.5 25t-1 25.5t-3 24t-5 14q-11 12 -162 12q-33 0 -93 -12t-80 -26q-19 -13 -34 -72.5t-31.5 -111t-42.5 -53.5q-42 26 -56 44v383z" />
+    <glyph glyph-name="text_width" unicode="&#xf035;" 
+d="M81 1407l54 -27q12 -5 211 -5q44 0 132 2t132 2q70 0 246.5 1t304.5 0.5t247 -4.5q33 -1 56 31l42 1q4 0 14 -0.5t14 -0.5q2 -112 2 -336q0 -80 -5 -109q-39 -14 -68 -18q-25 44 -54 128q-3 9 -11 47.5t-15 73.5t-7 36q-10 13 -27 19q-5 2 -66 2q-30 0 -93 1t-103 1
+t-94 -2t-96 -7q-9 -81 -8 -136l1 -152v52q0 -55 1 -154t1.5 -180t0.5 -153q0 -16 -2.5 -71.5t0 -91.5t12.5 -69q40 -21 124 -42.5t120 -37.5q5 -40 5 -50q0 -14 -3 -29l-34 -1q-76 -2 -218 8t-207 10q-50 0 -151 -9t-152 -9q-3 51 -3 52v9q17 27 61.5 43t98.5 29t78 27
+q7 16 11.5 74t6 145.5t1.5 155t-0.5 153.5t-0.5 89q0 7 -2.5 21.5t-2.5 22.5q0 7 0.5 44t1 73t0 76.5t-3 67.5t-6.5 32q-11 12 -162 12q-41 0 -163 -13.5t-138 -24.5q-19 -12 -34 -71.5t-31.5 -111.5t-42.5 -54q-42 26 -56 44v383zM1310 125q12 0 42 -19.5t57.5 -41.5
+t59.5 -49t36 -30q26 -21 26 -49t-26 -49q-4 -3 -36 -30t-59.5 -49t-57.5 -41.5t-42 -19.5q-13 0 -20.5 10.5t-10 28.5t-2.5 33.5t1.5 33t1.5 19.5h-1024q0 -2 1.5 -19.5t1.5 -33t-2.5 -33.5t-10 -28.5t-20.5 -10.5q-12 0 -42 19.5t-57.5 41.5t-59.5 49t-36 30q-26 21 -26 49
+t26 49q4 3 36 30t59.5 49t57.5 41.5t42 19.5q13 0 20.5 -10.5t10 -28.5t2.5 -33.5t-1.5 -33t-1.5 -19.5h1024q0 2 -1.5 19.5t-1.5 33t2.5 33.5t10 28.5t20.5 10.5z" />
+    <glyph glyph-name="align_left" unicode="&#xf036;" horiz-adv-x="1792" 
+d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1408 576v-128q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1280q26 0 45 -19t19 -45zM1664 960v-128q0 -26 -19 -45
+t-45 -19h-1536q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1536q26 0 45 -19t19 -45zM1280 1344v-128q0 -26 -19 -45t-45 -19h-1152q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" />
+    <glyph glyph-name="align_center" unicode="&#xf037;" horiz-adv-x="1792" 
+d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1408 576v-128q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h896q26 0 45 -19t19 -45zM1664 960v-128q0 -26 -19 -45t-45 -19
+h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1280 1344v-128q0 -26 -19 -45t-45 -19h-640q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h640q26 0 45 -19t19 -45z" />
+    <glyph glyph-name="align_right" unicode="&#xf038;" horiz-adv-x="1792" 
+d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 576v-128q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1280q26 0 45 -19t19 -45zM1792 960v-128q0 -26 -19 -45
+t-45 -19h-1536q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1536q26 0 45 -19t19 -45zM1792 1344v-128q0 -26 -19 -45t-45 -19h-1152q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" />
+    <glyph glyph-name="align_justify" unicode="&#xf039;" horiz-adv-x="1792" 
+d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 576v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 960v-128q0 -26 -19 -45
+t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 1344v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45z" />
+    <glyph glyph-name="list" unicode="&#xf03a;" horiz-adv-x="1792" 
+d="M256 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5zM256 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5
+t9.5 -22.5zM256 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1344
+q13 0 22.5 -9.5t9.5 -22.5zM256 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5zM1792 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5
+t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5zM1792 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5zM1792 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192
+q0 13 9.5 22.5t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5z" />
+    <glyph glyph-name="indent_left" unicode="&#xf03b;" horiz-adv-x="1792" 
+d="M384 992v-576q0 -13 -9.5 -22.5t-22.5 -9.5q-14 0 -23 9l-288 288q-9 9 -9 23t9 23l288 288q9 9 23 9q13 0 22.5 -9.5t9.5 -22.5zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5
+t9.5 -22.5zM1792 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088q13 0 22.5 -9.5t9.5 -22.5zM1792 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088
+q13 0 22.5 -9.5t9.5 -22.5zM1792 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5t9.5 -22.5z" />
+    <glyph glyph-name="indent_right" unicode="&#xf03c;" horiz-adv-x="1792" 
+d="M352 704q0 -14 -9 -23l-288 -288q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5v576q0 13 9.5 22.5t22.5 9.5q14 0 23 -9l288 -288q9 -9 9 -23zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5
+t9.5 -22.5zM1792 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088q13 0 22.5 -9.5t9.5 -22.5zM1792 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088
+q13 0 22.5 -9.5t9.5 -22.5zM1792 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5t9.5 -22.5z" />
+    <glyph glyph-name="facetime_video" unicode="&#xf03d;" horiz-adv-x="1792" 
+d="M1792 1184v-1088q0 -42 -39 -59q-13 -5 -25 -5q-27 0 -45 19l-403 403v-166q0 -119 -84.5 -203.5t-203.5 -84.5h-704q-119 0 -203.5 84.5t-84.5 203.5v704q0 119 84.5 203.5t203.5 84.5h704q119 0 203.5 -84.5t84.5 -203.5v-165l403 402q18 19 45 19q12 0 25 -5
+q39 -17 39 -59z" />
+    <glyph glyph-name="picture" unicode="&#xf03e;" horiz-adv-x="1920" 
+d="M640 960q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1664 576v-448h-1408v192l320 320l160 -160l512 512zM1760 1280h-1600q-13 0 -22.5 -9.5t-9.5 -22.5v-1216q0 -13 9.5 -22.5t22.5 -9.5h1600q13 0 22.5 9.5t9.5 22.5v1216
+q0 13 -9.5 22.5t-22.5 9.5zM1920 1248v-1216q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" />
+    <glyph glyph-name="pencil" unicode="&#xf040;" 
+d="M363 0l91 91l-235 235l-91 -91v-107h128v-128h107zM886 928q0 22 -22 22q-10 0 -17 -7l-542 -542q-7 -7 -7 -17q0 -22 22 -22q10 0 17 7l542 542q7 7 7 17zM832 1120l416 -416l-832 -832h-416v416zM1515 1024q0 -53 -37 -90l-166 -166l-416 416l166 165q36 38 90 38
+q53 0 91 -38l235 -234q37 -39 37 -91z" />
+    <glyph glyph-name="map_marker" unicode="&#xf041;" horiz-adv-x="1024" 
+d="M768 896q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM1024 896q0 -109 -33 -179l-364 -774q-16 -33 -47.5 -52t-67.5 -19t-67.5 19t-46.5 52l-365 774q-33 70 -33 179q0 212 150 362t362 150t362 -150t150 -362z" />
+    <glyph glyph-name="adjust" unicode="&#xf042;" 
+d="M768 96v1088q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="tint" unicode="&#xf043;" horiz-adv-x="1024" 
+d="M512 384q0 36 -20 69q-1 1 -15.5 22.5t-25.5 38t-25 44t-21 50.5q-4 16 -21 16t-21 -16q-7 -23 -21 -50.5t-25 -44t-25.5 -38t-15.5 -22.5q-20 -33 -20 -69q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1024 512q0 -212 -150 -362t-362 -150t-362 150t-150 362
+q0 145 81 275q6 9 62.5 90.5t101 151t99.5 178t83 201.5q9 30 34 47t51 17t51.5 -17t33.5 -47q28 -93 83 -201.5t99.5 -178t101 -151t62.5 -90.5q81 -127 81 -275z" />
+    <glyph glyph-name="edit" unicode="&#xf044;" horiz-adv-x="1792" 
+d="M888 352l116 116l-152 152l-116 -116v-56h96v-96h56zM1328 1072q-16 16 -33 -1l-350 -350q-17 -17 -1 -33t33 1l350 350q17 17 1 33zM1408 478v-190q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832
+q63 0 117 -25q15 -7 18 -23q3 -17 -9 -29l-49 -49q-14 -14 -32 -8q-23 6 -45 6h-832q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v126q0 13 9 22l64 64q15 15 35 7t20 -29zM1312 1216l288 -288l-672 -672h-288v288zM1756 1084l-92 -92
+l-288 288l92 92q28 28 68 28t68 -28l152 -152q28 -28 28 -68t-28 -68z" />
+    <glyph glyph-name="share" unicode="&#xf045;" horiz-adv-x="1664" 
+d="M1408 547v-259q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h255v0q13 0 22.5 -9.5t9.5 -22.5q0 -27 -26 -32q-77 -26 -133 -60q-10 -4 -16 -4h-112q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832
+q66 0 113 47t47 113v214q0 19 18 29q28 13 54 37q16 16 35 8q21 -9 21 -29zM1645 1043l-384 -384q-18 -19 -45 -19q-12 0 -25 5q-39 17 -39 59v192h-160q-323 0 -438 -131q-119 -137 -74 -473q3 -23 -20 -34q-8 -2 -12 -2q-16 0 -26 13q-10 14 -21 31t-39.5 68.5t-49.5 99.5
+t-38.5 114t-17.5 122q0 49 3.5 91t14 90t28 88t47 81.5t68.5 74t94.5 61.5t124.5 48.5t159.5 30.5t196.5 11h160v192q0 42 39 59q13 5 25 5q26 0 45 -19l384 -384q19 -19 19 -45t-19 -45z" />
+    <glyph glyph-name="check" unicode="&#xf046;" horiz-adv-x="1664" 
+d="M1408 606v-318q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832q63 0 117 -25q15 -7 18 -23q3 -17 -9 -29l-49 -49q-10 -10 -23 -10q-3 0 -9 2q-23 6 -45 6h-832q-66 0 -113 -47t-47 -113v-832
+q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v254q0 13 9 22l64 64q10 10 23 10q6 0 12 -3q20 -8 20 -29zM1639 1095l-814 -814q-24 -24 -57 -24t-57 24l-430 430q-24 24 -24 57t24 57l110 110q24 24 57 24t57 -24l263 -263l647 647q24 24 57 24t57 -24l110 -110
+q24 -24 24 -57t-24 -57z" />
+    <glyph glyph-name="move" unicode="&#xf047;" horiz-adv-x="1792" 
+d="M1792 640q0 -26 -19 -45l-256 -256q-19 -19 -45 -19t-45 19t-19 45v128h-384v-384h128q26 0 45 -19t19 -45t-19 -45l-256 -256q-19 -19 -45 -19t-45 19l-256 256q-19 19 -19 45t19 45t45 19h128v384h-384v-128q0 -26 -19 -45t-45 -19t-45 19l-256 256q-19 19 -19 45
+t19 45l256 256q19 19 45 19t45 -19t19 -45v-128h384v384h-128q-26 0 -45 19t-19 45t19 45l256 256q19 19 45 19t45 -19l256 -256q19 -19 19 -45t-19 -45t-45 -19h-128v-384h384v128q0 26 19 45t45 19t45 -19l256 -256q19 -19 19 -45z" />
+    <glyph glyph-name="step_backward" unicode="&#xf048;" horiz-adv-x="1024" 
+d="M979 1395q19 19 32 13t13 -32v-1472q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-678q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-678q4 10 13 19z" />
+    <glyph glyph-name="fast_backward" unicode="&#xf049;" horiz-adv-x="1792" 
+d="M1747 1395q19 19 32 13t13 -32v-1472q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-710q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-678q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-678q4 10 13 19l710 710
+q19 19 32 13t13 -32v-710q4 10 13 19z" />
+    <glyph glyph-name="backward" unicode="&#xf04a;" horiz-adv-x="1664" 
+d="M1619 1395q19 19 32 13t13 -32v-1472q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-710q0 -26 -13 -32t-32 13l-710 710q-19 19 -19 45t19 45l710 710q19 19 32 13t13 -32v-710q4 10 13 19z" />
+    <glyph glyph-name="play" unicode="&#xf04b;" horiz-adv-x="1408" 
+d="M1384 609l-1328 -738q-23 -13 -39.5 -3t-16.5 36v1472q0 26 16.5 36t39.5 -3l1328 -738q23 -13 23 -31t-23 -31z" />
+    <glyph glyph-name="pause" unicode="&#xf04c;" 
+d="M1536 1344v-1408q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h512q26 0 45 -19t19 -45zM640 1344v-1408q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h512q26 0 45 -19t19 -45z" />
+    <glyph glyph-name="stop" unicode="&#xf04d;" 
+d="M1536 1344v-1408q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h1408q26 0 45 -19t19 -45z" />
+    <glyph glyph-name="forward" unicode="&#xf04e;" horiz-adv-x="1664" 
+d="M45 -115q-19 -19 -32 -13t-13 32v1472q0 26 13 32t32 -13l710 -710q9 -9 13 -19v710q0 26 13 32t32 -13l710 -710q19 -19 19 -45t-19 -45l-710 -710q-19 -19 -32 -13t-13 32v710q-4 -10 -13 -19z" />
+    <glyph glyph-name="fast_forward" unicode="&#xf050;" horiz-adv-x="1792" 
+d="M45 -115q-19 -19 -32 -13t-13 32v1472q0 26 13 32t32 -13l710 -710q9 -9 13 -19v710q0 26 13 32t32 -13l710 -710q9 -9 13 -19v678q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-1408q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v678q-4 -10 -13 -19l-710 -710
+q-19 -19 -32 -13t-13 32v710q-4 -10 -13 -19z" />
+    <glyph glyph-name="step_forward" unicode="&#xf051;" horiz-adv-x="1024" 
+d="M45 -115q-19 -19 -32 -13t-13 32v1472q0 26 13 32t32 -13l710 -710q9 -9 13 -19v678q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-1408q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v678q-4 -10 -13 -19z" />
+    <glyph glyph-name="eject" unicode="&#xf052;" horiz-adv-x="1538" 
+d="M14 557l710 710q19 19 45 19t45 -19l710 -710q19 -19 13 -32t-32 -13h-1472q-26 0 -32 13t13 32zM1473 0h-1408q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1408q26 0 45 -19t19 -45v-256q0 -26 -19 -45t-45 -19z" />
+    <glyph glyph-name="chevron_left" unicode="&#xf053;" horiz-adv-x="1280" 
+d="M1171 1235l-531 -531l531 -531q19 -19 19 -45t-19 -45l-166 -166q-19 -19 -45 -19t-45 19l-742 742q-19 19 -19 45t19 45l742 742q19 19 45 19t45 -19l166 -166q19 -19 19 -45t-19 -45z" />
+    <glyph glyph-name="chevron_right" unicode="&#xf054;" horiz-adv-x="1280" 
+d="M1107 659l-742 -742q-19 -19 -45 -19t-45 19l-166 166q-19 19 -19 45t19 45l531 531l-531 531q-19 19 -19 45t19 45l166 166q19 19 45 19t45 -19l742 -742q19 -19 19 -45t-19 -45z" />
+    <glyph glyph-name="plus_sign" unicode="&#xf055;" 
+d="M1216 576v128q0 26 -19 45t-45 19h-256v256q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-256h-256q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h256v-256q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v256h256q26 0 45 19t19 45zM1536 640q0 -209 -103 -385.5
+t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="minus_sign" unicode="&#xf056;" 
+d="M1216 576v128q0 26 -19 45t-45 19h-768q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h768q26 0 45 19t19 45zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5
+t103 -385.5z" />
+    <glyph glyph-name="remove_sign" unicode="&#xf057;" 
+d="M1149 414q0 26 -19 45l-181 181l181 181q19 19 19 45q0 27 -19 46l-90 90q-19 19 -46 19q-26 0 -45 -19l-181 -181l-181 181q-19 19 -45 19q-27 0 -46 -19l-90 -90q-19 -19 -19 -46q0 -26 19 -45l181 -181l-181 -181q-19 -19 -19 -45q0 -27 19 -46l90 -90q19 -19 46 -19
+q26 0 45 19l181 181l181 -181q19 -19 45 -19q27 0 46 19l90 90q19 19 19 46zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="ok_sign" unicode="&#xf058;" 
+d="M1284 802q0 28 -18 46l-91 90q-19 19 -45 19t-45 -19l-408 -407l-226 226q-19 19 -45 19t-45 -19l-91 -90q-18 -18 -18 -46q0 -27 18 -45l362 -362q19 -19 45 -19q27 0 46 19l543 543q18 18 18 45zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103
+t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="question_sign" unicode="&#xf059;" 
+d="M896 160v192q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h192q14 0 23 9t9 23zM1152 832q0 88 -55.5 163t-138.5 116t-170 41q-243 0 -371 -213q-15 -24 8 -42l132 -100q7 -6 19 -6q16 0 25 12q53 68 86 92q34 24 86 24q48 0 85.5 -26t37.5 -59
+q0 -38 -20 -61t-68 -45q-63 -28 -115.5 -86.5t-52.5 -125.5v-36q0 -14 9 -23t23 -9h192q14 0 23 9t9 23q0 19 21.5 49.5t54.5 49.5q32 18 49 28.5t46 35t44.5 48t28 60.5t12.5 81zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5
+t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="info_sign" unicode="&#xf05a;" 
+d="M1024 160v160q0 14 -9 23t-23 9h-96v512q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-160q0 -14 9 -23t23 -9h96v-320h-96q-14 0 -23 -9t-9 -23v-160q0 -14 9 -23t23 -9h448q14 0 23 9t9 23zM896 1056v160q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-160q0 -14 9 -23
+t23 -9h192q14 0 23 9t9 23zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="screenshot" unicode="&#xf05b;" 
+d="M1197 512h-109q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h109q-32 108 -112.5 188.5t-188.5 112.5v-109q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v109q-108 -32 -188.5 -112.5t-112.5 -188.5h109q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-109
+q32 -108 112.5 -188.5t188.5 -112.5v109q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-109q108 32 188.5 112.5t112.5 188.5zM1536 704v-128q0 -26 -19 -45t-45 -19h-143q-37 -161 -154.5 -278.5t-278.5 -154.5v-143q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v143
+q-161 37 -278.5 154.5t-154.5 278.5h-143q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h143q37 161 154.5 278.5t278.5 154.5v143q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-143q161 -37 278.5 -154.5t154.5 -278.5h143q26 0 45 -19t19 -45z" />
+    <glyph glyph-name="remove_circle" unicode="&#xf05c;" 
+d="M1097 457l-146 -146q-10 -10 -23 -10t-23 10l-137 137l-137 -137q-10 -10 -23 -10t-23 10l-146 146q-10 10 -10 23t10 23l137 137l-137 137q-10 10 -10 23t10 23l146 146q10 10 23 10t23 -10l137 -137l137 137q10 10 23 10t23 -10l146 -146q10 -10 10 -23t-10 -23
+l-137 -137l137 -137q10 -10 10 -23t-10 -23zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5
+t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="ok_circle" unicode="&#xf05d;" 
+d="M1171 723l-422 -422q-19 -19 -45 -19t-45 19l-294 294q-19 19 -19 45t19 45l102 102q19 19 45 19t45 -19l147 -147l275 275q19 19 45 19t45 -19l102 -102q19 -19 19 -45t-19 -45zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198
+t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="ban_circle" unicode="&#xf05e;" 
+d="M1312 643q0 161 -87 295l-754 -753q137 -89 297 -89q111 0 211.5 43.5t173.5 116.5t116 174.5t43 212.5zM313 344l755 754q-135 91 -300 91q-148 0 -273 -73t-198 -199t-73 -274q0 -162 89 -299zM1536 643q0 -157 -61 -300t-163.5 -246t-245 -164t-298.5 -61t-298.5 61
+t-245 164t-163.5 246t-61 300t61 299.5t163.5 245.5t245 164t298.5 61t298.5 -61t245 -164t163.5 -245.5t61 -299.5z" />
+    <glyph glyph-name="arrow_left" unicode="&#xf060;" 
+d="M1536 640v-128q0 -53 -32.5 -90.5t-84.5 -37.5h-704l293 -294q38 -36 38 -90t-38 -90l-75 -76q-37 -37 -90 -37q-52 0 -91 37l-651 652q-37 37 -37 90q0 52 37 91l651 650q38 38 91 38q52 0 90 -38l75 -74q38 -38 38 -91t-38 -91l-293 -293h704q52 0 84.5 -37.5
+t32.5 -90.5z" />
+    <glyph glyph-name="arrow_right" unicode="&#xf061;" 
+d="M1472 576q0 -54 -37 -91l-651 -651q-39 -37 -91 -37q-51 0 -90 37l-75 75q-38 38 -38 91t38 91l293 293h-704q-52 0 -84.5 37.5t-32.5 90.5v128q0 53 32.5 90.5t84.5 37.5h704l-293 294q-38 36 -38 90t38 90l75 75q38 38 90 38q53 0 91 -38l651 -651q37 -35 37 -90z" />
+    <glyph glyph-name="arrow_up" unicode="&#xf062;" horiz-adv-x="1664" 
+d="M1611 565q0 -51 -37 -90l-75 -75q-38 -38 -91 -38q-54 0 -90 38l-294 293v-704q0 -52 -37.5 -84.5t-90.5 -32.5h-128q-53 0 -90.5 32.5t-37.5 84.5v704l-294 -293q-36 -38 -90 -38t-90 38l-75 75q-38 38 -38 90q0 53 38 91l651 651q35 37 90 37q54 0 91 -37l651 -651
+q37 -39 37 -91z" />
+    <glyph glyph-name="arrow_down" unicode="&#xf063;" horiz-adv-x="1664" 
+d="M1611 704q0 -53 -37 -90l-651 -652q-39 -37 -91 -37q-53 0 -90 37l-651 652q-38 36 -38 90q0 53 38 91l74 75q39 37 91 37q53 0 90 -37l294 -294v704q0 52 38 90t90 38h128q52 0 90 -38t38 -90v-704l294 294q37 37 90 37q52 0 91 -37l75 -75q37 -39 37 -91z" />
+    <glyph glyph-name="share_alt" unicode="&#xf064;" horiz-adv-x="1792" 
+d="M1792 896q0 -26 -19 -45l-512 -512q-19 -19 -45 -19t-45 19t-19 45v256h-224q-98 0 -175.5 -6t-154 -21.5t-133 -42.5t-105.5 -69.5t-80 -101t-48.5 -138.5t-17.5 -181q0 -55 5 -123q0 -6 2.5 -23.5t2.5 -26.5q0 -15 -8.5 -25t-23.5 -10q-16 0 -28 17q-7 9 -13 22
+t-13.5 30t-10.5 24q-127 285 -127 451q0 199 53 333q162 403 875 403h224v256q0 26 19 45t45 19t45 -19l512 -512q19 -19 19 -45z" />
+    <glyph glyph-name="resize_full" unicode="&#xf065;" 
+d="M755 480q0 -13 -10 -23l-332 -332l144 -144q19 -19 19 -45t-19 -45t-45 -19h-448q-26 0 -45 19t-19 45v448q0 26 19 45t45 19t45 -19l144 -144l332 332q10 10 23 10t23 -10l114 -114q10 -10 10 -23zM1536 1344v-448q0 -26 -19 -45t-45 -19t-45 19l-144 144l-332 -332
+q-10 -10 -23 -10t-23 10l-114 114q-10 10 -10 23t10 23l332 332l-144 144q-19 19 -19 45t19 45t45 19h448q26 0 45 -19t19 -45z" />
+    <glyph glyph-name="resize_small" unicode="&#xf066;" 
+d="M768 576v-448q0 -26 -19 -45t-45 -19t-45 19l-144 144l-332 -332q-10 -10 -23 -10t-23 10l-114 114q-10 10 -10 23t10 23l332 332l-144 144q-19 19 -19 45t19 45t45 19h448q26 0 45 -19t19 -45zM1523 1248q0 -13 -10 -23l-332 -332l144 -144q19 -19 19 -45t-19 -45
+t-45 -19h-448q-26 0 -45 19t-19 45v448q0 26 19 45t45 19t45 -19l144 -144l332 332q10 10 23 10t23 -10l114 -114q10 -10 10 -23z" />
+    <glyph glyph-name="plus" unicode="&#xf067;" horiz-adv-x="1408" 
+d="M1408 800v-192q0 -40 -28 -68t-68 -28h-416v-416q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v416h-416q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h416v416q0 40 28 68t68 28h192q40 0 68 -28t28 -68v-416h416q40 0 68 -28t28 -68z" />
+    <glyph glyph-name="minus" unicode="&#xf068;" horiz-adv-x="1408" 
+d="M1408 800v-192q0 -40 -28 -68t-68 -28h-1216q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h1216q40 0 68 -28t28 -68z" />
+    <glyph glyph-name="asterisk" unicode="&#xf069;" horiz-adv-x="1664" 
+d="M1482 486q46 -26 59.5 -77.5t-12.5 -97.5l-64 -110q-26 -46 -77.5 -59.5t-97.5 12.5l-266 153v-307q0 -52 -38 -90t-90 -38h-128q-52 0 -90 38t-38 90v307l-266 -153q-46 -26 -97.5 -12.5t-77.5 59.5l-64 110q-26 46 -12.5 97.5t59.5 77.5l266 154l-266 154
+q-46 26 -59.5 77.5t12.5 97.5l64 110q26 46 77.5 59.5t97.5 -12.5l266 -153v307q0 52 38 90t90 38h128q52 0 90 -38t38 -90v-307l266 153q46 26 97.5 12.5t77.5 -59.5l64 -110q26 -46 12.5 -97.5t-59.5 -77.5l-266 -154z" />
+    <glyph glyph-name="exclamation_sign" unicode="&#xf06a;" 
+d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM896 161v190q0 14 -9 23.5t-22 9.5h-192q-13 0 -23 -10t-10 -23v-190q0 -13 10 -23t23 -10h192
+q13 0 22 9.5t9 23.5zM894 505l18 621q0 12 -10 18q-10 8 -24 8h-220q-14 0 -24 -8q-10 -6 -10 -18l17 -621q0 -10 10 -17.5t24 -7.5h185q14 0 23.5 7.5t10.5 17.5z" />
+    <glyph glyph-name="gift" unicode="&#xf06b;" 
+d="M928 180v56v468v192h-320v-192v-468v-56q0 -25 18 -38.5t46 -13.5h192q28 0 46 13.5t18 38.5zM472 1024h195l-126 161q-26 31 -69 31q-40 0 -68 -28t-28 -68t28 -68t68 -28zM1160 1120q0 40 -28 68t-68 28q-43 0 -69 -31l-125 -161h194q40 0 68 28t28 68zM1536 864v-320
+q0 -14 -9 -23t-23 -9h-96v-416q0 -40 -28 -68t-68 -28h-1088q-40 0 -68 28t-28 68v416h-96q-14 0 -23 9t-9 23v320q0 14 9 23t23 9h440q-93 0 -158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5q107 0 168 -77l128 -165l128 165q61 77 168 77q93 0 158.5 -65.5t65.5 -158.5
+t-65.5 -158.5t-158.5 -65.5h440q14 0 23 -9t9 -23z" />
+    <glyph glyph-name="leaf" unicode="&#xf06c;" horiz-adv-x="1792" 
+d="M1280 832q0 26 -19 45t-45 19q-172 0 -318 -49.5t-259.5 -134t-235.5 -219.5q-19 -21 -19 -45q0 -26 19 -45t45 -19q24 0 45 19q27 24 74 71t67 66q137 124 268.5 176t313.5 52q26 0 45 19t19 45zM1792 1030q0 -95 -20 -193q-46 -224 -184.5 -383t-357.5 -268
+q-214 -108 -438 -108q-148 0 -286 47q-15 5 -88 42t-96 37q-16 0 -39.5 -32t-45 -70t-52.5 -70t-60 -32q-43 0 -63.5 17.5t-45.5 59.5q-2 4 -6 11t-5.5 10t-3 9.5t-1.5 13.5q0 35 31 73.5t68 65.5t68 56t31 48q0 4 -14 38t-16 44q-9 51 -9 104q0 115 43.5 220t119 184.5
+t170.5 139t204 95.5q55 18 145 25.5t179.5 9t178.5 6t163.5 24t113.5 56.5l29.5 29.5t29.5 28t27 20t36.5 16t43.5 4.5q39 0 70.5 -46t47.5 -112t24 -124t8 -96z" />
+    <glyph glyph-name="fire" unicode="&#xf06d;" horiz-adv-x="1408" 
+d="M1408 -160v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5zM1152 896q0 -78 -24.5 -144t-64 -112.5t-87.5 -88t-96 -77.5t-87.5 -72t-64 -81.5t-24.5 -96.5q0 -96 67 -224l-4 1l1 -1
+q-90 41 -160 83t-138.5 100t-113.5 122.5t-72.5 150.5t-27.5 184q0 78 24.5 144t64 112.5t87.5 88t96 77.5t87.5 72t64 81.5t24.5 96.5q0 94 -66 224l3 -1l-1 1q90 -41 160 -83t138.5 -100t113.5 -122.5t72.5 -150.5t27.5 -184z" />
+    <glyph glyph-name="eye_open" unicode="&#xf06e;" horiz-adv-x="1792" 
+d="M1664 576q-152 236 -381 353q61 -104 61 -225q0 -185 -131.5 -316.5t-316.5 -131.5t-316.5 131.5t-131.5 316.5q0 121 61 225q-229 -117 -381 -353q133 -205 333.5 -326.5t434.5 -121.5t434.5 121.5t333.5 326.5zM944 960q0 20 -14 34t-34 14q-125 0 -214.5 -89.5
+t-89.5 -214.5q0 -20 14 -34t34 -14t34 14t14 34q0 86 61 147t147 61q20 0 34 14t14 34zM1792 576q0 -34 -20 -69q-140 -230 -376.5 -368.5t-499.5 -138.5t-499.5 139t-376.5 368q-20 35 -20 69t20 69q140 229 376.5 368t499.5 139t499.5 -139t376.5 -368q20 -35 20 -69z" />
+    <glyph glyph-name="eye_close" unicode="&#xf070;" horiz-adv-x="1792" 
+d="M555 201l78 141q-87 63 -136 159t-49 203q0 121 61 225q-229 -117 -381 -353q167 -258 427 -375zM944 960q0 20 -14 34t-34 14q-125 0 -214.5 -89.5t-89.5 -214.5q0 -20 14 -34t34 -14t34 14t14 34q0 86 61 147t147 61q20 0 34 14t14 34zM1307 1151q0 -7 -1 -9
+q-106 -189 -316 -567t-315 -566l-49 -89q-10 -16 -28 -16q-12 0 -134 70q-16 10 -16 28q0 12 44 87q-143 65 -263.5 173t-208.5 245q-20 31 -20 69t20 69q153 235 380 371t496 136q89 0 180 -17l54 97q10 16 28 16q5 0 18 -6t31 -15.5t33 -18.5t31.5 -18.5t19.5 -11.5
+q16 -10 16 -27zM1344 704q0 -139 -79 -253.5t-209 -164.5l280 502q8 -45 8 -84zM1792 576q0 -35 -20 -69q-39 -64 -109 -145q-150 -172 -347.5 -267t-419.5 -95l74 132q212 18 392.5 137t301.5 307q-115 179 -282 294l63 112q95 -64 182.5 -153t144.5 -184q20 -34 20 -69z
+" />
+    <glyph glyph-name="warning_sign" unicode="&#xf071;" horiz-adv-x="1792" 
+d="M1024 161v190q0 14 -9.5 23.5t-22.5 9.5h-192q-13 0 -22.5 -9.5t-9.5 -23.5v-190q0 -14 9.5 -23.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 23.5zM1022 535l18 459q0 12 -10 19q-13 11 -24 11h-220q-11 0 -24 -11q-10 -7 -10 -21l17 -457q0 -10 10 -16.5t24 -6.5h185
+q14 0 23.5 6.5t10.5 16.5zM1008 1469l768 -1408q35 -63 -2 -126q-17 -29 -46.5 -46t-63.5 -17h-1536q-34 0 -63.5 17t-46.5 46q-37 63 -2 126l768 1408q17 31 47 49t65 18t65 -18t47 -49z" />
+    <glyph glyph-name="plane" unicode="&#xf072;" horiz-adv-x="1408" 
+d="M1376 1376q44 -52 12 -148t-108 -172l-161 -161l160 -696q5 -19 -12 -33l-128 -96q-7 -6 -19 -6q-4 0 -7 1q-15 3 -21 16l-279 508l-259 -259l53 -194q5 -17 -8 -31l-96 -96q-9 -9 -23 -9h-2q-15 2 -24 13l-189 252l-252 189q-11 7 -13 23q-1 13 9 25l96 97q9 9 23 9
+q6 0 8 -1l194 -53l259 259l-508 279q-14 8 -17 24q-2 16 9 27l128 128q14 13 30 8l665 -159l160 160q76 76 172 108t148 -12z" />
+    <glyph glyph-name="calendar" unicode="&#xf073;" horiz-adv-x="1664" 
+d="M128 -128h288v288h-288v-288zM480 -128h320v288h-320v-288zM128 224h288v320h-288v-320zM480 224h320v320h-320v-320zM128 608h288v288h-288v-288zM864 -128h320v288h-320v-288zM480 608h320v288h-320v-288zM1248 -128h288v288h-288v-288zM864 224h320v320h-320v-320z
+M512 1088v288q0 13 -9.5 22.5t-22.5 9.5h-64q-13 0 -22.5 -9.5t-9.5 -22.5v-288q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5zM1248 224h288v320h-288v-320zM864 608h320v288h-320v-288zM1248 608h288v288h-288v-288zM1280 1088v288q0 13 -9.5 22.5t-22.5 9.5h-64
+q-13 0 -22.5 -9.5t-9.5 -22.5v-288q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5zM1664 1152v-1280q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h384v96q0 66 47 113t113 47
+h64q66 0 113 -47t47 -113v-96h128q52 0 90 -38t38 -90z" />
+    <glyph glyph-name="random" unicode="&#xf074;" horiz-adv-x="1792" 
+d="M666 1055q-60 -92 -137 -273q-22 45 -37 72.5t-40.5 63.5t-51 56.5t-63 35t-81.5 14.5h-224q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h224q250 0 410 -225zM1792 256q0 -14 -9 -23l-320 -320q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5v192q-32 0 -85 -0.5t-81 -1t-73 1
+t-71 5t-64 10.5t-63 18.5t-58 28.5t-59 40t-55 53.5t-56 69.5q59 93 136 273q22 -45 37 -72.5t40.5 -63.5t51 -56.5t63 -35t81.5 -14.5h256v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23zM1792 1152q0 -14 -9 -23l-320 -320q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5
+v192h-256q-48 0 -87 -15t-69 -45t-51 -61.5t-45 -77.5q-32 -62 -78 -171q-29 -66 -49.5 -111t-54 -105t-64 -100t-74 -83t-90 -68.5t-106.5 -42t-128 -16.5h-224q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h224q48 0 87 15t69 45t51 61.5t45 77.5q32 62 78 171q29 66 49.5 111
+t54 105t64 100t74 83t90 68.5t106.5 42t128 16.5h256v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23z" />
+    <glyph glyph-name="comment" unicode="&#xf075;" horiz-adv-x="1792" 
+d="M1792 640q0 -174 -120 -321.5t-326 -233t-450 -85.5q-70 0 -145 8q-198 -175 -460 -242q-49 -14 -114 -22q-17 -2 -30.5 9t-17.5 29v1q-3 4 -0.5 12t2 10t4.5 9.5l6 9t7 8.5t8 9q7 8 31 34.5t34.5 38t31 39.5t32.5 51t27 59t26 76q-157 89 -247.5 220t-90.5 281
+q0 130 71 248.5t191 204.5t286 136.5t348 50.5q244 0 450 -85.5t326 -233t120 -321.5z" />
+    <glyph glyph-name="magnet" unicode="&#xf076;" 
+d="M1536 704v-128q0 -201 -98.5 -362t-274 -251.5t-395.5 -90.5t-395.5 90.5t-274 251.5t-98.5 362v128q0 26 19 45t45 19h384q26 0 45 -19t19 -45v-128q0 -52 23.5 -90t53.5 -57t71 -30t64 -13t44 -2t44 2t64 13t71 30t53.5 57t23.5 90v128q0 26 19 45t45 19h384
+q26 0 45 -19t19 -45zM512 1344v-384q0 -26 -19 -45t-45 -19h-384q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h384q26 0 45 -19t19 -45zM1536 1344v-384q0 -26 -19 -45t-45 -19h-384q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h384q26 0 45 -19t19 -45z" />
+    <glyph glyph-name="chevron_up" unicode="&#xf077;" horiz-adv-x="1792" 
+d="M1683 205l-166 -165q-19 -19 -45 -19t-45 19l-531 531l-531 -531q-19 -19 -45 -19t-45 19l-166 165q-19 19 -19 45.5t19 45.5l742 741q19 19 45 19t45 -19l742 -741q19 -19 19 -45.5t-19 -45.5z" />
+    <glyph glyph-name="chevron_down" unicode="&#xf078;" horiz-adv-x="1792" 
+d="M1683 728l-742 -741q-19 -19 -45 -19t-45 19l-742 741q-19 19 -19 45.5t19 45.5l166 165q19 19 45 19t45 -19l531 -531l531 531q19 19 45 19t45 -19l166 -165q19 -19 19 -45.5t-19 -45.5z" />
+    <glyph glyph-name="retweet" unicode="&#xf079;" horiz-adv-x="1920" 
+d="M1280 32q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-8 0 -13.5 2t-9 7t-5.5 8t-3 11.5t-1 11.5v13v11v160v416h-192q-26 0 -45 19t-19 45q0 24 15 41l320 384q19 22 49 22t49 -22l320 -384q15 -17 15 -41q0 -26 -19 -45t-45 -19h-192v-384h576q16 0 25 -11l160 -192q7 -10 7 -21
+zM1920 448q0 -24 -15 -41l-320 -384q-20 -23 -49 -23t-49 23l-320 384q-15 17 -15 41q0 26 19 45t45 19h192v384h-576q-16 0 -25 12l-160 192q-7 9 -7 20q0 13 9.5 22.5t22.5 9.5h960q8 0 13.5 -2t9 -7t5.5 -8t3 -11.5t1 -11.5v-13v-11v-160v-416h192q26 0 45 -19t19 -45z
+" />
+    <glyph glyph-name="shopping_cart" unicode="&#xf07a;" horiz-adv-x="1664" 
+d="M640 0q0 -52 -38 -90t-90 -38t-90 38t-38 90t38 90t90 38t90 -38t38 -90zM1536 0q0 -52 -38 -90t-90 -38t-90 38t-38 90t38 90t90 38t90 -38t38 -90zM1664 1088v-512q0 -24 -16.5 -42.5t-40.5 -21.5l-1044 -122q13 -60 13 -70q0 -16 -24 -64h920q26 0 45 -19t19 -45
+t-19 -45t-45 -19h-1024q-26 0 -45 19t-19 45q0 11 8 31.5t16 36t21.5 40t15.5 29.5l-177 823h-204q-26 0 -45 19t-19 45t19 45t45 19h256q16 0 28.5 -6.5t19.5 -15.5t13 -24.5t8 -26t5.5 -29.5t4.5 -26h1201q26 0 45 -19t19 -45z" />
+    <glyph glyph-name="folder_close" unicode="&#xf07b;" horiz-adv-x="1664" 
+d="M1664 928v-704q0 -92 -66 -158t-158 -66h-1216q-92 0 -158 66t-66 158v960q0 92 66 158t158 66h320q92 0 158 -66t66 -158v-32h672q92 0 158 -66t66 -158z" />
+    <glyph glyph-name="folder_open" unicode="&#xf07c;" horiz-adv-x="1920" 
+d="M1879 584q0 -31 -31 -66l-336 -396q-43 -51 -120.5 -86.5t-143.5 -35.5h-1088q-34 0 -60.5 13t-26.5 43q0 31 31 66l336 396q43 51 120.5 86.5t143.5 35.5h1088q34 0 60.5 -13t26.5 -43zM1536 928v-160h-832q-94 0 -197 -47.5t-164 -119.5l-337 -396l-5 -6q0 4 -0.5 12.5
+t-0.5 12.5v960q0 92 66 158t158 66h320q92 0 158 -66t66 -158v-32h544q92 0 158 -66t66 -158z" />
+    <glyph glyph-name="resize_vertical" unicode="&#xf07d;" horiz-adv-x="768" 
+d="M704 1216q0 -26 -19 -45t-45 -19h-128v-1024h128q26 0 45 -19t19 -45t-19 -45l-256 -256q-19 -19 -45 -19t-45 19l-256 256q-19 19 -19 45t19 45t45 19h128v1024h-128q-26 0 -45 19t-19 45t19 45l256 256q19 19 45 19t45 -19l256 -256q19 -19 19 -45z" />
+    <glyph glyph-name="resize_horizontal" unicode="&#xf07e;" horiz-adv-x="1792" 
+d="M1792 640q0 -26 -19 -45l-256 -256q-19 -19 -45 -19t-45 19t-19 45v128h-1024v-128q0 -26 -19 -45t-45 -19t-45 19l-256 256q-19 19 -19 45t19 45l256 256q19 19 45 19t45 -19t19 -45v-128h1024v128q0 26 19 45t45 19t45 -19l256 -256q19 -19 19 -45z" />
+    <glyph glyph-name="bar_chart" unicode="&#xf080;" horiz-adv-x="2048" 
+d="M640 640v-512h-256v512h256zM1024 1152v-1024h-256v1024h256zM2048 0v-128h-2048v1536h128v-1408h1920zM1408 896v-768h-256v768h256zM1792 1280v-1152h-256v1152h256z" />
+    <glyph glyph-name="twitter_sign" unicode="&#xf081;" 
+d="M1280 926q-56 -25 -121 -34q68 40 93 117q-65 -38 -134 -51q-61 66 -153 66q-87 0 -148.5 -61.5t-61.5 -148.5q0 -29 5 -48q-129 7 -242 65t-192 155q-29 -50 -29 -106q0 -114 91 -175q-47 1 -100 26v-2q0 -75 50 -133.5t123 -72.5q-29 -8 -51 -8q-13 0 -39 4
+q21 -63 74.5 -104t121.5 -42q-116 -90 -261 -90q-26 0 -50 3q148 -94 322 -94q112 0 210 35.5t168 95t120.5 137t75 162t24.5 168.5q0 18 -1 27q63 45 105 109zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5
+t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="facebook_sign" unicode="&#xf082;" 
+d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-188v595h199l30 232h-229v148q0 56 23.5 84t91.5 28l122 1v207q-63 9 -178 9q-136 0 -217.5 -80t-81.5 -226v-171h-200v-232h200v-595h-532q-119 0 -203.5 84.5t-84.5 203.5v960
+q0 119 84.5 203.5t203.5 84.5h960z" />
+    <glyph glyph-name="camera_retro" unicode="&#xf083;" horiz-adv-x="1792" 
+d="M928 704q0 14 -9 23t-23 9q-66 0 -113 -47t-47 -113q0 -14 9 -23t23 -9t23 9t9 23q0 40 28 68t68 28q14 0 23 9t9 23zM1152 574q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75t75 -181zM128 0h1536v128h-1536v-128zM1280 574q0 159 -112.5 271.5
+t-271.5 112.5t-271.5 -112.5t-112.5 -271.5t112.5 -271.5t271.5 -112.5t271.5 112.5t112.5 271.5zM256 1216h384v128h-384v-128zM128 1024h1536v118v138h-828l-64 -128h-644v-128zM1792 1280v-1280q0 -53 -37.5 -90.5t-90.5 -37.5h-1536q-53 0 -90.5 37.5t-37.5 90.5v1280
+q0 53 37.5 90.5t90.5 37.5h1536q53 0 90.5 -37.5t37.5 -90.5z" />
+    <glyph glyph-name="key" unicode="&#xf084;" horiz-adv-x="1792" 
+d="M832 1024q0 80 -56 136t-136 56t-136 -56t-56 -136q0 -42 19 -83q-41 19 -83 19q-80 0 -136 -56t-56 -136t56 -136t136 -56t136 56t56 136q0 42 -19 83q41 -19 83 -19q80 0 136 56t56 136zM1683 320q0 -17 -49 -66t-66 -49q-9 0 -28.5 16t-36.5 33t-38.5 40t-24.5 26
+l-96 -96l220 -220q28 -28 28 -68q0 -42 -39 -81t-81 -39q-40 0 -68 28l-671 671q-176 -131 -365 -131q-163 0 -265.5 102.5t-102.5 265.5q0 160 95 313t248 248t313 95q163 0 265.5 -102.5t102.5 -265.5q0 -189 -131 -365l355 -355l96 96q-3 3 -26 24.5t-40 38.5t-33 36.5
+t-16 28.5q0 17 49 66t66 49q13 0 23 -10q6 -6 46 -44.5t82 -79.5t86.5 -86t73 -78t28.5 -41z" />
+    <glyph glyph-name="cogs" unicode="&#xf085;" horiz-adv-x="1920" 
+d="M896 640q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM1664 128q0 52 -38 90t-90 38t-90 -38t-38 -90q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1664 1152q0 52 -38 90t-90 38t-90 -38t-38 -90q0 -53 37.5 -90.5t90.5 -37.5
+t90.5 37.5t37.5 90.5zM1280 731v-185q0 -10 -7 -19.5t-16 -10.5l-155 -24q-11 -35 -32 -76q34 -48 90 -115q7 -11 7 -20q0 -12 -7 -19q-23 -30 -82.5 -89.5t-78.5 -59.5q-11 0 -21 7l-115 90q-37 -19 -77 -31q-11 -108 -23 -155q-7 -24 -30 -24h-186q-11 0 -20 7.5t-10 17.5
+l-23 153q-34 10 -75 31l-118 -89q-7 -7 -20 -7q-11 0 -21 8q-144 133 -144 160q0 9 7 19q10 14 41 53t47 61q-23 44 -35 82l-152 24q-10 1 -17 9.5t-7 19.5v185q0 10 7 19.5t16 10.5l155 24q11 35 32 76q-34 48 -90 115q-7 11 -7 20q0 12 7 20q22 30 82 89t79 59q11 0 21 -7
+l115 -90q34 18 77 32q11 108 23 154q7 24 30 24h186q11 0 20 -7.5t10 -17.5l23 -153q34 -10 75 -31l118 89q8 7 20 7q11 0 21 -8q144 -133 144 -160q0 -8 -7 -19q-12 -16 -42 -54t-45 -60q23 -48 34 -82l152 -23q10 -2 17 -10.5t7 -19.5zM1920 198v-140q0 -16 -149 -31
+q-12 -27 -30 -52q51 -113 51 -138q0 -4 -4 -7q-122 -71 -124 -71q-8 0 -46 47t-52 68q-20 -2 -30 -2t-30 2q-14 -21 -52 -68t-46 -47q-2 0 -124 71q-4 3 -4 7q0 25 51 138q-18 25 -30 52q-149 15 -149 31v140q0 16 149 31q13 29 30 52q-51 113 -51 138q0 4 4 7q4 2 35 20
+t59 34t30 16q8 0 46 -46.5t52 -67.5q20 2 30 2t30 -2q51 71 92 112l6 2q4 0 124 -70q4 -3 4 -7q0 -25 -51 -138q17 -23 30 -52q149 -15 149 -31zM1920 1222v-140q0 -16 -149 -31q-12 -27 -30 -52q51 -113 51 -138q0 -4 -4 -7q-122 -71 -124 -71q-8 0 -46 47t-52 68
+q-20 -2 -30 -2t-30 2q-14 -21 -52 -68t-46 -47q-2 0 -124 71q-4 3 -4 7q0 25 51 138q-18 25 -30 52q-149 15 -149 31v140q0 16 149 31q13 29 30 52q-51 113 -51 138q0 4 4 7q4 2 35 20t59 34t30 16q8 0 46 -46.5t52 -67.5q20 2 30 2t30 -2q51 71 92 112l6 2q4 0 124 -70
+q4 -3 4 -7q0 -25 -51 -138q17 -23 30 -52q149 -15 149 -31z" />
+    <glyph glyph-name="comments" unicode="&#xf086;" horiz-adv-x="1792" 
+d="M1408 768q0 -139 -94 -257t-256.5 -186.5t-353.5 -68.5q-86 0 -176 16q-124 -88 -278 -128q-36 -9 -86 -16h-3q-11 0 -20.5 8t-11.5 21q-1 3 -1 6.5t0.5 6.5t2 6l2.5 5t3.5 5.5t4 5t4.5 5t4 4.5q5 6 23 25t26 29.5t22.5 29t25 38.5t20.5 44q-124 72 -195 177t-71 224
+q0 139 94 257t256.5 186.5t353.5 68.5t353.5 -68.5t256.5 -186.5t94 -257zM1792 512q0 -120 -71 -224.5t-195 -176.5q10 -24 20.5 -44t25 -38.5t22.5 -29t26 -29.5t23 -25q1 -1 4 -4.5t4.5 -5t4 -5t3.5 -5.5l2.5 -5t2 -6t0.5 -6.5t-1 -6.5q-3 -14 -13 -22t-22 -7
+q-50 7 -86 16q-154 40 -278 128q-90 -16 -176 -16q-271 0 -472 132q58 -4 88 -4q161 0 309 45t264 129q125 92 192 212t67 254q0 77 -23 152q129 -71 204 -178t75 -230z" />
+    <glyph glyph-name="thumbs_up_alt" unicode="&#xf087;" 
+d="M256 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 768q0 51 -39 89.5t-89 38.5h-352q0 58 48 159.5t48 160.5q0 98 -32 145t-128 47q-26 -26 -38 -85t-30.5 -125.5t-59.5 -109.5q-22 -23 -77 -91q-4 -5 -23 -30t-31.5 -41t-34.5 -42.5
+t-40 -44t-38.5 -35.5t-40 -27t-35.5 -9h-32v-640h32q13 0 31.5 -3t33 -6.5t38 -11t35 -11.5t35.5 -12.5t29 -10.5q211 -73 342 -73h121q192 0 192 167q0 26 -5 56q30 16 47.5 52.5t17.5 73.5t-18 69q53 50 53 119q0 25 -10 55.5t-25 47.5q32 1 53.5 47t21.5 81zM1536 769
+q0 -89 -49 -163q9 -33 9 -69q0 -77 -38 -144q3 -21 3 -43q0 -101 -60 -178q1 -139 -85 -219.5t-227 -80.5h-36h-93q-96 0 -189.5 22.5t-216.5 65.5q-116 40 -138 40h-288q-53 0 -90.5 37.5t-37.5 90.5v640q0 53 37.5 90.5t90.5 37.5h274q36 24 137 155q58 75 107 128
+q24 25 35.5 85.5t30.5 126.5t62 108q39 37 90 37q84 0 151 -32.5t102 -101.5t35 -186q0 -93 -48 -192h176q104 0 180 -76t76 -179z" />
+    <glyph glyph-name="thumbs_down_alt" unicode="&#xf088;" 
+d="M256 1088q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 512q0 35 -21.5 81t-53.5 47q15 17 25 47.5t10 55.5q0 69 -53 119q18 31 18 69q0 37 -17.5 73.5t-47.5 52.5q5 30 5 56q0 85 -49 126t-136 41h-128q-131 0 -342 -73q-5 -2 -29 -10.5
+t-35.5 -12.5t-35 -11.5t-38 -11t-33 -6.5t-31.5 -3h-32v-640h32q16 0 35.5 -9t40 -27t38.5 -35.5t40 -44t34.5 -42.5t31.5 -41t23 -30q55 -68 77 -91q41 -43 59.5 -109.5t30.5 -125.5t38 -85q96 0 128 47t32 145q0 59 -48 160.5t-48 159.5h352q50 0 89 38.5t39 89.5z
+M1536 511q0 -103 -76 -179t-180 -76h-176q48 -99 48 -192q0 -118 -35 -186q-35 -69 -102 -101.5t-151 -32.5q-51 0 -90 37q-34 33 -54 82t-25.5 90.5t-17.5 84.5t-31 64q-48 50 -107 127q-101 131 -137 155h-274q-53 0 -90.5 37.5t-37.5 90.5v640q0 53 37.5 90.5t90.5 37.5
+h288q22 0 138 40q128 44 223 66t200 22h112q140 0 226.5 -79t85.5 -216v-5q60 -77 60 -178q0 -22 -3 -43q38 -67 38 -144q0 -36 -9 -69q49 -73 49 -163z" />
+    <glyph glyph-name="star_half" unicode="&#xf089;" horiz-adv-x="896" 
+d="M832 1504v-1339l-449 -236q-22 -12 -40 -12q-21 0 -31.5 14.5t-10.5 35.5q0 6 2 20l86 500l-364 354q-25 27 -25 48q0 37 56 46l502 73l225 455q19 41 49 41z" />
+    <glyph glyph-name="heart_empty" unicode="&#xf08a;" horiz-adv-x="1792" 
+d="M1664 940q0 81 -21.5 143t-55 98.5t-81.5 59.5t-94 31t-98 8t-112 -25.5t-110.5 -64t-86.5 -72t-60 -61.5q-18 -22 -49 -22t-49 22q-24 28 -60 61.5t-86.5 72t-110.5 64t-112 25.5t-98 -8t-94 -31t-81.5 -59.5t-55 -98.5t-21.5 -143q0 -168 187 -355l581 -560l580 559
+q188 188 188 356zM1792 940q0 -221 -229 -450l-623 -600q-18 -18 -44 -18t-44 18l-624 602q-10 8 -27.5 26t-55.5 65.5t-68 97.5t-53.5 121t-23.5 138q0 220 127 344t351 124q62 0 126.5 -21.5t120 -58t95.5 -68.5t76 -68q36 36 76 68t95.5 68.5t120 58t126.5 21.5
+q224 0 351 -124t127 -344z" />
+    <glyph glyph-name="signout" unicode="&#xf08b;" horiz-adv-x="1664" 
+d="M640 96q0 -4 1 -20t0.5 -26.5t-3 -23.5t-10 -19.5t-20.5 -6.5h-320q-119 0 -203.5 84.5t-84.5 203.5v704q0 119 84.5 203.5t203.5 84.5h320q13 0 22.5 -9.5t9.5 -22.5q0 -4 1 -20t0.5 -26.5t-3 -23.5t-10 -19.5t-20.5 -6.5h-320q-66 0 -113 -47t-47 -113v-704
+q0 -66 47 -113t113 -47h288h11h13t11.5 -1t11.5 -3t8 -5.5t7 -9t2 -13.5zM1568 640q0 -26 -19 -45l-544 -544q-19 -19 -45 -19t-45 19t-19 45v288h-448q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h448v288q0 26 19 45t45 19t45 -19l544 -544q19 -19 19 -45z" />
+    <glyph glyph-name="linkedin_sign" unicode="&#xf08c;" 
+d="M237 122h231v694h-231v-694zM483 1030q-1 52 -36 86t-93 34t-94.5 -34t-36.5 -86q0 -51 35.5 -85.5t92.5 -34.5h1q59 0 95 34.5t36 85.5zM1068 122h231v398q0 154 -73 233t-193 79q-136 0 -209 -117h2v101h-231q3 -66 0 -694h231v388q0 38 7 56q15 35 45 59.5t74 24.5
+q116 0 116 -157v-371zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="pushpin" unicode="&#xf08d;" horiz-adv-x="1152" 
+d="M480 672v448q0 14 -9 23t-23 9t-23 -9t-9 -23v-448q0 -14 9 -23t23 -9t23 9t9 23zM1152 320q0 -26 -19 -45t-45 -19h-429l-51 -483q-2 -12 -10.5 -20.5t-20.5 -8.5h-1q-27 0 -32 27l-76 485h-404q-26 0 -45 19t-19 45q0 123 78.5 221.5t177.5 98.5v512q-52 0 -90 38
+t-38 90t38 90t90 38h640q52 0 90 -38t38 -90t-38 -90t-90 -38v-512q99 0 177.5 -98.5t78.5 -221.5z" />
+    <glyph glyph-name="external_link" unicode="&#xf08e;" horiz-adv-x="1792" 
+d="M1408 608v-320q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h704q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-704q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v320
+q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1792 1472v-512q0 -26 -19 -45t-45 -19t-45 19l-176 176l-652 -652q-10 -10 -23 -10t-23 10l-114 114q-10 10 -10 23t10 23l652 652l-176 176q-19 19 -19 45t19 45t45 19h512q26 0 45 -19t19 -45z" />
+    <glyph glyph-name="signin" unicode="&#xf090;" 
+d="M1184 640q0 -26 -19 -45l-544 -544q-19 -19 -45 -19t-45 19t-19 45v288h-448q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h448v288q0 26 19 45t45 19t45 -19l544 -544q19 -19 19 -45zM1536 992v-704q0 -119 -84.5 -203.5t-203.5 -84.5h-320q-13 0 -22.5 9.5t-9.5 22.5
+q0 4 -1 20t-0.5 26.5t3 23.5t10 19.5t20.5 6.5h320q66 0 113 47t47 113v704q0 66 -47 113t-113 47h-288h-11h-13t-11.5 1t-11.5 3t-8 5.5t-7 9t-2 13.5q0 4 -1 20t-0.5 26.5t3 23.5t10 19.5t20.5 6.5h320q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="trophy" unicode="&#xf091;" horiz-adv-x="1664" 
+d="M458 653q-74 162 -74 371h-256v-96q0 -78 94.5 -162t235.5 -113zM1536 928v96h-256q0 -209 -74 -371q141 29 235.5 113t94.5 162zM1664 1056v-128q0 -71 -41.5 -143t-112 -130t-173 -97.5t-215.5 -44.5q-42 -54 -95 -95q-38 -34 -52.5 -72.5t-14.5 -89.5q0 -54 30.5 -91
+t97.5 -37q75 0 133.5 -45.5t58.5 -114.5v-64q0 -14 -9 -23t-23 -9h-832q-14 0 -23 9t-9 23v64q0 69 58.5 114.5t133.5 45.5q67 0 97.5 37t30.5 91q0 51 -14.5 89.5t-52.5 72.5q-53 41 -95 95q-113 5 -215.5 44.5t-173 97.5t-112 130t-41.5 143v128q0 40 28 68t68 28h288v96
+q0 66 47 113t113 47h576q66 0 113 -47t47 -113v-96h288q40 0 68 -28t28 -68z" />
+    <glyph glyph-name="github_sign" unicode="&#xf092;" 
+d="M519 336q4 6 -3 13q-9 7 -14 2q-4 -6 3 -13q9 -7 14 -2zM491 377q-5 7 -12 4q-6 -4 0 -12q7 -8 12 -5q6 4 0 13zM450 417q2 4 -5 8q-7 2 -8 -2q-3 -5 4 -8q8 -2 9 2zM471 394q2 1 1.5 4.5t-3.5 5.5q-6 7 -10 3t1 -11q6 -6 11 -2zM557 319q2 7 -9 11q-9 3 -13 -4
+q-2 -7 9 -11q9 -3 13 4zM599 316q0 8 -12 8q-10 0 -10 -8t11 -8t11 8zM638 323q-2 7 -13 5t-9 -9q2 -8 12 -6t10 10zM1280 640q0 212 -150 362t-362 150t-362 -150t-150 -362q0 -167 98 -300.5t252 -185.5q18 -3 26.5 5t8.5 20q0 52 -1 95q-6 -1 -15.5 -2.5t-35.5 -2t-48 4
+t-43.5 20t-29.5 41.5q-23 59 -57 74q-2 1 -4.5 3.5l-8 8t-7 9.5t4 7.5t19.5 3.5q6 0 15 -2t30 -15.5t33 -35.5q16 -28 37.5 -42t43.5 -14t38 3.5t30 9.5q7 47 33 69q-49 6 -86 18.5t-73 39t-55.5 76t-19.5 119.5q0 79 53 137q-24 62 5 136q19 6 54.5 -7.5t60.5 -29.5l26 -16
+q58 17 128 17t128 -17q11 7 28.5 18t55.5 26t57 9q29 -74 5 -136q53 -58 53 -137q0 -57 -14 -100.5t-35.5 -70t-53.5 -44.5t-62.5 -26t-68.5 -12q35 -31 35 -95q0 -40 -0.5 -89t-0.5 -51q0 -12 8.5 -20t26.5 -5q154 52 252 185.5t98 300.5zM1536 1120v-960
+q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="upload_alt" unicode="&#xf093;" horiz-adv-x="1664" 
+d="M1280 64q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1536 64q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1664 288v-320q0 -40 -28 -68t-68 -28h-1472q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h427q21 -56 70.5 -92
+t110.5 -36h256q61 0 110.5 36t70.5 92h427q40 0 68 -28t28 -68zM1339 936q-17 -40 -59 -40h-256v-448q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v448h-256q-42 0 -59 40q-17 39 14 69l448 448q18 19 45 19t45 -19l448 -448q31 -30 14 -69z" />
+    <glyph glyph-name="lemon" unicode="&#xf094;" 
+d="M1407 710q0 44 -7 113.5t-18 96.5q-12 30 -17 44t-9 36.5t-4 48.5q0 23 5 68.5t5 67.5q0 37 -10 55q-4 1 -13 1q-19 0 -58 -4.5t-59 -4.5q-60 0 -176 24t-175 24q-43 0 -94.5 -11.5t-85 -23.5t-89.5 -34q-137 -54 -202 -103q-96 -73 -159.5 -189.5t-88 -236t-24.5 -248.5
+q0 -40 12.5 -120t12.5 -121q0 -23 -11 -66.5t-11 -65.5t12 -36.5t34 -14.5q24 0 72.5 11t73.5 11q57 0 169.5 -15.5t169.5 -15.5q181 0 284 36q129 45 235.5 152.5t166 245.5t59.5 275zM1535 712q0 -165 -70 -327.5t-196 -288t-281 -180.5q-124 -44 -326 -44
+q-57 0 -170 14.5t-169 14.5q-24 0 -72.5 -14.5t-73.5 -14.5q-73 0 -123.5 55.5t-50.5 128.5q0 24 11 68t11 67q0 40 -12.5 120.5t-12.5 121.5q0 111 18 217.5t54.5 209.5t100.5 194t150 156q78 59 232 120q194 78 316 78q60 0 175.5 -24t173.5 -24q19 0 57 5t58 5
+q81 0 118 -50.5t37 -134.5q0 -23 -5 -68t-5 -68q0 -13 2 -25t3.5 -16.5t7.5 -20.5t8 -20q16 -40 25 -118.5t9 -136.5z" />
+    <glyph glyph-name="phone" unicode="&#xf095;" horiz-adv-x="1408" 
+d="M1408 296q0 -27 -10 -70.5t-21 -68.5q-21 -50 -122 -106q-94 -51 -186 -51q-27 0 -53 3.5t-57.5 12.5t-47 14.5t-55.5 20.5t-49 18q-98 35 -175 83q-127 79 -264 216t-216 264q-48 77 -83 175q-3 9 -18 49t-20.5 55.5t-14.5 47t-12.5 57.5t-3.5 53q0 92 51 186
+q56 101 106 122q25 11 68.5 21t70.5 10q14 0 21 -3q18 -6 53 -76q11 -19 30 -54t35 -63.5t31 -53.5q3 -4 17.5 -25t21.5 -35.5t7 -28.5q0 -20 -28.5 -50t-62 -55t-62 -53t-28.5 -46q0 -9 5 -22.5t8.5 -20.5t14 -24t11.5 -19q76 -137 174 -235t235 -174q2 -1 19 -11.5t24 -14
+t20.5 -8.5t22.5 -5q18 0 46 28.5t53 62t55 62t50 28.5q14 0 28.5 -7t35.5 -21.5t25 -17.5q25 -15 53.5 -31t63.5 -35t54 -30q70 -35 76 -53q3 -7 3 -21z" />
+    <glyph glyph-name="check_empty" unicode="&#xf096;" horiz-adv-x="1408" 
+d="M1120 1280h-832q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v832q0 66 -47 113t-113 47zM1408 1120v-832q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832
+q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="bookmark_empty" unicode="&#xf097;" horiz-adv-x="1280" 
+d="M1152 1280h-1024v-1242l423 406l89 85l89 -85l423 -406v1242zM1164 1408q23 0 44 -9q33 -13 52.5 -41t19.5 -62v-1289q0 -34 -19.5 -62t-52.5 -41q-19 -8 -44 -8q-48 0 -83 32l-441 424l-441 -424q-36 -33 -83 -33q-23 0 -44 9q-33 13 -52.5 41t-19.5 62v1289
+q0 34 19.5 62t52.5 41q21 9 44 9h1048z" />
+    <glyph glyph-name="phone_sign" unicode="&#xf098;" 
+d="M1280 343q0 11 -2 16t-18 16.5t-40.5 25t-47.5 26.5t-45.5 25t-28.5 15q-5 3 -19 13t-25 15t-21 5q-15 0 -36.5 -20.5t-39.5 -45t-38.5 -45t-33.5 -20.5q-7 0 -16.5 3.5t-15.5 6.5t-17 9.5t-14 8.5q-99 55 -170 126.5t-127 170.5q-2 3 -8.5 14t-9.5 17t-6.5 15.5
+t-3.5 16.5q0 13 20.5 33.5t45 38.5t45 39.5t20.5 36.5q0 10 -5 21t-15 25t-13 19q-3 6 -15 28.5t-25 45.5t-26.5 47.5t-25 40.5t-16.5 18t-16 2q-48 0 -101 -22q-46 -21 -80 -94.5t-34 -130.5q0 -16 2.5 -34t5 -30.5t9 -33t10 -29.5t12.5 -33t11 -30q60 -164 216.5 -320.5
+t320.5 -216.5q6 -2 30 -11t33 -12.5t29.5 -10t33 -9t30.5 -5t34 -2.5q57 0 130.5 34t94.5 80q22 53 22 101zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z
+" />
+    <glyph glyph-name="twitter" unicode="&#xf099;" horiz-adv-x="1664" 
+d="M1620 1128q-67 -98 -162 -167q1 -14 1 -42q0 -130 -38 -259.5t-115.5 -248.5t-184.5 -210.5t-258 -146t-323 -54.5q-271 0 -496 145q35 -4 78 -4q225 0 401 138q-105 2 -188 64.5t-114 159.5q33 -5 61 -5q43 0 85 11q-112 23 -185.5 111.5t-73.5 205.5v4q68 -38 146 -41
+q-66 44 -105 115t-39 154q0 88 44 163q121 -149 294.5 -238.5t371.5 -99.5q-8 38 -8 74q0 134 94.5 228.5t228.5 94.5q140 0 236 -102q109 21 205 78q-37 -115 -142 -178q93 10 186 50z" />
+    <glyph glyph-name="facebook" unicode="&#xf09a;" horiz-adv-x="1024" 
+d="M959 1524v-264h-157q-86 0 -116 -36t-30 -108v-189h293l-39 -296h-254v-759h-306v759h-255v296h255v218q0 186 104 288.5t277 102.5q147 0 228 -12z" />
+    <glyph glyph-name="github" unicode="&#xf09b;" 
+d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5q0 -251 -146.5 -451.5t-378.5 -277.5q-27 -5 -40 7t-13 30q0 3 0.5 76.5t0.5 134.5q0 97 -52 142q57 6 102.5 18t94 39t81 66.5t53 105t20.5 150.5q0 119 -79 206q37 91 -8 204q-28 9 -81 -11t-92 -44l-38 -24
+q-93 26 -192 26t-192 -26q-16 11 -42.5 27t-83.5 38.5t-85 13.5q-45 -113 -8 -204q-79 -87 -79 -206q0 -85 20.5 -150t52.5 -105t80.5 -67t94 -39t102.5 -18q-39 -36 -49 -103q-21 -10 -45 -15t-57 -5t-65.5 21.5t-55.5 62.5q-19 32 -48.5 52t-49.5 24l-20 3q-21 0 -29 -4.5
+t-5 -11.5t9 -14t13 -12l7 -5q22 -10 43.5 -38t31.5 -51l10 -23q13 -38 44 -61.5t67 -30t69.5 -7t55.5 3.5l23 4q0 -38 0.5 -88.5t0.5 -54.5q0 -18 -13 -30t-40 -7q-232 77 -378.5 277.5t-146.5 451.5q0 209 103 385.5t279.5 279.5t385.5 103zM291 305q3 7 -7 12
+q-10 3 -13 -2q-3 -7 7 -12q9 -6 13 2zM322 271q7 5 -2 16q-10 9 -16 3q-7 -5 2 -16q10 -10 16 -3zM352 226q9 7 0 19q-8 13 -17 6q-9 -5 0 -18t17 -7zM394 184q8 8 -4 19q-12 12 -20 3q-9 -8 4 -19q12 -12 20 -3zM451 159q3 11 -13 16q-15 4 -19 -7t13 -15q15 -6 19 6z
+M514 154q0 13 -17 11q-16 0 -16 -11q0 -13 17 -11q16 0 16 11zM572 164q-2 11 -18 9q-16 -3 -14 -15t18 -8t14 14z" />
+    <glyph glyph-name="unlock" unicode="&#xf09c;" horiz-adv-x="1664" 
+d="M1664 960v-256q0 -26 -19 -45t-45 -19h-64q-26 0 -45 19t-19 45v256q0 106 -75 181t-181 75t-181 -75t-75 -181v-192h96q40 0 68 -28t28 -68v-576q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v576q0 40 28 68t68 28h672v192q0 185 131.5 316.5t316.5 131.5
+t316.5 -131.5t131.5 -316.5z" />
+    <glyph glyph-name="credit_card" unicode="&#xf09d;" horiz-adv-x="1920" 
+d="M1760 1408q66 0 113 -47t47 -113v-1216q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1600zM160 1280q-13 0 -22.5 -9.5t-9.5 -22.5v-224h1664v224q0 13 -9.5 22.5t-22.5 9.5h-1600zM1760 0q13 0 22.5 9.5t9.5 22.5v608h-1664v-608
+q0 -13 9.5 -22.5t22.5 -9.5h1600zM256 128v128h256v-128h-256zM640 128v128h384v-128h-384z" />
+    <glyph glyph-name="rss" unicode="&#xf09e;" horiz-adv-x="1408" 
+d="M384 192q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM896 69q2 -28 -17 -48q-18 -21 -47 -21h-135q-25 0 -43 16.5t-20 41.5q-22 229 -184.5 391.5t-391.5 184.5q-25 2 -41.5 20t-16.5 43v135q0 29 21 47q17 17 43 17h5q160 -13 306 -80.5
+t259 -181.5q114 -113 181.5 -259t80.5 -306zM1408 67q2 -27 -18 -47q-18 -20 -46 -20h-143q-26 0 -44.5 17.5t-19.5 42.5q-12 215 -101 408.5t-231.5 336t-336 231.5t-408.5 102q-25 1 -42.5 19.5t-17.5 43.5v143q0 28 20 46q18 18 44 18h3q262 -13 501.5 -120t425.5 -294
+q187 -186 294 -425.5t120 -501.5z" />
+    <glyph glyph-name="hdd" unicode="&#xf0a0;" 
+d="M1040 320q0 -33 -23.5 -56.5t-56.5 -23.5t-56.5 23.5t-23.5 56.5t23.5 56.5t56.5 23.5t56.5 -23.5t23.5 -56.5zM1296 320q0 -33 -23.5 -56.5t-56.5 -23.5t-56.5 23.5t-23.5 56.5t23.5 56.5t56.5 23.5t56.5 -23.5t23.5 -56.5zM1408 160v320q0 13 -9.5 22.5t-22.5 9.5
+h-1216q-13 0 -22.5 -9.5t-9.5 -22.5v-320q0 -13 9.5 -22.5t22.5 -9.5h1216q13 0 22.5 9.5t9.5 22.5zM178 640h1180l-157 482q-4 13 -16 21.5t-26 8.5h-782q-14 0 -26 -8.5t-16 -21.5zM1536 480v-320q0 -66 -47 -113t-113 -47h-1216q-66 0 -113 47t-47 113v320q0 25 16 75
+l197 606q17 53 63 86t101 33h782q55 0 101 -33t63 -86l197 -606q16 -50 16 -75z" />
+    <glyph glyph-name="bullhorn" unicode="&#xf0a1;" horiz-adv-x="1792" 
+d="M1664 896q53 0 90.5 -37.5t37.5 -90.5t-37.5 -90.5t-90.5 -37.5v-384q0 -52 -38 -90t-90 -38q-417 347 -812 380q-58 -19 -91 -66t-31 -100.5t40 -92.5q-20 -33 -23 -65.5t6 -58t33.5 -55t48 -50t61.5 -50.5q-29 -58 -111.5 -83t-168.5 -11.5t-132 55.5q-7 23 -29.5 87.5
+t-32 94.5t-23 89t-15 101t3.5 98.5t22 110.5h-122q-66 0 -113 47t-47 113v192q0 66 47 113t113 47h480q435 0 896 384q52 0 90 -38t38 -90v-384zM1536 292v954q-394 -302 -768 -343v-270q377 -42 768 -341z" />
+    <glyph glyph-name="bell" unicode="&#xf0a2;" horiz-adv-x="1792" 
+d="M912 -160q0 16 -16 16q-59 0 -101.5 42.5t-42.5 101.5q0 16 -16 16t-16 -16q0 -73 51.5 -124.5t124.5 -51.5q16 0 16 16zM246 128h1300q-266 300 -266 832q0 51 -24 105t-69 103t-121.5 80.5t-169.5 31.5t-169.5 -31.5t-121.5 -80.5t-69 -103t-24 -105q0 -532 -266 -832z
+M1728 128q0 -52 -38 -90t-90 -38h-448q0 -106 -75 -181t-181 -75t-181 75t-75 181h-448q-52 0 -90 38t-38 90q50 42 91 88t85 119.5t74.5 158.5t50 206t19.5 260q0 152 117 282.5t307 158.5q-8 19 -8 39q0 40 28 68t68 28t68 -28t28 -68q0 -20 -8 -39q190 -28 307 -158.5
+t117 -282.5q0 -139 19.5 -260t50 -206t74.5 -158.5t85 -119.5t91 -88z" />
+    <glyph glyph-name="certificate" unicode="&#xf0a3;" 
+d="M1376 640l138 -135q30 -28 20 -70q-12 -41 -52 -51l-188 -48l53 -186q12 -41 -19 -70q-29 -31 -70 -19l-186 53l-48 -188q-10 -40 -51 -52q-12 -2 -19 -2q-31 0 -51 22l-135 138l-135 -138q-28 -30 -70 -20q-41 11 -51 52l-48 188l-186 -53q-41 -12 -70 19q-31 29 -19 70
+l53 186l-188 48q-40 10 -52 51q-10 42 20 70l138 135l-138 135q-30 28 -20 70q12 41 52 51l188 48l-53 186q-12 41 19 70q29 31 70 19l186 -53l48 188q10 41 51 51q41 12 70 -19l135 -139l135 139q29 30 70 19q41 -10 51 -51l48 -188l186 53q41 12 70 -19q31 -29 19 -70
+l-53 -186l188 -48q40 -10 52 -51q10 -42 -20 -70z" />
+    <glyph glyph-name="hand_right" unicode="&#xf0a4;" horiz-adv-x="1792" 
+d="M256 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1664 768q0 51 -39 89.5t-89 38.5h-576q0 20 15 48.5t33 55t33 68t15 84.5q0 67 -44.5 97.5t-115.5 30.5q-24 0 -90 -139q-24 -44 -37 -65q-40 -64 -112 -145q-71 -81 -101 -106
+q-69 -57 -140 -57h-32v-640h32q72 0 167 -32t193.5 -64t179.5 -32q189 0 189 167q0 26 -5 56q30 16 47.5 52.5t17.5 73.5t-18 69q53 50 53 119q0 25 -10 55.5t-25 47.5h331q52 0 90 38t38 90zM1792 769q0 -105 -75.5 -181t-180.5 -76h-169q-4 -62 -37 -119q3 -21 3 -43
+q0 -101 -60 -178q1 -139 -85 -219.5t-227 -80.5q-133 0 -322 69q-164 59 -223 59h-288q-53 0 -90.5 37.5t-37.5 90.5v640q0 53 37.5 90.5t90.5 37.5h288q10 0 21.5 4.5t23.5 14t22.5 18t24 22.5t20.5 21.5t19 21.5t14 17q65 74 100 129q13 21 33 62t37 72t40.5 63t55 49.5
+t69.5 17.5q125 0 206.5 -67t81.5 -189q0 -68 -22 -128h374q104 0 180 -76t76 -179z" />
+    <glyph glyph-name="hand_left" unicode="&#xf0a5;" horiz-adv-x="1792" 
+d="M1376 128h32v640h-32q-35 0 -67.5 12t-62.5 37t-50 46t-49 54q-8 9 -12 14q-72 81 -112 145q-14 22 -38 68q-1 3 -10.5 22.5t-18.5 36t-20 35.5t-21.5 30.5t-18.5 11.5q-71 0 -115.5 -30.5t-44.5 -97.5q0 -43 15 -84.5t33 -68t33 -55t15 -48.5h-576q-50 0 -89 -38.5
+t-39 -89.5q0 -52 38 -90t90 -38h331q-15 -17 -25 -47.5t-10 -55.5q0 -69 53 -119q-18 -32 -18 -69t17.5 -73.5t47.5 -52.5q-4 -24 -4 -56q0 -85 48.5 -126t135.5 -41q84 0 183 32t194 64t167 32zM1664 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45z
+M1792 768v-640q0 -53 -37.5 -90.5t-90.5 -37.5h-288q-59 0 -223 -59q-190 -69 -317 -69q-142 0 -230 77.5t-87 217.5l1 5q-61 76 -61 178q0 22 3 43q-33 57 -37 119h-169q-105 0 -180.5 76t-75.5 181q0 103 76 179t180 76h374q-22 60 -22 128q0 122 81.5 189t206.5 67
+q38 0 69.5 -17.5t55 -49.5t40.5 -63t37 -72t33 -62q35 -55 100 -129q2 -3 14 -17t19 -21.5t20.5 -21.5t24 -22.5t22.5 -18t23.5 -14t21.5 -4.5h288q53 0 90.5 -37.5t37.5 -90.5z" />
+    <glyph glyph-name="hand_up" unicode="&#xf0a6;" 
+d="M1280 -64q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 700q0 189 -167 189q-26 0 -56 -5q-16 30 -52.5 47.5t-73.5 17.5t-69 -18q-50 53 -119 53q-25 0 -55.5 -10t-47.5 -25v331q0 52 -38 90t-90 38q-51 0 -89.5 -39t-38.5 -89v-576
+q-20 0 -48.5 15t-55 33t-68 33t-84.5 15q-67 0 -97.5 -44.5t-30.5 -115.5q0 -24 139 -90q44 -24 65 -37q64 -40 145 -112q81 -71 106 -101q57 -69 57 -140v-32h640v32q0 72 32 167t64 193.5t32 179.5zM1536 705q0 -133 -69 -322q-59 -164 -59 -223v-288q0 -53 -37.5 -90.5
+t-90.5 -37.5h-640q-53 0 -90.5 37.5t-37.5 90.5v288q0 10 -4.5 21.5t-14 23.5t-18 22.5t-22.5 24t-21.5 20.5t-21.5 19t-17 14q-74 65 -129 100q-21 13 -62 33t-72 37t-63 40.5t-49.5 55t-17.5 69.5q0 125 67 206.5t189 81.5q68 0 128 -22v374q0 104 76 180t179 76
+q105 0 181 -75.5t76 -180.5v-169q62 -4 119 -37q21 3 43 3q101 0 178 -60q139 1 219.5 -85t80.5 -227z" />
+    <glyph glyph-name="hand_down" unicode="&#xf0a7;" 
+d="M1408 576q0 84 -32 183t-64 194t-32 167v32h-640v-32q0 -35 -12 -67.5t-37 -62.5t-46 -50t-54 -49q-9 -8 -14 -12q-81 -72 -145 -112q-22 -14 -68 -38q-3 -1 -22.5 -10.5t-36 -18.5t-35.5 -20t-30.5 -21.5t-11.5 -18.5q0 -71 30.5 -115.5t97.5 -44.5q43 0 84.5 15t68 33
+t55 33t48.5 15v-576q0 -50 38.5 -89t89.5 -39q52 0 90 38t38 90v331q46 -35 103 -35q69 0 119 53q32 -18 69 -18t73.5 17.5t52.5 47.5q24 -4 56 -4q85 0 126 48.5t41 135.5zM1280 1344q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1536 580
+q0 -142 -77.5 -230t-217.5 -87l-5 1q-76 -61 -178 -61q-22 0 -43 3q-54 -30 -119 -37v-169q0 -105 -76 -180.5t-181 -75.5q-103 0 -179 76t-76 180v374q-54 -22 -128 -22q-121 0 -188.5 81.5t-67.5 206.5q0 38 17.5 69.5t49.5 55t63 40.5t72 37t62 33q55 35 129 100
+q3 2 17 14t21.5 19t21.5 20.5t22.5 24t18 22.5t14 23.5t4.5 21.5v288q0 53 37.5 90.5t90.5 37.5h640q53 0 90.5 -37.5t37.5 -90.5v-288q0 -59 59 -223q69 -190 69 -317z" />
+    <glyph glyph-name="circle_arrow_left" unicode="&#xf0a8;" 
+d="M1280 576v128q0 26 -19 45t-45 19h-502l189 189q19 19 19 45t-19 45l-91 91q-18 18 -45 18t-45 -18l-362 -362l-91 -91q-18 -18 -18 -45t18 -45l91 -91l362 -362q18 -18 45 -18t45 18l91 91q18 18 18 45t-18 45l-189 189h502q26 0 45 19t19 45zM1536 640
+q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="circle_arrow_right" unicode="&#xf0a9;" 
+d="M1285 640q0 27 -18 45l-91 91l-362 362q-18 18 -45 18t-45 -18l-91 -91q-18 -18 -18 -45t18 -45l189 -189h-502q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h502l-189 -189q-19 -19 -19 -45t19 -45l91 -91q18 -18 45 -18t45 18l362 362l91 91q18 18 18 45zM1536 640
+q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="circle_arrow_up" unicode="&#xf0aa;" 
+d="M1284 641q0 27 -18 45l-362 362l-91 91q-18 18 -45 18t-45 -18l-91 -91l-362 -362q-18 -18 -18 -45t18 -45l91 -91q18 -18 45 -18t45 18l189 189v-502q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v502l189 -189q19 -19 45 -19t45 19l91 91q18 18 18 45zM1536 640
+q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="circle_arrow_down" unicode="&#xf0ab;" 
+d="M1284 639q0 27 -18 45l-91 91q-18 18 -45 18t-45 -18l-189 -189v502q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-502l-189 189q-19 19 -45 19t-45 -19l-91 -91q-18 -18 -18 -45t18 -45l362 -362l91 -91q18 -18 45 -18t45 18l91 91l362 362q18 18 18 45zM1536 640
+q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="globe" unicode="&#xf0ac;" 
+d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM1042 887q-2 -1 -9.5 -9.5t-13.5 -9.5q2 0 4.5 5t5 11t3.5 7q6 7 22 15q14 6 52 12q34 8 51 -11
+q-2 2 9.5 13t14.5 12q3 2 15 4.5t15 7.5l2 22q-12 -1 -17.5 7t-6.5 21q0 -2 -6 -8q0 7 -4.5 8t-11.5 -1t-9 -1q-10 3 -15 7.5t-8 16.5t-4 15q-2 5 -9.5 11t-9.5 10q-1 2 -2.5 5.5t-3 6.5t-4 5.5t-5.5 2.5t-7 -5t-7.5 -10t-4.5 -5q-3 2 -6 1.5t-4.5 -1t-4.5 -3t-5 -3.5
+q-3 -2 -8.5 -3t-8.5 -2q15 5 -1 11q-10 4 -16 3q9 4 7.5 12t-8.5 14h5q-1 4 -8.5 8.5t-17.5 8.5t-13 6q-8 5 -34 9.5t-33 0.5q-5 -6 -4.5 -10.5t4 -14t3.5 -12.5q1 -6 -5.5 -13t-6.5 -12q0 -7 14 -15.5t10 -21.5q-3 -8 -16 -16t-16 -12q-5 -8 -1.5 -18.5t10.5 -16.5
+q2 -2 1.5 -4t-3.5 -4.5t-5.5 -4t-6.5 -3.5l-3 -2q-11 -5 -20.5 6t-13.5 26q-7 25 -16 30q-23 8 -29 -1q-5 13 -41 26q-25 9 -58 4q6 1 0 15q-7 15 -19 12q3 6 4 17.5t1 13.5q3 13 12 23q1 1 7 8.5t9.5 13.5t0.5 6q35 -4 50 11q5 5 11.5 17t10.5 17q9 6 14 5.5t14.5 -5.5
+t14.5 -5q14 -1 15.5 11t-7.5 20q12 -1 3 17q-4 7 -8 9q-12 4 -27 -5q-8 -4 2 -8q-1 1 -9.5 -10.5t-16.5 -17.5t-16 5q-1 1 -5.5 13.5t-9.5 13.5q-8 0 -16 -15q3 8 -11 15t-24 8q19 12 -8 27q-7 4 -20.5 5t-19.5 -4q-5 -7 -5.5 -11.5t5 -8t10.5 -5.5t11.5 -4t8.5 -3
+q14 -10 8 -14q-2 -1 -8.5 -3.5t-11.5 -4.5t-6 -4q-3 -4 0 -14t-2 -14q-5 5 -9 17.5t-7 16.5q7 -9 -25 -6l-10 1q-4 0 -16 -2t-20.5 -1t-13.5 8q-4 8 0 20q1 4 4 2q-4 3 -11 9.5t-10 8.5q-46 -15 -94 -41q6 -1 12 1q5 2 13 6.5t10 5.5q34 14 42 7l5 5q14 -16 20 -25
+q-7 4 -30 1q-20 -6 -22 -12q7 -12 5 -18q-4 3 -11.5 10t-14.5 11t-15 5q-16 0 -22 -1q-146 -80 -235 -222q7 -7 12 -8q4 -1 5 -9t2.5 -11t11.5 3q9 -8 3 -19q1 1 44 -27q19 -17 21 -21q3 -11 -10 -18q-1 2 -9 9t-9 4q-3 -5 0.5 -18.5t10.5 -12.5q-7 0 -9.5 -16t-2.5 -35.5
+t-1 -23.5l2 -1q-3 -12 5.5 -34.5t21.5 -19.5q-13 -3 20 -43q6 -8 8 -9q3 -2 12 -7.5t15 -10t10 -10.5q4 -5 10 -22.5t14 -23.5q-2 -6 9.5 -20t10.5 -23q-1 0 -2.5 -1t-2.5 -1q3 -7 15.5 -14t15.5 -13q1 -3 2 -10t3 -11t8 -2q2 20 -24 62q-15 25 -17 29q-3 5 -5.5 15.5
+t-4.5 14.5q2 0 6 -1.5t8.5 -3.5t7.5 -4t2 -3q-3 -7 2 -17.5t12 -18.5t17 -19t12 -13q6 -6 14 -19.5t0 -13.5q9 0 20 -10.5t17 -19.5q5 -8 8 -26t5 -24q2 -7 8.5 -13.5t12.5 -9.5l16 -8t13 -7q5 -2 18.5 -10.5t21.5 -11.5q10 -4 16 -4t14.5 2.5t13.5 3.5q15 2 29 -15t21 -21
+q36 -19 55 -11q-2 -1 0.5 -7.5t8 -15.5t9 -14.5t5.5 -8.5q5 -6 18 -15t18 -15q6 4 7 9q-3 -8 7 -20t18 -10q14 3 14 32q-31 -15 -49 18q0 1 -2.5 5.5t-4 8.5t-2.5 8.5t0 7.5t5 3q9 0 10 3.5t-2 12.5t-4 13q-1 8 -11 20t-12 15q-5 -9 -16 -8t-16 9q0 -1 -1.5 -5.5t-1.5 -6.5
+q-13 0 -15 1q1 3 2.5 17.5t3.5 22.5q1 4 5.5 12t7.5 14.5t4 12.5t-4.5 9.5t-17.5 2.5q-19 -1 -26 -20q-1 -3 -3 -10.5t-5 -11.5t-9 -7q-7 -3 -24 -2t-24 5q-13 8 -22.5 29t-9.5 37q0 10 2.5 26.5t3 25t-5.5 24.5q3 2 9 9.5t10 10.5q2 1 4.5 1.5t4.5 0t4 1.5t3 6q-1 1 -4 3
+q-3 3 -4 3q7 -3 28.5 1.5t27.5 -1.5q15 -11 22 2q0 1 -2.5 9.5t-0.5 13.5q5 -27 29 -9q3 -3 15.5 -5t17.5 -5q3 -2 7 -5.5t5.5 -4.5t5 0.5t8.5 6.5q10 -14 12 -24q11 -40 19 -44q7 -3 11 -2t4.5 9.5t0 14t-1.5 12.5l-1 8v18l-1 8q-15 3 -18.5 12t1.5 18.5t15 18.5q1 1 8 3.5
+t15.5 6.5t12.5 8q21 19 15 35q7 0 11 9q-1 0 -5 3t-7.5 5t-4.5 2q9 5 2 16q5 3 7.5 11t7.5 10q9 -12 21 -2q8 8 1 16q5 7 20.5 10.5t18.5 9.5q7 -2 8 2t1 12t3 12q4 5 15 9t13 5l17 11q3 4 0 4q18 -2 31 11q10 11 -6 20q3 6 -3 9.5t-15 5.5q3 1 11.5 0.5t10.5 1.5
+q15 10 -7 16q-17 5 -43 -12zM879 10q206 36 351 189q-3 3 -12.5 4.5t-12.5 3.5q-18 7 -24 8q1 7 -2.5 13t-8 9t-12.5 8t-11 7q-2 2 -7 6t-7 5.5t-7.5 4.5t-8.5 2t-10 -1l-3 -1q-3 -1 -5.5 -2.5t-5.5 -3t-4 -3t0 -2.5q-21 17 -36 22q-5 1 -11 5.5t-10.5 7t-10 1.5t-11.5 -7
+q-5 -5 -6 -15t-2 -13q-7 5 0 17.5t2 18.5q-3 6 -10.5 4.5t-12 -4.5t-11.5 -8.5t-9 -6.5t-8.5 -5.5t-8.5 -7.5q-3 -4 -6 -12t-5 -11q-2 4 -11.5 6.5t-9.5 5.5q2 -10 4 -35t5 -38q7 -31 -12 -48q-27 -25 -29 -40q-4 -22 12 -26q0 -7 -8 -20.5t-7 -21.5q0 -6 2 -16z" />
+    <glyph glyph-name="wrench" unicode="&#xf0ad;" horiz-adv-x="1664" 
+d="M384 64q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1028 484l-682 -682q-37 -37 -90 -37q-52 0 -91 37l-106 108q-38 36 -38 90q0 53 38 91l681 681q39 -98 114.5 -173.5t173.5 -114.5zM1662 919q0 -39 -23 -106q-47 -134 -164.5 -217.5
+t-258.5 -83.5q-185 0 -316.5 131.5t-131.5 316.5t131.5 316.5t316.5 131.5q58 0 121.5 -16.5t107.5 -46.5q16 -11 16 -28t-16 -28l-293 -169v-224l193 -107q5 3 79 48.5t135.5 81t70.5 35.5q15 0 23.5 -10t8.5 -25z" />
+    <glyph glyph-name="tasks" unicode="&#xf0ae;" horiz-adv-x="1792" 
+d="M1024 128h640v128h-640v-128zM640 640h1024v128h-1024v-128zM1280 1152h384v128h-384v-128zM1792 320v-256q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 832v-256q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19
+t-19 45v256q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 1344v-256q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1664q26 0 45 -19t19 -45z" />
+    <glyph glyph-name="filter" unicode="&#xf0b0;" horiz-adv-x="1408" 
+d="M1403 1241q17 -41 -14 -70l-493 -493v-742q0 -42 -39 -59q-13 -5 -25 -5q-27 0 -45 19l-256 256q-19 19 -19 45v486l-493 493q-31 29 -14 70q17 39 59 39h1280q42 0 59 -39z" />
+    <glyph glyph-name="briefcase" unicode="&#xf0b1;" horiz-adv-x="1792" 
+d="M640 1280h512v128h-512v-128zM1792 640v-480q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v480h672v-160q0 -26 19 -45t45 -19h320q26 0 45 19t19 45v160h672zM1024 640v-128h-256v128h256zM1792 1120v-384h-1792v384q0 66 47 113t113 47h352v160q0 40 28 68
+t68 28h576q40 0 68 -28t28 -68v-160h352q66 0 113 -47t47 -113z" />
+    <glyph glyph-name="fullscreen" unicode="&#xf0b2;" 
+d="M1283 995l-355 -355l355 -355l144 144q29 31 70 14q39 -17 39 -59v-448q0 -26 -19 -45t-45 -19h-448q-42 0 -59 40q-17 39 14 69l144 144l-355 355l-355 -355l144 -144q31 -30 14 -69q-17 -40 -59 -40h-448q-26 0 -45 19t-19 45v448q0 42 40 59q39 17 69 -14l144 -144
+l355 355l-355 355l-144 -144q-19 -19 -45 -19q-12 0 -24 5q-40 17 -40 59v448q0 26 19 45t45 19h448q42 0 59 -40q17 -39 -14 -69l-144 -144l355 -355l355 355l-144 144q-31 30 -14 69q17 40 59 40h448q26 0 45 -19t19 -45v-448q0 -42 -39 -59q-13 -5 -25 -5q-26 0 -45 19z
+" />
+    <glyph glyph-name="group" unicode="&#xf0c0;" horiz-adv-x="1920" 
+d="M593 640q-162 -5 -265 -128h-134q-82 0 -138 40.5t-56 118.5q0 353 124 353q6 0 43.5 -21t97.5 -42.5t119 -21.5q67 0 133 23q-5 -37 -5 -66q0 -139 81 -256zM1664 3q0 -120 -73 -189.5t-194 -69.5h-874q-121 0 -194 69.5t-73 189.5q0 53 3.5 103.5t14 109t26.5 108.5
+t43 97.5t62 81t85.5 53.5t111.5 20q10 0 43 -21.5t73 -48t107 -48t135 -21.5t135 21.5t107 48t73 48t43 21.5q61 0 111.5 -20t85.5 -53.5t62 -81t43 -97.5t26.5 -108.5t14 -109t3.5 -103.5zM640 1280q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75
+t75 -181zM1344 896q0 -159 -112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5zM1920 671q0 -78 -56 -118.5t-138 -40.5h-134q-103 123 -265 128q81 117 81 256q0 29 -5 66q66 -23 133 -23q59 0 119 21.5t97.5 42.5
+t43.5 21q124 0 124 -353zM1792 1280q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75t75 -181z" />
+    <glyph glyph-name="link" unicode="&#xf0c1;" horiz-adv-x="1664" 
+d="M1456 320q0 40 -28 68l-208 208q-28 28 -68 28q-42 0 -72 -32q3 -3 19 -18.5t21.5 -21.5t15 -19t13 -25.5t3.5 -27.5q0 -40 -28 -68t-68 -28q-15 0 -27.5 3.5t-25.5 13t-19 15t-21.5 21.5t-18.5 19q-33 -31 -33 -73q0 -40 28 -68l206 -207q27 -27 68 -27q40 0 68 26
+l147 146q28 28 28 67zM753 1025q0 40 -28 68l-206 207q-28 28 -68 28q-39 0 -68 -27l-147 -146q-28 -28 -28 -67q0 -40 28 -68l208 -208q27 -27 68 -27q42 0 72 31q-3 3 -19 18.5t-21.5 21.5t-15 19t-13 25.5t-3.5 27.5q0 40 28 68t68 28q15 0 27.5 -3.5t25.5 -13t19 -15
+t21.5 -21.5t18.5 -19q33 31 33 73zM1648 320q0 -120 -85 -203l-147 -146q-83 -83 -203 -83q-121 0 -204 85l-206 207q-83 83 -83 203q0 123 88 209l-88 88q-86 -88 -208 -88q-120 0 -204 84l-208 208q-84 84 -84 204t85 203l147 146q83 83 203 83q121 0 204 -85l206 -207
+q83 -83 83 -203q0 -123 -88 -209l88 -88q86 88 208 88q120 0 204 -84l208 -208q84 -84 84 -204z" />
+    <glyph glyph-name="cloud" unicode="&#xf0c2;" horiz-adv-x="1920" 
+d="M1920 384q0 -159 -112.5 -271.5t-271.5 -112.5h-1088q-185 0 -316.5 131.5t-131.5 316.5q0 132 71 241.5t187 163.5q-2 28 -2 43q0 212 150 362t362 150q158 0 286.5 -88t187.5 -230q70 62 166 62q106 0 181 -75t75 -181q0 -75 -41 -138q129 -30 213 -134.5t84 -239.5z
+" />
+    <glyph glyph-name="beaker" unicode="&#xf0c3;" horiz-adv-x="1664" 
+d="M1527 88q56 -89 21.5 -152.5t-140.5 -63.5h-1152q-106 0 -140.5 63.5t21.5 152.5l503 793v399h-64q-26 0 -45 19t-19 45t19 45t45 19h512q26 0 45 -19t19 -45t-19 -45t-45 -19h-64v-399zM748 813l-272 -429h712l-272 429l-20 31v37v399h-128v-399v-37z" />
+    <glyph glyph-name="cut" unicode="&#xf0c4;" horiz-adv-x="1792" 
+d="M960 640q26 0 45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45t19 45t45 19zM1260 576l507 -398q28 -20 25 -56q-5 -35 -35 -51l-128 -64q-13 -7 -29 -7q-17 0 -31 8l-690 387l-110 -66q-8 -4 -12 -5q14 -49 10 -97q-7 -77 -56 -147.5t-132 -123.5q-132 -84 -277 -84
+q-136 0 -222 78q-90 84 -79 207q7 76 56 147t131 124q132 84 278 84q83 0 151 -31q9 13 22 22l122 73l-122 73q-13 9 -22 22q-68 -31 -151 -31q-146 0 -278 84q-82 53 -131 124t-56 147q-5 59 15.5 113t63.5 93q85 79 222 79q145 0 277 -84q83 -52 132 -123t56 -148
+q4 -48 -10 -97q4 -1 12 -5l110 -66l690 387q14 8 31 8q16 0 29 -7l128 -64q30 -16 35 -51q3 -36 -25 -56zM579 836q46 42 21 108t-106 117q-92 59 -192 59q-74 0 -113 -36q-46 -42 -21 -108t106 -117q92 -59 192 -59q74 0 113 36zM494 91q81 51 106 117t-21 108
+q-39 36 -113 36q-100 0 -192 -59q-81 -51 -106 -117t21 -108q39 -36 113 -36q100 0 192 59zM672 704l96 -58v11q0 36 33 56l14 8l-79 47l-26 -26q-3 -3 -10 -11t-12 -12q-2 -2 -4 -3.5t-3 -2.5zM896 480l96 -32l736 576l-128 64l-768 -431v-113l-160 -96l9 -8q2 -2 7 -6
+q4 -4 11 -12t11 -12l26 -26zM1600 64l128 64l-520 408l-177 -138q-2 -3 -13 -7z" />
+    <glyph glyph-name="copy" unicode="&#xf0c5;" horiz-adv-x="1792" 
+d="M1696 1152q40 0 68 -28t28 -68v-1216q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v288h-544q-40 0 -68 28t-28 68v672q0 40 20 88t48 76l408 408q28 28 76 48t88 20h416q40 0 68 -28t28 -68v-328q68 40 128 40h416zM1152 939l-299 -299h299v299zM512 1323l-299 -299
+h299v299zM708 676l316 316v416h-384v-416q0 -40 -28 -68t-68 -28h-416v-640h512v256q0 40 20 88t48 76zM1664 -128v1152h-384v-416q0 -40 -28 -68t-68 -28h-416v-640h896z" />
+    <glyph glyph-name="paper_clip" unicode="&#xf0c6;" horiz-adv-x="1408" 
+d="M1404 151q0 -117 -79 -196t-196 -79q-135 0 -235 100l-777 776q-113 115 -113 271q0 159 110 270t269 111q158 0 273 -113l605 -606q10 -10 10 -22q0 -16 -30.5 -46.5t-46.5 -30.5q-13 0 -23 10l-606 607q-79 77 -181 77q-106 0 -179 -75t-73 -181q0 -105 76 -181
+l776 -777q63 -63 145 -63q64 0 106 42t42 106q0 82 -63 145l-581 581q-26 24 -60 24q-29 0 -48 -19t-19 -48q0 -32 25 -59l410 -410q10 -10 10 -22q0 -16 -31 -47t-47 -31q-12 0 -22 10l-410 410q-63 61 -63 149q0 82 57 139t139 57q88 0 149 -63l581 -581q100 -98 100 -235
+z" />
+    <glyph glyph-name="save" unicode="&#xf0c7;" 
+d="M384 0h768v384h-768v-384zM1280 0h128v896q0 14 -10 38.5t-20 34.5l-281 281q-10 10 -34 20t-39 10v-416q0 -40 -28 -68t-68 -28h-576q-40 0 -68 28t-28 68v416h-128v-1280h128v416q0 40 28 68t68 28h832q40 0 68 -28t28 -68v-416zM896 928v320q0 13 -9.5 22.5t-22.5 9.5
+h-192q-13 0 -22.5 -9.5t-9.5 -22.5v-320q0 -13 9.5 -22.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 22.5zM1536 896v-928q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h928q40 0 88 -20t76 -48l280 -280q28 -28 48 -76t20 -88z" />
+    <glyph glyph-name="sign_blank" unicode="&#xf0c8;" 
+d="M1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="reorder" unicode="&#xf0c9;" 
+d="M1536 192v-128q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1536 704v-128q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1536 1216v-128q0 -26 -19 -45
+t-45 -19h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45z" />
+    <glyph glyph-name="ul" unicode="&#xf0ca;" horiz-adv-x="1792" 
+d="M384 128q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM384 640q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5
+t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5zM384 1152q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1792 736v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5z
+M1792 1248v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5z" />
+    <glyph glyph-name="ol" unicode="&#xf0cb;" horiz-adv-x="1792" 
+d="M381 -84q0 -80 -54.5 -126t-135.5 -46q-106 0 -172 66l57 88q49 -45 106 -45q29 0 50.5 14.5t21.5 42.5q0 64 -105 56l-26 56q8 10 32.5 43.5t42.5 54t37 38.5v1q-16 0 -48.5 -1t-48.5 -1v-53h-106v152h333v-88l-95 -115q51 -12 81 -49t30 -88zM383 543v-159h-362
+q-6 36 -6 54q0 51 23.5 93t56.5 68t66 47.5t56.5 43.5t23.5 45q0 25 -14.5 38.5t-39.5 13.5q-46 0 -81 -58l-85 59q24 51 71.5 79.5t105.5 28.5q73 0 123 -41.5t50 -112.5q0 -50 -34 -91.5t-75 -64.5t-75.5 -50.5t-35.5 -52.5h127v60h105zM1792 224v-192q0 -13 -9.5 -22.5
+t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 14 9 23t23 9h1216q13 0 22.5 -9.5t9.5 -22.5zM384 1123v-99h-335v99h107q0 41 0.5 121.5t0.5 121.5v12h-2q-8 -17 -50 -54l-71 76l136 127h106v-404h108zM1792 736v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216
+q-13 0 -22.5 9.5t-9.5 22.5v192q0 14 9 23t23 9h1216q13 0 22.5 -9.5t9.5 -22.5zM1792 1248v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5z" />
+    <glyph glyph-name="strikethrough" unicode="&#xf0cc;" horiz-adv-x="1792" 
+d="M1760 640q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-1728q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h1728zM483 704q-28 35 -51 80q-48 98 -48 188q0 181 134 309q133 127 393 127q50 0 167 -19q66 -12 177 -48q10 -38 21 -118q14 -123 14 -183q0 -18 -5 -45l-12 -3l-84 6
+l-14 2q-50 149 -103 205q-88 91 -210 91q-114 0 -182 -59q-67 -58 -67 -146q0 -73 66 -140t279 -129q69 -20 173 -66q58 -28 95 -52h-743zM990 448h411q7 -39 7 -92q0 -111 -41 -212q-23 -56 -71 -104q-37 -35 -109 -81q-80 -48 -153 -66q-80 -21 -203 -21q-114 0 -195 23
+l-140 40q-57 16 -72 28q-8 8 -8 22v13q0 108 -2 156q-1 30 0 68l2 37v44l102 2q15 -34 30 -71t22.5 -56t12.5 -27q35 -57 80 -94q43 -36 105 -57q59 -22 132 -22q64 0 139 27q77 26 122 86q47 61 47 129q0 84 -81 157q-34 29 -137 71z" />
+    <glyph glyph-name="underline" unicode="&#xf0cd;" 
+d="M48 1313q-37 2 -45 4l-3 88q13 1 40 1q60 0 112 -4q132 -7 166 -7q86 0 168 3q116 4 146 5q56 0 86 2l-1 -14l2 -64v-9q-60 -9 -124 -9q-60 0 -79 -25q-13 -14 -13 -132q0 -13 0.5 -32.5t0.5 -25.5l1 -229l14 -280q6 -124 51 -202q35 -59 96 -92q88 -47 177 -47
+q104 0 191 28q56 18 99 51q48 36 65 64q36 56 53 114q21 73 21 229q0 79 -3.5 128t-11 122.5t-13.5 159.5l-4 59q-5 67 -24 88q-34 35 -77 34l-100 -2l-14 3l2 86h84l205 -10q76 -3 196 10l18 -2q6 -38 6 -51q0 -7 -4 -31q-45 -12 -84 -13q-73 -11 -79 -17q-15 -15 -15 -41
+q0 -7 1.5 -27t1.5 -31q8 -19 22 -396q6 -195 -15 -304q-15 -76 -41 -122q-38 -65 -112 -123q-75 -57 -182 -89q-109 -33 -255 -33q-167 0 -284 46q-119 47 -179 122q-61 76 -83 195q-16 80 -16 237v333q0 188 -17 213q-25 36 -147 39zM1536 -96v64q0 14 -9 23t-23 9h-1472
+q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h1472q14 0 23 9t9 23z" />
+    <glyph glyph-name="table" unicode="&#xf0ce;" horiz-adv-x="1664" 
+d="M512 160v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM512 544v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1024 160v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23
+v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM512 928v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1024 544v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1536 160v192
+q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1024 928v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1536 544v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192
+q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1536 928v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1664 1248v-1088q0 -66 -47 -113t-113 -47h-1344q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1344q66 0 113 -47t47 -113
+z" />
+    <glyph glyph-name="magic" unicode="&#xf0d0;" horiz-adv-x="1664" 
+d="M1190 955l293 293l-107 107l-293 -293zM1637 1248q0 -27 -18 -45l-1286 -1286q-18 -18 -45 -18t-45 18l-198 198q-18 18 -18 45t18 45l1286 1286q18 18 45 18t45 -18l198 -198q18 -18 18 -45zM286 1438l98 -30l-98 -30l-30 -98l-30 98l-98 30l98 30l30 98zM636 1276
+l196 -60l-196 -60l-60 -196l-60 196l-196 60l196 60l60 196zM1566 798l98 -30l-98 -30l-30 -98l-30 98l-98 30l98 30l30 98zM926 1438l98 -30l-98 -30l-30 -98l-30 98l-98 30l98 30l30 98z" />
+    <glyph glyph-name="truck" unicode="&#xf0d1;" horiz-adv-x="1792" 
+d="M640 128q0 52 -38 90t-90 38t-90 -38t-38 -90t38 -90t90 -38t90 38t38 90zM256 640h384v256h-158q-13 0 -22 -9l-195 -195q-9 -9 -9 -22v-30zM1536 128q0 52 -38 90t-90 38t-90 -38t-38 -90t38 -90t90 -38t90 38t38 90zM1792 1216v-1024q0 -15 -4 -26.5t-13.5 -18.5
+t-16.5 -11.5t-23.5 -6t-22.5 -2t-25.5 0t-22.5 0.5q0 -106 -75 -181t-181 -75t-181 75t-75 181h-384q0 -106 -75 -181t-181 -75t-181 75t-75 181h-64q-3 0 -22.5 -0.5t-25.5 0t-22.5 2t-23.5 6t-16.5 11.5t-13.5 18.5t-4 26.5q0 26 19 45t45 19v320q0 8 -0.5 35t0 38
+t2.5 34.5t6.5 37t14 30.5t22.5 30l198 198q19 19 50.5 32t58.5 13h160v192q0 26 19 45t45 19h1024q26 0 45 -19t19 -45z" />
+    <glyph glyph-name="pinterest" unicode="&#xf0d2;" 
+d="M1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103q-111 0 -218 32q59 93 78 164q9 34 54 211q20 -39 73 -67.5t114 -28.5q121 0 216 68.5t147 188.5t52 270q0 114 -59.5 214t-172.5 163t-255 63q-105 0 -196 -29t-154.5 -77t-109 -110.5t-67 -129.5t-21.5 -134
+q0 -104 40 -183t117 -111q30 -12 38 20q2 7 8 31t8 30q6 23 -11 43q-51 61 -51 151q0 151 104.5 259.5t273.5 108.5q151 0 235.5 -82t84.5 -213q0 -170 -68.5 -289t-175.5 -119q-61 0 -98 43.5t-23 104.5q8 35 26.5 93.5t30 103t11.5 75.5q0 50 -27 83t-77 33
+q-62 0 -105 -57t-43 -142q0 -73 25 -122l-99 -418q-17 -70 -13 -177q-206 91 -333 281t-127 423q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="pinterest_sign" unicode="&#xf0d3;" 
+d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-725q85 122 108 210q9 34 53 209q21 -39 73.5 -67t112.5 -28q181 0 295.5 147.5t114.5 373.5q0 84 -35 162.5t-96.5 139t-152.5 97t-197 36.5q-104 0 -194.5 -28.5t-153 -76.5
+t-107.5 -109.5t-66.5 -128t-21.5 -132.5q0 -102 39.5 -180t116.5 -110q13 -5 23.5 0t14.5 19q10 44 15 61q6 23 -11 42q-50 62 -50 150q0 150 103.5 256.5t270.5 106.5q149 0 232.5 -81t83.5 -210q0 -168 -67.5 -286t-173.5 -118q-60 0 -97 43.5t-23 103.5q8 34 26.5 92.5
+t29.5 102t11 74.5q0 49 -26.5 81.5t-75.5 32.5q-61 0 -103.5 -56.5t-42.5 -139.5q0 -72 24 -121l-98 -414q-24 -100 -7 -254h-183q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960z" />
+    <glyph glyph-name="google_plus_sign" unicode="&#xf0d4;" 
+d="M917 631q0 26 -6 64h-362v-132h217q-3 -24 -16.5 -50t-37.5 -53t-66.5 -44.5t-96.5 -17.5q-99 0 -169 71t-70 171t70 171t169 71q92 0 153 -59l104 101q-108 100 -257 100q-160 0 -272 -112.5t-112 -271.5t112 -271.5t272 -112.5q165 0 266.5 105t101.5 270zM1262 585
+h109v110h-109v110h-110v-110h-110v-110h110v-110h110v110zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="google_plus" unicode="&#xf0d5;" horiz-adv-x="2304" 
+d="M1437 623q0 -208 -87 -370.5t-248 -254t-369 -91.5q-149 0 -285 58t-234 156t-156 234t-58 285t58 285t156 234t234 156t285 58q286 0 491 -192l-199 -191q-117 113 -292 113q-123 0 -227.5 -62t-165.5 -168.5t-61 -232.5t61 -232.5t165.5 -168.5t227.5 -62
+q83 0 152.5 23t114.5 57.5t78.5 78.5t49 83t21.5 74h-416v252h692q12 -63 12 -122zM2304 745v-210h-209v-209h-210v209h-209v210h209v209h210v-209h209z" />
+    <glyph glyph-name="money" unicode="&#xf0d6;" horiz-adv-x="1920" 
+d="M768 384h384v96h-128v448h-114l-148 -137l77 -80q42 37 55 57h2v-288h-128v-96zM1280 640q0 -70 -21 -142t-59.5 -134t-101.5 -101t-138 -39t-138 39t-101.5 101t-59.5 134t-21 142t21 142t59.5 134t101.5 101t138 39t138 -39t101.5 -101t59.5 -134t21 -142zM1792 384
+v512q-106 0 -181 75t-75 181h-1152q0 -106 -75 -181t-181 -75v-512q106 0 181 -75t75 -181h1152q0 106 75 181t181 75zM1920 1216v-1152q0 -26 -19 -45t-45 -19h-1792q-26 0 -45 19t-19 45v1152q0 26 19 45t45 19h1792q26 0 45 -19t19 -45z" />
+    <glyph glyph-name="caret_down" unicode="&#xf0d7;" horiz-adv-x="1024" 
+d="M1024 832q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19l-448 448q-19 19 -19 45t19 45t45 19h896q26 0 45 -19t19 -45z" />
+    <glyph glyph-name="caret_up" unicode="&#xf0d8;" horiz-adv-x="1024" 
+d="M1024 320q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45l448 448q19 19 45 19t45 -19l448 -448q19 -19 19 -45z" />
+    <glyph glyph-name="caret_left" unicode="&#xf0d9;" horiz-adv-x="640" 
+d="M640 1088v-896q0 -26 -19 -45t-45 -19t-45 19l-448 448q-19 19 -19 45t19 45l448 448q19 19 45 19t45 -19t19 -45z" />
+    <glyph glyph-name="caret_right" unicode="&#xf0da;" horiz-adv-x="640" 
+d="M576 640q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19t-19 45v896q0 26 19 45t45 19t45 -19l448 -448q19 -19 19 -45z" />
+    <glyph glyph-name="columns" unicode="&#xf0db;" horiz-adv-x="1664" 
+d="M160 0h608v1152h-640v-1120q0 -13 9.5 -22.5t22.5 -9.5zM1536 32v1120h-640v-1152h608q13 0 22.5 9.5t9.5 22.5zM1664 1248v-1216q0 -66 -47 -113t-113 -47h-1344q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1344q66 0 113 -47t47 -113z" />
+    <glyph glyph-name="sort" unicode="&#xf0dc;" horiz-adv-x="1024" 
+d="M1024 448q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19l-448 448q-19 19 -19 45t19 45t45 19h896q26 0 45 -19t19 -45zM1024 832q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45l448 448q19 19 45 19t45 -19l448 -448q19 -19 19 -45z" />
+    <glyph glyph-name="sort_down" unicode="&#xf0dd;" horiz-adv-x="1024" 
+d="M1024 448q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19l-448 448q-19 19 -19 45t19 45t45 19h896q26 0 45 -19t19 -45z" />
+    <glyph glyph-name="sort_up" unicode="&#xf0de;" horiz-adv-x="1024" 
+d="M1024 832q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45l448 448q19 19 45 19t45 -19l448 -448q19 -19 19 -45z" />
+    <glyph glyph-name="envelope_alt" unicode="&#xf0e0;" horiz-adv-x="1792" 
+d="M1792 826v-794q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v794q44 -49 101 -87q362 -246 497 -345q57 -42 92.5 -65.5t94.5 -48t110 -24.5h1h1q51 0 110 24.5t94.5 48t92.5 65.5q170 123 498 345q57 39 100 87zM1792 1120q0 -79 -49 -151t-122 -123
+q-376 -261 -468 -325q-10 -7 -42.5 -30.5t-54 -38t-52 -32.5t-57.5 -27t-50 -9h-1h-1q-23 0 -50 9t-57.5 27t-52 32.5t-54 38t-42.5 30.5q-91 64 -262 182.5t-205 142.5q-62 42 -117 115.5t-55 136.5q0 78 41.5 130t118.5 52h1472q65 0 112.5 -47t47.5 -113z" />
+    <glyph glyph-name="linkedin" unicode="&#xf0e1;" 
+d="M349 911v-991h-330v991h330zM370 1217q1 -73 -50.5 -122t-135.5 -49h-2q-82 0 -132 49t-50 122q0 74 51.5 122.5t134.5 48.5t133 -48.5t51 -122.5zM1536 488v-568h-329v530q0 105 -40.5 164.5t-126.5 59.5q-63 0 -105.5 -34.5t-63.5 -85.5q-11 -30 -11 -81v-553h-329
+q2 399 2 647t-1 296l-1 48h329v-144h-2q20 32 41 56t56.5 52t87 43.5t114.5 15.5q171 0 275 -113.5t104 -332.5z" />
+    <glyph glyph-name="undo" unicode="&#xf0e2;" 
+d="M1536 640q0 -156 -61 -298t-164 -245t-245 -164t-298 -61q-172 0 -327 72.5t-264 204.5q-7 10 -6.5 22.5t8.5 20.5l137 138q10 9 25 9q16 -2 23 -12q73 -95 179 -147t225 -52q104 0 198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5t-40.5 198.5t-109.5 163.5
+t-163.5 109.5t-198.5 40.5q-98 0 -188 -35.5t-160 -101.5l137 -138q31 -30 14 -69q-17 -40 -59 -40h-448q-26 0 -45 19t-19 45v448q0 42 40 59q39 17 69 -14l130 -129q107 101 244.5 156.5t284.5 55.5q156 0 298 -61t245 -164t164 -245t61 -298z" />
+    <glyph glyph-name="legal" unicode="&#xf0e3;" horiz-adv-x="1792" 
+d="M1771 0q0 -53 -37 -90l-107 -108q-39 -37 -91 -37q-53 0 -90 37l-363 364q-38 36 -38 90q0 53 43 96l-256 256l-126 -126q-14 -14 -34 -14t-34 14q2 -2 12.5 -12t12.5 -13t10 -11.5t10 -13.5t6 -13.5t5.5 -16.5t1.5 -18q0 -38 -28 -68q-3 -3 -16.5 -18t-19 -20.5
+t-18.5 -16.5t-22 -15.5t-22 -9t-26 -4.5q-40 0 -68 28l-408 408q-28 28 -28 68q0 13 4.5 26t9 22t15.5 22t16.5 18.5t20.5 19t18 16.5q30 28 68 28q10 0 18 -1.5t16.5 -5.5t13.5 -6t13.5 -10t11.5 -10t13 -12.5t12 -12.5q-14 14 -14 34t14 34l348 348q14 14 34 14t34 -14
+q-2 2 -12.5 12t-12.5 13t-10 11.5t-10 13.5t-6 13.5t-5.5 16.5t-1.5 18q0 38 28 68q3 3 16.5 18t19 20.5t18.5 16.5t22 15.5t22 9t26 4.5q40 0 68 -28l408 -408q28 -28 28 -68q0 -13 -4.5 -26t-9 -22t-15.5 -22t-16.5 -18.5t-20.5 -19t-18 -16.5q-30 -28 -68 -28
+q-10 0 -18 1.5t-16.5 5.5t-13.5 6t-13.5 10t-11.5 10t-13 12.5t-12 12.5q14 -14 14 -34t-14 -34l-126 -126l256 -256q43 43 96 43q52 0 91 -37l363 -363q37 -39 37 -91z" />
+    <glyph glyph-name="dashboard" unicode="&#xf0e4;" horiz-adv-x="1792" 
+d="M384 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM576 832q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1004 351l101 382q6 26 -7.5 48.5t-38.5 29.5
+t-48 -6.5t-30 -39.5l-101 -382q-60 -5 -107 -43.5t-63 -98.5q-20 -77 20 -146t117 -89t146 20t89 117q16 60 -6 117t-72 91zM1664 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1024 1024q0 53 -37.5 90.5
+t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1472 832q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1792 384q0 -261 -141 -483q-19 -29 -54 -29h-1402q-35 0 -54 29
+q-141 221 -141 483q0 182 71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
+    <glyph glyph-name="comment_alt" unicode="&#xf0e5;" horiz-adv-x="1792" 
+d="M896 1152q-204 0 -381.5 -69.5t-282 -187.5t-104.5 -255q0 -112 71.5 -213.5t201.5 -175.5l87 -50l-27 -96q-24 -91 -70 -172q152 63 275 171l43 38l57 -6q69 -8 130 -8q204 0 381.5 69.5t282 187.5t104.5 255t-104.5 255t-282 187.5t-381.5 69.5zM1792 640
+q0 -174 -120 -321.5t-326 -233t-450 -85.5q-70 0 -145 8q-198 -175 -460 -242q-49 -14 -114 -22h-5q-15 0 -27 10.5t-16 27.5v1q-3 4 -0.5 12t2 10t4.5 9.5l6 9t7 8.5t8 9q7 8 31 34.5t34.5 38t31 39.5t32.5 51t27 59t26 76q-157 89 -247.5 220t-90.5 281q0 174 120 321.5
+t326 233t450 85.5t450 -85.5t326 -233t120 -321.5z" />
+    <glyph glyph-name="comments_alt" unicode="&#xf0e6;" horiz-adv-x="1792" 
+d="M704 1152q-153 0 -286 -52t-211.5 -141t-78.5 -191q0 -82 53 -158t149 -132l97 -56l-35 -84q34 20 62 39l44 31l53 -10q78 -14 153 -14q153 0 286 52t211.5 141t78.5 191t-78.5 191t-211.5 141t-286 52zM704 1280q191 0 353.5 -68.5t256.5 -186.5t94 -257t-94 -257
+t-256.5 -186.5t-353.5 -68.5q-86 0 -176 16q-124 -88 -278 -128q-36 -9 -86 -16h-3q-11 0 -20.5 8t-11.5 21q-1 3 -1 6.5t0.5 6.5t2 6l2.5 5t3.5 5.5t4 5t4.5 5t4 4.5q5 6 23 25t26 29.5t22.5 29t25 38.5t20.5 44q-124 72 -195 177t-71 224q0 139 94 257t256.5 186.5
+t353.5 68.5zM1526 111q10 -24 20.5 -44t25 -38.5t22.5 -29t26 -29.5t23 -25q1 -1 4 -4.5t4.5 -5t4 -5t3.5 -5.5l2.5 -5t2 -6t0.5 -6.5t-1 -6.5q-3 -14 -13 -22t-22 -7q-50 7 -86 16q-154 40 -278 128q-90 -16 -176 -16q-271 0 -472 132q58 -4 88 -4q161 0 309 45t264 129
+q125 92 192 212t67 254q0 77 -23 152q129 -71 204 -178t75 -230q0 -120 -71 -224.5t-195 -176.5z" />
+    <glyph glyph-name="bolt" unicode="&#xf0e7;" horiz-adv-x="896" 
+d="M885 970q18 -20 7 -44l-540 -1157q-13 -25 -42 -25q-4 0 -14 2q-17 5 -25.5 19t-4.5 30l197 808l-406 -101q-4 -1 -12 -1q-18 0 -31 11q-18 15 -13 39l201 825q4 14 16 23t28 9h328q19 0 32 -12.5t13 -29.5q0 -8 -5 -18l-171 -463l396 98q8 2 12 2q19 0 34 -15z" />
+    <glyph glyph-name="sitemap" unicode="&#xf0e8;" horiz-adv-x="1792" 
+d="M1792 288v-320q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h96v192h-512v-192h96q40 0 68 -28t28 -68v-320q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h96v192h-512v-192h96q40 0 68 -28t28 -68v-320
+q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h96v192q0 52 38 90t90 38h512v192h-96q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h320q40 0 68 -28t28 -68v-320q0 -40 -28 -68t-68 -28h-96v-192h512q52 0 90 -38t38 -90v-192h96q40 0 68 -28t28 -68
+z" />
+    <glyph glyph-name="umbrella" unicode="&#xf0e9;" horiz-adv-x="1664" 
+d="M896 708v-580q0 -104 -76 -180t-180 -76t-180 76t-76 180q0 26 19 45t45 19t45 -19t19 -45q0 -50 39 -89t89 -39t89 39t39 89v580q33 11 64 11t64 -11zM1664 681q0 -13 -9.5 -22.5t-22.5 -9.5q-11 0 -23 10q-49 46 -93 69t-102 23q-68 0 -128 -37t-103 -97
+q-7 -10 -17.5 -28t-14.5 -24q-11 -17 -28 -17q-18 0 -29 17q-4 6 -14.5 24t-17.5 28q-43 60 -102.5 97t-127.5 37t-127.5 -37t-102.5 -97q-7 -10 -17.5 -28t-14.5 -24q-11 -17 -29 -17q-17 0 -28 17q-4 6 -14.5 24t-17.5 28q-43 60 -103 97t-128 37q-58 0 -102 -23t-93 -69
+q-12 -10 -23 -10q-13 0 -22.5 9.5t-9.5 22.5q0 5 1 7q45 183 172.5 319.5t298 204.5t360.5 68q140 0 274.5 -40t246.5 -113.5t194.5 -187t115.5 -251.5q1 -2 1 -7zM896 1408v-98q-42 2 -64 2t-64 -2v98q0 26 19 45t45 19t45 -19t19 -45z" />
+    <glyph glyph-name="paste" unicode="&#xf0ea;" horiz-adv-x="1792" 
+d="M768 -128h896v640h-416q-40 0 -68 28t-28 68v416h-384v-1152zM1024 1312v64q0 13 -9.5 22.5t-22.5 9.5h-704q-13 0 -22.5 -9.5t-9.5 -22.5v-64q0 -13 9.5 -22.5t22.5 -9.5h704q13 0 22.5 9.5t9.5 22.5zM1280 640h299l-299 299v-299zM1792 512v-672q0 -40 -28 -68t-68 -28
+h-960q-40 0 -68 28t-28 68v160h-544q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h1088q40 0 68 -28t28 -68v-328q21 -13 36 -28l408 -408q28 -28 48 -76t20 -88z" />
+    <glyph glyph-name="light_bulb" unicode="&#xf0eb;" horiz-adv-x="1024" 
+d="M736 960q0 -13 -9.5 -22.5t-22.5 -9.5t-22.5 9.5t-9.5 22.5q0 46 -54 71t-106 25q-13 0 -22.5 9.5t-9.5 22.5t9.5 22.5t22.5 9.5q50 0 99.5 -16t87 -54t37.5 -90zM896 960q0 72 -34.5 134t-90 101.5t-123 62t-136.5 22.5t-136.5 -22.5t-123 -62t-90 -101.5t-34.5 -134
+q0 -101 68 -180q10 -11 30.5 -33t30.5 -33q128 -153 141 -298h228q13 145 141 298q10 11 30.5 33t30.5 33q68 79 68 180zM1024 960q0 -155 -103 -268q-45 -49 -74.5 -87t-59.5 -95.5t-34 -107.5q47 -28 47 -82q0 -37 -25 -64q25 -27 25 -64q0 -52 -45 -81q13 -23 13 -47
+q0 -46 -31.5 -71t-77.5 -25q-20 -44 -60 -70t-87 -26t-87 26t-60 70q-46 0 -77.5 25t-31.5 71q0 24 13 47q-45 29 -45 81q0 37 25 64q-25 27 -25 64q0 54 47 82q-4 50 -34 107.5t-59.5 95.5t-74.5 87q-103 113 -103 268q0 99 44.5 184.5t117 142t164 89t186.5 32.5
+t186.5 -32.5t164 -89t117 -142t44.5 -184.5z" />
+    <glyph glyph-name="exchange" unicode="&#xf0ec;" horiz-adv-x="1792" 
+d="M1792 352v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5q-12 0 -24 10l-319 320q-9 9 -9 22q0 14 9 23l320 320q9 9 23 9q13 0 22.5 -9.5t9.5 -22.5v-192h1376q13 0 22.5 -9.5t9.5 -22.5zM1792 896q0 -14 -9 -23l-320 -320q-9 -9 -23 -9
+q-13 0 -22.5 9.5t-9.5 22.5v192h-1376q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1376v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23z" />
+    <glyph glyph-name="cloud_download" unicode="&#xf0ed;" horiz-adv-x="1920" 
+d="M1280 608q0 14 -9 23t-23 9h-224v352q0 13 -9.5 22.5t-22.5 9.5h-192q-13 0 -22.5 -9.5t-9.5 -22.5v-352h-224q-13 0 -22.5 -9.5t-9.5 -22.5q0 -14 9 -23l352 -352q9 -9 23 -9t23 9l351 351q10 12 10 24zM1920 384q0 -159 -112.5 -271.5t-271.5 -112.5h-1088
+q-185 0 -316.5 131.5t-131.5 316.5q0 130 70 240t188 165q-2 30 -2 43q0 212 150 362t362 150q156 0 285.5 -87t188.5 -231q71 62 166 62q106 0 181 -75t75 -181q0 -76 -41 -138q130 -31 213.5 -135.5t83.5 -238.5z" />
+    <glyph glyph-name="cloud_upload" unicode="&#xf0ee;" horiz-adv-x="1920" 
+d="M1280 672q0 14 -9 23l-352 352q-9 9 -23 9t-23 -9l-351 -351q-10 -12 -10 -24q0 -14 9 -23t23 -9h224v-352q0 -13 9.5 -22.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 22.5v352h224q13 0 22.5 9.5t9.5 22.5zM1920 384q0 -159 -112.5 -271.5t-271.5 -112.5h-1088
+q-185 0 -316.5 131.5t-131.5 316.5q0 130 70 240t188 165q-2 30 -2 43q0 212 150 362t362 150q156 0 285.5 -87t188.5 -231q71 62 166 62q106 0 181 -75t75 -181q0 -76 -41 -138q130 -31 213.5 -135.5t83.5 -238.5z" />
+    <glyph glyph-name="user_md" unicode="&#xf0f0;" horiz-adv-x="1408" 
+d="M384 192q0 -26 -19 -45t-45 -19t-45 19t-19 45t19 45t45 19t45 -19t19 -45zM1408 131q0 -121 -73 -190t-194 -69h-874q-121 0 -194 69t-73 190q0 68 5.5 131t24 138t47.5 132.5t81 103t120 60.5q-22 -52 -22 -120v-203q-58 -20 -93 -70t-35 -111q0 -80 56 -136t136 -56
+t136 56t56 136q0 61 -35.5 111t-92.5 70v203q0 62 25 93q132 -104 295 -104t295 104q25 -31 25 -93v-64q-106 0 -181 -75t-75 -181v-89q-32 -29 -32 -71q0 -40 28 -68t68 -28t68 28t28 68q0 42 -32 71v89q0 52 38 90t90 38t90 -38t38 -90v-89q-32 -29 -32 -71q0 -40 28 -68
+t68 -28t68 28t28 68q0 42 -32 71v89q0 68 -34.5 127.5t-93.5 93.5q0 10 0.5 42.5t0 48t-2.5 41.5t-7 47t-13 40q68 -15 120 -60.5t81 -103t47.5 -132.5t24 -138t5.5 -131zM1088 1024q0 -159 -112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5
+t271.5 -112.5t112.5 -271.5z" />
+    <glyph glyph-name="stethoscope" unicode="&#xf0f1;" horiz-adv-x="1408" 
+d="M1280 832q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 832q0 -62 -35.5 -111t-92.5 -70v-395q0 -159 -131.5 -271.5t-316.5 -112.5t-316.5 112.5t-131.5 271.5v132q-164 20 -274 128t-110 252v512q0 26 19 45t45 19q6 0 16 -2q17 30 47 48
+t65 18q53 0 90.5 -37.5t37.5 -90.5t-37.5 -90.5t-90.5 -37.5q-33 0 -64 18v-402q0 -106 94 -181t226 -75t226 75t94 181v402q-31 -18 -64 -18q-53 0 -90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5q35 0 65 -18t47 -48q10 2 16 2q26 0 45 -19t19 -45v-512q0 -144 -110 -252
+t-274 -128v-132q0 -106 94 -181t226 -75t226 75t94 181v395q-57 21 -92.5 70t-35.5 111q0 80 56 136t136 56t136 -56t56 -136z" />
+    <glyph glyph-name="suitcase" unicode="&#xf0f2;" horiz-adv-x="1792" 
+d="M640 1152h512v128h-512v-128zM288 1152v-1280h-64q-92 0 -158 66t-66 158v832q0 92 66 158t158 66h64zM1408 1152v-1280h-1024v1280h128v160q0 40 28 68t68 28h576q40 0 68 -28t28 -68v-160h128zM1792 928v-832q0 -92 -66 -158t-158 -66h-64v1280h64q92 0 158 -66
+t66 -158z" />
+    <glyph glyph-name="bell_alt" unicode="&#xf0f3;" horiz-adv-x="1792" 
+d="M912 -160q0 16 -16 16q-59 0 -101.5 42.5t-42.5 101.5q0 16 -16 16t-16 -16q0 -73 51.5 -124.5t124.5 -51.5q16 0 16 16zM1728 128q0 -52 -38 -90t-90 -38h-448q0 -106 -75 -181t-181 -75t-181 75t-75 181h-448q-52 0 -90 38t-38 90q50 42 91 88t85 119.5t74.5 158.5
+t50 206t19.5 260q0 152 117 282.5t307 158.5q-8 19 -8 39q0 40 28 68t68 28t68 -28t28 -68q0 -20 -8 -39q190 -28 307 -158.5t117 -282.5q0 -139 19.5 -260t50 -206t74.5 -158.5t85 -119.5t91 -88z" />
+    <glyph glyph-name="coffee" unicode="&#xf0f4;" horiz-adv-x="1920" 
+d="M1664 896q0 80 -56 136t-136 56h-64v-384h64q80 0 136 56t56 136zM0 128h1792q0 -106 -75 -181t-181 -75h-1280q-106 0 -181 75t-75 181zM1856 896q0 -159 -112.5 -271.5t-271.5 -112.5h-64v-32q0 -92 -66 -158t-158 -66h-704q-92 0 -158 66t-66 158v736q0 26 19 45
+t45 19h1152q159 0 271.5 -112.5t112.5 -271.5z" />
+    <glyph glyph-name="food" unicode="&#xf0f5;" horiz-adv-x="1408" 
+d="M640 1472v-640q0 -61 -35.5 -111t-92.5 -70v-779q0 -52 -38 -90t-90 -38h-128q-52 0 -90 38t-38 90v779q-57 20 -92.5 70t-35.5 111v640q0 26 19 45t45 19t45 -19t19 -45v-416q0 -26 19 -45t45 -19t45 19t19 45v416q0 26 19 45t45 19t45 -19t19 -45v-416q0 -26 19 -45
+t45 -19t45 19t19 45v416q0 26 19 45t45 19t45 -19t19 -45zM1408 1472v-1600q0 -52 -38 -90t-90 -38h-128q-52 0 -90 38t-38 90v512h-224q-13 0 -22.5 9.5t-9.5 22.5v800q0 132 94 226t226 94h256q26 0 45 -19t19 -45z" />
+    <glyph glyph-name="file_text_alt" unicode="&#xf0f6;" 
+d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z
+M384 736q0 14 9 23t23 9h704q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-704q-14 0 -23 9t-9 23v64zM1120 512q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-704q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h704zM1120 256q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-704
+q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h704z" />
+    <glyph glyph-name="building" unicode="&#xf0f7;" horiz-adv-x="1408" 
+d="M384 224v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z
+M640 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z
+M1152 224v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM896 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z
+M640 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 992v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z
+M1152 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM896 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z
+M640 992v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 1248v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z
+M1152 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM896 992v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z
+M640 1248v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1152 992v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z
+M896 1248v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1152 1248v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z
+M896 -128h384v1536h-1152v-1536h384v224q0 13 9.5 22.5t22.5 9.5h320q13 0 22.5 -9.5t9.5 -22.5v-224zM1408 1472v-1664q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v1664q0 26 19 45t45 19h1280q26 0 45 -19t19 -45z" />
+    <glyph glyph-name="hospital" unicode="&#xf0f8;" horiz-adv-x="1408" 
+d="M384 224v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z
+M640 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z
+M1152 224v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM896 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z
+M640 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1152 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z
+M896 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1152 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z
+M896 -128h384v1152h-256v-32q0 -40 -28 -68t-68 -28h-448q-40 0 -68 28t-28 68v32h-256v-1152h384v224q0 13 9.5 22.5t22.5 9.5h320q13 0 22.5 -9.5t9.5 -22.5v-224zM896 1056v320q0 13 -9.5 22.5t-22.5 9.5h-64q-13 0 -22.5 -9.5t-9.5 -22.5v-96h-128v96q0 13 -9.5 22.5
+t-22.5 9.5h-64q-13 0 -22.5 -9.5t-9.5 -22.5v-320q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5v96h128v-96q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5zM1408 1088v-1280q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v1280q0 26 19 45t45 19h320
+v288q0 40 28 68t68 28h448q40 0 68 -28t28 -68v-288h320q26 0 45 -19t19 -45z" />
+    <glyph glyph-name="ambulance" unicode="&#xf0f9;" horiz-adv-x="1920" 
+d="M640 128q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM256 640h384v256h-158q-14 -2 -22 -9l-195 -195q-7 -12 -9 -22v-30zM1536 128q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5
+t90.5 37.5t37.5 90.5zM1664 800v192q0 14 -9 23t-23 9h-224v224q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-224h-224q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h224v-224q0 -14 9 -23t23 -9h192q14 0 23 9t9 23v224h224q14 0 23 9t9 23zM1920 1344v-1152
+q0 -26 -19 -45t-45 -19h-192q0 -106 -75 -181t-181 -75t-181 75t-75 181h-384q0 -106 -75 -181t-181 -75t-181 75t-75 181h-128q-26 0 -45 19t-19 45t19 45t45 19v416q0 26 13 58t32 51l198 198q19 19 51 32t58 13h160v320q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" />
+    <glyph glyph-name="medkit" unicode="&#xf0fa;" horiz-adv-x="1792" 
+d="M1280 416v192q0 14 -9 23t-23 9h-224v224q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-224h-224q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h224v-224q0 -14 9 -23t23 -9h192q14 0 23 9t9 23v224h224q14 0 23 9t9 23zM640 1152h512v128h-512v-128zM256 1152v-1280h-32
+q-92 0 -158 66t-66 158v832q0 92 66 158t158 66h32zM1440 1152v-1280h-1088v1280h160v160q0 40 28 68t68 28h576q40 0 68 -28t28 -68v-160h160zM1792 928v-832q0 -92 -66 -158t-158 -66h-32v1280h32q92 0 158 -66t66 -158z" />
+    <glyph glyph-name="fighter_jet" unicode="&#xf0fb;" horiz-adv-x="1920" 
+d="M1920 576q-1 -32 -288 -96l-352 -32l-224 -64h-64l-293 -352h69q26 0 45 -4.5t19 -11.5t-19 -11.5t-45 -4.5h-96h-160h-64v32h64v416h-160l-192 -224h-96l-32 32v192h32v32h128v8l-192 24v128l192 24v8h-128v32h-32v192l32 32h96l192 -224h160v416h-64v32h64h160h96
+q26 0 45 -4.5t19 -11.5t-19 -11.5t-45 -4.5h-69l293 -352h64l224 -64l352 -32q128 -28 200 -52t80 -34z" />
+    <glyph glyph-name="beer" unicode="&#xf0fc;" horiz-adv-x="1664" 
+d="M640 640v384h-256v-256q0 -53 37.5 -90.5t90.5 -37.5h128zM1664 192v-192h-1152v192l128 192h-128q-159 0 -271.5 112.5t-112.5 271.5v320l-64 64l32 128h480l32 128h960l32 -192l-64 -32v-800z" />
+    <glyph glyph-name="h_sign" unicode="&#xf0fd;" 
+d="M1280 192v896q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-320h-512v320q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-896q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v320h512v-320q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1536 1120v-960
+q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="f0fe" unicode="&#xf0fe;" 
+d="M1280 576v128q0 26 -19 45t-45 19h-320v320q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-320h-320q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h320v-320q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v320h320q26 0 45 19t19 45zM1536 1120v-960
+q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="double_angle_left" unicode="&#xf100;" horiz-adv-x="1024" 
+d="M627 160q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23t-10 -23l-393 -393l393 -393q10 -10 10 -23zM1011 160q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23
+t10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23t-10 -23l-393 -393l393 -393q10 -10 10 -23z" />
+    <glyph glyph-name="double_angle_right" unicode="&#xf101;" horiz-adv-x="1024" 
+d="M595 576q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23zM979 576q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23
+l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" />
+    <glyph glyph-name="double_angle_up" unicode="&#xf102;" horiz-adv-x="1152" 
+d="M1075 224q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-393 393l-393 -393q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l466 -466q10 -10 10 -23zM1075 608q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-393 393l-393 -393
+q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" />
+    <glyph glyph-name="double_angle_down" unicode="&#xf103;" horiz-adv-x="1152" 
+d="M1075 672q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l393 -393l393 393q10 10 23 10t23 -10l50 -50q10 -10 10 -23zM1075 1056q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23
+t10 23l50 50q10 10 23 10t23 -10l393 -393l393 393q10 10 23 10t23 -10l50 -50q10 -10 10 -23z" />
+    <glyph glyph-name="angle_left" unicode="&#xf104;" horiz-adv-x="640" 
+d="M627 992q0 -13 -10 -23l-393 -393l393 -393q10 -10 10 -23t-10 -23l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23z" />
+    <glyph glyph-name="angle_right" unicode="&#xf105;" horiz-adv-x="640" 
+d="M595 576q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" />
+    <glyph glyph-name="angle_up" unicode="&#xf106;" horiz-adv-x="1152" 
+d="M1075 352q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-393 393l-393 -393q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" />
+    <glyph glyph-name="angle_down" unicode="&#xf107;" horiz-adv-x="1152" 
+d="M1075 800q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l393 -393l393 393q10 10 23 10t23 -10l50 -50q10 -10 10 -23z" />
+    <glyph glyph-name="desktop" unicode="&#xf108;" horiz-adv-x="1920" 
+d="M1792 544v832q0 13 -9.5 22.5t-22.5 9.5h-1600q-13 0 -22.5 -9.5t-9.5 -22.5v-832q0 -13 9.5 -22.5t22.5 -9.5h1600q13 0 22.5 9.5t9.5 22.5zM1920 1376v-1088q0 -66 -47 -113t-113 -47h-544q0 -37 16 -77.5t32 -71t16 -43.5q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19
+t-19 45q0 14 16 44t32 70t16 78h-544q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" />
+    <glyph glyph-name="laptop" unicode="&#xf109;" horiz-adv-x="1920" 
+d="M416 256q-66 0 -113 47t-47 113v704q0 66 47 113t113 47h1088q66 0 113 -47t47 -113v-704q0 -66 -47 -113t-113 -47h-1088zM384 1120v-704q0 -13 9.5 -22.5t22.5 -9.5h1088q13 0 22.5 9.5t9.5 22.5v704q0 13 -9.5 22.5t-22.5 9.5h-1088q-13 0 -22.5 -9.5t-9.5 -22.5z
+M1760 192h160v-96q0 -40 -47 -68t-113 -28h-1600q-66 0 -113 28t-47 68v96h160h1600zM1040 96q16 0 16 16t-16 16h-160q-16 0 -16 -16t16 -16h160z" />
+    <glyph glyph-name="tablet" unicode="&#xf10a;" horiz-adv-x="1152" 
+d="M640 128q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1024 288v960q0 13 -9.5 22.5t-22.5 9.5h-832q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h832q13 0 22.5 9.5t9.5 22.5zM1152 1248v-1088q0 -66 -47 -113t-113 -47h-832
+q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h832q66 0 113 -47t47 -113z" />
+    <glyph glyph-name="mobile_phone" unicode="&#xf10b;" horiz-adv-x="768" 
+d="M464 128q0 33 -23.5 56.5t-56.5 23.5t-56.5 -23.5t-23.5 -56.5t23.5 -56.5t56.5 -23.5t56.5 23.5t23.5 56.5zM672 288v704q0 13 -9.5 22.5t-22.5 9.5h-512q-13 0 -22.5 -9.5t-9.5 -22.5v-704q0 -13 9.5 -22.5t22.5 -9.5h512q13 0 22.5 9.5t9.5 22.5zM480 1136
+q0 16 -16 16h-160q-16 0 -16 -16t16 -16h160q16 0 16 16zM768 1152v-1024q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v1024q0 52 38 90t90 38h512q52 0 90 -38t38 -90z" />
+    <glyph glyph-name="circle_blank" unicode="&#xf10c;" 
+d="M768 1184q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273t-73 273t-198 198t-273 73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103
+t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="quote_left" unicode="&#xf10d;" horiz-adv-x="1664" 
+d="M768 576v-384q0 -80 -56 -136t-136 -56h-384q-80 0 -136 56t-56 136v704q0 104 40.5 198.5t109.5 163.5t163.5 109.5t198.5 40.5h64q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-64q-106 0 -181 -75t-75 -181v-32q0 -40 28 -68t68 -28h224q80 0 136 -56t56 -136z
+M1664 576v-384q0 -80 -56 -136t-136 -56h-384q-80 0 -136 56t-56 136v704q0 104 40.5 198.5t109.5 163.5t163.5 109.5t198.5 40.5h64q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-64q-106 0 -181 -75t-75 -181v-32q0 -40 28 -68t68 -28h224q80 0 136 -56t56 -136z" />
+    <glyph glyph-name="quote_right" unicode="&#xf10e;" horiz-adv-x="1664" 
+d="M768 1216v-704q0 -104 -40.5 -198.5t-109.5 -163.5t-163.5 -109.5t-198.5 -40.5h-64q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h64q106 0 181 75t75 181v32q0 40 -28 68t-68 28h-224q-80 0 -136 56t-56 136v384q0 80 56 136t136 56h384q80 0 136 -56t56 -136zM1664 1216
+v-704q0 -104 -40.5 -198.5t-109.5 -163.5t-163.5 -109.5t-198.5 -40.5h-64q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h64q106 0 181 75t75 181v32q0 40 -28 68t-68 28h-224q-80 0 -136 56t-56 136v384q0 80 56 136t136 56h384q80 0 136 -56t56 -136z" />
+    <glyph glyph-name="spinner" unicode="&#xf110;" horiz-adv-x="1792" 
+d="M526 142q0 -53 -37.5 -90.5t-90.5 -37.5q-52 0 -90 38t-38 90q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1024 -64q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM320 640q0 -53 -37.5 -90.5t-90.5 -37.5
+t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1522 142q0 -52 -38 -90t-90 -38q-53 0 -90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM558 1138q0 -66 -47 -113t-113 -47t-113 47t-47 113t47 113t113 47t113 -47t47 -113z
+M1728 640q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1088 1344q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1618 1138q0 -93 -66 -158.5t-158 -65.5q-93 0 -158.5 65.5t-65.5 158.5
+q0 92 65.5 158t158.5 66q92 0 158 -66t66 -158z" />
+    <glyph glyph-name="circle" unicode="&#xf111;" 
+d="M1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="reply" unicode="&#xf112;" horiz-adv-x="1792" 
+d="M1792 416q0 -166 -127 -451q-3 -7 -10.5 -24t-13.5 -30t-13 -22q-12 -17 -28 -17q-15 0 -23.5 10t-8.5 25q0 9 2.5 26.5t2.5 23.5q5 68 5 123q0 101 -17.5 181t-48.5 138.5t-80 101t-105.5 69.5t-133 42.5t-154 21.5t-175.5 6h-224v-256q0 -26 -19 -45t-45 -19t-45 19
+l-512 512q-19 19 -19 45t19 45l512 512q19 19 45 19t45 -19t19 -45v-256h224q713 0 875 -403q53 -134 53 -333z" />
+    <glyph glyph-name="github_alt" unicode="&#xf113;" horiz-adv-x="1664" 
+d="M640 320q0 -40 -12.5 -82t-43 -76t-72.5 -34t-72.5 34t-43 76t-12.5 82t12.5 82t43 76t72.5 34t72.5 -34t43 -76t12.5 -82zM1280 320q0 -40 -12.5 -82t-43 -76t-72.5 -34t-72.5 34t-43 76t-12.5 82t12.5 82t43 76t72.5 34t72.5 -34t43 -76t12.5 -82zM1440 320
+q0 120 -69 204t-187 84q-41 0 -195 -21q-71 -11 -157 -11t-157 11q-152 21 -195 21q-118 0 -187 -84t-69 -204q0 -88 32 -153.5t81 -103t122 -60t140 -29.5t149 -7h168q82 0 149 7t140 29.5t122 60t81 103t32 153.5zM1664 496q0 -207 -61 -331q-38 -77 -105.5 -133t-141 -86
+t-170 -47.5t-171.5 -22t-167 -4.5q-78 0 -142 3t-147.5 12.5t-152.5 30t-137 51.5t-121 81t-86 115q-62 123 -62 331q0 237 136 396q-27 82 -27 170q0 116 51 218q108 0 190 -39.5t189 -123.5q147 35 309 35q148 0 280 -32q105 82 187 121t189 39q51 -102 51 -218
+q0 -87 -27 -168q136 -160 136 -398z" />
+    <glyph glyph-name="folder_close_alt" unicode="&#xf114;" horiz-adv-x="1664" 
+d="M1536 224v704q0 40 -28 68t-68 28h-704q-40 0 -68 28t-28 68v64q0 40 -28 68t-68 28h-320q-40 0 -68 -28t-28 -68v-960q0 -40 28 -68t68 -28h1216q40 0 68 28t28 68zM1664 928v-704q0 -92 -66 -158t-158 -66h-1216q-92 0 -158 66t-66 158v960q0 92 66 158t158 66h320
+q92 0 158 -66t66 -158v-32h672q92 0 158 -66t66 -158z" />
+    <glyph glyph-name="folder_open_alt" unicode="&#xf115;" horiz-adv-x="1920" 
+d="M1781 605q0 35 -53 35h-1088q-40 0 -85.5 -21.5t-71.5 -52.5l-294 -363q-18 -24 -18 -40q0 -35 53 -35h1088q40 0 86 22t71 53l294 363q18 22 18 39zM640 768h768v160q0 40 -28 68t-68 28h-576q-40 0 -68 28t-28 68v64q0 40 -28 68t-68 28h-320q-40 0 -68 -28t-28 -68
+v-853l256 315q44 53 116 87.5t140 34.5zM1909 605q0 -62 -46 -120l-295 -363q-43 -53 -116 -87.5t-140 -34.5h-1088q-92 0 -158 66t-66 158v960q0 92 66 158t158 66h320q92 0 158 -66t66 -158v-32h544q92 0 158 -66t66 -158v-160h192q54 0 99 -24.5t67 -70.5q15 -32 15 -68z
+" />
+    <glyph glyph-name="expand_alt" unicode="&#xf116;" horiz-adv-x="1792" 
+ />
+    <glyph glyph-name="collapse_alt" unicode="&#xf117;" horiz-adv-x="1792" 
+ />
+    <glyph glyph-name="smile" unicode="&#xf118;" 
+d="M1134 461q-37 -121 -138 -195t-228 -74t-228 74t-138 195q-8 25 4 48.5t38 31.5q25 8 48.5 -4t31.5 -38q25 -80 92.5 -129.5t151.5 -49.5t151.5 49.5t92.5 129.5q8 26 32 38t49 4t37 -31.5t4 -48.5zM640 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5
+t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1152 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1408 640q0 130 -51 248.5t-136.5 204t-204 136.5t-248.5 51t-248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5
+t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="frown" unicode="&#xf119;" 
+d="M1134 307q8 -25 -4 -48.5t-37 -31.5t-49 4t-32 38q-25 80 -92.5 129.5t-151.5 49.5t-151.5 -49.5t-92.5 -129.5q-8 -26 -31.5 -38t-48.5 -4q-26 8 -38 31.5t-4 48.5q37 121 138 195t228 74t228 -74t138 -195zM640 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5
+t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1152 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1408 640q0 130 -51 248.5t-136.5 204t-204 136.5t-248.5 51t-248.5 -51t-204 -136.5t-136.5 -204
+t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="meh" unicode="&#xf11a;" 
+d="M1152 448q0 -26 -19 -45t-45 -19h-640q-26 0 -45 19t-19 45t19 45t45 19h640q26 0 45 -19t19 -45zM640 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1152 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5
+t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1408 640q0 130 -51 248.5t-136.5 204t-204 136.5t-248.5 51t-248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5zM1536 640
+q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="gamepad" unicode="&#xf11b;" horiz-adv-x="1920" 
+d="M832 448v128q0 14 -9 23t-23 9h-192v192q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-192h-192q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h192v-192q0 -14 9 -23t23 -9h128q14 0 23 9t9 23v192h192q14 0 23 9t9 23zM1408 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5
+t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1664 640q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1920 512q0 -212 -150 -362t-362 -150q-192 0 -338 128h-220q-146 -128 -338 -128q-212 0 -362 150
+t-150 362t150 362t362 150h896q212 0 362 -150t150 -362z" />
+    <glyph glyph-name="keyboard" unicode="&#xf11c;" horiz-adv-x="1920" 
+d="M384 368v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM512 624v-96q0 -16 -16 -16h-224q-16 0 -16 16v96q0 16 16 16h224q16 0 16 -16zM384 880v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1408 368v-96q0 -16 -16 -16
+h-864q-16 0 -16 16v96q0 16 16 16h864q16 0 16 -16zM768 624v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM640 880v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1024 624v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16
+h96q16 0 16 -16zM896 880v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1280 624v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1664 368v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1152 880v-96
+q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1408 880v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1664 880v-352q0 -16 -16 -16h-224q-16 0 -16 16v96q0 16 16 16h112v240q0 16 16 16h96q16 0 16 -16zM1792 128v896h-1664v-896
+h1664zM1920 1024v-896q0 -53 -37.5 -90.5t-90.5 -37.5h-1664q-53 0 -90.5 37.5t-37.5 90.5v896q0 53 37.5 90.5t90.5 37.5h1664q53 0 90.5 -37.5t37.5 -90.5z" />
+    <glyph glyph-name="flag_alt" unicode="&#xf11d;" horiz-adv-x="1792" 
+d="M1664 491v616q-169 -91 -306 -91q-82 0 -145 32q-100 49 -184 76.5t-178 27.5q-173 0 -403 -127v-599q245 113 433 113q55 0 103.5 -7.5t98 -26t77 -31t82.5 -39.5l28 -14q44 -22 101 -22q120 0 293 92zM320 1280q0 -35 -17.5 -64t-46.5 -46v-1266q0 -14 -9 -23t-23 -9
+h-64q-14 0 -23 9t-9 23v1266q-29 17 -46.5 46t-17.5 64q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1792 1216v-763q0 -39 -35 -57q-10 -5 -17 -9q-218 -116 -369 -116q-88 0 -158 35l-28 14q-64 33 -99 48t-91 29t-114 14q-102 0 -235.5 -44t-228.5 -102
+q-15 -9 -33 -9q-16 0 -32 8q-32 19 -32 56v742q0 35 31 55q35 21 78.5 42.5t114 52t152.5 49.5t155 19q112 0 209 -31t209 -86q38 -19 89 -19q122 0 310 112q22 12 31 17q31 16 62 -2q31 -20 31 -55z" />
+    <glyph glyph-name="flag_checkered" unicode="&#xf11e;" horiz-adv-x="1792" 
+d="M832 536v192q-181 -16 -384 -117v-185q205 96 384 110zM832 954v197q-172 -8 -384 -126v-189q215 111 384 118zM1664 491v184q-235 -116 -384 -71v224q-20 6 -39 15q-5 3 -33 17t-34.5 17t-31.5 15t-34.5 15.5t-32.5 13t-36 12.5t-35 8.5t-39.5 7.5t-39.5 4t-44 2
+q-23 0 -49 -3v-222h19q102 0 192.5 -29t197.5 -82q19 -9 39 -15v-188q42 -17 91 -17q120 0 293 92zM1664 918v189q-169 -91 -306 -91q-45 0 -78 8v-196q148 -42 384 90zM320 1280q0 -35 -17.5 -64t-46.5 -46v-1266q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v1266
+q-29 17 -46.5 46t-17.5 64q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1792 1216v-763q0 -39 -35 -57q-10 -5 -17 -9q-218 -116 -369 -116q-88 0 -158 35l-28 14q-64 33 -99 48t-91 29t-114 14q-102 0 -235.5 -44t-228.5 -102q-15 -9 -33 -9q-16 0 -32 8
+q-32 19 -32 56v742q0 35 31 55q35 21 78.5 42.5t114 52t152.5 49.5t155 19q112 0 209 -31t209 -86q38 -19 89 -19q122 0 310 112q22 12 31 17q31 16 62 -2q31 -20 31 -55z" />
+    <glyph glyph-name="terminal" unicode="&#xf120;" horiz-adv-x="1664" 
+d="M585 553l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23t-10 -23zM1664 96v-64q0 -14 -9 -23t-23 -9h-960q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h960q14 0 23 -9
+t9 -23z" />
+    <glyph glyph-name="code" unicode="&#xf121;" horiz-adv-x="1920" 
+d="M617 137l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23t-10 -23l-393 -393l393 -393q10 -10 10 -23t-10 -23zM1208 1204l-373 -1291q-4 -13 -15.5 -19.5t-23.5 -2.5l-62 17q-13 4 -19.5 15.5t-2.5 24.5
+l373 1291q4 13 15.5 19.5t23.5 2.5l62 -17q13 -4 19.5 -15.5t2.5 -24.5zM1865 553l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23t-10 -23z" />
+    <glyph glyph-name="reply_all" unicode="&#xf122;" horiz-adv-x="1792" 
+d="M640 454v-70q0 -42 -39 -59q-13 -5 -25 -5q-27 0 -45 19l-512 512q-19 19 -19 45t19 45l512 512q29 31 70 14q39 -17 39 -59v-69l-397 -398q-19 -19 -19 -45t19 -45zM1792 416q0 -58 -17 -133.5t-38.5 -138t-48 -125t-40.5 -90.5l-20 -40q-8 -17 -28 -17q-6 0 -9 1
+q-25 8 -23 34q43 400 -106 565q-64 71 -170.5 110.5t-267.5 52.5v-251q0 -42 -39 -59q-13 -5 -25 -5q-27 0 -45 19l-512 512q-19 19 -19 45t19 45l512 512q29 31 70 14q39 -17 39 -59v-262q411 -28 599 -221q169 -173 169 -509z" />
+    <glyph glyph-name="star_half_empty" unicode="&#xf123;" horiz-adv-x="1664" 
+d="M1186 579l257 250l-356 52l-66 10l-30 60l-159 322v-963l59 -31l318 -168l-60 355l-12 66zM1638 841l-363 -354l86 -500q5 -33 -6 -51.5t-34 -18.5q-17 0 -40 12l-449 236l-449 -236q-23 -12 -40 -12q-23 0 -34 18.5t-6 51.5l86 500l-364 354q-32 32 -23 59.5t54 34.5
+l502 73l225 455q20 41 49 41q28 0 49 -41l225 -455l502 -73q45 -7 54 -34.5t-24 -59.5z" />
+    <glyph glyph-name="location_arrow" unicode="&#xf124;" horiz-adv-x="1408" 
+d="M1401 1187l-640 -1280q-17 -35 -57 -35q-5 0 -15 2q-22 5 -35.5 22.5t-13.5 39.5v576h-576q-22 0 -39.5 13.5t-22.5 35.5t4 42t29 30l1280 640q13 7 29 7q27 0 45 -19q15 -14 18.5 -34.5t-6.5 -39.5z" />
+    <glyph glyph-name="crop" unicode="&#xf125;" horiz-adv-x="1664" 
+d="M557 256h595v595zM512 301l595 595h-595v-595zM1664 224v-192q0 -14 -9 -23t-23 -9h-224v-224q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v224h-864q-14 0 -23 9t-9 23v864h-224q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h224v224q0 14 9 23t23 9h192q14 0 23 -9t9 -23
+v-224h851l246 247q10 9 23 9t23 -9q9 -10 9 -23t-9 -23l-247 -246v-851h224q14 0 23 -9t9 -23z" />
+    <glyph glyph-name="code_fork" unicode="&#xf126;" horiz-adv-x="1024" 
+d="M288 64q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM288 1216q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM928 1088q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM1024 1088q0 -52 -26 -96.5t-70 -69.5
+q-2 -287 -226 -414q-67 -38 -203 -81q-128 -40 -169.5 -71t-41.5 -100v-26q44 -25 70 -69.5t26 -96.5q0 -80 -56 -136t-136 -56t-136 56t-56 136q0 52 26 96.5t70 69.5v820q-44 25 -70 69.5t-26 96.5q0 80 56 136t136 56t136 -56t56 -136q0 -52 -26 -96.5t-70 -69.5v-497
+q54 26 154 57q55 17 87.5 29.5t70.5 31t59 39.5t40.5 51t28 69.5t8.5 91.5q-44 25 -70 69.5t-26 96.5q0 80 56 136t136 56t136 -56t56 -136z" />
+    <glyph glyph-name="unlink" unicode="&#xf127;" horiz-adv-x="1664" 
+d="M439 265l-256 -256q-11 -9 -23 -9t-23 9q-9 10 -9 23t9 23l256 256q10 9 23 9t23 -9q9 -10 9 -23t-9 -23zM608 224v-320q0 -14 -9 -23t-23 -9t-23 9t-9 23v320q0 14 9 23t23 9t23 -9t9 -23zM384 448q0 -14 -9 -23t-23 -9h-320q-14 0 -23 9t-9 23t9 23t23 9h320
+q14 0 23 -9t9 -23zM1648 320q0 -120 -85 -203l-147 -146q-83 -83 -203 -83q-121 0 -204 85l-334 335q-21 21 -42 56l239 18l273 -274q27 -27 68 -27.5t68 26.5l147 146q28 28 28 67q0 40 -28 68l-274 275l18 239q35 -21 56 -42l336 -336q84 -86 84 -204zM1031 1044l-239 -18
+l-273 274q-28 28 -68 28q-39 0 -68 -27l-147 -146q-28 -28 -28 -67q0 -40 28 -68l274 -274l-18 -240q-35 21 -56 42l-336 336q-84 86 -84 204q0 120 85 203l147 146q83 83 203 83q121 0 204 -85l334 -335q21 -21 42 -56zM1664 960q0 -14 -9 -23t-23 -9h-320q-14 0 -23 9
+t-9 23t9 23t23 9h320q14 0 23 -9t9 -23zM1120 1504v-320q0 -14 -9 -23t-23 -9t-23 9t-9 23v320q0 14 9 23t23 9t23 -9t9 -23zM1527 1353l-256 -256q-11 -9 -23 -9t-23 9q-9 10 -9 23t9 23l256 256q10 9 23 9t23 -9q9 -10 9 -23t-9 -23z" />
+    <glyph glyph-name="question" unicode="&#xf128;" horiz-adv-x="1024" 
+d="M704 280v-240q0 -16 -12 -28t-28 -12h-240q-16 0 -28 12t-12 28v240q0 16 12 28t28 12h240q16 0 28 -12t12 -28zM1020 880q0 -54 -15.5 -101t-35 -76.5t-55 -59.5t-57.5 -43.5t-61 -35.5q-41 -23 -68.5 -65t-27.5 -67q0 -17 -12 -32.5t-28 -15.5h-240q-15 0 -25.5 18.5
+t-10.5 37.5v45q0 83 65 156.5t143 108.5q59 27 84 56t25 76q0 42 -46.5 74t-107.5 32q-65 0 -108 -29q-35 -25 -107 -115q-13 -16 -31 -16q-12 0 -25 8l-164 125q-13 10 -15.5 25t5.5 28q160 266 464 266q80 0 161 -31t146 -83t106 -127.5t41 -158.5z" />
+    <glyph glyph-name="_279" unicode="&#xf129;" horiz-adv-x="640" 
+d="M640 192v-128q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h64v384h-64q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h384q26 0 45 -19t19 -45v-576h64q26 0 45 -19t19 -45zM512 1344v-192q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v192
+q0 26 19 45t45 19h256q26 0 45 -19t19 -45z" />
+    <glyph glyph-name="exclamation" unicode="&#xf12a;" horiz-adv-x="640" 
+d="M512 288v-224q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v224q0 26 19 45t45 19h256q26 0 45 -19t19 -45zM542 1344l-28 -768q-1 -26 -20.5 -45t-45.5 -19h-256q-26 0 -45.5 19t-20.5 45l-28 768q-1 26 17.5 45t44.5 19h320q26 0 44.5 -19t17.5 -45z" />
+    <glyph glyph-name="superscript" unicode="&#xf12b;" 
+d="M897 167v-167h-248l-159 252l-24 42q-8 9 -11 21h-3q-1 -3 -2.5 -6.5t-3.5 -8t-3 -6.5q-10 -20 -25 -44l-155 -250h-258v167h128l197 291l-185 272h-137v168h276l139 -228q2 -4 23 -42q8 -9 11 -21h3q3 9 11 21l25 42l140 228h257v-168h-125l-184 -267l204 -296h109z
+M1534 846v-206h-514l-3 27q-4 28 -4 46q0 64 26 117t65 86.5t84 65t84 54.5t65 54t26 64q0 38 -29.5 62.5t-70.5 24.5q-51 0 -97 -39q-14 -11 -36 -38l-105 92q26 37 63 66q83 65 188 65q110 0 178 -59.5t68 -158.5q0 -56 -24.5 -103t-62 -76.5t-81.5 -58.5t-82 -50.5
+t-65.5 -51.5t-30.5 -63h232v80h126z" />
+    <glyph glyph-name="subscript" unicode="&#xf12c;" 
+d="M897 167v-167h-248l-159 252l-24 42q-8 9 -11 21h-3q-1 -3 -2.5 -6.5t-3.5 -8t-3 -6.5q-10 -20 -25 -44l-155 -250h-258v167h128l197 291l-185 272h-137v168h276l139 -228q2 -4 23 -42q8 -9 11 -21h3q3 9 11 21l25 42l140 228h257v-168h-125l-184 -267l204 -296h109z
+M1536 -50v-206h-514l-4 27q-3 45 -3 46q0 64 26 117t65 86.5t84 65t84 54.5t65 54t26 64q0 38 -29.5 62.5t-70.5 24.5q-51 0 -97 -39q-14 -11 -36 -38l-105 92q26 37 63 66q80 65 188 65q110 0 178 -59.5t68 -158.5q0 -66 -34.5 -118.5t-84 -86t-99.5 -62.5t-87 -63t-41 -73
+h232v80h126z" />
+    <glyph glyph-name="_283" unicode="&#xf12d;" horiz-adv-x="1920" 
+d="M896 128l336 384h-768l-336 -384h768zM1909 1205q15 -34 9.5 -71.5t-30.5 -65.5l-896 -1024q-38 -44 -96 -44h-768q-38 0 -69.5 20.5t-47.5 54.5q-15 34 -9.5 71.5t30.5 65.5l896 1024q38 44 96 44h768q38 0 69.5 -20.5t47.5 -54.5z" />
+    <glyph glyph-name="puzzle_piece" unicode="&#xf12e;" horiz-adv-x="1664" 
+d="M1664 438q0 -81 -44.5 -135t-123.5 -54q-41 0 -77.5 17.5t-59 38t-56.5 38t-71 17.5q-110 0 -110 -124q0 -39 16 -115t15 -115v-5q-22 0 -33 -1q-34 -3 -97.5 -11.5t-115.5 -13.5t-98 -5q-61 0 -103 26.5t-42 83.5q0 37 17.5 71t38 56.5t38 59t17.5 77.5q0 79 -54 123.5
+t-135 44.5q-84 0 -143 -45.5t-59 -127.5q0 -43 15 -83t33.5 -64.5t33.5 -53t15 -50.5q0 -45 -46 -89q-37 -35 -117 -35q-95 0 -245 24q-9 2 -27.5 4t-27.5 4l-13 2q-1 0 -3 1q-2 0 -2 1v1024q2 -1 17.5 -3.5t34 -5t21.5 -3.5q150 -24 245 -24q80 0 117 35q46 44 46 89
+q0 22 -15 50.5t-33.5 53t-33.5 64.5t-15 83q0 82 59 127.5t144 45.5q80 0 134 -44.5t54 -123.5q0 -41 -17.5 -77.5t-38 -59t-38 -56.5t-17.5 -71q0 -57 42 -83.5t103 -26.5q64 0 180 15t163 17v-2q-1 -2 -3.5 -17.5t-5 -34t-3.5 -21.5q-24 -150 -24 -245q0 -80 35 -117
+q44 -46 89 -46q22 0 50.5 15t53 33.5t64.5 33.5t83 15q82 0 127.5 -59t45.5 -143z" />
+    <glyph glyph-name="microphone" unicode="&#xf130;" horiz-adv-x="1152" 
+d="M1152 832v-128q0 -221 -147.5 -384.5t-364.5 -187.5v-132h256q26 0 45 -19t19 -45t-19 -45t-45 -19h-640q-26 0 -45 19t-19 45t19 45t45 19h256v132q-217 24 -364.5 187.5t-147.5 384.5v128q0 26 19 45t45 19t45 -19t19 -45v-128q0 -185 131.5 -316.5t316.5 -131.5
+t316.5 131.5t131.5 316.5v128q0 26 19 45t45 19t45 -19t19 -45zM896 1216v-512q0 -132 -94 -226t-226 -94t-226 94t-94 226v512q0 132 94 226t226 94t226 -94t94 -226z" />
+    <glyph glyph-name="microphone_off" unicode="&#xf131;" horiz-adv-x="1408" 
+d="M271 591l-101 -101q-42 103 -42 214v128q0 26 19 45t45 19t45 -19t19 -45v-128q0 -53 15 -113zM1385 1193l-361 -361v-128q0 -132 -94 -226t-226 -94q-55 0 -109 19l-96 -96q97 -51 205 -51q185 0 316.5 131.5t131.5 316.5v128q0 26 19 45t45 19t45 -19t19 -45v-128
+q0 -221 -147.5 -384.5t-364.5 -187.5v-132h256q26 0 45 -19t19 -45t-19 -45t-45 -19h-640q-26 0 -45 19t-19 45t19 45t45 19h256v132q-125 13 -235 81l-254 -254q-10 -10 -23 -10t-23 10l-82 82q-10 10 -10 23t10 23l1234 1234q10 10 23 10t23 -10l82 -82q10 -10 10 -23
+t-10 -23zM1005 1325l-621 -621v512q0 132 94 226t226 94q102 0 184.5 -59t116.5 -152z" />
+    <glyph glyph-name="shield" unicode="&#xf132;" horiz-adv-x="1280" 
+d="M1088 576v640h-448v-1137q119 63 213 137q235 184 235 360zM1280 1344v-768q0 -86 -33.5 -170.5t-83 -150t-118 -127.5t-126.5 -103t-121 -77.5t-89.5 -49.5t-42.5 -20q-12 -6 -26 -6t-26 6q-16 7 -42.5 20t-89.5 49.5t-121 77.5t-126.5 103t-118 127.5t-83 150
+t-33.5 170.5v768q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" />
+    <glyph glyph-name="calendar_empty" unicode="&#xf133;" horiz-adv-x="1664" 
+d="M128 -128h1408v1024h-1408v-1024zM512 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1280 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1664 1152v-1280
+q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h384v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h128q52 0 90 -38t38 -90z" />
+    <glyph glyph-name="fire_extinguisher" unicode="&#xf134;" horiz-adv-x="1408" 
+d="M512 1344q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 1376v-320q0 -16 -12 -25q-8 -7 -20 -7q-4 0 -7 1l-448 96q-11 2 -18 11t-7 20h-256v-102q111 -23 183.5 -111t72.5 -203v-800q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v800
+q0 106 62.5 190.5t161.5 114.5v111h-32q-59 0 -115 -23.5t-91.5 -53t-66 -66.5t-40.5 -53.5t-14 -24.5q-17 -35 -57 -35q-16 0 -29 7q-23 12 -31.5 37t3.5 49q5 10 14.5 26t37.5 53.5t60.5 70t85 67t108.5 52.5q-25 42 -25 86q0 66 47 113t113 47t113 -47t47 -113
+q0 -33 -14 -64h302q0 11 7 20t18 11l448 96q3 1 7 1q12 0 20 -7q12 -9 12 -25z" />
+    <glyph glyph-name="rocket" unicode="&#xf135;" horiz-adv-x="1664" 
+d="M1440 1088q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM1664 1376q0 -249 -75.5 -430.5t-253.5 -360.5q-81 -80 -195 -176l-20 -379q-2 -16 -16 -26l-384 -224q-7 -4 -16 -4q-12 0 -23 9l-64 64q-13 14 -8 32l85 276l-281 281l-276 -85q-3 -1 -9 -1
+q-14 0 -23 9l-64 64q-17 19 -5 39l224 384q10 14 26 16l379 20q96 114 176 195q188 187 358 258t431 71q14 0 24 -9.5t10 -22.5z" />
+    <glyph glyph-name="maxcdn" unicode="&#xf136;" horiz-adv-x="1792" 
+d="M1745 763l-164 -763h-334l178 832q13 56 -15 88q-27 33 -83 33h-169l-204 -953h-334l204 953h-286l-204 -953h-334l204 953l-153 327h1276q101 0 189.5 -40.5t147.5 -113.5q60 -73 81 -168.5t0 -194.5z" />
+    <glyph glyph-name="chevron_sign_left" unicode="&#xf137;" 
+d="M909 141l102 102q19 19 19 45t-19 45l-307 307l307 307q19 19 19 45t-19 45l-102 102q-19 19 -45 19t-45 -19l-454 -454q-19 -19 -19 -45t19 -45l454 -454q19 -19 45 -19t45 19zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5
+t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="chevron_sign_right" unicode="&#xf138;" 
+d="M717 141l454 454q19 19 19 45t-19 45l-454 454q-19 19 -45 19t-45 -19l-102 -102q-19 -19 -19 -45t19 -45l307 -307l-307 -307q-19 -19 -19 -45t19 -45l102 -102q19 -19 45 -19t45 19zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5
+t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="chevron_sign_up" unicode="&#xf139;" 
+d="M1165 397l102 102q19 19 19 45t-19 45l-454 454q-19 19 -45 19t-45 -19l-454 -454q-19 -19 -19 -45t19 -45l102 -102q19 -19 45 -19t45 19l307 307l307 -307q19 -19 45 -19t45 19zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5
+t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="chevron_sign_down" unicode="&#xf13a;" 
+d="M813 237l454 454q19 19 19 45t-19 45l-102 102q-19 19 -45 19t-45 -19l-307 -307l-307 307q-19 19 -45 19t-45 -19l-102 -102q-19 -19 -19 -45t19 -45l454 -454q19 -19 45 -19t45 19zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5
+t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="html5" unicode="&#xf13b;" horiz-adv-x="1408" 
+d="M1130 939l16 175h-884l47 -534h612l-22 -228l-197 -53l-196 53l-13 140h-175l22 -278l362 -100h4v1l359 99l50 544h-644l-15 181h674zM0 1408h1408l-128 -1438l-578 -162l-574 162z" />
+    <glyph glyph-name="css3" unicode="&#xf13c;" horiz-adv-x="1792" 
+d="M275 1408h1505l-266 -1333l-804 -267l-698 267l71 356h297l-29 -147l422 -161l486 161l68 339h-1208l58 297h1209l38 191h-1208z" />
+    <glyph glyph-name="anchor" unicode="&#xf13d;" horiz-adv-x="1792" 
+d="M960 1280q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1792 352v-352q0 -22 -20 -30q-8 -2 -12 -2q-12 0 -23 9l-93 93q-119 -143 -318.5 -226.5t-429.5 -83.5t-429.5 83.5t-318.5 226.5l-93 -93q-9 -9 -23 -9q-4 0 -12 2q-20 8 -20 30v352
+q0 14 9 23t23 9h352q22 0 30 -20q8 -19 -7 -35l-100 -100q67 -91 189.5 -153.5t271.5 -82.5v647h-192q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h192v163q-58 34 -93 92.5t-35 128.5q0 106 75 181t181 75t181 -75t75 -181q0 -70 -35 -128.5t-93 -92.5v-163h192q26 0 45 -19
+t19 -45v-128q0 -26 -19 -45t-45 -19h-192v-647q149 20 271.5 82.5t189.5 153.5l-100 100q-15 16 -7 35q8 20 30 20h352q14 0 23 -9t9 -23z" />
+    <glyph glyph-name="unlock_alt" unicode="&#xf13e;" horiz-adv-x="1152" 
+d="M1056 768q40 0 68 -28t28 -68v-576q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v576q0 40 28 68t68 28h32v320q0 185 131.5 316.5t316.5 131.5t316.5 -131.5t131.5 -316.5q0 -26 -19 -45t-45 -19h-64q-26 0 -45 19t-19 45q0 106 -75 181t-181 75t-181 -75t-75 -181
+v-320h736z" />
+    <glyph glyph-name="bullseye" unicode="&#xf140;" 
+d="M1024 640q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75t75 -181zM1152 640q0 159 -112.5 271.5t-271.5 112.5t-271.5 -112.5t-112.5 -271.5t112.5 -271.5t271.5 -112.5t271.5 112.5t112.5 271.5zM1280 640q0 -212 -150 -362t-362 -150t-362 150
+t-150 362t150 362t362 150t362 -150t150 -362zM1408 640q0 130 -51 248.5t-136.5 204t-204 136.5t-248.5 51t-248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5zM1536 640
+q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="ellipsis_horizontal" unicode="&#xf141;" horiz-adv-x="1408" 
+d="M384 800v-192q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68zM896 800v-192q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68zM1408 800v-192q0 -40 -28 -68t-68 -28h-192
+q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68z" />
+    <glyph glyph-name="ellipsis_vertical" unicode="&#xf142;" horiz-adv-x="384" 
+d="M384 288v-192q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68zM384 800v-192q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68zM384 1312v-192q0 -40 -28 -68t-68 -28h-192
+q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68z" />
+    <glyph glyph-name="_303" unicode="&#xf143;" 
+d="M512 256q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM863 162q-13 233 -176.5 396.5t-396.5 176.5q-14 1 -24 -9t-10 -23v-128q0 -13 8.5 -22t21.5 -10q154 -11 264 -121t121 -264q1 -13 10 -21.5t22 -8.5h128
+q13 0 23 10t9 24zM1247 161q-5 154 -56 297.5t-139.5 260t-205 205t-260 139.5t-297.5 56q-14 1 -23 -9q-10 -10 -10 -23v-128q0 -13 9 -22t22 -10q204 -7 378 -111.5t278.5 -278.5t111.5 -378q1 -13 10 -22t22 -9h128q13 0 23 10q11 9 9 23zM1536 1120v-960
+q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="play_sign" unicode="&#xf144;" 
+d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM1152 585q32 18 32 55t-32 55l-544 320q-31 19 -64 1q-32 -19 -32 -56v-640q0 -37 32 -56
+q16 -8 32 -8q17 0 32 9z" />
+    <glyph glyph-name="ticket" unicode="&#xf145;" horiz-adv-x="1792" 
+d="M1024 1084l316 -316l-572 -572l-316 316zM813 105l618 618q19 19 19 45t-19 45l-362 362q-18 18 -45 18t-45 -18l-618 -618q-19 -19 -19 -45t19 -45l362 -362q18 -18 45 -18t45 18zM1702 742l-907 -908q-37 -37 -90.5 -37t-90.5 37l-126 126q56 56 56 136t-56 136
+t-136 56t-136 -56l-125 126q-37 37 -37 90.5t37 90.5l907 906q37 37 90.5 37t90.5 -37l125 -125q-56 -56 -56 -136t56 -136t136 -56t136 56l126 -125q37 -37 37 -90.5t-37 -90.5z" />
+    <glyph glyph-name="minus_sign_alt" unicode="&#xf146;" 
+d="M1280 576v128q0 26 -19 45t-45 19h-896q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h896q26 0 45 19t19 45zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5
+t84.5 -203.5z" />
+    <glyph glyph-name="check_minus" unicode="&#xf147;" horiz-adv-x="1408" 
+d="M1152 736v-64q0 -14 -9 -23t-23 -9h-832q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h832q14 0 23 -9t9 -23zM1280 288v832q0 66 -47 113t-113 47h-832q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113zM1408 1120v-832q0 -119 -84.5 -203.5
+t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="level_up" unicode="&#xf148;" horiz-adv-x="1024" 
+d="M1018 933q-18 -37 -58 -37h-192v-864q0 -14 -9 -23t-23 -9h-704q-21 0 -29 18q-8 20 4 35l160 192q9 11 25 11h320v640h-192q-40 0 -58 37q-17 37 9 68l320 384q18 22 49 22t49 -22l320 -384q27 -32 9 -68z" />
+    <glyph glyph-name="level_down" unicode="&#xf149;" horiz-adv-x="1024" 
+d="M32 1280h704q13 0 22.5 -9.5t9.5 -23.5v-863h192q40 0 58 -37t-9 -69l-320 -384q-18 -22 -49 -22t-49 22l-320 384q-26 31 -9 69q18 37 58 37h192v640h-320q-14 0 -25 11l-160 192q-13 14 -4 34q9 19 29 19z" />
+    <glyph glyph-name="check_sign" unicode="&#xf14a;" 
+d="M685 237l614 614q19 19 19 45t-19 45l-102 102q-19 19 -45 19t-45 -19l-467 -467l-211 211q-19 19 -45 19t-45 -19l-102 -102q-19 -19 -19 -45t19 -45l358 -358q19 -19 45 -19t45 19zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5
+t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="edit_sign" unicode="&#xf14b;" 
+d="M404 428l152 -152l-52 -52h-56v96h-96v56zM818 818q14 -13 -3 -30l-291 -291q-17 -17 -30 -3q-14 13 3 30l291 291q17 17 30 3zM544 128l544 544l-288 288l-544 -544v-288h288zM1152 736l92 92q28 28 28 68t-28 68l-152 152q-28 28 -68 28t-68 -28l-92 -92zM1536 1120
+v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="_312" unicode="&#xf14c;" 
+d="M1280 608v480q0 26 -19 45t-45 19h-480q-42 0 -59 -39q-17 -41 14 -70l144 -144l-534 -534q-19 -19 -19 -45t19 -45l102 -102q19 -19 45 -19t45 19l534 534l144 -144q18 -19 45 -19q12 0 25 5q39 17 39 59zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960
+q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="share_sign" unicode="&#xf14d;" 
+d="M1005 435l352 352q19 19 19 45t-19 45l-352 352q-30 31 -69 14q-40 -17 -40 -59v-160q-119 0 -216 -19.5t-162.5 -51t-114 -79t-76.5 -95.5t-44.5 -109t-21.5 -111.5t-5 -110.5q0 -181 167 -404q11 -12 25 -12q7 0 13 3q22 9 19 33q-44 354 62 473q46 52 130 75.5
+t224 23.5v-160q0 -42 40 -59q12 -5 24 -5q26 0 45 19zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="compass" unicode="&#xf14e;" 
+d="M640 448l256 128l-256 128v-256zM1024 1039v-542l-512 -256v542zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103
+t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="collapse" unicode="&#xf150;" 
+d="M1145 861q18 -35 -5 -66l-320 -448q-19 -27 -52 -27t-52 27l-320 448q-23 31 -5 66q17 35 57 35h640q40 0 57 -35zM1280 160v960q0 13 -9.5 22.5t-22.5 9.5h-960q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h960q13 0 22.5 9.5t9.5 22.5zM1536 1120
+v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="collapse_top" unicode="&#xf151;" 
+d="M1145 419q-17 -35 -57 -35h-640q-40 0 -57 35q-18 35 5 66l320 448q19 27 52 27t52 -27l320 -448q23 -31 5 -66zM1280 160v960q0 13 -9.5 22.5t-22.5 9.5h-960q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h960q13 0 22.5 9.5t9.5 22.5zM1536 1120v-960
+q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="_317" unicode="&#xf152;" 
+d="M1088 640q0 -33 -27 -52l-448 -320q-31 -23 -66 -5q-35 17 -35 57v640q0 40 35 57q35 18 66 -5l448 -320q27 -19 27 -52zM1280 160v960q0 14 -9 23t-23 9h-960q-14 0 -23 -9t-9 -23v-960q0 -14 9 -23t23 -9h960q14 0 23 9t9 23zM1536 1120v-960q0 -119 -84.5 -203.5
+t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="eur" unicode="&#xf153;" horiz-adv-x="1024" 
+d="M976 229l35 -159q3 -12 -3 -22.5t-17 -14.5l-5 -1q-4 -2 -10.5 -3.5t-16 -4.5t-21.5 -5.5t-25.5 -5t-30 -5t-33.5 -4.5t-36.5 -3t-38.5 -1q-234 0 -409 130.5t-238 351.5h-95q-13 0 -22.5 9.5t-9.5 22.5v113q0 13 9.5 22.5t22.5 9.5h66q-2 57 1 105h-67q-14 0 -23 9
+t-9 23v114q0 14 9 23t23 9h98q67 210 243.5 338t400.5 128q102 0 194 -23q11 -3 20 -15q6 -11 3 -24l-43 -159q-3 -13 -14 -19.5t-24 -2.5l-4 1q-4 1 -11.5 2.5l-17.5 3.5t-22.5 3.5t-26 3t-29 2.5t-29.5 1q-126 0 -226 -64t-150 -176h468q16 0 25 -12q10 -12 7 -26
+l-24 -114q-5 -26 -32 -26h-488q-3 -37 0 -105h459q15 0 25 -12q9 -12 6 -27l-24 -112q-2 -11 -11 -18.5t-20 -7.5h-387q48 -117 149.5 -185.5t228.5 -68.5q18 0 36 1.5t33.5 3.5t29.5 4.5t24.5 5t18.5 4.5l12 3l5 2q13 5 26 -2q12 -7 15 -21z" />
+    <glyph glyph-name="gbp" unicode="&#xf154;" horiz-adv-x="1024" 
+d="M1020 399v-367q0 -14 -9 -23t-23 -9h-956q-14 0 -23 9t-9 23v150q0 13 9.5 22.5t22.5 9.5h97v383h-95q-14 0 -23 9.5t-9 22.5v131q0 14 9 23t23 9h95v223q0 171 123.5 282t314.5 111q185 0 335 -125q9 -8 10 -20.5t-7 -22.5l-103 -127q-9 -11 -22 -12q-13 -2 -23 7
+q-5 5 -26 19t-69 32t-93 18q-85 0 -137 -47t-52 -123v-215h305q13 0 22.5 -9t9.5 -23v-131q0 -13 -9.5 -22.5t-22.5 -9.5h-305v-379h414v181q0 13 9 22.5t23 9.5h162q14 0 23 -9.5t9 -22.5z" />
+    <glyph glyph-name="usd" unicode="&#xf155;" horiz-adv-x="1024" 
+d="M978 351q0 -153 -99.5 -263.5t-258.5 -136.5v-175q0 -14 -9 -23t-23 -9h-135q-13 0 -22.5 9.5t-9.5 22.5v175q-66 9 -127.5 31t-101.5 44.5t-74 48t-46.5 37.5t-17.5 18q-17 21 -2 41l103 135q7 10 23 12q15 2 24 -9l2 -2q113 -99 243 -125q37 -8 74 -8q81 0 142.5 43
+t61.5 122q0 28 -15 53t-33.5 42t-58.5 37.5t-66 32t-80 32.5q-39 16 -61.5 25t-61.5 26.5t-62.5 31t-56.5 35.5t-53.5 42.5t-43.5 49t-35.5 58t-21 66.5t-8.5 78q0 138 98 242t255 134v180q0 13 9.5 22.5t22.5 9.5h135q14 0 23 -9t9 -23v-176q57 -6 110.5 -23t87 -33.5
+t63.5 -37.5t39 -29t15 -14q17 -18 5 -38l-81 -146q-8 -15 -23 -16q-14 -3 -27 7q-3 3 -14.5 12t-39 26.5t-58.5 32t-74.5 26t-85.5 11.5q-95 0 -155 -43t-60 -111q0 -26 8.5 -48t29.5 -41.5t39.5 -33t56 -31t60.5 -27t70 -27.5q53 -20 81 -31.5t76 -35t75.5 -42.5t62 -50
+t53 -63.5t31.5 -76.5t13 -94z" />
+    <glyph glyph-name="inr" unicode="&#xf156;" horiz-adv-x="898" 
+d="M898 1066v-102q0 -14 -9 -23t-23 -9h-168q-23 -144 -129 -234t-276 -110q167 -178 459 -536q14 -16 4 -34q-8 -18 -29 -18h-195q-16 0 -25 12q-306 367 -498 571q-9 9 -9 22v127q0 13 9.5 22.5t22.5 9.5h112q132 0 212.5 43t102.5 125h-427q-14 0 -23 9t-9 23v102
+q0 14 9 23t23 9h413q-57 113 -268 113h-145q-13 0 -22.5 9.5t-9.5 22.5v133q0 14 9 23t23 9h832q14 0 23 -9t9 -23v-102q0 -14 -9 -23t-23 -9h-233q47 -61 64 -144h171q14 0 23 -9t9 -23z" />
+    <glyph glyph-name="jpy" unicode="&#xf157;" horiz-adv-x="1027" 
+d="M603 0h-172q-13 0 -22.5 9t-9.5 23v330h-288q-13 0 -22.5 9t-9.5 23v103q0 13 9.5 22.5t22.5 9.5h288v85h-288q-13 0 -22.5 9t-9.5 23v104q0 13 9.5 22.5t22.5 9.5h214l-321 578q-8 16 0 32q10 16 28 16h194q19 0 29 -18l215 -425q19 -38 56 -125q10 24 30.5 68t27.5 61
+l191 420q8 19 29 19h191q17 0 27 -16q9 -14 1 -31l-313 -579h215q13 0 22.5 -9.5t9.5 -22.5v-104q0 -14 -9.5 -23t-22.5 -9h-290v-85h290q13 0 22.5 -9.5t9.5 -22.5v-103q0 -14 -9.5 -23t-22.5 -9h-290v-330q0 -13 -9.5 -22.5t-22.5 -9.5z" />
+    <glyph glyph-name="rub" unicode="&#xf158;" horiz-adv-x="1280" 
+d="M1043 971q0 100 -65 162t-171 62h-320v-448h320q106 0 171 62t65 162zM1280 971q0 -193 -126.5 -315t-326.5 -122h-340v-118h505q14 0 23 -9t9 -23v-128q0 -14 -9 -23t-23 -9h-505v-192q0 -14 -9.5 -23t-22.5 -9h-167q-14 0 -23 9t-9 23v192h-224q-14 0 -23 9t-9 23v128
+q0 14 9 23t23 9h224v118h-224q-14 0 -23 9t-9 23v149q0 13 9 22.5t23 9.5h224v629q0 14 9 23t23 9h539q200 0 326.5 -122t126.5 -315z" />
+    <glyph glyph-name="krw" unicode="&#xf159;" horiz-adv-x="1792" 
+d="M514 341l81 299h-159l75 -300q1 -1 1 -3t1 -3q0 1 0.5 3.5t0.5 3.5zM630 768l35 128h-292l32 -128h225zM822 768h139l-35 128h-70zM1271 340l78 300h-162l81 -299q0 -1 0.5 -3.5t1.5 -3.5q0 1 0.5 3t0.5 3zM1382 768l33 128h-297l34 -128h230zM1792 736v-64q0 -14 -9 -23
+t-23 -9h-213l-164 -616q-7 -24 -31 -24h-159q-24 0 -31 24l-166 616h-209l-167 -616q-7 -24 -31 -24h-159q-11 0 -19.5 7t-10.5 17l-160 616h-208q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h175l-33 128h-142q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h109l-89 344q-5 15 5 28
+q10 12 26 12h137q26 0 31 -24l90 -360h359l97 360q7 24 31 24h126q24 0 31 -24l98 -360h365l93 360q5 24 31 24h137q16 0 26 -12q10 -13 5 -28l-91 -344h111q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-145l-34 -128h179q14 0 23 -9t9 -23z" />
+    <glyph glyph-name="btc" unicode="&#xf15a;" horiz-adv-x="1280" 
+d="M1167 896q18 -182 -131 -258q117 -28 175 -103t45 -214q-7 -71 -32.5 -125t-64.5 -89t-97 -58.5t-121.5 -34.5t-145.5 -15v-255h-154v251q-80 0 -122 1v-252h-154v255q-18 0 -54 0.5t-55 0.5h-200l31 183h111q50 0 58 51v402h16q-6 1 -16 1v287q-13 68 -89 68h-111v164
+l212 -1q64 0 97 1v252h154v-247q82 2 122 2v245h154v-252q79 -7 140 -22.5t113 -45t82.5 -78t36.5 -114.5zM952 351q0 36 -15 64t-37 46t-57.5 30.5t-65.5 18.5t-74 9t-69 3t-64.5 -1t-47.5 -1v-338q8 0 37 -0.5t48 -0.5t53 1.5t58.5 4t57 8.5t55.5 14t47.5 21t39.5 30
+t24.5 40t9.5 51zM881 827q0 33 -12.5 58.5t-30.5 42t-48 28t-55 16.5t-61.5 8t-58 2.5t-54 -1t-39.5 -0.5v-307q5 0 34.5 -0.5t46.5 0t50 2t55 5.5t51.5 11t48.5 18.5t37 27t27 38.5t9 51z" />
+    <glyph glyph-name="file" unicode="&#xf15b;" 
+d="M1024 1024v472q22 -14 36 -28l408 -408q14 -14 28 -36h-472zM896 992q0 -40 28 -68t68 -28h544v-1056q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h800v-544z" />
+    <glyph glyph-name="file_text" unicode="&#xf15c;" 
+d="M1468 1060q14 -14 28 -36h-472v472q22 -14 36 -28zM992 896h544v-1056q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h800v-544q0 -40 28 -68t68 -28zM1152 160v64q0 14 -9 23t-23 9h-704q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h704
+q14 0 23 9t9 23zM1152 416v64q0 14 -9 23t-23 9h-704q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h704q14 0 23 9t9 23zM1152 672v64q0 14 -9 23t-23 9h-704q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h704q14 0 23 9t9 23z" />
+    <glyph glyph-name="sort_by_alphabet" unicode="&#xf15d;" horiz-adv-x="1664" 
+d="M1191 1128h177l-72 218l-12 47q-2 16 -2 20h-4l-3 -20q0 -1 -3.5 -18t-7.5 -29zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9t9 -23zM1572 -23
+v-233h-584v90l369 529q12 18 21 27l11 9v3q-2 0 -6.5 -0.5t-7.5 -0.5q-12 -3 -30 -3h-232v-115h-120v229h567v-89l-369 -530q-6 -8 -21 -26l-11 -11v-2l14 2q9 2 30 2h248v119h121zM1661 874v-106h-288v106h75l-47 144h-243l-47 -144h75v-106h-287v106h70l230 662h162
+l230 -662h70z" />
+    <glyph glyph-name="_329" unicode="&#xf15e;" horiz-adv-x="1664" 
+d="M1191 104h177l-72 218l-12 47q-2 16 -2 20h-4l-3 -20q0 -1 -3.5 -18t-7.5 -29zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9t9 -23zM1661 -150
+v-106h-288v106h75l-47 144h-243l-47 -144h75v-106h-287v106h70l230 662h162l230 -662h70zM1572 1001v-233h-584v90l369 529q12 18 21 27l11 9v3q-2 0 -6.5 -0.5t-7.5 -0.5q-12 -3 -30 -3h-232v-115h-120v229h567v-89l-369 -530q-6 -8 -21 -26l-11 -10v-3l14 3q9 1 30 1h248
+v119h121z" />
+    <glyph glyph-name="sort_by_attributes" unicode="&#xf160;" horiz-adv-x="1792" 
+d="M736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9t9 -23zM1792 -32v-192q0 -14 -9 -23t-23 -9h-832q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h832
+q14 0 23 -9t9 -23zM1600 480v-192q0 -14 -9 -23t-23 -9h-640q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h640q14 0 23 -9t9 -23zM1408 992v-192q0 -14 -9 -23t-23 -9h-448q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h448q14 0 23 -9t9 -23zM1216 1504v-192q0 -14 -9 -23t-23 -9h-256
+q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h256q14 0 23 -9t9 -23z" />
+    <glyph glyph-name="sort_by_attributes_alt" unicode="&#xf161;" horiz-adv-x="1792" 
+d="M1216 -32v-192q0 -14 -9 -23t-23 -9h-256q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h256q14 0 23 -9t9 -23zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192
+q14 0 23 -9t9 -23zM1408 480v-192q0 -14 -9 -23t-23 -9h-448q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h448q14 0 23 -9t9 -23zM1600 992v-192q0 -14 -9 -23t-23 -9h-640q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h640q14 0 23 -9t9 -23zM1792 1504v-192q0 -14 -9 -23t-23 -9h-832
+q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h832q14 0 23 -9t9 -23z" />
+    <glyph glyph-name="sort_by_order" unicode="&#xf162;" 
+d="M1346 223q0 63 -44 116t-103 53q-52 0 -83 -37t-31 -94t36.5 -95t104.5 -38q50 0 85 27t35 68zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9t9 -23
+zM1486 165q0 -62 -13 -121.5t-41 -114t-68 -95.5t-98.5 -65.5t-127.5 -24.5q-62 0 -108 16q-24 8 -42 15l39 113q15 -7 31 -11q37 -13 75 -13q84 0 134.5 58.5t66.5 145.5h-2q-21 -23 -61.5 -37t-84.5 -14q-106 0 -173 71.5t-67 172.5q0 105 72 178t181 73q123 0 205 -94.5
+t82 -252.5zM1456 882v-114h-469v114h167v432q0 7 0.5 19t0.5 17v16h-2l-7 -12q-8 -13 -26 -31l-62 -58l-82 86l192 185h123v-654h165z" />
+    <glyph glyph-name="sort_by_order_alt" unicode="&#xf163;" 
+d="M1346 1247q0 63 -44 116t-103 53q-52 0 -83 -37t-31 -94t36.5 -95t104.5 -38q50 0 85 27t35 68zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9
+t9 -23zM1456 -142v-114h-469v114h167v432q0 7 0.5 19t0.5 17v16h-2l-7 -12q-8 -13 -26 -31l-62 -58l-82 86l192 185h123v-654h165zM1486 1189q0 -62 -13 -121.5t-41 -114t-68 -95.5t-98.5 -65.5t-127.5 -24.5q-62 0 -108 16q-24 8 -42 15l39 113q15 -7 31 -11q37 -13 75 -13
+q84 0 134.5 58.5t66.5 145.5h-2q-21 -23 -61.5 -37t-84.5 -14q-106 0 -173 71.5t-67 172.5q0 105 72 178t181 73q123 0 205 -94.5t82 -252.5z" />
+    <glyph glyph-name="_334" unicode="&#xf164;" horiz-adv-x="1664" 
+d="M256 192q0 26 -19 45t-45 19q-27 0 -45.5 -19t-18.5 -45q0 -27 18.5 -45.5t45.5 -18.5q26 0 45 18.5t19 45.5zM416 704v-640q0 -26 -19 -45t-45 -19h-288q-26 0 -45 19t-19 45v640q0 26 19 45t45 19h288q26 0 45 -19t19 -45zM1600 704q0 -86 -55 -149q15 -44 15 -76
+q3 -76 -43 -137q17 -56 0 -117q-15 -57 -54 -94q9 -112 -49 -181q-64 -76 -197 -78h-36h-76h-17q-66 0 -144 15.5t-121.5 29t-120.5 39.5q-123 43 -158 44q-26 1 -45 19.5t-19 44.5v641q0 25 18 43.5t43 20.5q24 2 76 59t101 121q68 87 101 120q18 18 31 48t17.5 48.5
+t13.5 60.5q7 39 12.5 61t19.5 52t34 50q19 19 45 19q46 0 82.5 -10.5t60 -26t40 -40.5t24 -45t12 -50t5 -45t0.5 -39q0 -38 -9.5 -76t-19 -60t-27.5 -56q-3 -6 -10 -18t-11 -22t-8 -24h277q78 0 135 -57t57 -135z" />
+    <glyph glyph-name="_335" unicode="&#xf165;" horiz-adv-x="1664" 
+d="M256 960q0 -26 -19 -45t-45 -19q-27 0 -45.5 19t-18.5 45q0 27 18.5 45.5t45.5 18.5q26 0 45 -18.5t19 -45.5zM416 448v640q0 26 -19 45t-45 19h-288q-26 0 -45 -19t-19 -45v-640q0 -26 19 -45t45 -19h288q26 0 45 19t19 45zM1545 597q55 -61 55 -149q-1 -78 -57.5 -135
+t-134.5 -57h-277q4 -14 8 -24t11 -22t10 -18q18 -37 27 -57t19 -58.5t10 -76.5q0 -24 -0.5 -39t-5 -45t-12 -50t-24 -45t-40 -40.5t-60 -26t-82.5 -10.5q-26 0 -45 19q-20 20 -34 50t-19.5 52t-12.5 61q-9 42 -13.5 60.5t-17.5 48.5t-31 48q-33 33 -101 120q-49 64 -101 121
+t-76 59q-25 2 -43 20.5t-18 43.5v641q0 26 19 44.5t45 19.5q35 1 158 44q77 26 120.5 39.5t121.5 29t144 15.5h17h76h36q133 -2 197 -78q58 -69 49 -181q39 -37 54 -94q17 -61 0 -117q46 -61 43 -137q0 -32 -15 -76z" />
+    <glyph glyph-name="youtube_sign" unicode="&#xf166;" 
+d="M919 233v157q0 50 -29 50q-17 0 -33 -16v-224q16 -16 33 -16q29 0 29 49zM1103 355h66v34q0 51 -33 51t-33 -51v-34zM532 621v-70h-80v-423h-74v423h-78v70h232zM733 495v-367h-67v40q-39 -45 -76 -45q-33 0 -42 28q-6 17 -6 54v290h66v-270q0 -24 1 -26q1 -15 15 -15
+q20 0 42 31v280h67zM985 384v-146q0 -52 -7 -73q-12 -42 -53 -42q-35 0 -68 41v-36h-67v493h67v-161q32 40 68 40q41 0 53 -42q7 -21 7 -74zM1236 255v-9q0 -29 -2 -43q-3 -22 -15 -40q-27 -40 -80 -40q-52 0 -81 38q-21 27 -21 86v129q0 59 20 86q29 38 80 38t78 -38
+q21 -29 21 -86v-76h-133v-65q0 -51 34 -51q24 0 30 26q0 1 0.5 7t0.5 16.5v21.5h68zM785 1079v-156q0 -51 -32 -51t-32 51v156q0 52 32 52t32 -52zM1318 366q0 177 -19 260q-10 44 -43 73.5t-76 34.5q-136 15 -412 15q-275 0 -411 -15q-44 -5 -76.5 -34.5t-42.5 -73.5
+q-20 -87 -20 -260q0 -176 20 -260q10 -43 42.5 -73t75.5 -35q137 -15 412 -15t412 15q43 5 75.5 35t42.5 73q20 84 20 260zM563 1017l90 296h-75l-51 -195l-53 195h-78q7 -23 23 -69l24 -69q35 -103 46 -158v-201h74v201zM852 936v130q0 58 -21 87q-29 38 -78 38
+q-51 0 -78 -38q-21 -29 -21 -87v-130q0 -58 21 -87q27 -38 78 -38q49 0 78 38q21 27 21 87zM1033 816h67v370h-67v-283q-22 -31 -42 -31q-15 0 -16 16q-1 2 -1 26v272h-67v-293q0 -37 6 -55q11 -27 43 -27q36 0 77 45v-40zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5
+h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="youtube" unicode="&#xf167;" 
+d="M971 292v-211q0 -67 -39 -67q-23 0 -45 22v301q22 22 45 22q39 0 39 -67zM1309 291v-46h-90v46q0 68 45 68t45 -68zM343 509h107v94h-312v-94h105v-569h100v569zM631 -60h89v494h-89v-378q-30 -42 -57 -42q-18 0 -21 21q-1 3 -1 35v364h-89v-391q0 -49 8 -73
+q12 -37 58 -37q48 0 102 61v-54zM1060 88v197q0 73 -9 99q-17 56 -71 56q-50 0 -93 -54v217h-89v-663h89v48q45 -55 93 -55q54 0 71 55q9 27 9 100zM1398 98v13h-91q0 -51 -2 -61q-7 -36 -40 -36q-46 0 -46 69v87h179v103q0 79 -27 116q-39 51 -106 51q-68 0 -107 -51
+q-28 -37 -28 -116v-173q0 -79 29 -116q39 -51 108 -51q72 0 108 53q18 27 21 54q2 9 2 58zM790 1011v210q0 69 -43 69t-43 -69v-210q0 -70 43 -70t43 70zM1509 260q0 -234 -26 -350q-14 -59 -58 -99t-102 -46q-184 -21 -555 -21t-555 21q-58 6 -102.5 46t-57.5 99
+q-26 112 -26 350q0 234 26 350q14 59 58 99t103 47q183 20 554 20t555 -20q58 -7 102.5 -47t57.5 -99q26 -112 26 -350zM511 1536h102l-121 -399v-271h-100v271q-14 74 -61 212q-37 103 -65 187h106l71 -263zM881 1203v-175q0 -81 -28 -118q-38 -51 -106 -51q-67 0 -105 51
+q-28 38 -28 118v175q0 80 28 117q38 51 105 51q68 0 106 -51q28 -37 28 -117zM1216 1365v-499h-91v55q-53 -62 -103 -62q-46 0 -59 37q-8 24 -8 75v394h91v-367q0 -33 1 -35q3 -22 21 -22q27 0 57 43v381h91z" />
+    <glyph glyph-name="xing" unicode="&#xf168;" horiz-adv-x="1408" 
+d="M597 869q-10 -18 -257 -456q-27 -46 -65 -46h-239q-21 0 -31 17t0 36l253 448q1 0 0 1l-161 279q-12 22 -1 37q9 15 32 15h239q40 0 66 -45zM1403 1511q11 -16 0 -37l-528 -934v-1l336 -615q11 -20 1 -37q-10 -15 -32 -15h-239q-42 0 -66 45l-339 622q18 32 531 942
+q25 45 64 45h241q22 0 31 -15z" />
+    <glyph glyph-name="xing_sign" unicode="&#xf169;" 
+d="M685 771q0 1 -126 222q-21 34 -52 34h-184q-18 0 -26 -11q-7 -12 1 -29l125 -216v-1l-196 -346q-9 -14 0 -28q8 -13 24 -13h185q31 0 50 36zM1309 1268q-7 12 -24 12h-187q-30 0 -49 -35l-411 -729q1 -2 262 -481q20 -35 52 -35h184q18 0 25 12q8 13 -1 28l-260 476v1
+l409 723q8 16 0 28zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="youtube_play" unicode="&#xf16a;" horiz-adv-x="1792" 
+d="M711 408l484 250l-484 253v-503zM896 1270q168 0 324.5 -4.5t229.5 -9.5l73 -4q1 0 17 -1.5t23 -3t23.5 -4.5t28.5 -8t28 -13t31 -19.5t29 -26.5q6 -6 15.5 -18.5t29 -58.5t26.5 -101q8 -64 12.5 -136.5t5.5 -113.5v-40v-136q1 -145 -18 -290q-7 -55 -25 -99.5t-32 -61.5
+l-14 -17q-14 -15 -29 -26.5t-31 -19t-28 -12.5t-28.5 -8t-24 -4.5t-23 -3t-16.5 -1.5q-251 -19 -627 -19q-207 2 -359.5 6.5t-200.5 7.5l-49 4l-36 4q-36 5 -54.5 10t-51 21t-56.5 41q-6 6 -15.5 18.5t-29 58.5t-26.5 101q-8 64 -12.5 136.5t-5.5 113.5v40v136
+q-1 145 18 290q7 55 25 99.5t32 61.5l14 17q14 15 29 26.5t31 19.5t28 13t28.5 8t23.5 4.5t23 3t17 1.5q251 18 627 18z" />
+    <glyph glyph-name="dropbox" unicode="&#xf16b;" horiz-adv-x="1792" 
+d="M402 829l494 -305l-342 -285l-490 319zM1388 274v-108l-490 -293v-1l-1 1l-1 -1v1l-489 293v108l147 -96l342 284v2l1 -1l1 1v-2l343 -284zM554 1418l342 -285l-494 -304l-338 270zM1390 829l338 -271l-489 -319l-343 285zM1239 1418l489 -319l-338 -270l-494 304z" />
+    <glyph glyph-name="stackexchange" unicode="&#xf16c;" 
+d="M1289 -96h-1118v480h-160v-640h1438v640h-160v-480zM347 428l33 157l783 -165l-33 -156zM450 802l67 146l725 -339l-67 -145zM651 1158l102 123l614 -513l-102 -123zM1048 1536l477 -641l-128 -96l-477 641zM330 65v159h800v-159h-800z" />
+    <glyph glyph-name="instagram" unicode="&#xf16d;" 
+d="M1024 640q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM1162 640q0 -164 -115 -279t-279 -115t-279 115t-115 279t115 279t279 115t279 -115t115 -279zM1270 1050q0 -38 -27 -65t-65 -27t-65 27t-27 65t27 65t65 27t65 -27t27 -65zM768 1270
+q-7 0 -76.5 0.5t-105.5 0t-96.5 -3t-103 -10t-71.5 -18.5q-50 -20 -88 -58t-58 -88q-11 -29 -18.5 -71.5t-10 -103t-3 -96.5t0 -105.5t0.5 -76.5t-0.5 -76.5t0 -105.5t3 -96.5t10 -103t18.5 -71.5q20 -50 58 -88t88 -58q29 -11 71.5 -18.5t103 -10t96.5 -3t105.5 0t76.5 0.5
+t76.5 -0.5t105.5 0t96.5 3t103 10t71.5 18.5q50 20 88 58t58 88q11 29 18.5 71.5t10 103t3 96.5t0 105.5t-0.5 76.5t0.5 76.5t0 105.5t-3 96.5t-10 103t-18.5 71.5q-20 50 -58 88t-88 58q-29 11 -71.5 18.5t-103 10t-96.5 3t-105.5 0t-76.5 -0.5zM1536 640q0 -229 -5 -317
+q-10 -208 -124 -322t-322 -124q-88 -5 -317 -5t-317 5q-208 10 -322 124t-124 322q-5 88 -5 317t5 317q10 208 124 322t322 124q88 5 317 5t317 -5q208 -10 322 -124t124 -322q5 -88 5 -317z" />
+    <glyph glyph-name="flickr" unicode="&#xf16e;" 
+d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960zM698 640q0 88 -62 150t-150 62t-150 -62t-62 -150t62 -150t150 -62t150 62t62 150zM1262 640q0 88 -62 150
+t-150 62t-150 -62t-62 -150t62 -150t150 -62t150 62t62 150z" />
+    <glyph glyph-name="adn" unicode="&#xf170;" 
+d="M768 914l201 -306h-402zM1133 384h94l-459 691l-459 -691h94l104 160h522zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="f171" unicode="&#xf171;" horiz-adv-x="1408" 
+d="M815 677q8 -63 -50.5 -101t-111.5 -6q-39 17 -53.5 58t-0.5 82t52 58q36 18 72.5 12t64 -35.5t27.5 -67.5zM926 698q-14 107 -113 164t-197 13q-63 -28 -100.5 -88.5t-34.5 -129.5q4 -91 77.5 -155t165.5 -56q91 8 152 84t50 168zM1165 1240q-20 27 -56 44.5t-58 22
+t-71 12.5q-291 47 -566 -2q-43 -7 -66 -12t-55 -22t-50 -43q30 -28 76 -45.5t73.5 -22t87.5 -11.5q228 -29 448 -1q63 8 89.5 12t72.5 21.5t75 46.5zM1222 205q-8 -26 -15.5 -76.5t-14 -84t-28.5 -70t-58 -56.5q-86 -48 -189.5 -71.5t-202 -22t-201.5 18.5q-46 8 -81.5 18
+t-76.5 27t-73 43.5t-52 61.5q-25 96 -57 292l6 16l18 9q223 -148 506.5 -148t507.5 148q21 -6 24 -23t-5 -45t-8 -37zM1403 1166q-26 -167 -111 -655q-5 -30 -27 -56t-43.5 -40t-54.5 -31q-252 -126 -610 -88q-248 27 -394 139q-15 12 -25.5 26.5t-17 35t-9 34t-6 39.5
+t-5.5 35q-9 50 -26.5 150t-28 161.5t-23.5 147.5t-22 158q3 26 17.5 48.5t31.5 37.5t45 30t46 22.5t48 18.5q125 46 313 64q379 37 676 -50q155 -46 215 -122q16 -20 16.5 -51t-5.5 -54z" />
+    <glyph glyph-name="bitbucket_sign" unicode="&#xf172;" 
+d="M848 666q0 43 -41 66t-77 1q-43 -20 -42.5 -72.5t43.5 -70.5q39 -23 81 4t36 72zM928 682q8 -66 -36 -121t-110 -61t-119 40t-56 113q-2 49 25.5 93t72.5 64q70 31 141.5 -10t81.5 -118zM1100 1073q-20 -21 -53.5 -34t-53 -16t-63.5 -8q-155 -20 -324 0q-44 6 -63 9.5
+t-52.5 16t-54.5 32.5q13 19 36 31t40 15.5t47 8.5q198 35 408 1q33 -5 51 -8.5t43 -16t39 -31.5zM1142 327q0 7 5.5 26.5t3 32t-17.5 16.5q-161 -106 -365 -106t-366 106l-12 -6l-5 -12q26 -154 41 -210q47 -81 204 -108q249 -46 428 53q34 19 49 51.5t22.5 85.5t12.5 71z
+M1272 1020q9 53 -8 75q-43 55 -155 88q-216 63 -487 36q-132 -12 -226 -46q-38 -15 -59.5 -25t-47 -34t-29.5 -54q8 -68 19 -138t29 -171t24 -137q1 -5 5 -31t7 -36t12 -27t22 -28q105 -80 284 -100q259 -28 440 63q24 13 39.5 23t31 29t19.5 40q48 267 80 473zM1536 1120
+v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="tumblr" unicode="&#xf173;" horiz-adv-x="1024" 
+d="M944 207l80 -237q-23 -35 -111 -66t-177 -32q-104 -2 -190.5 26t-142.5 74t-95 106t-55.5 120t-16.5 118v544h-168v215q72 26 129 69.5t91 90t58 102t34 99t15 88.5q1 5 4.5 8.5t7.5 3.5h244v-424h333v-252h-334v-518q0 -30 6.5 -56t22.5 -52.5t49.5 -41.5t81.5 -14
+q78 2 134 29z" />
+    <glyph glyph-name="tumblr_sign" unicode="&#xf174;" 
+d="M1136 75l-62 183q-44 -22 -103 -22q-36 -1 -62 10.5t-38.5 31.5t-17.5 40.5t-5 43.5v398h257v194h-256v326h-188q-8 0 -9 -10q-5 -44 -17.5 -87t-39 -95t-77 -95t-118.5 -68v-165h130v-418q0 -57 21.5 -115t65 -111t121 -85.5t176.5 -30.5q69 1 136.5 25t85.5 50z
+M1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="long_arrow_down" unicode="&#xf175;" horiz-adv-x="768" 
+d="M765 237q8 -19 -5 -35l-350 -384q-10 -10 -23 -10q-14 0 -24 10l-355 384q-13 16 -5 35q9 19 29 19h224v1248q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1248h224q21 0 29 -19z" />
+    <glyph glyph-name="long_arrow_up" unicode="&#xf176;" horiz-adv-x="768" 
+d="M765 1043q-9 -19 -29 -19h-224v-1248q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v1248h-224q-21 0 -29 19t5 35l350 384q10 10 23 10q14 0 24 -10l355 -384q13 -16 5 -35z" />
+    <glyph glyph-name="long_arrow_left" unicode="&#xf177;" horiz-adv-x="1792" 
+d="M1792 736v-192q0 -14 -9 -23t-23 -9h-1248v-224q0 -21 -19 -29t-35 5l-384 350q-10 10 -10 23q0 14 10 24l384 354q16 14 35 6q19 -9 19 -29v-224h1248q14 0 23 -9t9 -23z" />
+    <glyph glyph-name="long_arrow_right" unicode="&#xf178;" horiz-adv-x="1792" 
+d="M1728 643q0 -14 -10 -24l-384 -354q-16 -14 -35 -6q-19 9 -19 29v224h-1248q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h1248v224q0 21 19 29t35 -5l384 -350q10 -10 10 -23z" />
+    <glyph glyph-name="apple" unicode="&#xf179;" horiz-adv-x="1408" 
+d="M1393 321q-39 -125 -123 -250q-129 -196 -257 -196q-49 0 -140 32q-86 32 -151 32q-61 0 -142 -33q-81 -34 -132 -34q-152 0 -301 259q-147 261 -147 503q0 228 113 374q113 144 284 144q72 0 177 -30q104 -30 138 -30q45 0 143 34q102 34 173 34q119 0 213 -65
+q52 -36 104 -100q-79 -67 -114 -118q-65 -94 -65 -207q0 -124 69 -223t158 -126zM1017 1494q0 -61 -29 -136q-30 -75 -93 -138q-54 -54 -108 -72q-37 -11 -104 -17q3 149 78 257q74 107 250 148q1 -3 2.5 -11t2.5 -11q0 -4 0.5 -10t0.5 -10z" />
+    <glyph glyph-name="windows" unicode="&#xf17a;" horiz-adv-x="1664" 
+d="M682 530v-651l-682 94v557h682zM682 1273v-659h-682v565zM1664 530v-786l-907 125v661h907zM1664 1408v-794h-907v669z" />
+    <glyph glyph-name="android" unicode="&#xf17b;" horiz-adv-x="1408" 
+d="M493 1053q16 0 27.5 11.5t11.5 27.5t-11.5 27.5t-27.5 11.5t-27 -11.5t-11 -27.5t11 -27.5t27 -11.5zM915 1053q16 0 27 11.5t11 27.5t-11 27.5t-27 11.5t-27.5 -11.5t-11.5 -27.5t11.5 -27.5t27.5 -11.5zM103 869q42 0 72 -30t30 -72v-430q0 -43 -29.5 -73t-72.5 -30
+t-73 30t-30 73v430q0 42 30 72t73 30zM1163 850v-666q0 -46 -32 -78t-77 -32h-75v-227q0 -43 -30 -73t-73 -30t-73 30t-30 73v227h-138v-227q0 -43 -30 -73t-73 -30q-42 0 -72 30t-30 73l-1 227h-74q-46 0 -78 32t-32 78v666h918zM931 1255q107 -55 171 -153.5t64 -215.5
+h-925q0 117 64 215.5t172 153.5l-71 131q-7 13 5 20q13 6 20 -6l72 -132q95 42 201 42t201 -42l72 132q7 12 20 6q12 -7 5 -20zM1408 767v-430q0 -43 -30 -73t-73 -30q-42 0 -72 30t-30 73v430q0 43 30 72.5t72 29.5q43 0 73 -29.5t30 -72.5z" />
+    <glyph glyph-name="linux" unicode="&#xf17c;" 
+d="M663 1125q-11 -1 -15.5 -10.5t-8.5 -9.5q-5 -1 -5 5q0 12 19 15h10zM750 1111q-4 -1 -11.5 6.5t-17.5 4.5q24 11 32 -2q3 -6 -3 -9zM399 684q-4 1 -6 -3t-4.5 -12.5t-5.5 -13.5t-10 -13q-10 -11 -1 -12q4 -1 12.5 7t12.5 18q1 3 2 7t2 6t1.5 4.5t0.5 4v3t-1 2.5t-3 2z
+M1254 325q0 18 -55 42q4 15 7.5 27.5t5 26t3 21.5t0.5 22.5t-1 19.5t-3.5 22t-4 20.5t-5 25t-5.5 26.5q-10 48 -47 103t-72 75q24 -20 57 -83q87 -162 54 -278q-11 -40 -50 -42q-31 -4 -38.5 18.5t-8 83.5t-11.5 107q-9 39 -19.5 69t-19.5 45.5t-15.5 24.5t-13 15t-7.5 7
+q-14 62 -31 103t-29.5 56t-23.5 33t-15 40q-4 21 6 53.5t4.5 49.5t-44.5 25q-15 3 -44.5 18t-35.5 16q-8 1 -11 26t8 51t36 27q37 3 51 -30t4 -58q-11 -19 -2 -26.5t30 -0.5q13 4 13 36v37q-5 30 -13.5 50t-21 30.5t-23.5 15t-27 7.5q-107 -8 -89 -134q0 -15 -1 -15
+q-9 9 -29.5 10.5t-33 -0.5t-15.5 5q1 57 -16 90t-45 34q-27 1 -41.5 -27.5t-16.5 -59.5q-1 -15 3.5 -37t13 -37.5t15.5 -13.5q10 3 16 14q4 9 -7 8q-7 0 -15.5 14.5t-9.5 33.5q-1 22 9 37t34 14q17 0 27 -21t9.5 -39t-1.5 -22q-22 -15 -31 -29q-8 -12 -27.5 -23.5
+t-20.5 -12.5q-13 -14 -15.5 -27t7.5 -18q14 -8 25 -19.5t16 -19t18.5 -13t35.5 -6.5q47 -2 102 15q2 1 23 7t34.5 10.5t29.5 13t21 17.5q9 14 20 8q5 -3 6.5 -8.5t-3 -12t-16.5 -9.5q-20 -6 -56.5 -21.5t-45.5 -19.5q-44 -19 -70 -23q-25 -5 -79 2q-10 2 -9 -2t17 -19
+q25 -23 67 -22q17 1 36 7t36 14t33.5 17.5t30 17t24.5 12t17.5 2.5t8.5 -11q0 -2 -1 -4.5t-4 -5t-6 -4.5t-8.5 -5t-9 -4.5t-10 -5t-9.5 -4.5q-28 -14 -67.5 -44t-66.5 -43t-49 -1q-21 11 -63 73q-22 31 -25 22q-1 -3 -1 -10q0 -25 -15 -56.5t-29.5 -55.5t-21 -58t11.5 -63
+q-23 -6 -62.5 -90t-47.5 -141q-2 -18 -1.5 -69t-5.5 -59q-8 -24 -29 -3q-32 31 -36 94q-2 28 4 56q4 19 -1 18q-2 -1 -4 -5q-36 -65 10 -166q5 -12 25 -28t24 -20q20 -23 104 -90.5t93 -76.5q16 -15 17.5 -38t-14 -43t-45.5 -23q8 -15 29 -44.5t28 -54t7 -70.5q46 24 7 92
+q-4 8 -10.5 16t-9.5 12t-2 6q3 5 13 9.5t20 -2.5q46 -52 166 -36q133 15 177 87q23 38 34 30q12 -6 10 -52q-1 -25 -23 -92q-9 -23 -6 -37.5t24 -15.5q3 19 14.5 77t13.5 90q2 21 -6.5 73.5t-7.5 97t23 70.5q15 18 51 18q1 37 34.5 53t72.5 10.5t60 -22.5zM626 1152
+q3 17 -2.5 30t-11.5 15q-9 2 -9 -7q2 -5 5 -6q10 0 7 -15q-3 -20 8 -20q3 0 3 3zM1045 955q-2 8 -6.5 11.5t-13 5t-14.5 5.5q-5 3 -9.5 8t-7 8t-5.5 6.5t-4 4t-4 -1.5q-14 -16 7 -43.5t39 -31.5q9 -1 14.5 8t3.5 20zM867 1168q0 11 -5 19.5t-11 12.5t-9 3q-6 0 -8 -2t0 -4
+t5 -3q14 -4 18 -31q0 -3 8 2q2 2 2 3zM921 1401q0 2 -2.5 5t-9 7t-9.5 6q-15 15 -24 15q-9 -1 -11.5 -7.5t-1 -13t-0.5 -12.5q-1 -4 -6 -10.5t-6 -9t3 -8.5q4 -3 8 0t11 9t15 9q1 1 9 1t15 2t9 7zM1486 60q20 -12 31 -24.5t12 -24t-2.5 -22.5t-15.5 -22t-23.5 -19.5
+t-30 -18.5t-31.5 -16.5t-32 -15.5t-27 -13q-38 -19 -85.5 -56t-75.5 -64q-17 -16 -68 -19.5t-89 14.5q-18 9 -29.5 23.5t-16.5 25.5t-22 19.5t-47 9.5q-44 1 -130 1q-19 0 -57 -1.5t-58 -2.5q-44 -1 -79.5 -15t-53.5 -30t-43.5 -28.5t-53.5 -11.5q-29 1 -111 31t-146 43
+q-19 4 -51 9.5t-50 9t-39.5 9.5t-33.5 14.5t-17 19.5q-10 23 7 66.5t18 54.5q1 16 -4 40t-10 42.5t-4.5 36.5t10.5 27q14 12 57 14t60 12q30 18 42 35t12 51q21 -73 -32 -106q-32 -20 -83 -15q-34 3 -43 -10q-13 -15 5 -57q2 -6 8 -18t8.5 -18t4.5 -17t1 -22q0 -15 -17 -49
+t-14 -48q3 -17 37 -26q20 -6 84.5 -18.5t99.5 -20.5q24 -6 74 -22t82.5 -23t55.5 -4q43 6 64.5 28t23 48t-7.5 58.5t-19 52t-20 36.5q-121 190 -169 242q-68 74 -113 40q-11 -9 -15 15q-3 16 -2 38q1 29 10 52t24 47t22 42q8 21 26.5 72t29.5 78t30 61t39 54
+q110 143 124 195q-12 112 -16 310q-2 90 24 151.5t106 104.5q39 21 104 21q53 1 106 -13.5t89 -41.5q57 -42 91.5 -121.5t29.5 -147.5q-5 -95 30 -214q34 -113 133 -218q55 -59 99.5 -163t59.5 -191q8 -49 5 -84.5t-12 -55.5t-20 -22q-10 -2 -23.5 -19t-27 -35.5
+t-40.5 -33.5t-61 -14q-18 1 -31.5 5t-22.5 13.5t-13.5 15.5t-11.5 20.5t-9 19.5q-22 37 -41 30t-28 -49t7 -97q20 -70 1 -195q-10 -65 18 -100.5t73 -33t85 35.5q59 49 89.5 66.5t103.5 42.5q53 18 77 36.5t18.5 34.5t-25 28.5t-51.5 23.5q-33 11 -49.5 48t-15 72.5
+t15.5 47.5q1 -31 8 -56.5t14.5 -40.5t20.5 -28.5t21 -19t21.5 -13t16.5 -9.5z" />
+    <glyph glyph-name="dribble" unicode="&#xf17d;" 
+d="M1024 36q-42 241 -140 498h-2l-2 -1q-16 -6 -43 -16.5t-101 -49t-137 -82t-131 -114.5t-103 -148l-15 11q184 -150 418 -150q132 0 256 52zM839 643q-21 49 -53 111q-311 -93 -673 -93q-1 -7 -1 -21q0 -124 44 -236.5t124 -201.5q50 89 123.5 166.5t142.5 124.5t130.5 81
+t99.5 48l37 13q4 1 13 3.5t13 4.5zM732 855q-120 213 -244 378q-138 -65 -234 -186t-128 -272q302 0 606 80zM1416 536q-210 60 -409 29q87 -239 128 -469q111 75 185 189.5t96 250.5zM611 1277q-1 0 -2 -1q1 1 2 1zM1201 1132q-185 164 -433 164q-76 0 -155 -19
+q131 -170 246 -382q69 26 130 60.5t96.5 61.5t65.5 57t37.5 40.5zM1424 647q-3 232 -149 410l-1 -1q-9 -12 -19 -24.5t-43.5 -44.5t-71 -60.5t-100 -65t-131.5 -64.5q25 -53 44 -95q2 -5 6.5 -17t7.5 -17q36 5 74.5 7t73.5 2t69 -1.5t64 -4t56.5 -5.5t48 -6.5t36.5 -6
+t25 -4.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="skype" unicode="&#xf17e;" 
+d="M1173 473q0 50 -19.5 91.5t-48.5 68.5t-73 49t-82.5 34t-87.5 23l-104 24q-30 7 -44 10.5t-35 11.5t-30 16t-16.5 21t-7.5 30q0 77 144 77q43 0 77 -12t54 -28.5t38 -33.5t40 -29t48 -12q47 0 75.5 32t28.5 77q0 55 -56 99.5t-142 67.5t-182 23q-68 0 -132 -15.5
+t-119.5 -47t-89 -87t-33.5 -128.5q0 -61 19 -106.5t56 -75.5t80 -48.5t103 -32.5l146 -36q90 -22 112 -36q32 -20 32 -60q0 -39 -40 -64.5t-105 -25.5q-51 0 -91.5 16t-65 38.5t-45.5 45t-46 38.5t-54 16q-50 0 -75.5 -30t-25.5 -75q0 -92 122 -157.5t291 -65.5
+q73 0 140 18.5t122.5 53.5t88.5 93.5t33 131.5zM1536 256q0 -159 -112.5 -271.5t-271.5 -112.5q-130 0 -234 80q-77 -16 -150 -16q-143 0 -273.5 55.5t-225 150t-150 225t-55.5 273.5q0 73 16 150q-80 104 -80 234q0 159 112.5 271.5t271.5 112.5q130 0 234 -80
+q77 16 150 16q143 0 273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -73 -16 -150q80 -104 80 -234z" />
+    <glyph glyph-name="foursquare" unicode="&#xf180;" horiz-adv-x="1280" 
+d="M1000 1102l37 194q5 23 -9 40t-35 17h-712q-23 0 -38.5 -17t-15.5 -37v-1101q0 -7 6 -1l291 352q23 26 38 33.5t48 7.5h239q22 0 37 14.5t18 29.5q24 130 37 191q4 21 -11.5 40t-36.5 19h-294q-29 0 -48 19t-19 48v42q0 29 19 47.5t48 18.5h346q18 0 35 13.5t20 29.5z
+M1227 1324q-15 -73 -53.5 -266.5t-69.5 -350t-35 -173.5q-6 -22 -9 -32.5t-14 -32.5t-24.5 -33t-38.5 -21t-58 -10h-271q-13 0 -22 -10q-8 -9 -426 -494q-22 -25 -58.5 -28.5t-48.5 5.5q-55 22 -55 98v1410q0 55 38 102.5t120 47.5h888q95 0 127 -53t10 -159zM1227 1324
+l-158 -790q4 17 35 173.5t69.5 350t53.5 266.5z" />
+    <glyph glyph-name="trello" unicode="&#xf181;" 
+d="M704 192v1024q0 14 -9 23t-23 9h-480q-14 0 -23 -9t-9 -23v-1024q0 -14 9 -23t23 -9h480q14 0 23 9t9 23zM1376 576v640q0 14 -9 23t-23 9h-480q-14 0 -23 -9t-9 -23v-640q0 -14 9 -23t23 -9h480q14 0 23 9t9 23zM1536 1344v-1408q0 -26 -19 -45t-45 -19h-1408
+q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h1408q26 0 45 -19t19 -45z" />
+    <glyph glyph-name="female" unicode="&#xf182;" horiz-adv-x="1280" 
+d="M1280 480q0 -40 -28 -68t-68 -28q-51 0 -80 43l-227 341h-45v-132l247 -411q9 -15 9 -33q0 -26 -19 -45t-45 -19h-192v-272q0 -46 -33 -79t-79 -33h-160q-46 0 -79 33t-33 79v272h-192q-26 0 -45 19t-19 45q0 18 9 33l247 411v132h-45l-227 -341q-29 -43 -80 -43
+q-40 0 -68 28t-28 68q0 29 16 53l256 384q73 107 176 107h384q103 0 176 -107l256 -384q16 -24 16 -53zM864 1280q0 -93 -65.5 -158.5t-158.5 -65.5t-158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5t158.5 -65.5t65.5 -158.5z" />
+    <glyph glyph-name="male" unicode="&#xf183;" horiz-adv-x="1024" 
+d="M1024 832v-416q0 -40 -28 -68t-68 -28t-68 28t-28 68v352h-64v-912q0 -46 -33 -79t-79 -33t-79 33t-33 79v464h-64v-464q0 -46 -33 -79t-79 -33t-79 33t-33 79v912h-64v-352q0 -40 -28 -68t-68 -28t-68 28t-28 68v416q0 80 56 136t136 56h640q80 0 136 -56t56 -136z
+M736 1280q0 -93 -65.5 -158.5t-158.5 -65.5t-158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5t158.5 -65.5t65.5 -158.5z" />
+    <glyph glyph-name="gittip" unicode="&#xf184;" 
+d="M773 234l350 473q16 22 24.5 59t-6 85t-61.5 79q-40 26 -83 25.5t-73.5 -17.5t-54.5 -45q-36 -40 -96 -40q-59 0 -95 40q-24 28 -54.5 45t-73.5 17.5t-84 -25.5q-46 -31 -60.5 -79t-6 -85t24.5 -59zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103
+t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="sun" unicode="&#xf185;" horiz-adv-x="1792" 
+d="M1472 640q0 117 -45.5 223.5t-123 184t-184 123t-223.5 45.5t-223.5 -45.5t-184 -123t-123 -184t-45.5 -223.5t45.5 -223.5t123 -184t184 -123t223.5 -45.5t223.5 45.5t184 123t123 184t45.5 223.5zM1748 363q-4 -15 -20 -20l-292 -96v-306q0 -16 -13 -26q-15 -10 -29 -4
+l-292 94l-180 -248q-10 -13 -26 -13t-26 13l-180 248l-292 -94q-14 -6 -29 4q-13 10 -13 26v306l-292 96q-16 5 -20 20q-5 17 4 29l180 248l-180 248q-9 13 -4 29q4 15 20 20l292 96v306q0 16 13 26q15 10 29 4l292 -94l180 248q9 12 26 12t26 -12l180 -248l292 94
+q14 6 29 -4q13 -10 13 -26v-306l292 -96q16 -5 20 -20q5 -16 -4 -29l-180 -248l180 -248q9 -12 4 -29z" />
+    <glyph glyph-name="_366" unicode="&#xf186;" 
+d="M1262 233q-54 -9 -110 -9q-182 0 -337 90t-245 245t-90 337q0 192 104 357q-201 -60 -328.5 -229t-127.5 -384q0 -130 51 -248.5t136.5 -204t204 -136.5t248.5 -51q144 0 273.5 61.5t220.5 171.5zM1465 318q-94 -203 -283.5 -324.5t-413.5 -121.5q-156 0 -298 61
+t-245 164t-164 245t-61 298q0 153 57.5 292.5t156 241.5t235.5 164.5t290 68.5q44 2 61 -39q18 -41 -15 -72q-86 -78 -131.5 -181.5t-45.5 -218.5q0 -148 73 -273t198 -198t273 -73q118 0 228 51q41 18 72 -13q14 -14 17.5 -34t-4.5 -38z" />
+    <glyph glyph-name="archive" unicode="&#xf187;" horiz-adv-x="1792" 
+d="M1088 704q0 26 -19 45t-45 19h-256q-26 0 -45 -19t-19 -45t19 -45t45 -19h256q26 0 45 19t19 45zM1664 896v-960q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v960q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1728 1344v-256q0 -26 -19 -45t-45 -19h-1536
+q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1536q26 0 45 -19t19 -45z" />
+    <glyph glyph-name="bug" unicode="&#xf188;" horiz-adv-x="1664" 
+d="M1632 576q0 -26 -19 -45t-45 -19h-224q0 -171 -67 -290l208 -209q19 -19 19 -45t-19 -45q-18 -19 -45 -19t-45 19l-198 197q-5 -5 -15 -13t-42 -28.5t-65 -36.5t-82 -29t-97 -13v896h-128v-896q-51 0 -101.5 13.5t-87 33t-66 39t-43.5 32.5l-15 14l-183 -207
+q-20 -21 -48 -21q-24 0 -43 16q-19 18 -20.5 44.5t15.5 46.5l202 227q-58 114 -58 274h-224q-26 0 -45 19t-19 45t19 45t45 19h224v294l-173 173q-19 19 -19 45t19 45t45 19t45 -19l173 -173h844l173 173q19 19 45 19t45 -19t19 -45t-19 -45l-173 -173v-294h224q26 0 45 -19
+t19 -45zM1152 1152h-640q0 133 93.5 226.5t226.5 93.5t226.5 -93.5t93.5 -226.5z" />
+    <glyph glyph-name="vk" unicode="&#xf189;" horiz-adv-x="1920" 
+d="M1917 1016q23 -64 -150 -294q-24 -32 -65 -85q-40 -51 -55 -72t-30.5 -49.5t-12 -42t13 -34.5t32.5 -43t57 -53q4 -2 5 -4q141 -131 191 -221q3 -5 6.5 -12.5t7 -26.5t-0.5 -34t-25 -27.5t-59 -12.5l-256 -4q-24 -5 -56 5t-52 22l-20 12q-30 21 -70 64t-68.5 77.5t-61 58
+t-56.5 15.5q-3 -1 -8 -3.5t-17 -14.5t-21.5 -29.5t-17 -52t-6.5 -77.5q0 -15 -3.5 -27.5t-7.5 -18.5l-4 -5q-18 -19 -53 -22h-115q-71 -4 -146 16.5t-131.5 53t-103 66t-70.5 57.5l-25 24q-10 10 -27.5 30t-71.5 91t-106 151t-122.5 211t-130.5 272q-6 16 -6 27t3 16l4 6
+q15 19 57 19l274 2q12 -2 23 -6.5t16 -8.5l5 -3q16 -11 24 -32q20 -50 46 -103.5t41 -81.5l16 -29q29 -60 56 -104t48.5 -68.5t41.5 -38.5t34 -14t27 5q2 1 5 5t12 22t13.5 47t9.5 81t0 125q-2 40 -9 73t-14 46l-6 12q-25 34 -85 43q-13 2 5 24q16 19 38 30q53 26 239 24
+q82 -1 135 -13q20 -5 33.5 -13.5t20.5 -24t10.5 -32t3.5 -45.5t-1 -55t-2.5 -70.5t-1.5 -82.5q0 -11 -1 -42t-0.5 -48t3.5 -40.5t11.5 -39t22.5 -24.5q8 -2 17 -4t26 11t38 34.5t52 67t68 107.5q60 104 107 225q4 10 10 17.5t11 10.5l4 3l5 2.5t13 3t20 0.5l288 2
+q39 5 64 -2.5t31 -16.5z" />
+    <glyph glyph-name="weibo" unicode="&#xf18a;" horiz-adv-x="1792" 
+d="M675 252q21 34 11 69t-45 50q-34 14 -73 1t-60 -46q-22 -34 -13 -68.5t43 -50.5t74.5 -2.5t62.5 47.5zM769 373q8 13 3.5 26.5t-17.5 18.5q-14 5 -28.5 -0.5t-21.5 -18.5q-17 -31 13 -45q14 -5 29 0.5t22 18.5zM943 266q-45 -102 -158 -150t-224 -12
+q-107 34 -147.5 126.5t6.5 187.5q47 93 151.5 139t210.5 19q111 -29 158.5 -119.5t2.5 -190.5zM1255 426q-9 96 -89 170t-208.5 109t-274.5 21q-223 -23 -369.5 -141.5t-132.5 -264.5q9 -96 89 -170t208.5 -109t274.5 -21q223 23 369.5 141.5t132.5 264.5zM1563 422
+q0 -68 -37 -139.5t-109 -137t-168.5 -117.5t-226 -83t-270.5 -31t-275 33.5t-240.5 93t-171.5 151t-65 199.5q0 115 69.5 245t197.5 258q169 169 341.5 236t246.5 -7q65 -64 20 -209q-4 -14 -1 -20t10 -7t14.5 0.5t13.5 3.5l6 2q139 59 246 59t153 -61q45 -63 0 -178
+q-2 -13 -4.5 -20t4.5 -12.5t12 -7.5t17 -6q57 -18 103 -47t80 -81.5t34 -116.5zM1489 1046q42 -47 54.5 -108.5t-6.5 -117.5q-8 -23 -29.5 -34t-44.5 -4q-23 8 -34 29.5t-4 44.5q20 63 -24 111t-107 35q-24 -5 -45 8t-25 37q-5 24 8 44.5t37 25.5q60 13 119 -5.5t101 -65.5z
+M1670 1209q87 -96 112.5 -222.5t-13.5 -241.5q-9 -27 -34 -40t-52 -4t-40 34t-5 52q28 82 10 172t-80 158q-62 69 -148 95.5t-173 8.5q-28 -6 -52 9.5t-30 43.5t9.5 51.5t43.5 29.5q123 26 244 -11.5t208 -134.5z" />
+    <glyph glyph-name="renren" unicode="&#xf18b;" 
+d="M1133 -34q-171 -94 -368 -94q-196 0 -367 94q138 87 235.5 211t131.5 268q35 -144 132.5 -268t235.5 -211zM638 1394v-485q0 -252 -126.5 -459.5t-330.5 -306.5q-181 215 -181 495q0 187 83.5 349.5t229.5 269.5t325 137zM1536 638q0 -280 -181 -495
+q-204 99 -330.5 306.5t-126.5 459.5v485q179 -30 325 -137t229.5 -269.5t83.5 -349.5z" />
+    <glyph glyph-name="_372" unicode="&#xf18c;" horiz-adv-x="1408" 
+d="M1402 433q-32 -80 -76 -138t-91 -88.5t-99 -46.5t-101.5 -14.5t-96.5 8.5t-86.5 22t-69.5 27.5t-46 22.5l-17 10q-113 -228 -289.5 -359.5t-384.5 -132.5q-19 0 -32 13t-13 32t13 31.5t32 12.5q173 1 322.5 107.5t251.5 294.5q-36 -14 -72 -23t-83 -13t-91 2.5t-93 28.5
+t-92 59t-84.5 100t-74.5 146q114 47 214 57t167.5 -7.5t124.5 -56.5t88.5 -77t56.5 -82q53 131 79 291q-7 -1 -18 -2.5t-46.5 -2.5t-69.5 0.5t-81.5 10t-88.5 23t-84 42.5t-75 65t-54.5 94.5t-28.5 127.5q70 28 133.5 36.5t112.5 -1t92 -30t73.5 -50t56 -61t42 -63t27.5 -56
+t16 -39.5l4 -16q12 122 12 195q-8 6 -21.5 16t-49 44.5t-63.5 71.5t-54 93t-33 112.5t12 127t70 138.5q73 -25 127.5 -61.5t84.5 -76.5t48 -85t20.5 -89t-0.5 -85.5t-13 -76.5t-19 -62t-17 -42l-7 -15q1 -4 1 -50t-1 -72q3 7 10 18.5t30.5 43t50.5 58t71 55.5t91.5 44.5
+t112 14.5t132.5 -24q-2 -78 -21.5 -141.5t-50 -104.5t-69.5 -71.5t-81.5 -45.5t-84.5 -24t-80 -9.5t-67.5 1t-46.5 4.5l-17 3q-23 -147 -73 -283q6 7 18 18.5t49.5 41t77.5 52.5t99.5 42t117.5 20t129 -23.5t137 -77.5z" />
+    <glyph glyph-name="stack_exchange" unicode="&#xf18d;" horiz-adv-x="1280" 
+d="M1259 283v-66q0 -85 -57.5 -144.5t-138.5 -59.5h-57l-260 -269v269h-529q-81 0 -138.5 59.5t-57.5 144.5v66h1238zM1259 609v-255h-1238v255h1238zM1259 937v-255h-1238v255h1238zM1259 1077v-67h-1238v67q0 84 57.5 143.5t138.5 59.5h846q81 0 138.5 -59.5t57.5 -143.5z
+" />
+    <glyph glyph-name="_374" unicode="&#xf18e;" 
+d="M1152 640q0 -14 -9 -23l-320 -320q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5v192h-352q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h352v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198
+t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="arrow_circle_alt_left" unicode="&#xf190;" 
+d="M1152 736v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-352v-192q0 -14 -9 -23t-23 -9q-12 0 -24 10l-319 319q-9 9 -9 23t9 23l320 320q9 9 23 9q13 0 22.5 -9.5t9.5 -22.5v-192h352q13 0 22.5 -9.5t9.5 -22.5zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198
+t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="_376" unicode="&#xf191;" 
+d="M1024 960v-640q0 -26 -19 -45t-45 -19q-20 0 -37 12l-448 320q-27 19 -27 52t27 52l448 320q17 12 37 12q26 0 45 -19t19 -45zM1280 160v960q0 13 -9.5 22.5t-22.5 9.5h-960q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h960q13 0 22.5 9.5t9.5 22.5z
+M1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="dot_circle_alt" unicode="&#xf192;" 
+d="M1024 640q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75t75 -181zM768 1184q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273t-73 273t-198 198t-273 73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5
+t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="_378" unicode="&#xf193;" horiz-adv-x="1664" 
+d="M1023 349l102 -204q-58 -179 -210 -290t-339 -111q-156 0 -288.5 77.5t-210 210t-77.5 288.5q0 181 104.5 330t274.5 211l17 -131q-122 -54 -195 -165.5t-73 -244.5q0 -185 131.5 -316.5t316.5 -131.5q126 0 232.5 65t165 175.5t49.5 236.5zM1571 249l58 -114l-256 -128
+q-13 -7 -29 -7q-40 0 -57 35l-239 477h-472q-24 0 -42.5 16.5t-21.5 40.5l-96 779q-2 17 6 42q14 51 57 82.5t97 31.5q66 0 113 -47t47 -113q0 -69 -52 -117.5t-120 -41.5l37 -289h423v-128h-407l16 -128h455q40 0 57 -35l228 -455z" />
+    <glyph glyph-name="vimeo_square" unicode="&#xf194;" 
+d="M1292 898q10 216 -161 222q-231 8 -312 -261q44 19 82 19q85 0 74 -96q-4 -57 -74 -167t-105 -110q-43 0 -82 169q-13 54 -45 255q-30 189 -160 177q-59 -7 -164 -100l-81 -72l-81 -72l52 -67q76 52 87 52q57 0 107 -179q15 -55 45 -164.5t45 -164.5q68 -179 164 -179
+q157 0 383 294q220 283 226 444zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="_380" unicode="&#xf195;" horiz-adv-x="1152" 
+d="M1152 704q0 -191 -94.5 -353t-256.5 -256.5t-353 -94.5h-160q-14 0 -23 9t-9 23v611l-215 -66q-3 -1 -9 -1q-10 0 -19 6q-13 10 -13 26v128q0 23 23 31l233 71v93l-215 -66q-3 -1 -9 -1q-10 0 -19 6q-13 10 -13 26v128q0 23 23 31l233 71v250q0 14 9 23t23 9h160
+q14 0 23 -9t9 -23v-181l375 116q15 5 28 -5t13 -26v-128q0 -23 -23 -31l-393 -121v-93l375 116q15 5 28 -5t13 -26v-128q0 -23 -23 -31l-393 -121v-487q188 13 318 151t130 328q0 14 9 23t23 9h160q14 0 23 -9t9 -23z" />
+    <glyph glyph-name="plus_square_o" unicode="&#xf196;" horiz-adv-x="1408" 
+d="M1152 736v-64q0 -14 -9 -23t-23 -9h-352v-352q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v352h-352q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h352v352q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-352h352q14 0 23 -9t9 -23zM1280 288v832q0 66 -47 113t-113 47h-832
+q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113zM1408 1120v-832q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="_382" unicode="&#xf197;" horiz-adv-x="2176" 
+d="M620 416q-110 -64 -268 -64h-128v64h-64q-13 0 -22.5 23.5t-9.5 56.5q0 24 7 49q-58 2 -96.5 10.5t-38.5 20.5t38.5 20.5t96.5 10.5q-7 25 -7 49q0 33 9.5 56.5t22.5 23.5h64v64h128q158 0 268 -64h1113q42 -7 106.5 -18t80.5 -14q89 -15 150 -40.5t83.5 -47.5t22.5 -40
+t-22.5 -40t-83.5 -47.5t-150 -40.5q-16 -3 -80.5 -14t-106.5 -18h-1113zM1739 668q53 -36 53 -92t-53 -92l81 -30q68 48 68 122t-68 122zM625 400h1015q-217 -38 -456 -80q-57 0 -113 -24t-83 -48l-28 -24l-288 -288q-26 -26 -70.5 -45t-89.5 -19h-96l-93 464h29
+q157 0 273 64zM352 816h-29l93 464h96q46 0 90 -19t70 -45l288 -288q4 -4 11 -10.5t30.5 -23t48.5 -29t61.5 -23t72.5 -10.5l456 -80h-1015q-116 64 -273 64z" />
+    <glyph glyph-name="_383" unicode="&#xf198;" horiz-adv-x="1664" 
+d="M1519 760q62 0 103.5 -40.5t41.5 -101.5q0 -97 -93 -130l-172 -59l56 -167q7 -21 7 -47q0 -59 -42 -102t-101 -43q-47 0 -85.5 27t-53.5 72l-55 165l-310 -106l55 -164q8 -24 8 -47q0 -59 -42 -102t-102 -43q-47 0 -85 27t-53 72l-55 163l-153 -53q-29 -9 -50 -9
+q-61 0 -101.5 40t-40.5 101q0 47 27.5 85t71.5 53l156 53l-105 313l-156 -54q-26 -8 -48 -8q-60 0 -101 40.5t-41 100.5q0 47 27.5 85t71.5 53l157 53l-53 159q-8 24 -8 47q0 60 42 102.5t102 42.5q47 0 85 -27t53 -72l54 -160l310 105l-54 160q-8 24 -8 47q0 59 42.5 102
+t101.5 43q47 0 85.5 -27.5t53.5 -71.5l53 -161l162 55q21 6 43 6q60 0 102.5 -39.5t42.5 -98.5q0 -45 -30 -81.5t-74 -51.5l-157 -54l105 -316l164 56q24 8 46 8zM725 498l310 105l-105 315l-310 -107z" />
+    <glyph glyph-name="_384" unicode="&#xf199;" 
+d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960zM1280 352v436q-31 -35 -64 -55q-34 -22 -132.5 -85t-151.5 -99q-98 -69 -164 -69v0v0q-66 0 -164 69
+q-47 32 -142 92.5t-142 92.5q-12 8 -33 27t-31 27v-436q0 -40 28 -68t68 -28h832q40 0 68 28t28 68zM1280 925q0 41 -27.5 70t-68.5 29h-832q-40 0 -68 -28t-28 -68q0 -37 30.5 -76.5t67.5 -64.5q47 -32 137.5 -89t129.5 -83q3 -2 17 -11.5t21 -14t21 -13t23.5 -13
+t21.5 -9.5t22.5 -7.5t20.5 -2.5t20.5 2.5t22.5 7.5t21.5 9.5t23.5 13t21 13t21 14t17 11.5l267 174q35 23 66.5 62.5t31.5 73.5z" />
+    <glyph glyph-name="_385" unicode="&#xf19a;" horiz-adv-x="1792" 
+d="M127 640q0 163 67 313l367 -1005q-196 95 -315 281t-119 411zM1415 679q0 -19 -2.5 -38.5t-10 -49.5t-11.5 -44t-17.5 -59t-17.5 -58l-76 -256l-278 826q46 3 88 8q19 2 26 18.5t-2.5 31t-28.5 13.5l-205 -10q-75 1 -202 10q-12 1 -20.5 -5t-11.5 -15t-1.5 -18.5t9 -16.5
+t19.5 -8l80 -8l120 -328l-168 -504l-280 832q46 3 88 8q19 2 26 18.5t-2.5 31t-28.5 13.5l-205 -10q-7 0 -23 0.5t-26 0.5q105 160 274.5 253.5t367.5 93.5q147 0 280.5 -53t238.5 -149h-10q-55 0 -92 -40.5t-37 -95.5q0 -12 2 -24t4 -21.5t8 -23t9 -21t12 -22.5t12.5 -21
+t14.5 -24t14 -23q63 -107 63 -212zM909 573l237 -647q1 -6 5 -11q-126 -44 -255 -44q-112 0 -217 32zM1570 1009q95 -174 95 -369q0 -209 -104 -385.5t-279 -278.5l235 678q59 169 59 276q0 42 -6 79zM896 1536q182 0 348 -71t286 -191t191 -286t71 -348t-71 -348t-191 -286
+t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71zM896 -215q173 0 331.5 68t273 182.5t182.5 273t68 331.5t-68 331.5t-182.5 273t-273 182.5t-331.5 68t-331.5 -68t-273 -182.5t-182.5 -273t-68 -331.5t68 -331.5t182.5 -273
+t273 -182.5t331.5 -68z" />
+    <glyph glyph-name="_386" unicode="&#xf19b;" horiz-adv-x="1792" 
+d="M1086 1536v-1536l-272 -128q-228 20 -414 102t-293 208.5t-107 272.5q0 140 100.5 263.5t275 205.5t391.5 108v-172q-217 -38 -356.5 -150t-139.5 -255q0 -152 154.5 -267t388.5 -145v1360zM1755 954l37 -390l-525 114l147 83q-119 70 -280 99v172q277 -33 481 -157z" />
+    <glyph glyph-name="_387" unicode="&#xf19c;" horiz-adv-x="2048" 
+d="M960 1536l960 -384v-128h-128q0 -26 -20.5 -45t-48.5 -19h-1526q-28 0 -48.5 19t-20.5 45h-128v128zM256 896h256v-768h128v768h256v-768h128v768h256v-768h128v768h256v-768h59q28 0 48.5 -19t20.5 -45v-64h-1664v64q0 26 20.5 45t48.5 19h59v768zM1851 -64
+q28 0 48.5 -19t20.5 -45v-128h-1920v128q0 26 20.5 45t48.5 19h1782z" />
+    <glyph glyph-name="_388" unicode="&#xf19d;" horiz-adv-x="2304" 
+d="M1774 700l18 -316q4 -69 -82 -128t-235 -93.5t-323 -34.5t-323 34.5t-235 93.5t-82 128l18 316l574 -181q22 -7 48 -7t48 7zM2304 1024q0 -23 -22 -31l-1120 -352q-4 -1 -10 -1t-10 1l-652 206q-43 -34 -71 -111.5t-34 -178.5q63 -36 63 -109q0 -69 -58 -107l58 -433
+q2 -14 -8 -25q-9 -11 -24 -11h-192q-15 0 -24 11q-10 11 -8 25l58 433q-58 38 -58 107q0 73 65 111q11 207 98 330l-333 104q-22 8 -22 31t22 31l1120 352q4 1 10 1t10 -1l1120 -352q22 -8 22 -31z" />
+    <glyph glyph-name="_389" unicode="&#xf19e;" 
+d="M859 579l13 -707q-62 11 -105 11q-41 0 -105 -11l13 707q-40 69 -168.5 295.5t-216.5 374.5t-181 287q58 -15 108 -15q44 0 111 15q63 -111 133.5 -229.5t167 -276.5t138.5 -227q37 61 109.5 177.5t117.5 190t105 176t107 189.5q54 -14 107 -14q56 0 114 14v0
+q-28 -39 -60 -88.5t-49.5 -78.5t-56.5 -96t-49 -84q-146 -248 -353 -610z" />
+    <glyph glyph-name="uniF1A0" unicode="&#xf1a0;" 
+d="M768 750h725q12 -67 12 -128q0 -217 -91 -387.5t-259.5 -266.5t-386.5 -96q-157 0 -299 60.5t-245 163.5t-163.5 245t-60.5 299t60.5 299t163.5 245t245 163.5t299 60.5q300 0 515 -201l-209 -201q-123 119 -306 119q-129 0 -238.5 -65t-173.5 -176.5t-64 -243.5
+t64 -243.5t173.5 -176.5t238.5 -65q87 0 160 24t120 60t82 82t51.5 87t22.5 78h-436v264z" />
+    <glyph glyph-name="f1a1" unicode="&#xf1a1;" horiz-adv-x="1792" 
+d="M1095 369q16 -16 0 -31q-62 -62 -199 -62t-199 62q-16 15 0 31q6 6 15 6t15 -6q48 -49 169 -49q120 0 169 49q6 6 15 6t15 -6zM788 550q0 -37 -26 -63t-63 -26t-63.5 26t-26.5 63q0 38 26.5 64t63.5 26t63 -26.5t26 -63.5zM1183 550q0 -37 -26.5 -63t-63.5 -26t-63 26
+t-26 63t26 63.5t63 26.5t63.5 -26t26.5 -64zM1434 670q0 49 -35 84t-85 35t-86 -36q-130 90 -311 96l63 283l200 -45q0 -37 26 -63t63 -26t63.5 26.5t26.5 63.5t-26.5 63.5t-63.5 26.5q-54 0 -80 -50l-221 49q-19 5 -25 -16l-69 -312q-180 -7 -309 -97q-35 37 -87 37
+q-50 0 -85 -35t-35 -84q0 -35 18.5 -64t49.5 -44q-6 -27 -6 -56q0 -142 140 -243t337 -101q198 0 338 101t140 243q0 32 -7 57q30 15 48 43.5t18 63.5zM1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191
+t348 71t348 -71t286 -191t191 -286t71 -348z" />
+    <glyph glyph-name="_392" unicode="&#xf1a2;" 
+d="M939 407q13 -13 0 -26q-53 -53 -171 -53t-171 53q-13 13 0 26q5 6 13 6t13 -6q42 -42 145 -42t145 42q5 6 13 6t13 -6zM676 563q0 -31 -23 -54t-54 -23t-54 23t-23 54q0 32 22.5 54.5t54.5 22.5t54.5 -22.5t22.5 -54.5zM1014 563q0 -31 -23 -54t-54 -23t-54 23t-23 54
+q0 32 22.5 54.5t54.5 22.5t54.5 -22.5t22.5 -54.5zM1229 666q0 42 -30 72t-73 30q-42 0 -73 -31q-113 78 -267 82l54 243l171 -39q1 -32 23.5 -54t53.5 -22q32 0 54.5 22.5t22.5 54.5t-22.5 54.5t-54.5 22.5q-48 0 -69 -43l-189 42q-17 5 -21 -13l-60 -268q-154 -6 -265 -83
+q-30 32 -74 32q-43 0 -73 -30t-30 -72q0 -30 16 -55t42 -38q-5 -25 -5 -48q0 -122 120 -208.5t289 -86.5q170 0 290 86.5t120 208.5q0 25 -6 49q25 13 40.5 37.5t15.5 54.5zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960
+q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="_393" unicode="&#xf1a3;" 
+d="M866 697l90 27v62q0 79 -58 135t-138 56t-138 -55.5t-58 -134.5v-283q0 -20 -14 -33.5t-33 -13.5t-32.5 13.5t-13.5 33.5v120h-151v-122q0 -82 57.5 -139t139.5 -57q81 0 138.5 56.5t57.5 136.5v280q0 19 13.5 33t33.5 14q19 0 32.5 -14t13.5 -33v-54zM1199 502v122h-150
+v-126q0 -20 -13.5 -33.5t-33.5 -13.5q-19 0 -32.5 14t-13.5 33v123l-90 -26l-60 28v-123q0 -80 58 -137t139 -57t138.5 57t57.5 139zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103
+t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="f1a4" unicode="&#xf1a4;" horiz-adv-x="1920" 
+d="M1062 824v118q0 42 -30 72t-72 30t-72 -30t-30 -72v-612q0 -175 -126 -299t-303 -124q-178 0 -303.5 125.5t-125.5 303.5v266h328v-262q0 -43 30 -72.5t72 -29.5t72 29.5t30 72.5v620q0 171 126.5 292t301.5 121q176 0 302 -122t126 -294v-136l-195 -58zM1592 602h328
+v-266q0 -178 -125.5 -303.5t-303.5 -125.5q-177 0 -303 124.5t-126 300.5v268l131 -61l195 58v-270q0 -42 30 -71.5t72 -29.5t72 29.5t30 71.5v275z" />
+    <glyph glyph-name="_395" unicode="&#xf1a5;" 
+d="M1472 160v480h-704v704h-480q-93 0 -158.5 -65.5t-65.5 -158.5v-480h704v-704h480q93 0 158.5 65.5t65.5 158.5zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5
+t84.5 -203.5z" />
+    <glyph glyph-name="_396" unicode="&#xf1a6;" horiz-adv-x="2048" 
+d="M328 1254h204v-983h-532v697h328v286zM328 435v369h-123v-369h123zM614 968v-697h205v697h-205zM614 1254v-204h205v204h-205zM901 968h533v-942h-533v163h328v82h-328v697zM1229 435v369h-123v-369h123zM1516 968h532v-942h-532v163h327v82h-327v697zM1843 435v369h-123
+v-369h123z" />
+    <glyph glyph-name="_397" unicode="&#xf1a7;" 
+d="M1046 516q0 -64 -38 -109t-91 -45q-43 0 -70 15v277q28 17 70 17q53 0 91 -45.5t38 -109.5zM703 944q0 -64 -38 -109.5t-91 -45.5q-43 0 -70 15v277q28 17 70 17q53 0 91 -45t38 -109zM1265 513q0 134 -88 229t-213 95q-20 0 -39 -3q-23 -78 -78 -136q-87 -95 -211 -101
+v-636l211 41v206q51 -19 117 -19q125 0 213 95t88 229zM922 940q0 134 -88.5 229t-213.5 95q-74 0 -141 -36h-186v-840l211 41v206q55 -19 116 -19q125 0 213.5 95t88.5 229zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960
+q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="_398" unicode="&#xf1a8;" horiz-adv-x="2038" 
+d="M1222 607q75 3 143.5 -20.5t118 -58.5t101 -94.5t84 -108t75.5 -120.5q33 -56 78.5 -109t75.5 -80.5t99 -88.5q-48 -30 -108.5 -57.5t-138.5 -59t-114 -47.5q-44 37 -74 115t-43.5 164.5t-33 180.5t-42.5 168.5t-72.5 123t-122.5 48.5l-10 -2l-6 -4q4 -5 13 -14
+q6 -5 28 -23.5t25.5 -22t19 -18t18 -20.5t11.5 -21t10.5 -27.5t4.5 -31t4 -40.5l1 -33q1 -26 -2.5 -57.5t-7.5 -52t-12.5 -58.5t-11.5 -53q-35 1 -101 -9.5t-98 -10.5q-39 0 -72 10q-2 16 -2 47q0 74 3 96q2 13 31.5 41.5t57 59t26.5 51.5q-24 2 -43 -24
+q-36 -53 -111.5 -99.5t-136.5 -46.5q-25 0 -75.5 63t-106.5 139.5t-84 96.5q-6 4 -27 30q-482 -112 -513 -112q-16 0 -28 11t-12 27q0 15 8.5 26.5t22.5 14.5l486 106q-8 14 -8 25t5.5 17.5t16 11.5t20 7t23 4.5t18.5 4.5q4 1 15.5 7.5t17.5 6.5q15 0 28 -16t20 -33
+q163 37 172 37q17 0 29.5 -11t12.5 -28q0 -15 -8.5 -26t-23.5 -14l-182 -40l-1 -16q-1 -26 81.5 -117.5t104.5 -91.5q47 0 119 80t72 129q0 36 -23.5 53t-51 18.5t-51 11.5t-23.5 34q0 16 10 34l-68 19q43 44 43 117q0 26 -5 58q82 16 144 16q44 0 71.5 -1.5t48.5 -8.5
+t31 -13.5t20.5 -24.5t15.5 -33.5t17 -47.5t24 -60l50 25q-3 -40 -23 -60t-42.5 -21t-40 -6.5t-16.5 -20.5zM1282 842q-5 5 -13.5 15.5t-12 14.5t-10.5 11.5t-10 10.5l-8 8t-8.5 7.5t-8 5t-8.5 4.5q-7 3 -14.5 5t-20.5 2.5t-22 0.5h-32.5h-37.5q-126 0 -217 -43
+q16 30 36 46.5t54 29.5t65.5 36t46 36.5t50 55t43.5 50.5q12 -9 28 -31.5t32 -36.5t38 -13l12 1v-76l22 -1q247 95 371 190q28 21 50 39t42.5 37.5t33 31t29.5 34t24 31t24.5 37t23 38t27 47.5t29.5 53l7 9q-2 -53 -43 -139q-79 -165 -205 -264t-306 -142q-14 -3 -42 -7.5
+t-50 -9.5t-39 -14q3 -19 24.5 -46t21.5 -34q0 -11 -26 -30zM1061 -79q39 26 131.5 47.5t146.5 21.5q9 0 22.5 -15.5t28 -42.5t26 -50t24 -51t14.5 -33q-121 -45 -244 -45q-61 0 -125 11zM822 568l48 12l109 -177l-73 -48zM1323 51q3 -15 3 -16q0 -7 -17.5 -14.5t-46 -13
+t-54 -9.5t-53.5 -7.5t-32 -4.5l-7 43q21 2 60.5 8.5t72 10t60.5 3.5h14zM866 679l-96 -20l-6 17q10 1 32.5 7t34.5 6q19 0 35 -10zM1061 45h31l10 -83l-41 -12v95zM1950 1535v1v-1zM1950 1535l-1 -5l-2 -2l1 3zM1950 1535l1 1z" />
+    <glyph glyph-name="_399" unicode="&#xf1a9;" 
+d="M1167 -50q-5 19 -24 5q-30 -22 -87 -39t-131 -17q-129 0 -193 49q-5 4 -13 4q-11 0 -26 -12q-7 -6 -7.5 -16t7.5 -20q34 -32 87.5 -46t102.5 -12.5t99 4.5q41 4 84.5 20.5t65 30t28.5 20.5q12 12 7 29zM1128 65q-19 47 -39 61q-23 15 -76 15q-47 0 -71 -10
+q-29 -12 -78 -56q-26 -24 -12 -44q9 -8 17.5 -4.5t31.5 23.5q3 2 10.5 8.5t10.5 8.5t10 7t11.5 7t12.5 5t15 4.5t16.5 2.5t20.5 1q27 0 44.5 -7.5t23 -14.5t13.5 -22q10 -17 12.5 -20t12.5 1q23 12 14 34zM1483 346q0 22 -5 44.5t-16.5 45t-34 36.5t-52.5 14
+q-33 0 -97 -41.5t-129 -83.5t-101 -42q-27 -1 -63.5 19t-76 49t-83.5 58t-100 49t-111 19q-115 -1 -197 -78.5t-84 -178.5q-2 -112 74 -164q29 -20 62.5 -28.5t103.5 -8.5q57 0 132 32.5t134 71t120 70.5t93 31q26 -1 65 -31.5t71.5 -67t68 -67.5t55.5 -32q35 -3 58.5 14
+t55.5 63q28 41 42.5 101t14.5 106zM1536 506q0 -164 -62 -304.5t-166 -236t-242.5 -149.5t-290.5 -54t-293 57.5t-247.5 157t-170.5 241.5t-64 302q0 89 19.5 172.5t49 145.5t70.5 118.5t78.5 94t78.5 69.5t64.5 46.5t42.5 24.5q14 8 51 26.5t54.5 28.5t48 30t60.5 44
+q36 28 58 72.5t30 125.5q129 -155 186 -193q44 -29 130 -68t129 -66q21 -13 39 -25t60.5 -46.5t76 -70.5t75 -95t69 -122t47 -148.5t19.5 -177.5z" />
+    <glyph glyph-name="_400" unicode="&#xf1aa;" 
+d="M1070 463l-160 -160l-151 -152l-30 -30q-65 -64 -151.5 -87t-171.5 -2q-16 -70 -72 -115t-129 -45q-85 0 -145 60.5t-60 145.5q0 72 44.5 128t113.5 72q-22 86 1 173t88 152l12 12l151 -152l-11 -11q-37 -37 -37 -89t37 -90q37 -37 89 -37t89 37l30 30l151 152l161 160z
+M729 1145l12 -12l-152 -152l-12 12q-37 37 -89 37t-89 -37t-37 -89.5t37 -89.5l29 -29l152 -152l160 -160l-151 -152l-161 160l-151 152l-30 30q-68 67 -90 159.5t5 179.5q-70 15 -115 71t-45 129q0 85 60 145.5t145 60.5q76 0 133.5 -49t69.5 -123q84 20 169.5 -3.5
+t149.5 -87.5zM1536 78q0 -85 -60 -145.5t-145 -60.5q-74 0 -131 47t-71 118q-86 -28 -179.5 -6t-161.5 90l-11 12l151 152l12 -12q37 -37 89 -37t89 37t37 89t-37 89l-30 30l-152 152l-160 160l152 152l160 -160l152 -152l29 -30q64 -64 87.5 -150.5t2.5 -171.5
+q76 -11 126.5 -68.5t50.5 -134.5zM1534 1202q0 -77 -51 -135t-127 -69q26 -85 3 -176.5t-90 -158.5l-12 -12l-151 152l12 12q37 37 37 89t-37 89t-89 37t-89 -37l-30 -30l-152 -152l-160 -160l-152 152l161 160l152 152l29 30q67 67 159 89.5t178 -3.5q11 75 68.5 126
+t135.5 51q85 0 145 -60.5t60 -145.5z" />
+    <glyph glyph-name="f1ab" unicode="&#xf1ab;" 
+d="M654 458q-1 -3 -12.5 0.5t-31.5 11.5l-20 9q-44 20 -87 49q-7 5 -41 31.5t-38 28.5q-67 -103 -134 -181q-81 -95 -105 -110q-4 -2 -19.5 -4t-18.5 0q6 4 82 92q21 24 85.5 115t78.5 118q17 30 51 98.5t36 77.5q-8 1 -110 -33q-8 -2 -27.5 -7.5t-34.5 -9.5t-17 -5
+q-2 -2 -2 -10.5t-1 -9.5q-5 -10 -31 -15q-23 -7 -47 0q-18 4 -28 21q-4 6 -5 23q6 2 24.5 5t29.5 6q58 16 105 32q100 35 102 35q10 2 43 19.5t44 21.5q9 3 21.5 8t14.5 5.5t6 -0.5q2 -12 -1 -33q0 -2 -12.5 -27t-26.5 -53.5t-17 -33.5q-25 -50 -77 -131l64 -28
+q12 -6 74.5 -32t67.5 -28q4 -1 10.5 -25.5t4.5 -30.5zM449 944q3 -15 -4 -28q-12 -23 -50 -38q-30 -12 -60 -12q-26 3 -49 26q-14 15 -18 41l1 3q3 -3 19.5 -5t26.5 0t58 16q36 12 55 14q17 0 21 -17zM1147 815l63 -227l-139 42zM39 15l694 232v1032l-694 -233v-1031z
+M1280 332l102 -31l-181 657l-100 31l-216 -536l102 -31l45 110l211 -65zM777 1294l573 -184v380zM1088 -29l158 -13l-54 -160l-40 66q-130 -83 -276 -108q-58 -12 -91 -12h-84q-79 0 -199.5 39t-183.5 85q-8 7 -8 16q0 8 5 13.5t13 5.5q4 0 18 -7.5t30.5 -16.5t20.5 -11
+q73 -37 159.5 -61.5t157.5 -24.5q95 0 167 14.5t157 50.5q15 7 30.5 15.5t34 19t28.5 16.5zM1536 1050v-1079l-774 246q-14 -6 -375 -127.5t-368 -121.5q-13 0 -18 13q0 1 -1 3v1078q3 9 4 10q5 6 20 11q107 36 149 50v384l558 -198q2 0 160.5 55t316 108.5t161.5 53.5
+q20 0 20 -21v-418z" />
+    <glyph glyph-name="_402" unicode="&#xf1ac;" horiz-adv-x="1792" 
+d="M288 1152q66 0 113 -47t47 -113v-1088q0 -66 -47 -113t-113 -47h-128q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h128zM1664 989q58 -34 93 -93t35 -128v-768q0 -106 -75 -181t-181 -75h-864q-66 0 -113 47t-47 113v1536q0 40 28 68t68 28h672q40 0 88 -20t76 -48
+l152 -152q28 -28 48 -76t20 -88v-163zM928 0v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM928 256v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM928 512v128q0 14 -9 23
+t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM1184 0v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM1184 256v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128
+q14 0 23 9t9 23zM1184 512v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM1440 0v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM1440 256v128q0 14 -9 23t-23 9h-128
+q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM1440 512v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM1536 896v256h-160q-40 0 -68 28t-28 68v160h-640v-512h896z" />
+    <glyph glyph-name="_403" unicode="&#xf1ad;" 
+d="M1344 1536q26 0 45 -19t19 -45v-1664q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v1664q0 26 19 45t45 19h1280zM512 1248v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23zM512 992v-64q0 -14 9 -23t23 -9h64q14 0 23 9
+t9 23v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23zM512 736v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23zM512 480v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23zM384 160v64
+q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM384 416v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM384 672v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64
+q14 0 23 9t9 23zM384 928v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM384 1184v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM896 -96v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9
+t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM896 416v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM896 672v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM896 928v64
+q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM896 1184v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1152 160v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64
+q14 0 23 9t9 23zM1152 416v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1152 672v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1152 928v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9
+t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1152 1184v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23z" />
+    <glyph glyph-name="_404" unicode="&#xf1ae;" horiz-adv-x="1280" 
+d="M1188 988l-292 -292v-824q0 -46 -33 -79t-79 -33t-79 33t-33 79v384h-64v-384q0 -46 -33 -79t-79 -33t-79 33t-33 79v824l-292 292q-28 28 -28 68t28 68q29 28 68.5 28t67.5 -28l228 -228h368l228 228q28 28 68 28t68 -28q28 -29 28 -68.5t-28 -67.5zM864 1152
+q0 -93 -65.5 -158.5t-158.5 -65.5t-158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5t158.5 -65.5t65.5 -158.5z" />
+    <glyph glyph-name="uniF1B1" unicode="&#xf1b0;" horiz-adv-x="1664" 
+d="M780 1064q0 -60 -19 -113.5t-63 -92.5t-105 -39q-76 0 -138 57.5t-92 135.5t-30 151q0 60 19 113.5t63 92.5t105 39q77 0 138.5 -57.5t91.5 -135t30 -151.5zM438 581q0 -80 -42 -139t-119 -59q-76 0 -141.5 55.5t-100.5 133.5t-35 152q0 80 42 139.5t119 59.5
+q76 0 141.5 -55.5t100.5 -134t35 -152.5zM832 608q118 0 255 -97.5t229 -237t92 -254.5q0 -46 -17 -76.5t-48.5 -45t-64.5 -20t-76 -5.5q-68 0 -187.5 45t-182.5 45q-66 0 -192.5 -44.5t-200.5 -44.5q-183 0 -183 146q0 86 56 191.5t139.5 192.5t187.5 146t193 59zM1071 819
+q-61 0 -105 39t-63 92.5t-19 113.5q0 74 30 151.5t91.5 135t138.5 57.5q61 0 105 -39t63 -92.5t19 -113.5q0 -73 -30 -151t-92 -135.5t-138 -57.5zM1503 923q77 0 119 -59.5t42 -139.5q0 -74 -35 -152t-100.5 -133.5t-141.5 -55.5q-77 0 -119 59t-42 139q0 74 35 152.5
+t100.5 134t141.5 55.5z" />
+    <glyph glyph-name="_406" unicode="&#xf1b1;" horiz-adv-x="768" 
+d="M704 1008q0 -145 -57 -243.5t-152 -135.5l45 -821q2 -26 -16 -45t-44 -19h-192q-26 0 -44 19t-16 45l45 821q-95 37 -152 135.5t-57 243.5q0 128 42.5 249.5t117.5 200t160 78.5t160 -78.5t117.5 -200t42.5 -249.5z" />
+    <glyph glyph-name="_407" unicode="&#xf1b2;" horiz-adv-x="1792" 
+d="M896 -93l640 349v636l-640 -233v-752zM832 772l698 254l-698 254l-698 -254zM1664 1024v-768q0 -35 -18 -65t-49 -47l-704 -384q-28 -16 -61 -16t-61 16l-704 384q-31 17 -49 47t-18 65v768q0 40 23 73t61 47l704 256q22 8 44 8t44 -8l704 -256q38 -14 61 -47t23 -73z
+" />
+    <glyph glyph-name="_408" unicode="&#xf1b3;" horiz-adv-x="2304" 
+d="M640 -96l384 192v314l-384 -164v-342zM576 358l404 173l-404 173l-404 -173zM1664 -96l384 192v314l-384 -164v-342zM1600 358l404 173l-404 173l-404 -173zM1152 651l384 165v266l-384 -164v-267zM1088 1030l441 189l-441 189l-441 -189zM2176 512v-416q0 -36 -19 -67
+t-52 -47l-448 -224q-25 -14 -57 -14t-57 14l-448 224q-4 2 -7 4q-2 -2 -7 -4l-448 -224q-25 -14 -57 -14t-57 14l-448 224q-33 16 -52 47t-19 67v416q0 38 21.5 70t56.5 48l434 186v400q0 38 21.5 70t56.5 48l448 192q23 10 50 10t50 -10l448 -192q35 -16 56.5 -48t21.5 -70
+v-400l434 -186q36 -16 57 -48t21 -70z" />
+    <glyph glyph-name="_409" unicode="&#xf1b4;" horiz-adv-x="2048" 
+d="M1848 1197h-511v-124h511v124zM1596 771q-90 0 -146 -52.5t-62 -142.5h408q-18 195 -200 195zM1612 186q63 0 122 32t76 87h221q-100 -307 -427 -307q-214 0 -340.5 132t-126.5 347q0 208 130.5 345.5t336.5 137.5q138 0 240.5 -68t153 -179t50.5 -248q0 -17 -2 -47h-658
+q0 -111 57.5 -171.5t166.5 -60.5zM277 236h296q205 0 205 167q0 180 -199 180h-302v-347zM277 773h281q78 0 123.5 36.5t45.5 113.5q0 144 -190 144h-260v-294zM0 1282h594q87 0 155 -14t126.5 -47.5t90 -96.5t31.5 -154q0 -181 -172 -263q114 -32 172 -115t58 -204
+q0 -75 -24.5 -136.5t-66 -103.5t-98.5 -71t-121 -42t-134 -13h-611v1260z" />
+    <glyph glyph-name="_410" unicode="&#xf1b5;" 
+d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960zM499 1041h-371v-787h382q117 0 197 57.5t80 170.5q0 158 -143 200q107 52 107 164q0 57 -19.5 96.5
+t-56.5 60.5t-79 29.5t-97 8.5zM477 723h-176v184h163q119 0 119 -90q0 -94 -106 -94zM486 388h-185v217h189q124 0 124 -113q0 -104 -128 -104zM1136 356q-68 0 -104 38t-36 107h411q1 10 1 30q0 132 -74.5 220.5t-203.5 88.5q-128 0 -210 -86t-82 -216q0 -135 79 -217
+t213 -82q205 0 267 191h-138q-11 -34 -47.5 -54t-75.5 -20zM1126 722q113 0 124 -122h-254q4 56 39 89t91 33zM964 988h319v-77h-319v77z" />
+    <glyph glyph-name="_411" unicode="&#xf1b6;" horiz-adv-x="1792" 
+d="M1582 954q0 -101 -71.5 -172.5t-172.5 -71.5t-172.5 71.5t-71.5 172.5t71.5 172.5t172.5 71.5t172.5 -71.5t71.5 -172.5zM812 212q0 104 -73 177t-177 73q-27 0 -54 -6l104 -42q77 -31 109.5 -106.5t1.5 -151.5q-31 -77 -107 -109t-152 -1q-21 8 -62 24.5t-61 24.5
+q32 -60 91 -96.5t130 -36.5q104 0 177 73t73 177zM1642 953q0 126 -89.5 215.5t-215.5 89.5q-127 0 -216.5 -89.5t-89.5 -215.5q0 -127 89.5 -216t216.5 -89q126 0 215.5 89t89.5 216zM1792 953q0 -189 -133.5 -322t-321.5 -133l-437 -319q-12 -129 -109 -218t-229 -89
+q-121 0 -214 76t-118 192l-230 92v429l389 -157q79 48 173 48q13 0 35 -2l284 407q2 187 135.5 319t320.5 132q188 0 321.5 -133.5t133.5 -321.5z" />
+    <glyph glyph-name="_412" unicode="&#xf1b7;" 
+d="M1242 889q0 80 -57 136.5t-137 56.5t-136.5 -57t-56.5 -136q0 -80 56.5 -136.5t136.5 -56.5t137 56.5t57 136.5zM632 301q0 -83 -58 -140.5t-140 -57.5q-56 0 -103 29t-72 77q52 -20 98 -40q60 -24 120 1.5t85 86.5q24 60 -1.5 120t-86.5 84l-82 33q22 5 42 5
+q82 0 140 -57.5t58 -140.5zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v153l172 -69q20 -92 93.5 -152t168.5 -60q104 0 181 70t87 173l345 252q150 0 255.5 105.5t105.5 254.5q0 150 -105.5 255.5t-255.5 105.5
+q-148 0 -253 -104.5t-107 -252.5l-225 -322q-9 1 -28 1q-75 0 -137 -37l-297 119v468q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5zM1289 887q0 -100 -71 -170.5t-171 -70.5t-170.5 70.5t-70.5 170.5t70.5 171t170.5 71q101 0 171.5 -70.5t70.5 -171.5z
+" />
+    <glyph glyph-name="_413" unicode="&#xf1b8;" horiz-adv-x="1792" 
+d="M836 367l-15 -368l-2 -22l-420 29q-36 3 -67 31.5t-47 65.5q-11 27 -14.5 55t4 65t12 55t21.5 64t19 53q78 -12 509 -28zM449 953l180 -379l-147 92q-63 -72 -111.5 -144.5t-72.5 -125t-39.5 -94.5t-18.5 -63l-4 -21l-190 357q-17 26 -18 56t6 47l8 18q35 63 114 188
+l-140 86zM1680 436l-188 -359q-12 -29 -36.5 -46.5t-43.5 -20.5l-18 -4q-71 -7 -219 -12l8 -164l-230 367l211 362l7 -173q170 -16 283 -5t170 33zM895 1360q-47 -63 -265 -435l-317 187l-19 12l225 356q20 31 60 45t80 10q24 -2 48.5 -12t42 -21t41.5 -33t36 -34.5
+t36 -39.5t32 -35zM1550 1053l212 -363q18 -37 12.5 -76t-27.5 -74q-13 -20 -33 -37t-38 -28t-48.5 -22t-47 -16t-51.5 -14t-46 -12q-34 72 -265 436l313 195zM1407 1279l142 83l-220 -373l-419 20l151 86q-34 89 -75 166t-75.5 123.5t-64.5 80t-47 46.5l-17 13l405 -1
+q31 3 58 -10.5t39 -28.5l11 -15q39 -61 112 -190z" />
+    <glyph glyph-name="_414" unicode="&#xf1b9;" horiz-adv-x="2048" 
+d="M480 448q0 66 -47 113t-113 47t-113 -47t-47 -113t47 -113t113 -47t113 47t47 113zM516 768h1016l-89 357q-2 8 -14 17.5t-21 9.5h-768q-9 0 -21 -9.5t-14 -17.5zM1888 448q0 66 -47 113t-113 47t-113 -47t-47 -113t47 -113t113 -47t113 47t47 113zM2048 544v-384
+q0 -14 -9 -23t-23 -9h-96v-128q0 -80 -56 -136t-136 -56t-136 56t-56 136v128h-1024v-128q0 -80 -56 -136t-136 -56t-136 56t-56 136v128h-96q-14 0 -23 9t-9 23v384q0 93 65.5 158.5t158.5 65.5h28l105 419q23 94 104 157.5t179 63.5h768q98 0 179 -63.5t104 -157.5
+l105 -419h28q93 0 158.5 -65.5t65.5 -158.5z" />
+    <glyph glyph-name="_415" unicode="&#xf1ba;" horiz-adv-x="2048" 
+d="M1824 640q93 0 158.5 -65.5t65.5 -158.5v-384q0 -14 -9 -23t-23 -9h-96v-64q0 -80 -56 -136t-136 -56t-136 56t-56 136v64h-1024v-64q0 -80 -56 -136t-136 -56t-136 56t-56 136v64h-96q-14 0 -23 9t-9 23v384q0 93 65.5 158.5t158.5 65.5h28l105 419q23 94 104 157.5
+t179 63.5h128v224q0 14 9 23t23 9h448q14 0 23 -9t9 -23v-224h128q98 0 179 -63.5t104 -157.5l105 -419h28zM320 160q66 0 113 47t47 113t-47 113t-113 47t-113 -47t-47 -113t47 -113t113 -47zM516 640h1016l-89 357q-2 8 -14 17.5t-21 9.5h-768q-9 0 -21 -9.5t-14 -17.5z
+M1728 160q66 0 113 47t47 113t-47 113t-113 47t-113 -47t-47 -113t47 -113t113 -47z" />
+    <glyph glyph-name="_416" unicode="&#xf1bb;" 
+d="M1504 64q0 -26 -19 -45t-45 -19h-462q1 -17 6 -87.5t5 -108.5q0 -25 -18 -42.5t-43 -17.5h-320q-25 0 -43 17.5t-18 42.5q0 38 5 108.5t6 87.5h-462q-26 0 -45 19t-19 45t19 45l402 403h-229q-26 0 -45 19t-19 45t19 45l402 403h-197q-26 0 -45 19t-19 45t19 45l384 384
+q19 19 45 19t45 -19l384 -384q19 -19 19 -45t-19 -45t-45 -19h-197l402 -403q19 -19 19 -45t-19 -45t-45 -19h-229l402 -403q19 -19 19 -45z" />
+    <glyph glyph-name="_417" unicode="&#xf1bc;" 
+d="M1127 326q0 32 -30 51q-193 115 -447 115q-133 0 -287 -34q-42 -9 -42 -52q0 -20 13.5 -34.5t35.5 -14.5q5 0 37 8q132 27 243 27q226 0 397 -103q19 -11 33 -11q19 0 33 13.5t14 34.5zM1223 541q0 40 -35 61q-237 141 -548 141q-153 0 -303 -42q-48 -13 -48 -64
+q0 -25 17.5 -42.5t42.5 -17.5q7 0 37 8q122 33 251 33q279 0 488 -124q24 -13 38 -13q25 0 42.5 17.5t17.5 42.5zM1331 789q0 47 -40 70q-126 73 -293 110.5t-343 37.5q-204 0 -364 -47q-23 -7 -38.5 -25.5t-15.5 -48.5q0 -31 20.5 -52t51.5 -21q11 0 40 8q133 37 307 37
+q159 0 309.5 -34t253.5 -95q21 -12 40 -12q29 0 50.5 20.5t21.5 51.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="_418" unicode="&#xf1bd;" horiz-adv-x="1024" 
+d="M1024 1233l-303 -582l24 -31h279v-415h-507l-44 -30l-142 -273l-30 -30h-301v303l303 583l-24 30h-279v415h507l44 30l142 273l30 30h301v-303z" />
+    <glyph glyph-name="_419" unicode="&#xf1be;" horiz-adv-x="2304" 
+d="M784 164l16 241l-16 523q-1 10 -7.5 17t-16.5 7q-9 0 -16 -7t-7 -17l-14 -523l14 -241q1 -10 7.5 -16.5t15.5 -6.5q22 0 24 23zM1080 193l11 211l-12 586q0 16 -13 24q-8 5 -16 5t-16 -5q-13 -8 -13 -24l-1 -6l-10 -579q0 -1 11 -236v-1q0 -10 6 -17q9 -11 23 -11
+q11 0 20 9q9 7 9 20zM35 533l20 -128l-20 -126q-2 -9 -9 -9t-9 9l-17 126l17 128q2 9 9 9t9 -9zM121 612l26 -207l-26 -203q-2 -9 -10 -9q-9 0 -9 10l-23 202l23 207q0 9 9 9q8 0 10 -9zM401 159zM213 650l25 -245l-25 -237q0 -11 -11 -11q-10 0 -12 11l-21 237l21 245
+q2 12 12 12q11 0 11 -12zM307 657l23 -252l-23 -244q-2 -13 -14 -13q-13 0 -13 13l-21 244l21 252q0 13 13 13q12 0 14 -13zM401 639l21 -234l-21 -246q-2 -16 -16 -16q-6 0 -10.5 4.5t-4.5 11.5l-20 246l20 234q0 6 4.5 10.5t10.5 4.5q14 0 16 -15zM784 164zM495 785
+l21 -380l-21 -246q0 -7 -5 -12.5t-12 -5.5q-16 0 -18 18l-18 246l18 380q2 18 18 18q7 0 12 -5.5t5 -12.5zM589 871l19 -468l-19 -244q0 -8 -5.5 -13.5t-13.5 -5.5q-18 0 -20 19l-16 244l16 468q2 19 20 19q8 0 13.5 -5.5t5.5 -13.5zM687 911l18 -506l-18 -242
+q-2 -21 -22 -21q-19 0 -21 21l-16 242l16 506q0 9 6.5 15.5t14.5 6.5q9 0 15 -6.5t7 -15.5zM1079 169v0v0v0zM881 915l15 -510l-15 -239q0 -10 -7.5 -17.5t-17.5 -7.5t-17 7t-8 18l-14 239l14 510q0 11 7.5 18t17.5 7t17.5 -7t7.5 -18zM980 896l14 -492l-14 -236
+q0 -11 -8 -19t-19 -8t-19 8t-9 19l-12 236l12 492q1 12 9 20t19 8t18.5 -8t8.5 -20zM1192 404l-14 -231v0q0 -13 -9 -22t-22 -9t-22 9t-10 22l-6 114l-6 117l12 636v3q2 15 12 24q9 7 20 7q8 0 15 -5q14 -8 16 -26zM2304 423q0 -117 -83 -199.5t-200 -82.5h-786
+q-13 2 -22 11t-9 22v899q0 23 28 33q85 34 181 34q195 0 338 -131.5t160 -323.5q53 22 110 22q117 0 200 -83t83 -201z" />
+    <glyph glyph-name="uniF1C0" unicode="&#xf1c0;" 
+d="M768 768q237 0 443 43t325 127v-170q0 -69 -103 -128t-280 -93.5t-385 -34.5t-385 34.5t-280 93.5t-103 128v170q119 -84 325 -127t443 -43zM768 0q237 0 443 43t325 127v-170q0 -69 -103 -128t-280 -93.5t-385 -34.5t-385 34.5t-280 93.5t-103 128v170q119 -84 325 -127
+t443 -43zM768 384q237 0 443 43t325 127v-170q0 -69 -103 -128t-280 -93.5t-385 -34.5t-385 34.5t-280 93.5t-103 128v170q119 -84 325 -127t443 -43zM768 1536q208 0 385 -34.5t280 -93.5t103 -128v-128q0 -69 -103 -128t-280 -93.5t-385 -34.5t-385 34.5t-280 93.5
+t-103 128v128q0 69 103 128t280 93.5t385 34.5z" />
+    <glyph glyph-name="uniF1C1" unicode="&#xf1c1;" 
+d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z
+M894 465q33 -26 84 -56q59 7 117 7q147 0 177 -49q16 -22 2 -52q0 -1 -1 -2l-2 -2v-1q-6 -38 -71 -38q-48 0 -115 20t-130 53q-221 -24 -392 -83q-153 -262 -242 -262q-15 0 -28 7l-24 12q-1 1 -6 5q-10 10 -6 36q9 40 56 91.5t132 96.5q14 9 23 -6q2 -2 2 -4q52 85 107 197
+q68 136 104 262q-24 82 -30.5 159.5t6.5 127.5q11 40 42 40h21h1q23 0 35 -15q18 -21 9 -68q-2 -6 -4 -8q1 -3 1 -8v-30q-2 -123 -14 -192q55 -164 146 -238zM318 54q52 24 137 158q-51 -40 -87.5 -84t-49.5 -74zM716 974q-15 -42 -2 -132q1 7 7 44q0 3 7 43q1 4 4 8
+q-1 1 -1 2q-1 2 -1 3q-1 22 -13 36q0 -1 -1 -2v-2zM592 313q135 54 284 81q-2 1 -13 9.5t-16 13.5q-76 67 -127 176q-27 -86 -83 -197q-30 -56 -45 -83zM1238 329q-24 24 -140 24q76 -28 124 -28q14 0 18 1q0 1 -2 3z" />
+    <glyph glyph-name="_422" unicode="&#xf1c2;" 
+d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z
+M233 768v-107h70l164 -661h159l128 485q7 20 10 46q2 16 2 24h4l3 -24q1 -3 3.5 -20t5.5 -26l128 -485h159l164 661h70v107h-300v-107h90l-99 -438q-5 -20 -7 -46l-2 -21h-4q0 3 -0.5 6.5t-1.5 8t-1 6.5q-1 5 -4 21t-5 25l-144 545h-114l-144 -545q-2 -9 -4.5 -24.5
+t-3.5 -21.5l-4 -21h-4l-2 21q-2 26 -7 46l-99 438h90v107h-300z" />
+    <glyph glyph-name="_423" unicode="&#xf1c3;" 
+d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z
+M429 106v-106h281v106h-75l103 161q5 7 10 16.5t7.5 13.5t3.5 4h2q1 -4 5 -10q2 -4 4.5 -7.5t6 -8t6.5 -8.5l107 -161h-76v-106h291v106h-68l-192 273l195 282h67v107h-279v-107h74l-103 -159q-4 -7 -10 -16.5t-9 -13.5l-2 -3h-2q-1 4 -5 10q-6 11 -17 23l-106 159h76v107
+h-290v-107h68l189 -272l-194 -283h-68z" />
+    <glyph glyph-name="_424" unicode="&#xf1c4;" 
+d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z
+M416 106v-106h327v106h-93v167h137q76 0 118 15q67 23 106.5 87t39.5 146q0 81 -37 141t-100 87q-48 19 -130 19h-368v-107h92v-555h-92zM769 386h-119v268h120q52 0 83 -18q56 -33 56 -115q0 -89 -62 -120q-31 -15 -78 -15z" />
+    <glyph glyph-name="_425" unicode="&#xf1c5;" 
+d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z
+M1280 320v-320h-1024v192l192 192l128 -128l384 384zM448 512q-80 0 -136 56t-56 136t56 136t136 56t136 -56t56 -136t-56 -136t-136 -56z" />
+    <glyph glyph-name="_426" unicode="&#xf1c6;" 
+d="M640 1152v128h-128v-128h128zM768 1024v128h-128v-128h128zM640 896v128h-128v-128h128zM768 768v128h-128v-128h128zM1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400
+v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-128v-128h-128v128h-512v-1536h1280zM781 593l107 -349q8 -27 8 -52q0 -83 -72.5 -137.5t-183.5 -54.5t-183.5 54.5t-72.5 137.5q0 25 8 52q21 63 120 396v128h128v-128h79
+q22 0 39 -13t23 -34zM640 128q53 0 90.5 19t37.5 45t-37.5 45t-90.5 19t-90.5 -19t-37.5 -45t37.5 -45t90.5 -19z" />
+    <glyph glyph-name="_427" unicode="&#xf1c7;" 
+d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z
+M620 686q20 -8 20 -30v-544q0 -22 -20 -30q-8 -2 -12 -2q-12 0 -23 9l-166 167h-131q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h131l166 167q16 15 35 7zM1037 -3q31 0 50 24q129 159 129 363t-129 363q-16 21 -43 24t-47 -14q-21 -17 -23.5 -43.5t14.5 -47.5
+q100 -123 100 -282t-100 -282q-17 -21 -14.5 -47.5t23.5 -42.5q18 -15 40 -15zM826 145q27 0 47 20q87 93 87 219t-87 219q-18 19 -45 20t-46 -17t-20 -44.5t18 -46.5q52 -57 52 -131t-52 -131q-19 -20 -18 -46.5t20 -44.5q20 -17 44 -17z" />
+    <glyph glyph-name="_428" unicode="&#xf1c8;" 
+d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z
+M768 768q52 0 90 -38t38 -90v-384q0 -52 -38 -90t-90 -38h-384q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h384zM1260 766q20 -8 20 -30v-576q0 -22 -20 -30q-8 -2 -12 -2q-14 0 -23 9l-265 266v90l265 266q9 9 23 9q4 0 12 -2z" />
+    <glyph glyph-name="_429" unicode="&#xf1c9;" 
+d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z
+M480 768q8 11 21 12.5t24 -6.5l51 -38q11 -8 12.5 -21t-6.5 -24l-182 -243l182 -243q8 -11 6.5 -24t-12.5 -21l-51 -38q-11 -8 -24 -6.5t-21 12.5l-226 301q-14 19 0 38zM1282 467q14 -19 0 -38l-226 -301q-8 -11 -21 -12.5t-24 6.5l-51 38q-11 8 -12.5 21t6.5 24l182 243
+l-182 243q-8 11 -6.5 24t12.5 21l51 38q11 8 24 6.5t21 -12.5zM662 6q-13 2 -20.5 13t-5.5 24l138 831q2 13 13 20.5t24 5.5l63 -10q13 -2 20.5 -13t5.5 -24l-138 -831q-2 -13 -13 -20.5t-24 -5.5z" />
+    <glyph glyph-name="_430" unicode="&#xf1ca;" 
+d="M1497 709v-198q-101 -23 -198 -23q-65 -136 -165.5 -271t-181.5 -215.5t-128 -106.5q-80 -45 -162 3q-28 17 -60.5 43.5t-85 83.5t-102.5 128.5t-107.5 184t-105.5 244t-91.5 314.5t-70.5 390h283q26 -218 70 -398.5t104.5 -317t121.5 -235.5t140 -195q169 169 287 406
+q-142 72 -223 220t-81 333q0 192 104 314.5t284 122.5q178 0 273 -105.5t95 -297.5q0 -159 -58 -286q-7 -1 -19.5 -3t-46 -2t-63 6t-62 25.5t-50.5 51.5q31 103 31 184q0 87 -29 132t-79 45q-53 0 -85 -49.5t-32 -140.5q0 -186 105 -293.5t267 -107.5q62 0 121 14z" />
+    <glyph glyph-name="_431" unicode="&#xf1cb;" horiz-adv-x="1792" 
+d="M216 367l603 -402v359l-334 223zM154 511l193 129l-193 129v-258zM973 -35l603 402l-269 180l-334 -223v-359zM896 458l272 182l-272 182l-272 -182zM485 733l334 223v359l-603 -402zM1445 640l193 -129v258zM1307 733l269 180l-603 402v-359zM1792 913v-546
+q0 -41 -34 -64l-819 -546q-21 -13 -43 -13t-43 13l-819 546q-34 23 -34 64v546q0 41 34 64l819 546q21 13 43 13t43 -13l819 -546q34 -23 34 -64z" />
+    <glyph glyph-name="_432" unicode="&#xf1cc;" horiz-adv-x="2048" 
+d="M1800 764q111 -46 179.5 -145.5t68.5 -221.5q0 -164 -118 -280.5t-285 -116.5q-4 0 -11.5 0.5t-10.5 0.5h-1209h-1h-2h-5q-170 10 -288 125.5t-118 280.5q0 110 55 203t147 147q-12 39 -12 82q0 115 82 196t199 81q95 0 172 -58q75 154 222.5 248t326.5 94
+q166 0 306 -80.5t221.5 -218.5t81.5 -301q0 -6 -0.5 -18t-0.5 -18zM468 498q0 -122 84 -193t208 -71q137 0 240 99q-16 20 -47.5 56.5t-43.5 50.5q-67 -65 -144 -65q-55 0 -93.5 33.5t-38.5 87.5q0 53 38.5 87t91.5 34q44 0 84.5 -21t73 -55t65 -75t69 -82t77 -75t97 -55
+t121.5 -21q121 0 204.5 71.5t83.5 190.5q0 121 -84 192t-207 71q-143 0 -241 -97l93 -108q66 64 142 64q52 0 92 -33t40 -84q0 -57 -37 -91.5t-94 -34.5q-43 0 -82.5 21t-72 55t-65.5 75t-69.5 82t-77.5 75t-96.5 55t-118.5 21q-122 0 -207 -70.5t-85 -189.5z" />
+    <glyph glyph-name="_433" unicode="&#xf1cd;" horiz-adv-x="1792" 
+d="M896 1536q182 0 348 -71t286 -191t191 -286t71 -348t-71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71zM896 1408q-190 0 -361 -90l194 -194q82 28 167 28t167 -28l194 194q-171 90 -361 90zM218 279l194 194
+q-28 82 -28 167t28 167l-194 194q-90 -171 -90 -361t90 -361zM896 -128q190 0 361 90l-194 194q-82 -28 -167 -28t-167 28l-194 -194q171 -90 361 -90zM896 256q159 0 271.5 112.5t112.5 271.5t-112.5 271.5t-271.5 112.5t-271.5 -112.5t-112.5 -271.5t112.5 -271.5
+t271.5 -112.5zM1380 473l194 -194q90 171 90 361t-90 361l-194 -194q28 -82 28 -167t-28 -167z" />
+    <glyph glyph-name="_434" unicode="&#xf1ce;" horiz-adv-x="1792" 
+d="M1760 640q0 -176 -68.5 -336t-184 -275.5t-275.5 -184t-336 -68.5t-336 68.5t-275.5 184t-184 275.5t-68.5 336q0 213 97 398.5t265 305.5t374 151v-228q-221 -45 -366.5 -221t-145.5 -406q0 -130 51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5
+t136.5 204t51 248.5q0 230 -145.5 406t-366.5 221v228q206 -31 374 -151t265 -305.5t97 -398.5z" />
+    <glyph glyph-name="uniF1D0" unicode="&#xf1d0;" horiz-adv-x="1792" 
+d="M19 662q8 217 116 406t305 318h5q0 -1 -1 -3q-8 -8 -28 -33.5t-52 -76.5t-60 -110.5t-44.5 -135.5t-14 -150.5t39 -157.5t108.5 -154q50 -50 102 -69.5t90.5 -11.5t69.5 23.5t47 32.5l16 16q39 51 53 116.5t6.5 122.5t-21 107t-26.5 80l-14 29q-10 25 -30.5 49.5t-43 41
+t-43.5 29.5t-35 19l-13 6l104 115q39 -17 78 -52t59 -61l19 -27q1 48 -18.5 103.5t-40.5 87.5l-20 31l161 183l160 -181q-33 -46 -52.5 -102.5t-22.5 -90.5l-4 -33q22 37 61.5 72.5t67.5 52.5l28 17l103 -115q-44 -14 -85 -50t-60 -65l-19 -29q-31 -56 -48 -133.5t-7 -170
+t57 -156.5q33 -45 77.5 -60.5t85 -5.5t76 26.5t57.5 33.5l21 16q60 53 96.5 115t48.5 121.5t10 121.5t-18 118t-37 107.5t-45.5 93t-45 72t-34.5 47.5l-13 17q-14 13 -7 13l10 -3q40 -29 62.5 -46t62 -50t64 -58t58.5 -65t55.5 -77t45.5 -88t38 -103t23.5 -117t10.5 -136
+q3 -259 -108 -465t-312 -321t-456 -115q-185 0 -351 74t-283.5 198t-184 293t-60.5 353z" />
+    <glyph glyph-name="uniF1D1" unicode="&#xf1d1;" horiz-adv-x="1792" 
+d="M874 -102v-66q-208 6 -385 109.5t-283 275.5l58 34q29 -49 73 -99l65 57q148 -168 368 -212l-17 -86q65 -12 121 -13zM276 428l-83 -28q22 -60 49 -112l-57 -33q-98 180 -98 385t98 385l57 -33q-30 -56 -49 -112l82 -28q-35 -100 -35 -212q0 -109 36 -212zM1528 251
+l58 -34q-106 -172 -283 -275.5t-385 -109.5v66q56 1 121 13l-17 86q220 44 368 212l65 -57q44 50 73 99zM1377 805l-233 -80q14 -42 14 -85t-14 -85l232 -80q-31 -92 -98 -169l-185 162q-57 -67 -147 -85l48 -241q-52 -10 -98 -10t-98 10l48 241q-90 18 -147 85l-185 -162
+q-67 77 -98 169l232 80q-14 42 -14 85t14 85l-233 80q33 93 99 169l185 -162q59 68 147 86l-48 240q44 10 98 10t98 -10l-48 -240q88 -18 147 -86l185 162q66 -76 99 -169zM874 1448v-66q-65 -2 -121 -13l17 -86q-220 -42 -368 -211l-65 56q-38 -42 -73 -98l-57 33
+q106 172 282 275.5t385 109.5zM1705 640q0 -205 -98 -385l-57 33q27 52 49 112l-83 28q36 103 36 212q0 112 -35 212l82 28q-19 56 -49 112l57 33q98 -180 98 -385zM1585 1063l-57 -33q-35 56 -73 98l-65 -56q-148 169 -368 211l17 86q-56 11 -121 13v66q209 -6 385 -109.5
+t282 -275.5zM1748 640q0 173 -67.5 331t-181.5 272t-272 181.5t-331 67.5t-331 -67.5t-272 -181.5t-181.5 -272t-67.5 -331t67.5 -331t181.5 -272t272 -181.5t331 -67.5t331 67.5t272 181.5t181.5 272t67.5 331zM1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71
+t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
+    <glyph glyph-name="uniF1D2" unicode="&#xf1d2;" 
+d="M582 228q0 -66 -93 -66q-107 0 -107 63q0 64 98 64q102 0 102 -61zM546 694q0 -85 -74 -85q-77 0 -77 84q0 90 77 90q36 0 55 -25.5t19 -63.5zM712 769v125q-78 -29 -135 -29q-50 29 -110 29q-86 0 -145 -57t-59 -143q0 -50 29.5 -102t73.5 -67v-3q-38 -17 -38 -85
+q0 -53 41 -77v-3q-113 -37 -113 -139q0 -45 20 -78.5t54 -51t72 -25.5t81 -8q224 0 224 188q0 67 -48 99t-126 46q-27 5 -51.5 20.5t-24.5 39.5q0 44 49 52q77 15 122 70t45 134q0 24 -10 52q37 9 49 13zM771 350h137q-2 27 -2 82v387q0 46 2 69h-137q3 -23 3 -71v-392
+q0 -50 -3 -75zM1280 366v121q-30 -21 -68 -21q-53 0 -53 82v225h52q9 0 26.5 -1t26.5 -1v117h-105q0 82 3 102h-140q4 -24 4 -55v-47h-60v-117q36 3 37 3q3 0 11 -0.5t12 -0.5v-2h-2v-217q0 -37 2.5 -64t11.5 -56.5t24.5 -48.5t43.5 -31t66 -12q64 0 108 24zM924 1072
+q0 36 -24 63.5t-60 27.5t-60.5 -27t-24.5 -64q0 -36 25 -62.5t60 -26.5t59.5 27t24.5 62zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="_438" unicode="&#xf1d3;" horiz-adv-x="1792" 
+d="M595 22q0 100 -165 100q-158 0 -158 -104q0 -101 172 -101q151 0 151 105zM536 777q0 61 -30 102t-89 41q-124 0 -124 -145q0 -135 124 -135q119 0 119 137zM805 1101v-202q-36 -12 -79 -22q16 -43 16 -84q0 -127 -73 -216.5t-197 -112.5q-40 -8 -59.5 -27t-19.5 -58
+q0 -31 22.5 -51.5t58 -32t78.5 -22t86 -25.5t78.5 -37.5t58 -64t22.5 -98.5q0 -304 -363 -304q-69 0 -130 12.5t-116 41t-87.5 82t-32.5 127.5q0 165 182 225v4q-67 41 -67 126q0 109 63 137v4q-72 24 -119.5 108.5t-47.5 165.5q0 139 95 231.5t235 92.5q96 0 178 -47
+q98 0 218 47zM1123 220h-222q4 45 4 134v609q0 94 -4 128h222q-4 -33 -4 -124v-613q0 -89 4 -134zM1724 442v-196q-71 -39 -174 -39q-62 0 -107 20t-70 50t-39.5 78t-18.5 92t-4 103v351h2v4q-7 0 -19 1t-18 1q-21 0 -59 -6v190h96v76q0 54 -6 89h227q-6 -41 -6 -165h171
+v-190q-15 0 -43.5 2t-42.5 2h-85v-365q0 -131 87 -131q61 0 109 33zM1148 1389q0 -58 -39 -101.5t-96 -43.5q-58 0 -98 43.5t-40 101.5q0 59 39.5 103t98.5 44q58 0 96.5 -44.5t38.5 -102.5z" />
+    <glyph glyph-name="_439" unicode="&#xf1d4;" 
+d="M809 532l266 499h-112l-157 -312q-24 -48 -44 -92l-42 92l-155 312h-120l263 -493v-324h101v318zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="uniF1D5" unicode="&#xf1d5;" horiz-adv-x="1280" 
+d="M842 964q0 -80 -57 -136.5t-136 -56.5q-60 0 -111 35q-62 -67 -115 -146q-247 -371 -202 -859q1 -22 -12.5 -38.5t-34.5 -18.5h-5q-20 0 -35 13.5t-17 33.5q-14 126 -3.5 247.5t29.5 217t54 186t69 155.5t74 125q61 90 132 165q-16 35 -16 77q0 80 56.5 136.5t136.5 56.5
+t136.5 -56.5t56.5 -136.5zM1223 953q0 -158 -78 -292t-212.5 -212t-292.5 -78q-64 0 -131 14q-21 5 -32.5 23.5t-6.5 39.5q5 20 23 31.5t39 7.5q51 -13 108 -13q97 0 186 38t153 102t102 153t38 186t-38 186t-102 153t-153 102t-186 38t-186 -38t-153 -102t-102 -153
+t-38 -186q0 -114 52 -218q10 -20 3.5 -40t-25.5 -30t-39.5 -3t-30.5 26q-64 123 -64 265q0 119 46.5 227t124.5 186t186 124t226 46q158 0 292.5 -78t212.5 -212.5t78 -292.5z" />
+    <glyph glyph-name="uniF1D6" unicode="&#xf1d6;" horiz-adv-x="1792" 
+d="M270 730q-8 19 -8 52q0 20 11 49t24 45q-1 22 7.5 53t22.5 43q0 139 92.5 288.5t217.5 209.5q139 66 324 66q133 0 266 -55q49 -21 90 -48t71 -56t55 -68t42 -74t32.5 -84.5t25.5 -89.5t22 -98l1 -5q55 -83 55 -150q0 -14 -9 -40t-9 -38q0 -1 1.5 -3.5t3.5 -5t2 -3.5
+q77 -114 120.5 -214.5t43.5 -208.5q0 -43 -19.5 -100t-55.5 -57q-9 0 -19.5 7.5t-19 17.5t-19 26t-16 26.5t-13.5 26t-9 17.5q-1 1 -3 1l-5 -4q-59 -154 -132 -223q20 -20 61.5 -38.5t69 -41.5t35.5 -65q-2 -4 -4 -16t-7 -18q-64 -97 -302 -97q-53 0 -110.5 9t-98 20
+t-104.5 30q-15 5 -23 7q-14 4 -46 4.5t-40 1.5q-41 -45 -127.5 -65t-168.5 -20q-35 0 -69 1.5t-93 9t-101 20.5t-74.5 40t-32.5 64q0 40 10 59.5t41 48.5q11 2 40.5 13t49.5 12q4 0 14 2q2 2 2 4l-2 3q-48 11 -108 105.5t-73 156.5l-5 3q-4 0 -12 -20q-18 -41 -54.5 -74.5
+t-77.5 -37.5h-1q-4 0 -6 4.5t-5 5.5q-23 54 -23 100q0 275 252 466z" />
+    <glyph glyph-name="uniF1D7" unicode="&#xf1d7;" horiz-adv-x="2048" 
+d="M580 1075q0 41 -25 66t-66 25q-43 0 -76 -25.5t-33 -65.5q0 -39 33 -64.5t76 -25.5q41 0 66 24.5t25 65.5zM1323 568q0 28 -25.5 50t-65.5 22q-27 0 -49.5 -22.5t-22.5 -49.5q0 -28 22.5 -50.5t49.5 -22.5q40 0 65.5 22t25.5 51zM1087 1075q0 41 -24.5 66t-65.5 25
+q-43 0 -76 -25.5t-33 -65.5q0 -39 33 -64.5t76 -25.5q41 0 65.5 24.5t24.5 65.5zM1722 568q0 28 -26 50t-65 22q-27 0 -49.5 -22.5t-22.5 -49.5q0 -28 22.5 -50.5t49.5 -22.5q39 0 65 22t26 51zM1456 965q-31 4 -70 4q-169 0 -311 -77t-223.5 -208.5t-81.5 -287.5
+q0 -78 23 -152q-35 -3 -68 -3q-26 0 -50 1.5t-55 6.5t-44.5 7t-54.5 10.5t-50 10.5l-253 -127l72 218q-290 203 -290 490q0 169 97.5 311t264 223.5t363.5 81.5q176 0 332.5 -66t262 -182.5t136.5 -260.5zM2048 404q0 -117 -68.5 -223.5t-185.5 -193.5l55 -181l-199 109
+q-150 -37 -218 -37q-169 0 -311 70.5t-223.5 191.5t-81.5 264t81.5 264t223.5 191.5t311 70.5q161 0 303 -70.5t227.5 -192t85.5 -263.5z" />
+    <glyph glyph-name="_443" unicode="&#xf1d8;" horiz-adv-x="1792" 
+d="M1764 1525q33 -24 27 -64l-256 -1536q-5 -29 -32 -45q-14 -8 -31 -8q-11 0 -24 5l-453 185l-242 -295q-18 -23 -49 -23q-13 0 -22 4q-19 7 -30.5 23.5t-11.5 36.5v349l864 1059l-1069 -925l-395 162q-37 14 -40 55q-2 40 32 59l1664 960q15 9 32 9q20 0 36 -11z" />
+    <glyph glyph-name="_444" unicode="&#xf1d9;" horiz-adv-x="1792" 
+d="M1764 1525q33 -24 27 -64l-256 -1536q-5 -29 -32 -45q-14 -8 -31 -8q-11 0 -24 5l-527 215l-298 -327q-18 -21 -47 -21q-14 0 -23 4q-19 7 -30 23.5t-11 36.5v452l-472 193q-37 14 -40 55q-3 39 32 59l1664 960q35 21 68 -2zM1422 26l221 1323l-1434 -827l336 -137
+l863 639l-478 -797z" />
+    <glyph glyph-name="_445" unicode="&#xf1da;" 
+d="M1536 640q0 -156 -61 -298t-164 -245t-245 -164t-298 -61q-172 0 -327 72.5t-264 204.5q-7 10 -6.5 22.5t8.5 20.5l137 138q10 9 25 9q16 -2 23 -12q73 -95 179 -147t225 -52q104 0 198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5t-40.5 198.5t-109.5 163.5
+t-163.5 109.5t-198.5 40.5q-98 0 -188 -35.5t-160 -101.5l137 -138q31 -30 14 -69q-17 -40 -59 -40h-448q-26 0 -45 19t-19 45v448q0 42 40 59q39 17 69 -14l130 -129q107 101 244.5 156.5t284.5 55.5q156 0 298 -61t245 -164t164 -245t61 -298zM896 928v-448q0 -14 -9 -23
+t-23 -9h-320q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h224v352q0 14 9 23t23 9h64q14 0 23 -9t9 -23z" />
+    <glyph glyph-name="_446" unicode="&#xf1db;" 
+d="M768 1280q-130 0 -248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5t-51 248.5t-136.5 204t-204 136.5t-248.5 51zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103
+t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="_447" unicode="&#xf1dc;" horiz-adv-x="1792" 
+d="M1682 -128q-44 0 -132.5 3.5t-133.5 3.5q-44 0 -132 -3.5t-132 -3.5q-24 0 -37 20.5t-13 45.5q0 31 17 46t39 17t51 7t45 15q33 21 33 140l-1 391q0 21 -1 31q-13 4 -50 4h-675q-38 0 -51 -4q-1 -10 -1 -31l-1 -371q0 -142 37 -164q16 -10 48 -13t57 -3.5t45 -15
+t20 -45.5q0 -26 -12.5 -48t-36.5 -22q-47 0 -139.5 3.5t-138.5 3.5q-43 0 -128 -3.5t-127 -3.5q-23 0 -35.5 21t-12.5 45q0 30 15.5 45t36 17.5t47.5 7.5t42 15q33 23 33 143l-1 57v813q0 3 0.5 26t0 36.5t-1.5 38.5t-3.5 42t-6.5 36.5t-11 31.5t-16 18q-15 10 -45 12t-53 2
+t-41 14t-18 45q0 26 12 48t36 22q46 0 138.5 -3.5t138.5 -3.5q42 0 126.5 3.5t126.5 3.5q25 0 37.5 -22t12.5 -48q0 -30 -17 -43.5t-38.5 -14.5t-49.5 -4t-43 -13q-35 -21 -35 -160l1 -320q0 -21 1 -32q13 -3 39 -3h699q25 0 38 3q1 11 1 32l1 320q0 139 -35 160
+q-18 11 -58.5 12.5t-66 13t-25.5 49.5q0 26 12.5 48t37.5 22q44 0 132 -3.5t132 -3.5q43 0 129 3.5t129 3.5q25 0 37.5 -22t12.5 -48q0 -30 -17.5 -44t-40 -14.5t-51.5 -3t-44 -12.5q-35 -23 -35 -161l1 -943q0 -119 34 -140q16 -10 46 -13.5t53.5 -4.5t41.5 -15.5t18 -44.5
+q0 -26 -12 -48t-36 -22z" />
+    <glyph glyph-name="_448" unicode="&#xf1dd;" horiz-adv-x="1280" 
+d="M1278 1347v-73q0 -29 -18.5 -61t-42.5 -32q-50 0 -54 -1q-26 -6 -32 -31q-3 -11 -3 -64v-1152q0 -25 -18 -43t-43 -18h-108q-25 0 -43 18t-18 43v1218h-143v-1218q0 -25 -17.5 -43t-43.5 -18h-108q-26 0 -43.5 18t-17.5 43v496q-147 12 -245 59q-126 58 -192 179
+q-64 117 -64 259q0 166 88 286q88 118 209 159q111 37 417 37h479q25 0 43 -18t18 -43z" />
+    <glyph glyph-name="_449" unicode="&#xf1de;" 
+d="M352 128v-128h-352v128h352zM704 256q26 0 45 -19t19 -45v-256q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h256zM864 640v-128h-864v128h864zM224 1152v-128h-224v128h224zM1536 128v-128h-736v128h736zM576 1280q26 0 45 -19t19 -45v-256
+q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h256zM1216 768q26 0 45 -19t19 -45v-256q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h256zM1536 640v-128h-224v128h224zM1536 1152v-128h-864v128h864z" />
+    <glyph glyph-name="uniF1E0" unicode="&#xf1e0;" 
+d="M1216 512q133 0 226.5 -93.5t93.5 -226.5t-93.5 -226.5t-226.5 -93.5t-226.5 93.5t-93.5 226.5q0 12 2 34l-360 180q-92 -86 -218 -86q-133 0 -226.5 93.5t-93.5 226.5t93.5 226.5t226.5 93.5q126 0 218 -86l360 180q-2 22 -2 34q0 133 93.5 226.5t226.5 93.5
+t226.5 -93.5t93.5 -226.5t-93.5 -226.5t-226.5 -93.5q-126 0 -218 86l-360 -180q2 -22 2 -34t-2 -34l360 -180q92 86 218 86z" />
+    <glyph glyph-name="_451" unicode="&#xf1e1;" 
+d="M1280 341q0 88 -62.5 151t-150.5 63q-84 0 -145 -58l-241 120q2 16 2 23t-2 23l241 120q61 -58 145 -58q88 0 150.5 63t62.5 151t-62.5 150.5t-150.5 62.5t-151 -62.5t-63 -150.5q0 -7 2 -23l-241 -120q-62 57 -145 57q-88 0 -150.5 -62.5t-62.5 -150.5t62.5 -150.5
+t150.5 -62.5q83 0 145 57l241 -120q-2 -16 -2 -23q0 -88 63 -150.5t151 -62.5t150.5 62.5t62.5 150.5zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="_452" unicode="&#xf1e2;" horiz-adv-x="1792" 
+d="M571 947q-10 25 -34 35t-49 0q-108 -44 -191 -127t-127 -191q-10 -25 0 -49t35 -34q13 -5 24 -5q42 0 60 40q34 84 98.5 148.5t148.5 98.5q25 11 35 35t0 49zM1513 1303l46 -46l-244 -243l68 -68q19 -19 19 -45.5t-19 -45.5l-64 -64q89 -161 89 -343q0 -143 -55.5 -273.5
+t-150 -225t-225 -150t-273.5 -55.5t-273.5 55.5t-225 150t-150 225t-55.5 273.5t55.5 273.5t150 225t225 150t273.5 55.5q182 0 343 -89l64 64q19 19 45.5 19t45.5 -19l68 -68zM1521 1359q-10 -10 -22 -10q-13 0 -23 10l-91 90q-9 10 -9 23t9 23q10 9 23 9t23 -9l90 -91
+q10 -9 10 -22.5t-10 -22.5zM1751 1129q-11 -9 -23 -9t-23 9l-90 91q-10 9 -10 22.5t10 22.5q9 10 22.5 10t22.5 -10l91 -90q9 -10 9 -23t-9 -23zM1792 1312q0 -14 -9 -23t-23 -9h-96q-14 0 -23 9t-9 23t9 23t23 9h96q14 0 23 -9t9 -23zM1600 1504v-96q0 -14 -9 -23t-23 -9
+t-23 9t-9 23v96q0 14 9 23t23 9t23 -9t9 -23zM1751 1449l-91 -90q-10 -10 -22 -10q-13 0 -23 10q-10 9 -10 22.5t10 22.5l90 91q10 9 23 9t23 -9q9 -10 9 -23t-9 -23z" />
+    <glyph glyph-name="_453" unicode="&#xf1e3;" horiz-adv-x="1792" 
+d="M609 720l287 208l287 -208l-109 -336h-355zM896 1536q182 0 348 -71t286 -191t191 -286t71 -348t-71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71zM1515 186q149 203 149 454v3l-102 -89l-240 224l63 323
+l134 -12q-150 206 -389 282l53 -124l-287 -159l-287 159l53 124q-239 -76 -389 -282l135 12l62 -323l-240 -224l-102 89v-3q0 -251 149 -454l30 132l326 -40l139 -298l-116 -69q117 -39 240 -39t240 39l-116 69l139 298l326 40z" />
+    <glyph glyph-name="_454" unicode="&#xf1e4;" horiz-adv-x="1792" 
+d="M448 224v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM256 608v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM832 224v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23
+v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM640 608v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM66 768q-28 0 -47 19t-19 46v129h514v-129q0 -27 -19 -46t-46 -19h-383zM1216 224v-192q0 -14 -9 -23t-23 -9h-192
+q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1024 608v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1600 224v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23
+zM1408 608v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1792 1016v-13h-514v10q0 104 -382 102q-382 -1 -382 -102v-10h-514v13q0 17 8.5 43t34 64t65.5 75.5t110.5 76t160 67.5t224 47.5t293.5 18.5t293 -18.5t224 -47.5
+t160.5 -67.5t110.5 -76t65.5 -75.5t34 -64t8.5 -43zM1792 608v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1792 962v-129q0 -27 -19 -46t-46 -19h-384q-27 0 -46 19t-19 46v129h514z" />
+    <glyph glyph-name="_455" unicode="&#xf1e5;" horiz-adv-x="1792" 
+d="M704 1216v-768q0 -26 -19 -45t-45 -19v-576q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v512l249 873q7 23 31 23h424zM1024 1216v-704h-256v704h256zM1792 320v-512q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v576q-26 0 -45 19t-19 45v768h424q24 0 31 -23z
+M736 1504v-224h-352v224q0 14 9 23t23 9h288q14 0 23 -9t9 -23zM1408 1504v-224h-352v224q0 14 9 23t23 9h288q14 0 23 -9t9 -23z" />
+    <glyph glyph-name="_456" unicode="&#xf1e6;" horiz-adv-x="1792" 
+d="M1755 1083q37 -38 37 -90.5t-37 -90.5l-401 -400l150 -150l-160 -160q-163 -163 -389.5 -186.5t-411.5 100.5l-362 -362h-181v181l362 362q-124 185 -100.5 411.5t186.5 389.5l160 160l150 -150l400 401q38 37 91 37t90 -37t37 -90.5t-37 -90.5l-400 -401l234 -234
+l401 400q38 37 91 37t90 -37z" />
+    <glyph glyph-name="_457" unicode="&#xf1e7;" horiz-adv-x="1792" 
+d="M873 796q0 -83 -63.5 -142.5t-152.5 -59.5t-152.5 59.5t-63.5 142.5q0 84 63.5 143t152.5 59t152.5 -59t63.5 -143zM1375 796q0 -83 -63 -142.5t-153 -59.5q-89 0 -152.5 59.5t-63.5 142.5q0 84 63.5 143t152.5 59q90 0 153 -59t63 -143zM1600 616v667q0 87 -32 123.5
+t-111 36.5h-1112q-83 0 -112.5 -34t-29.5 -126v-673q43 -23 88.5 -40t81 -28t81 -18.5t71 -11t70 -4t58.5 -0.5t56.5 2t44.5 2q68 1 95 -27q6 -6 10 -9q26 -25 61 -51q7 91 118 87q5 0 36.5 -1.5t43 -2t45.5 -1t53 1t54.5 4.5t61 8.5t62 13.5t67 19.5t67.5 27t72 34.5z
+M1763 621q-121 -149 -372 -252q84 -285 -23 -465q-66 -113 -183 -148q-104 -32 -182 15q-86 51 -82 164l-1 326v1q-8 2 -24.5 6t-23.5 5l-1 -338q4 -114 -83 -164q-79 -47 -183 -15q-117 36 -182 150q-105 180 -22 463q-251 103 -372 252q-25 37 -4 63t60 -1q4 -2 11.5 -7
+t10.5 -8v694q0 72 47 123t114 51h1257q67 0 114 -51t47 -123v-694l21 15q39 27 60 1t-4 -63z" />
+    <glyph glyph-name="_458" unicode="&#xf1e8;" horiz-adv-x="1792" 
+d="M896 1102v-434h-145v434h145zM1294 1102v-434h-145v434h145zM1294 342l253 254v795h-1194v-1049h326v-217l217 217h398zM1692 1536v-1013l-434 -434h-326l-217 -217h-217v217h-398v1158l109 289h1483z" />
+    <glyph glyph-name="_459" unicode="&#xf1e9;" 
+d="M773 217v-127q-1 -292 -6 -305q-12 -32 -51 -40q-54 -9 -181.5 38t-162.5 89q-13 15 -17 36q-1 12 4 26q4 10 34 47t181 216q1 0 60 70q15 19 39.5 24.5t49.5 -3.5q24 -10 37.5 -29t12.5 -42zM624 468q-3 -55 -52 -70l-120 -39q-275 -88 -292 -88q-35 2 -54 36
+q-12 25 -17 75q-8 76 1 166.5t30 124.5t56 32q13 0 202 -77q71 -29 115 -47l84 -34q23 -9 35.5 -30.5t11.5 -48.5zM1450 171q-7 -54 -91.5 -161t-135.5 -127q-37 -14 -63 7q-14 10 -184 287l-47 77q-14 21 -11.5 46t19.5 46q35 43 83 26q1 -1 119 -40q203 -66 242 -79.5
+t47 -20.5q28 -22 22 -61zM778 803q5 -102 -54 -122q-58 -17 -114 71l-378 598q-8 35 19 62q41 43 207.5 89.5t224.5 31.5q40 -10 49 -45q3 -18 22 -305.5t24 -379.5zM1440 695q3 -39 -26 -59q-15 -10 -329 -86q-67 -15 -91 -23l1 2q-23 -6 -46 4t-37 32q-30 47 0 87
+q1 1 75 102q125 171 150 204t34 39q28 19 65 2q48 -23 123 -133.5t81 -167.5v-3z" />
+    <glyph glyph-name="_460" unicode="&#xf1ea;" horiz-adv-x="2048" 
+d="M1024 1024h-384v-384h384v384zM1152 384v-128h-640v128h640zM1152 1152v-640h-640v640h640zM1792 384v-128h-512v128h512zM1792 640v-128h-512v128h512zM1792 896v-128h-512v128h512zM1792 1152v-128h-512v128h512zM256 192v960h-128v-960q0 -26 19 -45t45 -19t45 19
+t19 45zM1920 192v1088h-1536v-1088q0 -33 -11 -64h1483q26 0 45 19t19 45zM2048 1408v-1216q0 -80 -56 -136t-136 -56h-1664q-80 0 -136 56t-56 136v1088h256v128h1792z" />
+    <glyph glyph-name="_461" unicode="&#xf1eb;" horiz-adv-x="2048" 
+d="M1024 13q-20 0 -93 73.5t-73 93.5q0 32 62.5 54t103.5 22t103.5 -22t62.5 -54q0 -20 -73 -93.5t-93 -73.5zM1294 284q-2 0 -40 25t-101.5 50t-128.5 25t-128.5 -25t-101 -50t-40.5 -25q-18 0 -93.5 75t-75.5 93q0 13 10 23q78 77 196 121t233 44t233 -44t196 -121
+q10 -10 10 -23q0 -18 -75.5 -93t-93.5 -75zM1567 556q-11 0 -23 8q-136 105 -252 154.5t-268 49.5q-85 0 -170.5 -22t-149 -53t-113.5 -62t-79 -53t-31 -22q-17 0 -92 75t-75 93q0 12 10 22q132 132 320 205t380 73t380 -73t320 -205q10 -10 10 -22q0 -18 -75 -93t-92 -75z
+M1838 827q-11 0 -22 9q-179 157 -371.5 236.5t-420.5 79.5t-420.5 -79.5t-371.5 -236.5q-11 -9 -22 -9q-17 0 -92.5 75t-75.5 93q0 13 10 23q187 186 445 288t527 102t527 -102t445 -288q10 -10 10 -23q0 -18 -75.5 -93t-92.5 -75z" />
+    <glyph glyph-name="_462" unicode="&#xf1ec;" horiz-adv-x="1792" 
+d="M384 0q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM768 0q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM384 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5
+t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1152 0q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM768 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5
+t37.5 90.5zM384 768q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1152 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM768 768q0 53 -37.5 90.5t-90.5 37.5
+t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1536 0v384q0 52 -38 90t-90 38t-90 -38t-38 -90v-384q0 -52 38 -90t90 -38t90 38t38 90zM1152 768q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5z
+M1536 1088v256q0 26 -19 45t-45 19h-1280q-26 0 -45 -19t-19 -45v-256q0 -26 19 -45t45 -19h1280q26 0 45 19t19 45zM1536 768q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1664 1408v-1536q0 -52 -38 -90t-90 -38
+h-1408q-52 0 -90 38t-38 90v1536q0 52 38 90t90 38h1408q52 0 90 -38t38 -90z" />
+    <glyph glyph-name="_463" unicode="&#xf1ed;" 
+d="M1519 890q18 -84 -4 -204q-87 -444 -565 -444h-44q-25 0 -44 -16.5t-24 -42.5l-4 -19l-55 -346l-2 -15q-5 -26 -24.5 -42.5t-44.5 -16.5h-251q-21 0 -33 15t-9 36q9 56 26.5 168t26.5 168t27 167.5t27 167.5q5 37 43 37h131q133 -2 236 21q175 39 287 144q102 95 155 246
+q24 70 35 133q1 6 2.5 7.5t3.5 1t6 -3.5q79 -59 98 -162zM1347 1172q0 -107 -46 -236q-80 -233 -302 -315q-113 -40 -252 -42q0 -1 -90 -1l-90 1q-100 0 -118 -96q-2 -8 -85 -530q-1 -10 -12 -10h-295q-22 0 -36.5 16.5t-11.5 38.5l232 1471q5 29 27.5 48t51.5 19h598
+q34 0 97.5 -13t111.5 -32q107 -41 163.5 -123t56.5 -196z" />
+    <glyph glyph-name="_464" unicode="&#xf1ee;" horiz-adv-x="1792" 
+d="M441 864q33 0 52 -26q266 -364 362 -774h-446q-127 441 -367 749q-12 16 -3 33.5t29 17.5h373zM1000 507q-49 -199 -125 -393q-79 310 -256 594q40 221 44 449q211 -340 337 -650zM1099 1216q235 -324 384.5 -698.5t184.5 -773.5h-451q-41 665 -553 1472h435zM1792 640
+q0 -424 -101 -812q-67 560 -359 1083q-25 301 -106 584q-4 16 5.5 28.5t25.5 12.5h359q21 0 38.5 -13t22.5 -33q115 -409 115 -850z" />
+    <glyph glyph-name="uniF1F0" unicode="&#xf1f0;" horiz-adv-x="2304" 
+d="M1975 546h-138q14 37 66 179l3 9q4 10 10 26t9 26l12 -55zM531 611l-58 295q-11 54 -75 54h-268l-2 -13q311 -79 403 -336zM710 960l-162 -438l-17 89q-26 70 -85 129.5t-131 88.5l135 -510h175l261 641h-176zM849 318h166l104 642h-166zM1617 944q-69 27 -149 27
+q-123 0 -201 -59t-79 -153q-1 -102 145 -174q48 -23 67 -41t19 -39q0 -30 -30 -46t-69 -16q-86 0 -156 33l-22 11l-23 -144q74 -34 185 -34q130 -1 208.5 59t80.5 160q0 106 -140 174q-49 25 -71 42t-22 38q0 22 24.5 38.5t70.5 16.5q70 1 124 -24l15 -8zM2042 960h-128
+q-65 0 -87 -54l-246 -588h174l35 96h212q5 -22 20 -96h154zM2304 1280v-1280q0 -52 -38 -90t-90 -38h-2048q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h2048q52 0 90 -38t38 -90z" />
+    <glyph glyph-name="_466" unicode="&#xf1f1;" horiz-adv-x="2304" 
+d="M1119 1195q-128 85 -281 85q-103 0 -197.5 -40.5t-162.5 -108.5t-108.5 -162t-40.5 -197q0 -104 40.5 -198t108.5 -162t162 -108.5t198 -40.5q153 0 281 85q-131 107 -178 265.5t0.5 316.5t177.5 265zM1152 1171q-126 -99 -172 -249.5t-0.5 -300.5t172.5 -249
+q127 99 172.5 249t-0.5 300.5t-172 249.5zM1185 1195q130 -107 177.5 -265.5t0.5 -317t-178 -264.5q128 -85 281 -85q104 0 198 40.5t162 108.5t108.5 162t40.5 198q0 103 -40.5 197t-108.5 162t-162.5 108.5t-197.5 40.5q-153 0 -281 -85zM1926 473h7v3h-17v-3h7v-17h3v17z
+M1955 456h4v20h-5l-6 -13l-6 13h-5v-20h3v15l6 -13h4l5 13v-15zM1947 16v-2h-2h-3v3h3h2v-1zM1947 7h3l-4 5h2l1 1q1 1 1 3t-1 3l-1 1h-3h-6v-13h3v5h1zM685 75q0 19 11 31t30 12q18 0 29 -12.5t11 -30.5q0 -19 -11 -31t-29 -12q-19 0 -30 12t-11 31zM1158 119q30 0 35 -32
+h-70q5 32 35 32zM1514 75q0 19 11 31t29 12t29.5 -12.5t11.5 -30.5q0 -19 -11 -31t-30 -12q-18 0 -29 12t-11 31zM1786 75q0 18 11.5 30.5t29.5 12.5t29.5 -12.5t11.5 -30.5q0 -19 -11.5 -31t-29.5 -12t-29.5 12.5t-11.5 30.5zM1944 3q-2 0 -4 1q-1 0 -3 2t-2 3q-1 2 -1 4
+q0 3 1 4q0 2 2 4l1 1q2 0 2 1q2 1 4 1q3 0 4 -1l4 -2l2 -4v-1q1 -2 1 -3l-1 -1v-3t-1 -1l-1 -2q-2 -2 -4 -2q-1 -1 -4 -1zM599 7h30v85q0 24 -14.5 38.5t-39.5 15.5q-32 0 -47 -24q-14 24 -45 24q-24 0 -39 -20v16h-30v-135h30v75q0 36 33 36q30 0 30 -36v-75h29v75
+q0 36 33 36q30 0 30 -36v-75zM765 7h29v68v67h-29v-16q-17 20 -43 20q-29 0 -48 -20t-19 -51t19 -51t48 -20q28 0 43 20v-17zM943 48q0 34 -47 40l-14 2q-23 4 -23 14q0 15 25 15q23 0 43 -11l12 24q-22 14 -55 14q-26 0 -41 -12t-15 -32q0 -33 47 -39l13 -2q24 -4 24 -14
+q0 -17 -31 -17q-25 0 -45 14l-13 -23q25 -17 58 -17q29 0 45.5 12t16.5 32zM1073 14l-8 25q-13 -7 -26 -7q-19 0 -19 22v61h48v27h-48v41h-30v-41h-28v-27h28v-61q0 -50 47 -50q21 0 36 10zM1159 146q-29 0 -48 -20t-19 -51q0 -32 19.5 -51.5t49.5 -19.5q33 0 55 19l-14 22
+q-18 -15 -39 -15q-34 0 -41 33h101v12q0 32 -18 51.5t-46 19.5zM1318 146q-23 0 -35 -20v16h-30v-135h30v76q0 35 29 35q10 0 18 -4l9 28q-9 4 -21 4zM1348 75q0 -31 19.5 -51t52.5 -20q29 0 48 16l-14 24q-18 -13 -35 -12q-18 0 -29.5 12t-11.5 31t11.5 31t29.5 12
+q19 0 35 -12l14 24q-20 16 -48 16q-33 0 -52.5 -20t-19.5 -51zM1593 7h30v68v67h-30v-16q-15 20 -42 20q-29 0 -48.5 -20t-19.5 -51t19.5 -51t48.5 -20q28 0 42 20v-17zM1726 146q-23 0 -35 -20v16h-29v-135h29v76q0 35 29 35q10 0 18 -4l9 28q-8 4 -21 4zM1866 7h29v68v122
+h-29v-71q-15 20 -43 20t-47.5 -20.5t-19.5 -50.5t19.5 -50.5t47.5 -20.5q29 0 43 20v-17zM1944 27l-2 -1h-3q-2 -1 -4 -3q-3 -1 -3 -4q-1 -2 -1 -6q0 -3 1 -5q0 -2 3 -4q2 -2 4 -3t5 -1q4 0 6 1q0 1 2 2l2 1q1 1 3 4q1 2 1 5q0 4 -1 6q-1 1 -3 4q0 1 -2 2l-2 1q-1 0 -3 0.5
+t-3 0.5zM2304 1280v-1280q0 -52 -38 -90t-90 -38h-2048q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h2048q52 0 90 -38t38 -90z" />
+    <glyph glyph-name="_467" unicode="&#xf1f2;" horiz-adv-x="2304" 
+d="M313 759q0 -51 -36 -84q-29 -26 -89 -26h-17v220h17q61 0 89 -27q36 -31 36 -83zM2089 824q0 -52 -64 -52h-19v101h20q63 0 63 -49zM380 759q0 74 -50 120.5t-129 46.5h-95v-333h95q74 0 119 38q60 51 60 128zM410 593h65v333h-65v-333zM730 694q0 40 -20.5 62t-75.5 42
+q-29 10 -39.5 19t-10.5 23q0 16 13.5 26.5t34.5 10.5q29 0 53 -27l34 44q-41 37 -98 37q-44 0 -74 -27.5t-30 -67.5q0 -35 18 -55.5t64 -36.5q37 -13 45 -19q19 -12 19 -34q0 -20 -14 -33.5t-36 -13.5q-48 0 -71 44l-42 -40q44 -64 115 -64q51 0 83 30.5t32 79.5zM1008 604
+v77q-37 -37 -78 -37q-49 0 -80.5 32.5t-31.5 82.5q0 48 31.5 81.5t77.5 33.5q43 0 81 -38v77q-40 20 -80 20q-74 0 -125.5 -50.5t-51.5 -123.5t51 -123.5t125 -50.5q42 0 81 19zM2240 0v527q-65 -40 -144.5 -84t-237.5 -117t-329.5 -137.5t-417.5 -134.5t-504 -118h1569
+q26 0 45 19t19 45zM1389 757q0 75 -53 128t-128 53t-128 -53t-53 -128t53 -128t128 -53t128 53t53 128zM1541 584l144 342h-71l-90 -224l-89 224h-71l142 -342h35zM1714 593h184v56h-119v90h115v56h-115v74h119v57h-184v-333zM2105 593h80l-105 140q76 16 76 94q0 47 -31 73
+t-87 26h-97v-333h65v133h9zM2304 1274v-1268q0 -56 -38.5 -95t-93.5 -39h-2040q-55 0 -93.5 39t-38.5 95v1268q0 56 38.5 95t93.5 39h2040q55 0 93.5 -39t38.5 -95z" />
+    <glyph glyph-name="f1f3" unicode="&#xf1f3;" horiz-adv-x="2304" 
+d="M119 854h89l-45 108zM740 328l74 79l-70 79h-163v-49h142v-55h-142v-54h159zM898 406l99 -110v217zM1186 453q0 33 -40 33h-84v-69h83q41 0 41 36zM1475 457q0 29 -42 29h-82v-61h81q43 0 43 32zM1197 923q0 29 -42 29h-82v-60h81q43 0 43 31zM1656 854h89l-44 108z
+M699 1009v-271h-66v212l-94 -212h-57l-94 212v-212h-132l-25 60h-135l-25 -60h-70l116 271h96l110 -257v257h106l85 -184l77 184h108zM1255 453q0 -20 -5.5 -35t-14 -25t-22.5 -16.5t-26 -10t-31.5 -4.5t-31.5 -1t-32.5 0.5t-29.5 0.5v-91h-126l-80 90l-83 -90h-256v271h260
+l80 -89l82 89h207q109 0 109 -89zM964 794v-56h-217v271h217v-57h-152v-49h148v-55h-148v-54h152zM2304 235v-229q0 -55 -38.5 -94.5t-93.5 -39.5h-2040q-55 0 -93.5 39.5t-38.5 94.5v678h111l25 61h55l25 -61h218v46l19 -46h113l20 47v-47h541v99l10 1q10 0 10 -14v-86h279
+v23q23 -12 55 -18t52.5 -6.5t63 0.5t51.5 1l25 61h56l25 -61h227v58l34 -58h182v378h-180v-44l-25 44h-185v-44l-23 44h-249q-69 0 -109 -22v22h-172v-22q-24 22 -73 22h-628l-43 -97l-43 97h-198v-44l-22 44h-169l-78 -179v391q0 55 38.5 94.5t93.5 39.5h2040
+q55 0 93.5 -39.5t38.5 -94.5v-678h-120q-51 0 -81 -22v22h-177q-55 0 -78 -22v22h-316v-22q-31 22 -87 22h-209v-22q-23 22 -91 22h-234l-54 -58l-50 58h-349v-378h343l55 59l52 -59h211v89h21q59 0 90 13v-102h174v99h8q8 0 10 -2t2 -10v-87h529q57 0 88 24v-24h168
+q60 0 95 17zM1546 469q0 -23 -12 -43t-34 -29q25 -9 34 -26t9 -46v-54h-65v45q0 33 -12 43.5t-46 10.5h-69v-99h-65v271h154q48 0 77 -15t29 -58zM1269 936q0 -24 -12.5 -44t-33.5 -29q26 -9 34.5 -25.5t8.5 -46.5v-53h-65q0 9 0.5 26.5t0 25t-3 18.5t-8.5 16t-17.5 8.5
+t-29.5 3.5h-70v-98h-64v271l153 -1q49 0 78 -14.5t29 -57.5zM1798 327v-56h-216v271h216v-56h-151v-49h148v-55h-148v-54zM1372 1009v-271h-66v271h66zM2065 357q0 -86 -102 -86h-126v58h126q34 0 34 25q0 16 -17 21t-41.5 5t-49.5 3.5t-42 22.5t-17 55q0 39 26 60t66 21
+h130v-57h-119q-36 0 -36 -25q0 -16 17.5 -20.5t42 -4t49 -2.5t42 -21.5t17.5 -54.5zM2304 407v-101q-24 -35 -88 -35h-125v58h125q33 0 33 25q0 13 -12.5 19t-31 5.5t-40 2t-40 8t-31 24t-12.5 48.5q0 39 26.5 60t66.5 21h129v-57h-118q-36 0 -36 -25q0 -20 29 -22t68.5 -5
+t56.5 -26zM2139 1008v-270h-92l-122 203v-203h-132l-26 60h-134l-25 -60h-75q-129 0 -129 133q0 138 133 138h63v-59q-7 0 -28 1t-28.5 0.5t-23 -2t-21.5 -6.5t-14.5 -13.5t-11.5 -23t-3 -33.5q0 -38 13.5 -58t49.5 -20h29l92 213h97l109 -256v256h99l114 -188v188h66z" />
+    <glyph glyph-name="_469" unicode="&#xf1f4;" horiz-adv-x="2304" 
+d="M745 630q0 -37 -25.5 -61.5t-62.5 -24.5q-29 0 -46.5 16t-17.5 44q0 37 25 62.5t62 25.5q28 0 46.5 -16.5t18.5 -45.5zM1530 779q0 -42 -22 -57t-66 -15l-32 -1l17 107q2 11 13 11h18q22 0 35 -2t25 -12.5t12 -30.5zM1881 630q0 -36 -25.5 -61t-61.5 -25q-29 0 -47 16
+t-18 44q0 37 25 62.5t62 25.5q28 0 46.5 -16.5t18.5 -45.5zM513 801q0 59 -38.5 85.5t-100.5 26.5h-160q-19 0 -21 -19l-65 -408q-1 -6 3 -11t10 -5h76q20 0 22 19l18 110q1 8 7 13t15 6.5t17 1.5t19 -1t14 -1q86 0 135 48.5t49 134.5zM822 489l41 261q1 6 -3 11t-10 5h-76
+q-14 0 -17 -33q-27 40 -95 40q-72 0 -122.5 -54t-50.5 -127q0 -59 34.5 -94t92.5 -35q28 0 58 12t48 32q-4 -12 -4 -21q0 -16 13 -16h69q19 0 22 19zM1269 752q0 5 -4 9.5t-9 4.5h-77q-11 0 -18 -10l-106 -156l-44 150q-5 16 -22 16h-75q-5 0 -9 -4.5t-4 -9.5q0 -2 19.5 -59
+t42 -123t23.5 -70q-82 -112 -82 -120q0 -13 13 -13h77q11 0 18 10l255 368q2 2 2 7zM1649 801q0 59 -38.5 85.5t-100.5 26.5h-159q-20 0 -22 -19l-65 -408q-1 -6 3 -11t10 -5h82q12 0 16 13l18 116q1 8 7 13t15 6.5t17 1.5t19 -1t14 -1q86 0 135 48.5t49 134.5zM1958 489
+l41 261q1 6 -3 11t-10 5h-76q-14 0 -17 -33q-26 40 -95 40q-72 0 -122.5 -54t-50.5 -127q0 -59 34.5 -94t92.5 -35q29 0 59 12t47 32q0 -1 -2 -9t-2 -12q0 -16 13 -16h69q19 0 22 19zM2176 898v1q0 14 -13 14h-74q-11 0 -13 -11l-65 -416l-1 -2q0 -5 4 -9.5t10 -4.5h66
+q19 0 21 19zM392 764q-5 -35 -26 -46t-60 -11l-33 -1l17 107q2 11 13 11h19q40 0 58 -11.5t12 -48.5zM2304 1280v-1280q0 -52 -38 -90t-90 -38h-2048q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h2048q52 0 90 -38t38 -90z" />
+    <glyph glyph-name="_470" unicode="&#xf1f5;" horiz-adv-x="2304" 
+d="M1597 633q0 -69 -21 -106q-19 -35 -52 -35q-23 0 -41 9v224q29 30 57 30q57 0 57 -122zM2035 669h-110q6 98 56 98q51 0 54 -98zM476 534q0 59 -33 91.5t-101 57.5q-36 13 -52 24t-16 25q0 26 38 26q58 0 124 -33l18 112q-67 32 -149 32q-77 0 -123 -38q-48 -39 -48 -109
+q0 -58 32.5 -90.5t99.5 -56.5q39 -14 54.5 -25.5t15.5 -27.5q0 -31 -48 -31q-29 0 -70 12.5t-72 30.5l-18 -113q72 -41 168 -41q81 0 129 37q51 41 51 117zM771 749l19 111h-96v135l-129 -21l-18 -114l-46 -8l-17 -103h62v-219q0 -84 44 -120q38 -30 111 -30q32 0 79 11v118
+q-32 -7 -44 -7q-42 0 -42 50v197h77zM1087 724v139q-15 3 -28 3q-32 0 -55.5 -16t-33.5 -46l-10 56h-131v-471h150v306q26 31 82 31q16 0 26 -2zM1124 389h150v471h-150v-471zM1746 638q0 122 -45 179q-40 52 -111 52q-64 0 -117 -56l-8 47h-132v-645l150 25v151
+q36 -11 68 -11q83 0 134 56q61 65 61 202zM1278 986q0 33 -23 56t-56 23t-56 -23t-23 -56t23 -56.5t56 -23.5t56 23.5t23 56.5zM2176 629q0 113 -48 176q-50 64 -144 64q-96 0 -151.5 -66t-55.5 -180q0 -128 63 -188q55 -55 161 -55q101 0 160 40l-16 103q-57 -31 -128 -31
+q-43 0 -63 19q-23 19 -28 66h248q2 14 2 52zM2304 1280v-1280q0 -52 -38 -90t-90 -38h-2048q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h2048q52 0 90 -38t38 -90z" />
+    <glyph glyph-name="_471" unicode="&#xf1f6;" horiz-adv-x="2048" 
+d="M1558 684q61 -356 298 -556q0 -52 -38 -90t-90 -38h-448q0 -106 -75 -181t-181 -75t-180.5 74.5t-75.5 180.5zM1024 -176q16 0 16 16t-16 16q-59 0 -101.5 42.5t-42.5 101.5q0 16 -16 16t-16 -16q0 -73 51.5 -124.5t124.5 -51.5zM2026 1424q8 -10 7.5 -23.5t-10.5 -22.5
+l-1872 -1622q-10 -8 -23.5 -7t-21.5 11l-84 96q-8 10 -7.5 23.5t10.5 21.5l186 161q-19 32 -19 66q50 42 91 88t85 119.5t74.5 158.5t50 206t19.5 260q0 152 117 282.5t307 158.5q-8 19 -8 39q0 40 28 68t68 28t68 -28t28 -68q0 -20 -8 -39q124 -18 219 -82.5t148 -157.5
+l418 363q10 8 23.5 7t21.5 -11z" />
+    <glyph glyph-name="_472" unicode="&#xf1f7;" horiz-adv-x="2048" 
+d="M1040 -160q0 16 -16 16q-59 0 -101.5 42.5t-42.5 101.5q0 16 -16 16t-16 -16q0 -73 51.5 -124.5t124.5 -51.5q16 0 16 16zM503 315l877 760q-42 88 -132.5 146.5t-223.5 58.5q-93 0 -169.5 -31.5t-121.5 -80.5t-69 -103t-24 -105q0 -384 -137 -645zM1856 128
+q0 -52 -38 -90t-90 -38h-448q0 -106 -75 -181t-181 -75t-180.5 74.5t-75.5 180.5l149 129h757q-166 187 -227 459l111 97q61 -356 298 -556zM1942 1520l84 -96q8 -10 7.5 -23.5t-10.5 -22.5l-1872 -1622q-10 -8 -23.5 -7t-21.5 11l-84 96q-8 10 -7.5 23.5t10.5 21.5l186 161
+q-19 32 -19 66q50 42 91 88t85 119.5t74.5 158.5t50 206t19.5 260q0 152 117 282.5t307 158.5q-8 19 -8 39q0 40 28 68t68 28t68 -28t28 -68q0 -20 -8 -39q124 -18 219 -82.5t148 -157.5l418 363q10 8 23.5 7t21.5 -11z" />
+    <glyph glyph-name="_473" unicode="&#xf1f8;" horiz-adv-x="1408" 
+d="M512 160v704q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-704q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM768 160v704q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-704q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1024 160v704q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-704
+q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM480 1152h448l-48 117q-7 9 -17 11h-317q-10 -2 -17 -11zM1408 1120v-64q0 -14 -9 -23t-23 -9h-96v-948q0 -83 -47 -143.5t-113 -60.5h-832q-66 0 -113 58.5t-47 141.5v952h-96q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h309l70 167
+q15 37 54 63t79 26h320q40 0 79 -26t54 -63l70 -167h309q14 0 23 -9t9 -23z" />
+    <glyph glyph-name="_474" unicode="&#xf1f9;" 
+d="M1150 462v-109q0 -50 -36.5 -89t-94 -60.5t-118 -32.5t-117.5 -11q-205 0 -342.5 139t-137.5 346q0 203 136 339t339 136q34 0 75.5 -4.5t93 -18t92.5 -34t69 -56.5t28 -81v-109q0 -16 -16 -16h-118q-16 0 -16 16v70q0 43 -65.5 67.5t-137.5 24.5q-140 0 -228.5 -91.5
+t-88.5 -237.5q0 -151 91.5 -249.5t233.5 -98.5q68 0 138 24t70 66v70q0 7 4.5 11.5t10.5 4.5h119q6 0 11 -4.5t5 -11.5zM768 1280q-130 0 -248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5
+t-51 248.5t-136.5 204t-204 136.5t-248.5 51zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="_475" unicode="&#xf1fa;" 
+d="M972 761q0 108 -53.5 169t-147.5 61q-63 0 -124 -30.5t-110 -84.5t-79.5 -137t-30.5 -180q0 -112 53.5 -173t150.5 -61q96 0 176 66.5t122.5 166t42.5 203.5zM1536 640q0 -111 -37 -197t-98.5 -135t-131.5 -74.5t-145 -27.5q-6 0 -15.5 -0.5t-16.5 -0.5q-95 0 -142 53
+q-28 33 -33 83q-52 -66 -131.5 -110t-173.5 -44q-161 0 -249.5 95.5t-88.5 269.5q0 157 66 290t179 210.5t246 77.5q87 0 155 -35.5t106 -99.5l2 19l11 56q1 6 5.5 12t9.5 6h118q5 0 13 -11q5 -5 3 -16l-120 -614q-5 -24 -5 -48q0 -39 12.5 -52t44.5 -13q28 1 57 5.5t73 24
+t77 50t57 89.5t24 137q0 292 -174 466t-466 174q-130 0 -248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51q228 0 405 144q11 9 24 8t21 -12l41 -49q8 -12 7 -24q-2 -13 -12 -22q-102 -83 -227.5 -128t-258.5 -45q-156 0 -298 61
+t-245 164t-164 245t-61 298t61 298t164 245t245 164t298 61q344 0 556 -212t212 -556z" />
+    <glyph glyph-name="_476" unicode="&#xf1fb;" horiz-adv-x="1792" 
+d="M1698 1442q94 -94 94 -226.5t-94 -225.5l-225 -223l104 -104q10 -10 10 -23t-10 -23l-210 -210q-10 -10 -23 -10t-23 10l-105 105l-603 -603q-37 -37 -90 -37h-203l-256 -128l-64 64l128 256v203q0 53 37 90l603 603l-105 105q-10 10 -10 23t10 23l210 210q10 10 23 10
+t23 -10l104 -104l223 225q93 94 225.5 94t226.5 -94zM512 64l576 576l-192 192l-576 -576v-192h192z" />
+    <glyph glyph-name="f1fc" unicode="&#xf1fc;" horiz-adv-x="1792" 
+d="M1615 1536q70 0 122.5 -46.5t52.5 -116.5q0 -63 -45 -151q-332 -629 -465 -752q-97 -91 -218 -91q-126 0 -216.5 92.5t-90.5 219.5q0 128 92 212l638 579q59 54 130 54zM706 502q39 -76 106.5 -130t150.5 -76l1 -71q4 -213 -129.5 -347t-348.5 -134q-123 0 -218 46.5
+t-152.5 127.5t-86.5 183t-29 220q7 -5 41 -30t62 -44.5t59 -36.5t46 -17q41 0 55 37q25 66 57.5 112.5t69.5 76t88 47.5t103 25.5t125 10.5z" />
+    <glyph glyph-name="_478" unicode="&#xf1fd;" horiz-adv-x="1792" 
+d="M1792 128v-384h-1792v384q45 0 85 14t59 27.5t47 37.5q30 27 51.5 38t56.5 11q24 0 44 -7t31 -15t33 -27q29 -25 47 -38t58 -27t86 -14q45 0 85 14.5t58 27t48 37.5q21 19 32.5 27t31 15t43.5 7q35 0 56.5 -11t51.5 -38q28 -24 47 -37.5t59 -27.5t85 -14t85 14t59 27.5
+t47 37.5q30 27 51.5 38t56.5 11q34 0 55.5 -11t51.5 -38q28 -24 47 -37.5t59 -27.5t85 -14zM1792 448v-192q-24 0 -44 7t-31 15t-33 27q-29 25 -47 38t-58 27t-85 14q-46 0 -86 -14t-58 -27t-47 -38q-22 -19 -33 -27t-31 -15t-44 -7q-35 0 -56.5 11t-51.5 38q-29 25 -47 38
+t-58 27t-86 14q-45 0 -85 -14.5t-58 -27t-48 -37.5q-21 -19 -32.5 -27t-31 -15t-43.5 -7q-35 0 -56.5 11t-51.5 38q-28 24 -47 37.5t-59 27.5t-85 14q-46 0 -86 -14t-58 -27t-47 -38q-30 -27 -51.5 -38t-56.5 -11v192q0 80 56 136t136 56h64v448h256v-448h256v448h256v-448
+h256v448h256v-448h64q80 0 136 -56t56 -136zM512 1312q0 -77 -36 -118.5t-92 -41.5q-53 0 -90.5 37.5t-37.5 90.5q0 29 9.5 51t23.5 34t31 28t31 31.5t23.5 44.5t9.5 67q38 0 83 -74t45 -150zM1024 1312q0 -77 -36 -118.5t-92 -41.5q-53 0 -90.5 37.5t-37.5 90.5
+q0 29 9.5 51t23.5 34t31 28t31 31.5t23.5 44.5t9.5 67q38 0 83 -74t45 -150zM1536 1312q0 -77 -36 -118.5t-92 -41.5q-53 0 -90.5 37.5t-37.5 90.5q0 29 9.5 51t23.5 34t31 28t31 31.5t23.5 44.5t9.5 67q38 0 83 -74t45 -150z" />
+    <glyph glyph-name="_479" unicode="&#xf1fe;" horiz-adv-x="2048" 
+d="M2048 0v-128h-2048v1536h128v-1408h1920zM1664 1024l256 -896h-1664v576l448 576l576 -576z" />
+    <glyph glyph-name="_480" unicode="&#xf200;" horiz-adv-x="1792" 
+d="M768 646l546 -546q-106 -108 -247.5 -168t-298.5 -60q-209 0 -385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103v-762zM955 640h773q0 -157 -60 -298.5t-168 -247.5zM1664 768h-768v768q209 0 385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="_481" unicode="&#xf201;" horiz-adv-x="2048" 
+d="M2048 0v-128h-2048v1536h128v-1408h1920zM1920 1248v-435q0 -21 -19.5 -29.5t-35.5 7.5l-121 121l-633 -633q-10 -10 -23 -10t-23 10l-233 233l-416 -416l-192 192l585 585q10 10 23 10t23 -10l233 -233l464 464l-121 121q-16 16 -7.5 35.5t29.5 19.5h435q14 0 23 -9
+t9 -23z" />
+    <glyph glyph-name="_482" unicode="&#xf202;" horiz-adv-x="1792" 
+d="M1292 832q0 -6 10 -41q10 -29 25 -49.5t41 -34t44 -20t55 -16.5q325 -91 325 -332q0 -146 -105.5 -242.5t-254.5 -96.5q-59 0 -111.5 18.5t-91.5 45.5t-77 74.5t-63 87.5t-53.5 103.5t-43.5 103t-39.5 106.5t-35.5 95q-32 81 -61.5 133.5t-73.5 96.5t-104 64t-142 20
+q-96 0 -183 -55.5t-138 -144.5t-51 -185q0 -160 106.5 -279.5t263.5 -119.5q177 0 258 95q56 63 83 116l84 -152q-15 -34 -44 -70l1 -1q-131 -152 -388 -152q-147 0 -269.5 79t-190.5 207.5t-68 274.5q0 105 43.5 206t116 176.5t172 121.5t204.5 46q87 0 159 -19t123.5 -50
+t95 -80t72.5 -99t58.5 -117t50.5 -124.5t50 -130.5t55 -127q96 -200 233 -200q81 0 138.5 48.5t57.5 128.5q0 42 -19 72t-50.5 46t-72.5 31.5t-84.5 27t-87.5 34t-81 52t-65 82t-39 122.5q-3 16 -3 33q0 110 87.5 192t198.5 78q78 -3 120.5 -14.5t90.5 -53.5h-1
+q12 -11 23 -24.5t26 -36t19 -27.5l-129 -99q-26 49 -54 70v1q-23 21 -97 21q-49 0 -84 -33t-35 -83z" />
+    <glyph glyph-name="_483" unicode="&#xf203;" 
+d="M1432 484q0 173 -234 239q-35 10 -53 16.5t-38 25t-29 46.5q0 2 -2 8.5t-3 12t-1 7.5q0 36 24.5 59.5t60.5 23.5q54 0 71 -15h-1q20 -15 39 -51l93 71q-39 54 -49 64q-33 29 -67.5 39t-85.5 10q-80 0 -142 -57.5t-62 -137.5q0 -7 2 -23q16 -96 64.5 -140t148.5 -73
+q29 -8 49 -15.5t45 -21.5t38.5 -34.5t13.5 -46.5v-5q1 -58 -40.5 -93t-100.5 -35q-97 0 -167 144q-23 47 -51.5 121.5t-48 125.5t-54 110.5t-74 95.5t-103.5 60.5t-147 24.5q-101 0 -192 -56t-144 -148t-50 -192v-1q4 -108 50.5 -199t133.5 -147.5t196 -56.5q186 0 279 110
+q20 27 31 51l-60 109q-42 -80 -99 -116t-146 -36q-115 0 -191 87t-76 204q0 105 82 189t186 84q112 0 170 -53.5t104 -172.5q8 -21 25.5 -68.5t28.5 -76.5t31.5 -74.5t38.5 -74t45.5 -62.5t55.5 -53.5t66 -33t80 -13.5q107 0 183 69.5t76 174.5zM1536 1120v-960
+q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="_484" unicode="&#xf204;" horiz-adv-x="2048" 
+d="M1152 640q0 104 -40.5 198.5t-109.5 163.5t-163.5 109.5t-198.5 40.5t-198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5t198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5zM1920 640q0 104 -40.5 198.5
+t-109.5 163.5t-163.5 109.5t-198.5 40.5h-386q119 -90 188.5 -224t69.5 -288t-69.5 -288t-188.5 -224h386q104 0 198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5zM2048 640q0 -130 -51 -248.5t-136.5 -204t-204 -136.5t-248.5 -51h-768q-130 0 -248.5 51t-204 136.5
+t-136.5 204t-51 248.5t51 248.5t136.5 204t204 136.5t248.5 51h768q130 0 248.5 -51t204 -136.5t136.5 -204t51 -248.5z" />
+    <glyph glyph-name="_485" unicode="&#xf205;" horiz-adv-x="2048" 
+d="M0 640q0 130 51 248.5t136.5 204t204 136.5t248.5 51h768q130 0 248.5 -51t204 -136.5t136.5 -204t51 -248.5t-51 -248.5t-136.5 -204t-204 -136.5t-248.5 -51h-768q-130 0 -248.5 51t-204 136.5t-136.5 204t-51 248.5zM1408 128q104 0 198.5 40.5t163.5 109.5
+t109.5 163.5t40.5 198.5t-40.5 198.5t-109.5 163.5t-163.5 109.5t-198.5 40.5t-198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5z" />
+    <glyph glyph-name="_486" unicode="&#xf206;" horiz-adv-x="2304" 
+d="M762 384h-314q-40 0 -57.5 35t6.5 67l188 251q-65 31 -137 31q-132 0 -226 -94t-94 -226t94 -226t226 -94q115 0 203 72.5t111 183.5zM576 512h186q-18 85 -75 148zM1056 512l288 384h-480l-99 -132q105 -103 126 -252h165zM2176 448q0 132 -94 226t-226 94
+q-60 0 -121 -24l174 -260q15 -23 10 -49t-27 -40q-15 -11 -36 -11q-35 0 -53 29l-174 260q-93 -95 -93 -225q0 -132 94 -226t226 -94t226 94t94 226zM2304 448q0 -185 -131.5 -316.5t-316.5 -131.5t-316.5 131.5t-131.5 316.5q0 97 39.5 183.5t109.5 149.5l-65 98l-353 -469
+q-18 -26 -51 -26h-197q-23 -164 -149 -274t-294 -110q-185 0 -316.5 131.5t-131.5 316.5t131.5 316.5t316.5 131.5q114 0 215 -55l137 183h-224q-26 0 -45 19t-19 45t19 45t45 19h384v-128h435l-85 128h-222q-26 0 -45 19t-19 45t19 45t45 19h256q33 0 53 -28l267 -400
+q91 44 192 44q185 0 316.5 -131.5t131.5 -316.5z" />
+    <glyph glyph-name="_487" unicode="&#xf207;" 
+d="M384 320q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1408 320q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1362 716l-72 384q-5 23 -22.5 37.5t-40.5 14.5
+h-918q-23 0 -40.5 -14.5t-22.5 -37.5l-72 -384q-5 -30 14 -53t49 -23h1062q30 0 49 23t14 53zM1136 1328q0 20 -14 34t-34 14h-640q-20 0 -34 -14t-14 -34t14 -34t34 -14h640q20 0 34 14t14 34zM1536 603v-603h-128v-128q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5
+t-37.5 90.5v128h-768v-128q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5v128h-128v603q0 112 25 223l103 454q9 78 97.5 137t230 89t312.5 30t312.5 -30t230 -89t97.5 -137l105 -454q23 -102 23 -223z" />
+    <glyph glyph-name="_488" unicode="&#xf208;" horiz-adv-x="2048" 
+d="M1463 704q0 -35 -25 -60.5t-61 -25.5h-702q-36 0 -61 25.5t-25 60.5t25 60.5t61 25.5h702q36 0 61 -25.5t25 -60.5zM1677 704q0 86 -23 170h-982q-36 0 -61 25t-25 60q0 36 25 61t61 25h908q-88 143 -235 227t-320 84q-177 0 -327.5 -87.5t-238 -237.5t-87.5 -327
+q0 -86 23 -170h982q36 0 61 -25t25 -60q0 -36 -25 -61t-61 -25h-908q88 -143 235.5 -227t320.5 -84q132 0 253 51.5t208 139t139 208t52 253.5zM2048 959q0 -35 -25 -60t-61 -25h-131q17 -85 17 -170q0 -167 -65.5 -319.5t-175.5 -263t-262.5 -176t-319.5 -65.5
+q-246 0 -448.5 133t-301.5 350h-189q-36 0 -61 25t-25 61q0 35 25 60t61 25h132q-17 85 -17 170q0 167 65.5 319.5t175.5 263t262.5 176t320.5 65.5q245 0 447.5 -133t301.5 -350h188q36 0 61 -25t25 -61z" />
+    <glyph glyph-name="_489" unicode="&#xf209;" horiz-adv-x="1280" 
+d="M953 1158l-114 -328l117 -21q165 451 165 518q0 56 -38 56q-57 0 -130 -225zM654 471l33 -88q37 42 71 67l-33 5.5t-38.5 7t-32.5 8.5zM362 1367q0 -98 159 -521q17 10 49 10q15 0 75 -5l-121 351q-75 220 -123 220q-19 0 -29 -17.5t-10 -37.5zM283 608q0 -36 51.5 -119
+t117.5 -153t100 -70q14 0 25.5 13t11.5 27q0 24 -32 102q-13 32 -32 72t-47.5 89t-61.5 81t-62 32q-20 0 -45.5 -27t-25.5 -47zM125 273q0 -41 25 -104q59 -145 183.5 -227t281.5 -82q227 0 382 170q152 169 152 427q0 43 -1 67t-11.5 62t-30.5 56q-56 49 -211.5 75.5
+t-270.5 26.5q-37 0 -49 -11q-12 -5 -12 -35q0 -34 21.5 -60t55.5 -40t77.5 -23.5t87.5 -11.5t85 -4t70 0h23q24 0 40 -19q15 -19 19 -55q-28 -28 -96 -54q-61 -22 -93 -46q-64 -46 -108.5 -114t-44.5 -137q0 -31 18.5 -88.5t18.5 -87.5l-3 -12q-4 -12 -4 -14
+q-137 10 -146 216q-8 -2 -41 -2q2 -7 2 -21q0 -53 -40.5 -89.5t-94.5 -36.5q-82 0 -166.5 78t-84.5 159q0 34 33 67q52 -64 60 -76q77 -104 133 -104q12 0 26.5 8.5t14.5 20.5q0 34 -87.5 145t-116.5 111q-43 0 -70 -44.5t-27 -90.5zM11 264q0 101 42.5 163t136.5 88
+q-28 74 -28 104q0 62 61 123t122 61q29 0 70 -15q-163 462 -163 567q0 80 41 130.5t119 50.5q131 0 325 -581q6 -17 8 -23q6 16 29 79.5t43.5 118.5t54 127.5t64.5 123t70.5 86.5t76.5 36q71 0 112 -49t41 -122q0 -108 -159 -550q61 -15 100.5 -46t58.5 -78t26 -93.5
+t7 -110.5q0 -150 -47 -280t-132 -225t-211 -150t-278 -55q-111 0 -223 42q-149 57 -258 191.5t-109 286.5z" />
+    <glyph glyph-name="_490" unicode="&#xf20a;" horiz-adv-x="2048" 
+d="M785 528h207q-14 -158 -98.5 -248.5t-214.5 -90.5q-162 0 -254.5 116t-92.5 316q0 194 93 311.5t233 117.5q148 0 232 -87t97 -247h-203q-5 64 -35.5 99t-81.5 35q-57 0 -88.5 -60.5t-31.5 -177.5q0 -48 5 -84t18 -69.5t40 -51.5t66 -18q95 0 109 139zM1497 528h206
+q-14 -158 -98 -248.5t-214 -90.5q-162 0 -254.5 116t-92.5 316q0 194 93 311.5t233 117.5q148 0 232 -87t97 -247h-204q-4 64 -35 99t-81 35q-57 0 -88.5 -60.5t-31.5 -177.5q0 -48 5 -84t18 -69.5t39.5 -51.5t65.5 -18q49 0 76.5 38t33.5 101zM1856 647q0 207 -15.5 307
+t-60.5 161q-6 8 -13.5 14t-21.5 15t-16 11q-86 63 -697 63q-625 0 -710 -63q-5 -4 -17.5 -11.5t-21 -14t-14.5 -14.5q-45 -60 -60 -159.5t-15 -308.5q0 -208 15 -307.5t60 -160.5q6 -8 15 -15t20.5 -14t17.5 -12q44 -33 239.5 -49t470.5 -16q610 0 697 65q5 4 17 11t20.5 14
+t13.5 16q46 60 61 159t15 309zM2048 1408v-1536h-2048v1536h2048z" />
+    <glyph glyph-name="_491" unicode="&#xf20b;" 
+d="M992 912v-496q0 -14 -9 -23t-23 -9h-160q-14 0 -23 9t-9 23v496q0 112 -80 192t-192 80h-272v-1152q0 -14 -9 -23t-23 -9h-160q-14 0 -23 9t-9 23v1344q0 14 9 23t23 9h464q135 0 249 -66.5t180.5 -180.5t66.5 -249zM1376 1376v-880q0 -135 -66.5 -249t-180.5 -180.5
+t-249 -66.5h-464q-14 0 -23 9t-9 23v960q0 14 9 23t23 9h160q14 0 23 -9t9 -23v-768h272q112 0 192 80t80 192v880q0 14 9 23t23 9h160q14 0 23 -9t9 -23z" />
+    <glyph glyph-name="_492" unicode="&#xf20c;" 
+d="M1311 694v-114q0 -24 -13.5 -38t-37.5 -14h-202q-24 0 -38 14t-14 38v114q0 24 14 38t38 14h202q24 0 37.5 -14t13.5 -38zM821 464v250q0 53 -32.5 85.5t-85.5 32.5h-133q-68 0 -96 -52q-28 52 -96 52h-130q-53 0 -85.5 -32.5t-32.5 -85.5v-250q0 -22 21 -22h55
+q22 0 22 22v230q0 24 13.5 38t38.5 14h94q24 0 38 -14t14 -38v-230q0 -22 21 -22h54q22 0 22 22v230q0 24 14 38t38 14h97q24 0 37.5 -14t13.5 -38v-230q0 -22 22 -22h55q21 0 21 22zM1410 560v154q0 53 -33 85.5t-86 32.5h-264q-53 0 -86 -32.5t-33 -85.5v-410
+q0 -21 22 -21h55q21 0 21 21v180q31 -42 94 -42h191q53 0 86 32.5t33 85.5zM1536 1176v-1072q0 -96 -68 -164t-164 -68h-1072q-96 0 -164 68t-68 164v1072q0 96 68 164t164 68h1072q96 0 164 -68t68 -164z" />
+    <glyph glyph-name="_493" unicode="&#xf20d;" 
+d="M915 450h-294l147 551zM1001 128h311l-324 1024h-440l-324 -1024h311l383 314zM1536 1120v-960q0 -118 -85 -203t-203 -85h-960q-118 0 -203 85t-85 203v960q0 118 85 203t203 85h960q118 0 203 -85t85 -203z" />
+    <glyph glyph-name="_494" unicode="&#xf20e;" horiz-adv-x="2048" 
+d="M2048 641q0 -21 -13 -36.5t-33 -19.5l-205 -356q3 -9 3 -18q0 -20 -12.5 -35.5t-32.5 -19.5l-193 -337q3 -8 3 -16q0 -23 -16.5 -40t-40.5 -17q-25 0 -41 18h-400q-17 -20 -43 -20t-43 20h-399q-17 -20 -43 -20q-23 0 -40 16.5t-17 40.5q0 8 4 20l-193 335
+q-20 4 -32.5 19.5t-12.5 35.5q0 9 3 18l-206 356q-20 5 -32.5 20.5t-12.5 35.5q0 21 13.5 36.5t33.5 19.5l199 344q0 1 -0.5 3t-0.5 3q0 36 34 51l209 363q-4 10 -4 18q0 24 17 40.5t40 16.5q26 0 44 -21h396q16 21 43 21t43 -21h398q18 21 44 21q23 0 40 -16.5t17 -40.5
+q0 -6 -4 -18l207 -358q23 -1 39 -17.5t16 -38.5q0 -13 -7 -27l187 -324q19 -4 31.5 -19.5t12.5 -35.5zM1063 -158h389l-342 354h-143l-342 -354h360q18 16 39 16t39 -16zM112 654q1 -4 1 -13q0 -10 -2 -15l208 -360l15 -6l188 199v347l-187 194q-13 -8 -29 -10zM986 1438
+h-388l190 -200l554 200h-280q-16 -16 -38 -16t-38 16zM1689 226q1 6 5 11l-64 68l-17 -79h76zM1583 226l22 105l-252 266l-296 -307l63 -64h463zM1495 -142l16 28l65 310h-427l333 -343q8 4 13 5zM578 -158h5l342 354h-373v-335l4 -6q14 -5 22 -13zM552 226h402l64 66
+l-309 321l-157 -166v-221zM359 226h163v189l-168 -177q4 -8 5 -12zM358 1051q0 -1 0.5 -2t0.5 -2q0 -16 -8 -29l171 -177v269zM552 1121v-311l153 -157l297 314l-223 236zM556 1425l-4 -8v-264l205 74l-191 201q-6 -2 -10 -3zM1447 1438h-16l-621 -224l213 -225zM1023 946
+l-297 -315l311 -319l296 307zM688 634l-136 141v-284zM1038 270l-42 -44h85zM1374 618l238 -251l132 624l-3 5l-1 1zM1718 1018q-8 13 -8 29v2l-216 376q-5 1 -13 5l-437 -463l310 -327zM522 1142v223l-163 -282zM522 196h-163l163 -283v283zM1607 196l-48 -227l130 227h-82
+zM1729 266l207 361q-2 10 -2 14q0 1 3 16l-171 296l-129 -612l77 -82q5 3 15 7z" />
+    <glyph glyph-name="f210" unicode="&#xf210;" 
+d="M0 856q0 131 91.5 226.5t222.5 95.5h742l352 358v-1470q0 -132 -91.5 -227t-222.5 -95h-780q-131 0 -222.5 95t-91.5 227v790zM1232 102l-176 180v425q0 46 -32 79t-78 33h-484q-46 0 -78 -33t-32 -79v-492q0 -46 32.5 -79.5t77.5 -33.5h770z" />
+    <glyph glyph-name="_496" unicode="&#xf211;" 
+d="M934 1386q-317 -121 -556 -362.5t-358 -560.5q-20 89 -20 176q0 208 102.5 384.5t278.5 279t384 102.5q82 0 169 -19zM1203 1267q93 -65 164 -155q-389 -113 -674.5 -400.5t-396.5 -676.5q-93 72 -155 162q112 386 395 671t667 399zM470 -67q115 356 379.5 622t619.5 384
+q40 -92 54 -195q-292 -120 -516 -345t-343 -518q-103 14 -194 52zM1536 -125q-193 50 -367 115q-135 -84 -290 -107q109 205 274 370.5t369 275.5q-21 -152 -101 -284q65 -175 115 -370z" />
+    <glyph glyph-name="f212" unicode="&#xf212;" horiz-adv-x="2048" 
+d="M1893 1144l155 -1272q-131 0 -257 57q-200 91 -393 91q-226 0 -374 -148q-148 148 -374 148q-193 0 -393 -91q-128 -57 -252 -57h-5l155 1272q224 127 482 127q233 0 387 -106q154 106 387 106q258 0 482 -127zM1398 157q129 0 232 -28.5t260 -93.5l-124 1021
+q-171 78 -368 78q-224 0 -374 -141q-150 141 -374 141q-197 0 -368 -78l-124 -1021q105 43 165.5 65t148.5 39.5t178 17.5q202 0 374 -108q172 108 374 108zM1438 191l-55 907q-211 -4 -359 -155q-152 155 -374 155q-176 0 -336 -66l-114 -941q124 51 228.5 76t221.5 25
+q209 0 374 -102q172 107 374 102z" />
+    <glyph glyph-name="_498" unicode="&#xf213;" horiz-adv-x="2048" 
+d="M1500 165v733q0 21 -15 36t-35 15h-93q-20 0 -35 -15t-15 -36v-733q0 -20 15 -35t35 -15h93q20 0 35 15t15 35zM1216 165v531q0 20 -15 35t-35 15h-101q-20 0 -35 -15t-15 -35v-531q0 -20 15 -35t35 -15h101q20 0 35 15t15 35zM924 165v429q0 20 -15 35t-35 15h-101
+q-20 0 -35 -15t-15 -35v-429q0 -20 15 -35t35 -15h101q20 0 35 15t15 35zM632 165v362q0 20 -15 35t-35 15h-101q-20 0 -35 -15t-15 -35v-362q0 -20 15 -35t35 -15h101q20 0 35 15t15 35zM2048 311q0 -166 -118 -284t-284 -118h-1244q-166 0 -284 118t-118 284
+q0 116 63 214.5t168 148.5q-10 34 -10 73q0 113 80.5 193.5t193.5 80.5q102 0 180 -67q45 183 194 300t338 117q149 0 275 -73.5t199.5 -199.5t73.5 -275q0 -66 -14 -122q135 -33 221 -142.5t86 -247.5z" />
+    <glyph glyph-name="_499" unicode="&#xf214;" 
+d="M0 1536h1536v-1392l-776 -338l-760 338v1392zM1436 209v926h-1336v-926l661 -294zM1436 1235v201h-1336v-201h1336zM181 937v-115h-37v115h37zM181 789v-115h-37v115h37zM181 641v-115h-37v115h37zM181 493v-115h-37v115h37zM181 345v-115h-37v115h37zM207 202l15 34
+l105 -47l-15 -33zM343 142l15 34l105 -46l-15 -34zM478 82l15 34l105 -46l-15 -34zM614 23l15 33l104 -46l-15 -34zM797 10l105 46l15 -33l-105 -47zM932 70l105 46l15 -34l-105 -46zM1068 130l105 46l15 -34l-105 -46zM1203 189l105 47l15 -34l-105 -46zM259 1389v-36h-114
+v36h114zM421 1389v-36h-115v36h115zM583 1389v-36h-115v36h115zM744 1389v-36h-114v36h114zM906 1389v-36h-114v36h114zM1068 1389v-36h-115v36h115zM1230 1389v-36h-115v36h115zM1391 1389v-36h-114v36h114zM181 1049v-79h-37v115h115v-36h-78zM421 1085v-36h-115v36h115z
+M583 1085v-36h-115v36h115zM744 1085v-36h-114v36h114zM906 1085v-36h-114v36h114zM1068 1085v-36h-115v36h115zM1230 1085v-36h-115v36h115zM1355 970v79h-78v36h115v-115h-37zM1355 822v115h37v-115h-37zM1355 674v115h37v-115h-37zM1355 526v115h37v-115h-37zM1355 378
+v115h37v-115h-37zM1355 230v115h37v-115h-37zM760 265q-129 0 -221 91.5t-92 221.5q0 129 92 221t221 92q130 0 221.5 -92t91.5 -221q0 -130 -91.5 -221.5t-221.5 -91.5zM595 646q0 -36 19.5 -56.5t49.5 -25t64 -7t64 -2t49.5 -9t19.5 -30.5q0 -49 -112 -49q-97 0 -123 51
+h-3l-31 -63q67 -42 162 -42q29 0 56.5 5t55.5 16t45.5 33t17.5 53q0 46 -27.5 69.5t-67.5 27t-79.5 3t-67 5t-27.5 25.5q0 21 20.5 33t40.5 15t41 3q34 0 70.5 -11t51.5 -34h3l30 58q-3 1 -21 8.5t-22.5 9t-19.5 7t-22 7t-20 4.5t-24 4t-23 1q-29 0 -56.5 -5t-54 -16.5
+t-43 -34t-16.5 -53.5z" />
+    <glyph glyph-name="_500" unicode="&#xf215;" horiz-adv-x="2048" 
+d="M863 504q0 112 -79.5 191.5t-191.5 79.5t-191 -79.5t-79 -191.5t79 -191t191 -79t191.5 79t79.5 191zM1726 505q0 112 -79 191t-191 79t-191.5 -79t-79.5 -191q0 -113 79.5 -192t191.5 -79t191 79.5t79 191.5zM2048 1314v-1348q0 -44 -31.5 -75.5t-76.5 -31.5h-1832
+q-45 0 -76.5 31.5t-31.5 75.5v1348q0 44 31.5 75.5t76.5 31.5h431q44 0 76 -31.5t32 -75.5v-161h754v161q0 44 32 75.5t76 31.5h431q45 0 76.5 -31.5t31.5 -75.5z" />
+    <glyph glyph-name="_501" unicode="&#xf216;" horiz-adv-x="2048" 
+d="M1430 953zM1690 749q148 0 253 -98.5t105 -244.5q0 -157 -109 -261.5t-267 -104.5q-85 0 -162 27.5t-138 73.5t-118 106t-109 126t-103.5 132.5t-108.5 126.5t-117 106t-136 73.5t-159 27.5q-154 0 -251.5 -91.5t-97.5 -244.5q0 -157 104 -250t263 -93q100 0 208 37.5
+t193 98.5q5 4 21 18.5t30 24t22 9.5q14 0 24.5 -10.5t10.5 -24.5q0 -24 -60 -77q-101 -88 -234.5 -142t-260.5 -54q-133 0 -245.5 58t-180 165t-67.5 241q0 205 141.5 341t347.5 136q120 0 226.5 -43.5t185.5 -113t151.5 -153t139 -167.5t133.5 -153.5t149.5 -113
+t172.5 -43.5q102 0 168.5 61.5t66.5 162.5q0 95 -64.5 159t-159.5 64q-30 0 -81.5 -18.5t-68.5 -18.5q-20 0 -35.5 15t-15.5 35q0 18 8.5 57t8.5 59q0 159 -107.5 263t-266.5 104q-58 0 -111.5 -18.5t-84 -40.5t-55.5 -40.5t-33 -18.5q-15 0 -25.5 10.5t-10.5 25.5
+q0 19 25 46q59 67 147 103.5t182 36.5q191 0 318 -125.5t127 -315.5q0 -37 -4 -66q57 15 115 15z" />
+    <glyph glyph-name="_502" unicode="&#xf217;" horiz-adv-x="1664" 
+d="M1216 832q0 26 -19 45t-45 19h-128v128q0 26 -19 45t-45 19t-45 -19t-19 -45v-128h-128q-26 0 -45 -19t-19 -45t19 -45t45 -19h128v-128q0 -26 19 -45t45 -19t45 19t19 45v128h128q26 0 45 19t19 45zM640 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5
+t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1536 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1664 1088v-512q0 -24 -16 -42.5t-41 -21.5l-1044 -122q1 -7 4.5 -21.5t6 -26.5t2.5 -22q0 -16 -24 -64h920
+q26 0 45 -19t19 -45t-19 -45t-45 -19h-1024q-26 0 -45 19t-19 45q0 14 11 39.5t29.5 59.5t20.5 38l-177 823h-204q-26 0 -45 19t-19 45t19 45t45 19h256q16 0 28.5 -6.5t20 -15.5t13 -24.5t7.5 -26.5t5.5 -29.5t4.5 -25.5h1201q26 0 45 -19t19 -45z" />
+    <glyph glyph-name="_503" unicode="&#xf218;" horiz-adv-x="1664" 
+d="M1280 832q0 26 -19 45t-45 19t-45 -19l-147 -146v293q0 26 -19 45t-45 19t-45 -19t-19 -45v-293l-147 146q-19 19 -45 19t-45 -19t-19 -45t19 -45l256 -256q19 -19 45 -19t45 19l256 256q19 19 19 45zM640 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5
+t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1536 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1664 1088v-512q0 -24 -16 -42.5t-41 -21.5l-1044 -122q1 -7 4.5 -21.5t6 -26.5t2.5 -22q0 -16 -24 -64h920
+q26 0 45 -19t19 -45t-19 -45t-45 -19h-1024q-26 0 -45 19t-19 45q0 14 11 39.5t29.5 59.5t20.5 38l-177 823h-204q-26 0 -45 19t-19 45t19 45t45 19h256q16 0 28.5 -6.5t20 -15.5t13 -24.5t7.5 -26.5t5.5 -29.5t4.5 -25.5h1201q26 0 45 -19t19 -45z" />
+    <glyph glyph-name="_504" unicode="&#xf219;" horiz-adv-x="2048" 
+d="M212 768l623 -665l-300 665h-323zM1024 -4l349 772h-698zM538 896l204 384h-262l-288 -384h346zM1213 103l623 665h-323zM683 896h682l-204 384h-274zM1510 896h346l-288 384h-262zM1651 1382l384 -512q14 -18 13 -41.5t-17 -40.5l-960 -1024q-18 -20 -47 -20t-47 20
+l-960 1024q-16 17 -17 40.5t13 41.5l384 512q18 26 51 26h1152q33 0 51 -26z" />
+    <glyph glyph-name="_505" unicode="&#xf21a;" horiz-adv-x="2048" 
+d="M1811 -19q19 19 45 19t45 -19l128 -128l-90 -90l-83 83l-83 -83q-18 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-83 83l-83 -83
+q-19 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-128 128l90 90l83 -83l83 83q19 19 45 19t45 -19l83 -83l83 83q19 19 45 19t45 -19l83 -83l83 83q19 19 45 19t45 -19l83 -83l83 83q19 19 45 19t45 -19l83 -83l83 83q19 19 45 19t45 -19l83 -83l83 83
+q19 19 45 19t45 -19l83 -83zM237 19q-19 -19 -45 -19t-45 19l-128 128l90 90l83 -82l83 82q19 19 45 19t45 -19l83 -82l64 64v293l-210 314q-17 26 -7 56.5t40 40.5l177 58v299h128v128h256v128h256v-128h256v-128h128v-299l177 -58q30 -10 40 -40.5t-7 -56.5l-210 -314
+v-293l19 18q19 19 45 19t45 -19l83 -82l83 82q19 19 45 19t45 -19l128 -128l-90 -90l-83 83l-83 -83q-18 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-83 83l-83 -83
+q-19 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-83 83zM640 1152v-128l384 128l384 -128v128h-128v128h-512v-128h-128z" />
+    <glyph glyph-name="_506" unicode="&#xf21b;" 
+d="M576 0l96 448l-96 128l-128 64zM832 0l128 640l-128 -64l-96 -128zM992 1010q-2 4 -4 6q-10 8 -96 8q-70 0 -167 -19q-7 -2 -21 -2t-21 2q-97 19 -167 19q-86 0 -96 -8q-2 -2 -4 -6q2 -18 4 -27q2 -3 7.5 -6.5t7.5 -10.5q2 -4 7.5 -20.5t7 -20.5t7.5 -17t8.5 -17t9 -14
+t12 -13.5t14 -9.5t17.5 -8t20.5 -4t24.5 -2q36 0 59 12.5t32.5 30t14.5 34.5t11.5 29.5t17.5 12.5h12q11 0 17.5 -12.5t11.5 -29.5t14.5 -34.5t32.5 -30t59 -12.5q13 0 24.5 2t20.5 4t17.5 8t14 9.5t12 13.5t9 14t8.5 17t7.5 17t7 20.5t7.5 20.5q2 7 7.5 10.5t7.5 6.5
+q2 9 4 27zM1408 131q0 -121 -73 -190t-194 -69h-874q-121 0 -194 69t-73 190q0 61 4.5 118t19 125.5t37.5 123.5t63.5 103.5t93.5 74.5l-90 220h214q-22 64 -22 128q0 12 2 32q-194 40 -194 96q0 57 210 99q17 62 51.5 134t70.5 114q32 37 76 37q30 0 84 -31t84 -31t84 31
+t84 31q44 0 76 -37q36 -42 70.5 -114t51.5 -134q210 -42 210 -99q0 -56 -194 -96q7 -81 -20 -160h214l-82 -225q63 -33 107.5 -96.5t65.5 -143.5t29 -151.5t8 -148.5z" />
+    <glyph glyph-name="_507" unicode="&#xf21c;" horiz-adv-x="2304" 
+d="M2301 500q12 -103 -22 -198.5t-99 -163.5t-158.5 -106t-196.5 -31q-161 11 -279.5 125t-134.5 274q-12 111 27.5 210.5t118.5 170.5l-71 107q-96 -80 -151 -194t-55 -244q0 -27 -18.5 -46.5t-45.5 -19.5h-256h-69q-23 -164 -149 -274t-294 -110q-185 0 -316.5 131.5
+t-131.5 316.5t131.5 316.5t316.5 131.5q76 0 152 -27l24 45q-123 110 -304 110h-64q-26 0 -45 19t-19 45t19 45t45 19h128q78 0 145 -13.5t116.5 -38.5t71.5 -39.5t51 -36.5h512h115l-85 128h-222q-30 0 -49 22.5t-14 52.5q4 23 23 38t43 15h253q33 0 53 -28l70 -105
+l114 114q19 19 46 19h101q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-179l115 -172q131 63 275 36q143 -26 244 -134.5t118 -253.5zM448 128q115 0 203 72.5t111 183.5h-314q-35 0 -55 31q-18 32 -1 63l147 277q-47 13 -91 13q-132 0 -226 -94t-94 -226t94 -226
+t226 -94zM1856 128q132 0 226 94t94 226t-94 226t-226 94q-60 0 -121 -24l174 -260q15 -23 10 -49t-27 -40q-15 -11 -36 -11q-35 0 -53 29l-174 260q-93 -95 -93 -225q0 -132 94 -226t226 -94z" />
+    <glyph glyph-name="_508" unicode="&#xf21d;" 
+d="M1408 0q0 -63 -61.5 -113.5t-164 -81t-225 -46t-253.5 -15.5t-253.5 15.5t-225 46t-164 81t-61.5 113.5q0 49 33 88.5t91 66.5t118 44.5t131 29.5q26 5 48 -10.5t26 -41.5q5 -26 -10.5 -48t-41.5 -26q-58 -10 -106 -23.5t-76.5 -25.5t-48.5 -23.5t-27.5 -19.5t-8.5 -12
+q3 -11 27 -26.5t73 -33t114 -32.5t160.5 -25t201.5 -10t201.5 10t160.5 25t114 33t73 33.5t27 27.5q-1 4 -8.5 11t-27.5 19t-48.5 23.5t-76.5 25t-106 23.5q-26 4 -41.5 26t-10.5 48q4 26 26 41.5t48 10.5q71 -12 131 -29.5t118 -44.5t91 -66.5t33 -88.5zM1024 896v-384
+q0 -26 -19 -45t-45 -19h-64v-384q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v384h-64q-26 0 -45 19t-19 45v384q0 53 37.5 90.5t90.5 37.5h384q53 0 90.5 -37.5t37.5 -90.5zM928 1280q0 -93 -65.5 -158.5t-158.5 -65.5t-158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5
+t158.5 -65.5t65.5 -158.5z" />
+    <glyph glyph-name="_509" unicode="&#xf21e;" horiz-adv-x="1792" 
+d="M1280 512h305q-5 -6 -10 -10.5t-9 -7.5l-3 -4l-623 -600q-18 -18 -44 -18t-44 18l-624 602q-5 2 -21 20h369q22 0 39.5 13.5t22.5 34.5l70 281l190 -667q6 -20 23 -33t39 -13q21 0 38 13t23 33l146 485l56 -112q18 -35 57 -35zM1792 940q0 -145 -103 -300h-369l-111 221
+q-8 17 -25.5 27t-36.5 8q-45 -5 -56 -46l-129 -430l-196 686q-6 20 -23.5 33t-39.5 13t-39 -13.5t-22 -34.5l-116 -464h-423q-103 155 -103 300q0 220 127 344t351 124q62 0 126.5 -21.5t120 -58t95.5 -68.5t76 -68q36 36 76 68t95.5 68.5t120 58t126.5 21.5q224 0 351 -124
+t127 -344z" />
+    <glyph glyph-name="venus" unicode="&#xf221;" horiz-adv-x="1280" 
+d="M1152 960q0 -221 -147.5 -384.5t-364.5 -187.5v-260h224q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-224v-224q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v224h-224q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h224v260q-150 16 -271.5 103t-186 224t-52.5 292
+q11 134 80.5 249t182 188t245.5 88q170 19 319 -54t236 -212t87 -306zM128 960q0 -185 131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5z" />
+    <glyph glyph-name="_511" unicode="&#xf222;" 
+d="M1472 1408q26 0 45 -19t19 -45v-416q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v262l-382 -383q126 -156 126 -359q0 -117 -45.5 -223.5t-123 -184t-184 -123t-223.5 -45.5t-223.5 45.5t-184 123t-123 184t-45.5 223.5t45.5 223.5t123 184t184 123t223.5 45.5
+q203 0 359 -126l382 382h-261q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h416zM576 0q185 0 316.5 131.5t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
+    <glyph glyph-name="_512" unicode="&#xf223;" horiz-adv-x="1280" 
+d="M830 1220q145 -72 233.5 -210.5t88.5 -305.5q0 -221 -147.5 -384.5t-364.5 -187.5v-132h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-96v-96q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v96h-96q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96v132q-217 24 -364.5 187.5
+t-147.5 384.5q0 167 88.5 305.5t233.5 210.5q-165 96 -228 273q-6 16 3.5 29.5t26.5 13.5h69q21 0 29 -20q44 -106 140 -171t214 -65t214 65t140 171q8 20 37 20h61q17 0 26.5 -13.5t3.5 -29.5q-63 -177 -228 -273zM576 256q185 0 316.5 131.5t131.5 316.5t-131.5 316.5
+t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
+    <glyph glyph-name="_513" unicode="&#xf224;" 
+d="M1024 1504q0 14 9 23t23 9h288q26 0 45 -19t19 -45v-288q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v134l-254 -255q126 -158 126 -359q0 -221 -147.5 -384.5t-364.5 -187.5v-132h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-96v-96q0 -14 -9 -23t-23 -9h-64
+q-14 0 -23 9t-9 23v96h-96q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96v132q-149 16 -270.5 103t-186.5 223.5t-53 291.5q16 204 160 353.5t347 172.5q118 14 228 -19t198 -103l255 254h-134q-14 0 -23 9t-9 23v64zM576 256q185 0 316.5 131.5t131.5 316.5t-131.5 316.5
+t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
+    <glyph glyph-name="_514" unicode="&#xf225;" horiz-adv-x="1792" 
+d="M1280 1504q0 14 9 23t23 9h288q26 0 45 -19t19 -45v-288q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v134l-254 -255q126 -158 126 -359q0 -221 -147.5 -384.5t-364.5 -187.5v-132h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-96v-96q0 -14 -9 -23t-23 -9h-64
+q-14 0 -23 9t-9 23v96h-96q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96v132q-217 24 -364.5 187.5t-147.5 384.5q0 201 126 359l-52 53l-101 -111q-9 -10 -22 -10.5t-23 7.5l-48 44q-10 8 -10.5 21.5t8.5 23.5l105 115l-111 112v-134q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9
+t-9 23v288q0 26 19 45t45 19h288q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-133l106 -107l86 94q9 10 22 10.5t23 -7.5l48 -44q10 -8 10.5 -21.5t-8.5 -23.5l-90 -99l57 -56q158 126 359 126t359 -126l255 254h-134q-14 0 -23 9t-9 23v64zM832 256q185 0 316.5 131.5
+t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
+    <glyph glyph-name="_515" unicode="&#xf226;" horiz-adv-x="1792" 
+d="M1790 1007q12 -155 -52.5 -292t-186 -224t-271.5 -103v-260h224q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-224v-224q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v224h-512v-224q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v224h-224q-14 0 -23 9t-9 23v64q0 14 9 23
+t23 9h224v260q-150 16 -271.5 103t-186 224t-52.5 292q17 206 164.5 356.5t352.5 169.5q206 21 377 -94q171 115 377 94q205 -19 352.5 -169.5t164.5 -356.5zM896 647q128 131 128 313t-128 313q-128 -131 -128 -313t128 -313zM576 512q115 0 218 57q-154 165 -154 391
+q0 224 154 391q-103 57 -218 57q-185 0 -316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5zM1152 128v260q-137 15 -256 94q-119 -79 -256 -94v-260h512zM1216 512q185 0 316.5 131.5t131.5 316.5t-131.5 316.5t-316.5 131.5q-115 0 -218 -57q154 -167 154 -391
+q0 -226 -154 -391q103 -57 218 -57z" />
+    <glyph glyph-name="_516" unicode="&#xf227;" horiz-adv-x="1920" 
+d="M1536 1120q0 14 9 23t23 9h288q26 0 45 -19t19 -45v-288q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v134l-254 -255q76 -95 107.5 -214t9.5 -247q-31 -182 -166 -312t-318 -156q-210 -29 -384.5 80t-241.5 300q-117 6 -221 57.5t-177.5 133t-113.5 192.5t-32 230
+q9 135 78 252t182 191.5t248 89.5q118 14 227.5 -19t198.5 -103l255 254h-134q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h288q26 0 45 -19t19 -45v-288q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v134l-254 -255q59 -74 93 -169q182 -9 328 -124l255 254h-134q-14 0 -23 9
+t-9 23v64zM1024 704q0 20 -4 58q-162 -25 -271 -150t-109 -292q0 -20 4 -58q162 25 271 150t109 292zM128 704q0 -168 111 -294t276 -149q-3 29 -3 59q0 210 135 369.5t338 196.5q-53 120 -163.5 193t-245.5 73q-185 0 -316.5 -131.5t-131.5 -316.5zM1088 -128
+q185 0 316.5 131.5t131.5 316.5q0 168 -111 294t-276 149q3 -28 3 -59q0 -210 -135 -369.5t-338 -196.5q53 -120 163.5 -193t245.5 -73z" />
+    <glyph glyph-name="_517" unicode="&#xf228;" horiz-adv-x="2048" 
+d="M1664 1504q0 14 9 23t23 9h288q26 0 45 -19t19 -45v-288q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v134l-254 -255q76 -95 107.5 -214t9.5 -247q-32 -180 -164.5 -310t-313.5 -157q-223 -34 -409 90q-117 -78 -256 -93v-132h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23
+t-23 -9h-96v-96q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v96h-96q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96v132q-155 17 -279.5 109.5t-187 237.5t-39.5 307q25 187 159.5 322.5t320.5 164.5q224 34 410 -90q146 97 320 97q201 0 359 -126l255 254h-134q-14 0 -23 9
+t-9 23v64zM896 391q128 131 128 313t-128 313q-128 -131 -128 -313t128 -313zM128 704q0 -185 131.5 -316.5t316.5 -131.5q117 0 218 57q-154 167 -154 391t154 391q-101 57 -218 57q-185 0 -316.5 -131.5t-131.5 -316.5zM1216 256q185 0 316.5 131.5t131.5 316.5
+t-131.5 316.5t-316.5 131.5q-117 0 -218 -57q154 -167 154 -391t-154 -391q101 -57 218 -57z" />
+    <glyph glyph-name="_518" unicode="&#xf229;" 
+d="M1472 1408q26 0 45 -19t19 -45v-416q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v262l-213 -214l140 -140q9 -10 9 -23t-9 -22l-46 -46q-9 -9 -22 -9t-23 9l-140 141l-78 -79q126 -156 126 -359q0 -117 -45.5 -223.5t-123 -184t-184 -123t-223.5 -45.5t-223.5 45.5
+t-184 123t-123 184t-45.5 223.5t45.5 223.5t123 184t184 123t223.5 45.5q203 0 359 -126l78 78l-172 172q-9 10 -9 23t9 22l46 46q9 9 22 9t23 -9l172 -172l213 213h-261q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h416zM576 0q185 0 316.5 131.5t131.5 316.5t-131.5 316.5
+t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
+    <glyph glyph-name="_519" unicode="&#xf22a;" horiz-adv-x="1280" 
+d="M640 892q217 -24 364.5 -187.5t147.5 -384.5q0 -167 -87 -306t-236 -212t-319 -54q-133 15 -245.5 88t-182 188t-80.5 249q-12 155 52.5 292t186 224t271.5 103v132h-160q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h160v165l-92 -92q-10 -9 -23 -9t-22 9l-46 46q-9 9 -9 22
+t9 23l202 201q19 19 45 19t45 -19l202 -201q9 -10 9 -23t-9 -22l-46 -46q-9 -9 -22 -9t-23 9l-92 92v-165h160q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-160v-132zM576 -128q185 0 316.5 131.5t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5
+t131.5 -316.5t316.5 -131.5z" />
+    <glyph glyph-name="_520" unicode="&#xf22b;" horiz-adv-x="2048" 
+d="M1901 621q19 -19 19 -45t-19 -45l-294 -294q-9 -10 -22.5 -10t-22.5 10l-45 45q-10 9 -10 22.5t10 22.5l185 185h-294v-224q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v224h-132q-24 -217 -187.5 -364.5t-384.5 -147.5q-167 0 -306 87t-212 236t-54 319q15 133 88 245.5
+t188 182t249 80.5q155 12 292 -52.5t224 -186t103 -271.5h132v224q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-224h294l-185 185q-10 9 -10 22.5t10 22.5l45 45q9 10 22.5 10t22.5 -10zM576 128q185 0 316.5 131.5t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5
+t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
+    <glyph glyph-name="_521" unicode="&#xf22c;" horiz-adv-x="1280" 
+d="M1152 960q0 -221 -147.5 -384.5t-364.5 -187.5v-612q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v612q-217 24 -364.5 187.5t-147.5 384.5q0 117 45.5 223.5t123 184t184 123t223.5 45.5t223.5 -45.5t184 -123t123 -184t45.5 -223.5zM576 512q185 0 316.5 131.5
+t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
+    <glyph glyph-name="_522" unicode="&#xf22d;" horiz-adv-x="1280" 
+d="M1024 576q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5zM1152 576q0 -117 -45.5 -223.5t-123 -184t-184 -123t-223.5 -45.5t-223.5 45.5t-184 123t-123 184t-45.5 223.5t45.5 223.5t123 184t184 123
+t223.5 45.5t223.5 -45.5t184 -123t123 -184t45.5 -223.5z" />
+    <glyph glyph-name="_523" unicode="&#xf22e;" horiz-adv-x="1792" 
+ />
+    <glyph glyph-name="_524" unicode="&#xf22f;" horiz-adv-x="1792" 
+ />
+    <glyph glyph-name="_525" unicode="&#xf230;" 
+d="M1451 1408q35 0 60 -25t25 -60v-1366q0 -35 -25 -60t-60 -25h-391v595h199l30 232h-229v148q0 56 23.5 84t91.5 28l122 1v207q-63 9 -178 9q-136 0 -217.5 -80t-81.5 -226v-171h-200v-232h200v-595h-735q-35 0 -60 25t-25 60v1366q0 35 25 60t60 25h1366z" />
+    <glyph glyph-name="_526" unicode="&#xf231;" horiz-adv-x="1280" 
+d="M0 939q0 108 37.5 203.5t103.5 166.5t152 123t185 78t202 26q158 0 294 -66.5t221 -193.5t85 -287q0 -96 -19 -188t-60 -177t-100 -149.5t-145 -103t-189 -38.5q-68 0 -135 32t-96 88q-10 -39 -28 -112.5t-23.5 -95t-20.5 -71t-26 -71t-32 -62.5t-46 -77.5t-62 -86.5
+l-14 -5l-9 10q-15 157 -15 188q0 92 21.5 206.5t66.5 287.5t52 203q-32 65 -32 169q0 83 52 156t132 73q61 0 95 -40.5t34 -102.5q0 -66 -44 -191t-44 -187q0 -63 45 -104.5t109 -41.5q55 0 102 25t78.5 68t56 95t38 110.5t20 111t6.5 99.5q0 173 -109.5 269.5t-285.5 96.5
+q-200 0 -334 -129.5t-134 -328.5q0 -44 12.5 -85t27 -65t27 -45.5t12.5 -30.5q0 -28 -15 -73t-37 -45q-2 0 -17 3q-51 15 -90.5 56t-61 94.5t-32.5 108t-11 106.5z" />
+    <glyph glyph-name="_527" unicode="&#xf232;" 
+d="M985 562q13 0 97.5 -44t89.5 -53q2 -5 2 -15q0 -33 -17 -76q-16 -39 -71 -65.5t-102 -26.5q-57 0 -190 62q-98 45 -170 118t-148 185q-72 107 -71 194v8q3 91 74 158q24 22 52 22q6 0 18 -1.5t19 -1.5q19 0 26.5 -6.5t15.5 -27.5q8 -20 33 -88t25 -75q0 -21 -34.5 -57.5
+t-34.5 -46.5q0 -7 5 -15q34 -73 102 -137q56 -53 151 -101q12 -7 22 -7q15 0 54 48.5t52 48.5zM782 32q127 0 243.5 50t200.5 134t134 200.5t50 243.5t-50 243.5t-134 200.5t-200.5 134t-243.5 50t-243.5 -50t-200.5 -134t-134 -200.5t-50 -243.5q0 -203 120 -368l-79 -233
+l242 77q158 -104 345 -104zM782 1414q153 0 292.5 -60t240.5 -161t161 -240.5t60 -292.5t-60 -292.5t-161 -240.5t-240.5 -161t-292.5 -60q-195 0 -365 94l-417 -134l136 405q-108 178 -108 389q0 153 60 292.5t161 240.5t240.5 161t292.5 60z" />
+    <glyph glyph-name="_528" unicode="&#xf233;" horiz-adv-x="1792" 
+d="M128 128h1024v128h-1024v-128zM128 640h1024v128h-1024v-128zM1696 192q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM128 1152h1024v128h-1024v-128zM1696 704q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM1696 1216
+q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM1792 384v-384h-1792v384h1792zM1792 896v-384h-1792v384h1792zM1792 1408v-384h-1792v384h1792z" />
+    <glyph glyph-name="_529" unicode="&#xf234;" horiz-adv-x="2048" 
+d="M704 640q-159 0 -271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5t-112.5 -271.5t-271.5 -112.5zM1664 512h352q13 0 22.5 -9.5t9.5 -22.5v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-352v-352q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5
+t-9.5 22.5v352h-352q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h352v352q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5v-352zM928 288q0 -52 38 -90t90 -38h256v-238q-68 -50 -171 -50h-874q-121 0 -194 69t-73 190q0 53 3.5 103.5t14 109t26.5 108.5
+t43 97.5t62 81t85.5 53.5t111.5 20q19 0 39 -17q79 -61 154.5 -91.5t164.5 -30.5t164.5 30.5t154.5 91.5q20 17 39 17q132 0 217 -96h-223q-52 0 -90 -38t-38 -90v-192z" />
+    <glyph glyph-name="_530" unicode="&#xf235;" horiz-adv-x="2048" 
+d="M704 640q-159 0 -271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5t-112.5 -271.5t-271.5 -112.5zM1781 320l249 -249q9 -9 9 -23q0 -13 -9 -22l-136 -136q-9 -9 -22 -9q-14 0 -23 9l-249 249l-249 -249q-9 -9 -23 -9q-13 0 -22 9l-136 136
+q-9 9 -9 22q0 14 9 23l249 249l-249 249q-9 9 -9 23q0 13 9 22l136 136q9 9 22 9q14 0 23 -9l249 -249l249 249q9 9 23 9q13 0 22 -9l136 -136q9 -9 9 -22q0 -14 -9 -23zM1283 320l-181 -181q-37 -37 -37 -91q0 -53 37 -90l83 -83q-21 -3 -44 -3h-874q-121 0 -194 69
+t-73 190q0 53 3.5 103.5t14 109t26.5 108.5t43 97.5t62 81t85.5 53.5t111.5 20q19 0 39 -17q154 -122 319 -122t319 122q20 17 39 17q28 0 57 -6q-28 -27 -41 -50t-13 -56q0 -54 37 -91z" />
+    <glyph glyph-name="_531" unicode="&#xf236;" horiz-adv-x="2048" 
+d="M256 512h1728q26 0 45 -19t19 -45v-448h-256v256h-1536v-256h-256v1216q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-704zM832 832q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM2048 576v64q0 159 -112.5 271.5t-271.5 112.5h-704
+q-26 0 -45 -19t-19 -45v-384h1152z" />
+    <glyph glyph-name="_532" unicode="&#xf237;" 
+d="M1536 1536l-192 -448h192v-192h-274l-55 -128h329v-192h-411l-357 -832l-357 832h-411v192h329l-55 128h-274v192h192l-192 448h256l323 -768h378l323 768h256zM768 320l108 256h-216z" />
+    <glyph glyph-name="_533" unicode="&#xf238;" 
+d="M1088 1536q185 0 316.5 -93.5t131.5 -226.5v-896q0 -130 -125.5 -222t-305.5 -97l213 -202q16 -15 8 -35t-30 -20h-1056q-22 0 -30 20t8 35l213 202q-180 5 -305.5 97t-125.5 222v896q0 133 131.5 226.5t316.5 93.5h640zM768 192q80 0 136 56t56 136t-56 136t-136 56
+t-136 -56t-56 -136t56 -136t136 -56zM1344 768v512h-1152v-512h1152z" />
+    <glyph glyph-name="_534" unicode="&#xf239;" 
+d="M1088 1536q185 0 316.5 -93.5t131.5 -226.5v-896q0 -130 -125.5 -222t-305.5 -97l213 -202q16 -15 8 -35t-30 -20h-1056q-22 0 -30 20t8 35l213 202q-180 5 -305.5 97t-125.5 222v896q0 133 131.5 226.5t316.5 93.5h640zM288 224q66 0 113 47t47 113t-47 113t-113 47
+t-113 -47t-47 -113t47 -113t113 -47zM704 768v512h-544v-512h544zM1248 224q66 0 113 47t47 113t-47 113t-113 47t-113 -47t-47 -113t47 -113t113 -47zM1408 768v512h-576v-512h576z" />
+    <glyph glyph-name="_535" unicode="&#xf23a;" horiz-adv-x="1792" 
+d="M597 1115v-1173q0 -25 -12.5 -42.5t-36.5 -17.5q-17 0 -33 8l-465 233q-21 10 -35.5 33.5t-14.5 46.5v1140q0 20 10 34t29 14q14 0 44 -15l511 -256q3 -3 3 -5zM661 1014l534 -866l-534 266v600zM1792 996v-1054q0 -25 -14 -40.5t-38 -15.5t-47 13l-441 220zM1789 1116
+q0 -3 -256.5 -419.5t-300.5 -487.5l-390 634l324 527q17 28 52 28q14 0 26 -6l541 -270q4 -2 4 -6z" />
+    <glyph glyph-name="_536" unicode="&#xf23b;" 
+d="M809 532l266 499h-112l-157 -312q-24 -48 -44 -92l-42 92l-155 312h-120l263 -493v-324h101v318zM1536 1408v-1536h-1536v1536h1536z" />
+    <glyph glyph-name="_537" unicode="&#xf23c;" horiz-adv-x="2296" 
+d="M478 -139q-8 -16 -27 -34.5t-37 -25.5q-25 -9 -51.5 3.5t-28.5 31.5q-1 22 40 55t68 38q23 4 34 -21.5t2 -46.5zM1819 -139q7 -16 26 -34.5t38 -25.5q25 -9 51.5 3.5t27.5 31.5q2 22 -39.5 55t-68.5 38q-22 4 -33 -21.5t-2 -46.5zM1867 -30q13 -27 56.5 -59.5t77.5 -41.5
+q45 -13 82 4.5t37 50.5q0 46 -67.5 100.5t-115.5 59.5q-40 5 -63.5 -37.5t-6.5 -76.5zM428 -30q-13 -27 -56 -59.5t-77 -41.5q-45 -13 -82 4.5t-37 50.5q0 46 67.5 100.5t115.5 59.5q40 5 63 -37.5t6 -76.5zM1158 1094h1q-41 0 -76 -15q27 -8 44 -30.5t17 -49.5
+q0 -35 -27 -60t-65 -25q-52 0 -80 43q-5 -23 -5 -42q0 -74 56 -126.5t135 -52.5q80 0 136 52.5t56 126.5t-56 126.5t-136 52.5zM1462 1312q-99 109 -220.5 131.5t-245.5 -44.5q27 60 82.5 96.5t118 39.5t121.5 -17t99.5 -74.5t44.5 -131.5zM2212 73q8 -11 -11 -42
+q7 -23 7 -40q1 -56 -44.5 -112.5t-109.5 -91.5t-118 -37q-48 -2 -92 21.5t-66 65.5q-687 -25 -1259 0q-23 -41 -66.5 -65t-92.5 -22q-86 3 -179.5 80.5t-92.5 160.5q2 22 7 40q-19 31 -11 42q6 10 31 1q14 22 41 51q-7 29 2 38q11 10 39 -4q29 20 59 34q0 29 13 37
+q23 12 51 -16q35 5 61 -2q18 -4 38 -19v73q-11 0 -18 2q-53 10 -97 44.5t-55 87.5q-9 38 0 81q15 62 93 95q2 17 19 35.5t36 23.5t33 -7.5t19 -30.5h13q46 -5 60 -23q3 -3 5 -7q10 1 30.5 3.5t30.5 3.5q-15 11 -30 17q-23 40 -91 43q0 6 1 10q-62 2 -118.5 18.5t-84.5 47.5
+q-32 36 -42.5 92t-2.5 112q16 126 90 179q23 16 52 4.5t32 -40.5q0 -1 1.5 -14t2.5 -21t3 -20t5.5 -19t8.5 -10q27 -14 76 -12q48 46 98 74q-40 4 -162 -14l47 46q61 58 163 111q145 73 282 86q-20 8 -41 15.5t-47 14t-42.5 10.5t-47.5 11t-43 10q595 126 904 -139
+q98 -84 158 -222q85 -10 121 9h1q5 3 8.5 10t5.5 19t3 19.5t3 21.5l1 14q3 28 32 40t52 -5q73 -52 91 -178q7 -57 -3.5 -113t-42.5 -91q-28 -32 -83.5 -48.5t-115.5 -18.5v-10q-71 -2 -95 -43q-14 -5 -31 -17q11 -1 32 -3.5t30 -3.5q1 5 5 8q16 18 60 23h13q5 18 19 30t33 8
+t36 -23t19 -36q79 -32 93 -95q9 -40 1 -81q-12 -53 -56 -88t-97 -44q-10 -2 -17 -2q0 -49 -1 -73q20 15 38 19q26 7 61 2q28 28 51 16q14 -9 14 -37q33 -16 59 -34q27 13 38 4q10 -10 2 -38q28 -30 41 -51q23 8 31 -1zM1937 1025q0 -29 -9 -54q82 -32 112 -132
+q4 37 -9.5 98.5t-41.5 90.5q-20 19 -36 17t-16 -20zM1859 925q35 -42 47.5 -108.5t-0.5 -124.5q67 13 97 45q13 14 18 28q-3 64 -31 114.5t-79 66.5q-15 -15 -52 -21zM1822 921q-30 0 -44 1q42 -115 53 -239q21 0 43 3q16 68 1 135t-53 100zM258 839q30 100 112 132
+q-9 25 -9 54q0 18 -16.5 20t-35.5 -17q-28 -29 -41.5 -90.5t-9.5 -98.5zM294 737q29 -31 97 -45q-13 58 -0.5 124.5t47.5 108.5v0q-37 6 -52 21q-51 -16 -78.5 -66t-31.5 -115q9 -17 18 -28zM471 683q14 124 73 235q-19 -4 -55 -18l-45 -19v1q-46 -89 -20 -196q25 -3 47 -3z
+M1434 644q8 -38 16.5 -108.5t11.5 -89.5q3 -18 9.5 -21.5t23.5 4.5q40 20 62 85.5t23 125.5q-24 2 -146 4zM1152 1285q-116 0 -199 -82.5t-83 -198.5q0 -117 83 -199.5t199 -82.5t199 82.5t83 199.5q0 116 -83 198.5t-199 82.5zM1380 646q-105 2 -211 0v1q-1 -27 2.5 -86
+t13.5 -66q29 -14 93.5 -14.5t95.5 10.5q9 3 11 39t-0.5 69.5t-4.5 46.5zM1112 447q8 4 9.5 48t-0.5 88t-4 63v1q-212 -3 -214 -3q-4 -20 -7 -62t0 -83t14 -46q34 -15 101 -16t101 10zM718 636q-16 -59 4.5 -118.5t77.5 -84.5q15 -8 24 -5t12 21q3 16 8 90t10 103
+q-69 -2 -136 -6zM591 510q3 -23 -34 -36q132 -141 271.5 -240t305.5 -154q172 49 310.5 146t293.5 250q-33 13 -30 34q0 2 0.5 3.5t1.5 3t1 2.5v1v-1q-17 2 -50 5.5t-48 4.5q-26 -90 -82 -132q-51 -38 -82 1q-5 6 -9 14q-7 13 -17 62q-2 -5 -5 -9t-7.5 -7t-8 -5.5t-9.5 -4
+l-10 -2.5t-12 -2l-12 -1.5t-13.5 -1t-13.5 -0.5q-106 -9 -163 11q-4 -17 -10 -26.5t-21 -15t-23 -7t-36 -3.5q-6 -1 -9 -1q-179 -17 -203 40q-2 -63 -56 -54q-47 8 -91 54q-12 13 -20 26q-17 29 -26 65q-58 -6 -87 -10q1 -2 4 -10zM507 -118q3 14 3 30q-17 71 -51 130
+t-73 70q-41 12 -101.5 -14.5t-104.5 -80t-39 -107.5q35 -53 100 -93t119 -42q51 -2 94 28t53 79zM510 53q23 -63 27 -119q195 113 392 174q-98 52 -180.5 120t-179.5 165q-6 -4 -29 -13q0 -1 -1 -4t-1 -5q31 -18 22 -37q-12 -23 -56 -34q-10 -13 -29 -24h-1q-2 -83 1 -150
+q19 -34 35 -73zM579 -113q532 -21 1145 0q-254 147 -428 196q-76 -35 -156 -57q-8 -3 -16 0q-65 21 -129 49q-208 -60 -416 -188h-1v-1q1 0 1 1zM1763 -67q4 54 28 120q14 38 33 71l-1 -1q3 77 3 153q-15 8 -30 25q-42 9 -56 33q-9 20 22 38q-2 4 -2 9q-16 4 -28 12
+q-204 -190 -383 -284q198 -59 414 -176zM2155 -90q5 54 -39 107.5t-104 80t-102 14.5q-38 -11 -72.5 -70.5t-51.5 -129.5q0 -16 3 -30q10 -49 53 -79t94 -28q54 2 119 42t100 93z" />
+    <glyph glyph-name="_538" unicode="&#xf23d;" horiz-adv-x="2304" 
+d="M1524 -25q0 -68 -48 -116t-116 -48t-116.5 48t-48.5 116t48.5 116.5t116.5 48.5t116 -48.5t48 -116.5zM775 -25q0 -68 -48.5 -116t-116.5 -48t-116 48t-48 116t48 116.5t116 48.5t116.5 -48.5t48.5 -116.5zM0 1469q57 -60 110.5 -104.5t121 -82t136 -63t166 -45.5
+t200 -31.5t250 -18.5t304 -9.5t372.5 -2.5q139 0 244.5 -5t181 -16.5t124 -27.5t71 -39.5t24 -51.5t-19.5 -64t-56.5 -76.5t-89.5 -91t-116 -104.5t-139 -119q-185 -157 -286 -247q29 51 76.5 109t94 105.5t94.5 98.5t83 91.5t54 80.5t13 70t-45.5 55.5t-116.5 41t-204 23.5
+t-304 5q-168 -2 -314 6t-256 23t-204.5 41t-159.5 51.5t-122.5 62.5t-91.5 66.5t-68 71.5t-50.5 69.5t-40 68t-36.5 59.5z" />
+    <glyph glyph-name="_539" unicode="&#xf23e;" horiz-adv-x="1792" 
+d="M896 1472q-169 0 -323 -66t-265.5 -177.5t-177.5 -265.5t-66 -323t66 -323t177.5 -265.5t265.5 -177.5t323 -66t323 66t265.5 177.5t177.5 265.5t66 323t-66 323t-177.5 265.5t-265.5 177.5t-323 66zM896 1536q182 0 348 -71t286 -191t191 -286t71 -348t-71 -348
+t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71zM496 704q16 0 16 -16v-480q0 -16 -16 -16h-32q-16 0 -16 16v480q0 16 16 16h32zM896 640q53 0 90.5 -37.5t37.5 -90.5q0 -35 -17.5 -64t-46.5 -46v-114q0 -14 -9 -23
+t-23 -9h-64q-14 0 -23 9t-9 23v114q-29 17 -46.5 46t-17.5 64q0 53 37.5 90.5t90.5 37.5zM896 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM544 928v-96
+q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v96q0 93 65.5 158.5t158.5 65.5t158.5 -65.5t65.5 -158.5v-96q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v96q0 146 -103 249t-249 103t-249 -103t-103 -249zM1408 192v512q0 26 -19 45t-45 19h-896q-26 0 -45 -19t-19 -45v-512
+q0 -26 19 -45t45 -19h896q26 0 45 19t19 45z" />
+    <glyph glyph-name="_540" unicode="&#xf240;" horiz-adv-x="2304" 
+d="M1920 1024v-768h-1664v768h1664zM2048 448h128v384h-128v288q0 14 -9 23t-23 9h-1856q-14 0 -23 -9t-9 -23v-960q0 -14 9 -23t23 -9h1856q14 0 23 9t9 23v288zM2304 832v-384q0 -53 -37.5 -90.5t-90.5 -37.5v-160q0 -66 -47 -113t-113 -47h-1856q-66 0 -113 47t-47 113
+v960q0 66 47 113t113 47h1856q66 0 113 -47t47 -113v-160q53 0 90.5 -37.5t37.5 -90.5z" />
+    <glyph glyph-name="_541" unicode="&#xf241;" horiz-adv-x="2304" 
+d="M256 256v768h1280v-768h-1280zM2176 960q53 0 90.5 -37.5t37.5 -90.5v-384q0 -53 -37.5 -90.5t-90.5 -37.5v-160q0 -66 -47 -113t-113 -47h-1856q-66 0 -113 47t-47 113v960q0 66 47 113t113 47h1856q66 0 113 -47t47 -113v-160zM2176 448v384h-128v288q0 14 -9 23t-23 9
+h-1856q-14 0 -23 -9t-9 -23v-960q0 -14 9 -23t23 -9h1856q14 0 23 9t9 23v288h128z" />
+    <glyph glyph-name="_542" unicode="&#xf242;" horiz-adv-x="2304" 
+d="M256 256v768h896v-768h-896zM2176 960q53 0 90.5 -37.5t37.5 -90.5v-384q0 -53 -37.5 -90.5t-90.5 -37.5v-160q0 -66 -47 -113t-113 -47h-1856q-66 0 -113 47t-47 113v960q0 66 47 113t113 47h1856q66 0 113 -47t47 -113v-160zM2176 448v384h-128v288q0 14 -9 23t-23 9
+h-1856q-14 0 -23 -9t-9 -23v-960q0 -14 9 -23t23 -9h1856q14 0 23 9t9 23v288h128z" />
+    <glyph glyph-name="_543" unicode="&#xf243;" horiz-adv-x="2304" 
+d="M256 256v768h512v-768h-512zM2176 960q53 0 90.5 -37.5t37.5 -90.5v-384q0 -53 -37.5 -90.5t-90.5 -37.5v-160q0 -66 -47 -113t-113 -47h-1856q-66 0 -113 47t-47 113v960q0 66 47 113t113 47h1856q66 0 113 -47t47 -113v-160zM2176 448v384h-128v288q0 14 -9 23t-23 9
+h-1856q-14 0 -23 -9t-9 -23v-960q0 -14 9 -23t23 -9h1856q14 0 23 9t9 23v288h128z" />
+    <glyph glyph-name="_544" unicode="&#xf244;" horiz-adv-x="2304" 
+d="M2176 960q53 0 90.5 -37.5t37.5 -90.5v-384q0 -53 -37.5 -90.5t-90.5 -37.5v-160q0 -66 -47 -113t-113 -47h-1856q-66 0 -113 47t-47 113v960q0 66 47 113t113 47h1856q66 0 113 -47t47 -113v-160zM2176 448v384h-128v288q0 14 -9 23t-23 9h-1856q-14 0 -23 -9t-9 -23
+v-960q0 -14 9 -23t23 -9h1856q14 0 23 9t9 23v288h128z" />
+    <glyph glyph-name="_545" unicode="&#xf245;" horiz-adv-x="1280" 
+d="M1133 493q31 -30 14 -69q-17 -40 -59 -40h-382l201 -476q10 -25 0 -49t-34 -35l-177 -75q-25 -10 -49 0t-35 34l-191 452l-312 -312q-19 -19 -45 -19q-12 0 -24 5q-40 17 -40 59v1504q0 42 40 59q12 5 24 5q27 0 45 -19z" />
+    <glyph glyph-name="_546" unicode="&#xf246;" horiz-adv-x="1024" 
+d="M832 1408q-320 0 -320 -224v-416h128v-128h-128v-544q0 -224 320 -224h64v-128h-64q-272 0 -384 146q-112 -146 -384 -146h-64v128h64q320 0 320 224v544h-128v128h128v416q0 224 -320 224h-64v128h64q272 0 384 -146q112 146 384 146h64v-128h-64z" />
+    <glyph glyph-name="_547" unicode="&#xf247;" horiz-adv-x="2048" 
+d="M2048 1152h-128v-1024h128v-384h-384v128h-1280v-128h-384v384h128v1024h-128v384h384v-128h1280v128h384v-384zM1792 1408v-128h128v128h-128zM128 1408v-128h128v128h-128zM256 -128v128h-128v-128h128zM1664 0v128h128v1024h-128v128h-1280v-128h-128v-1024h128v-128
+h1280zM1920 -128v128h-128v-128h128zM1280 896h384v-768h-896v256h-384v768h896v-256zM512 512h640v512h-640v-512zM1536 256v512h-256v-384h-384v-128h640z" />
+    <glyph glyph-name="_548" unicode="&#xf248;" horiz-adv-x="2304" 
+d="M2304 768h-128v-640h128v-384h-384v128h-896v-128h-384v384h128v128h-384v-128h-384v384h128v640h-128v384h384v-128h896v128h384v-384h-128v-128h384v128h384v-384zM2048 1024v-128h128v128h-128zM1408 1408v-128h128v128h-128zM128 1408v-128h128v128h-128zM256 256
+v128h-128v-128h128zM1536 384h-128v-128h128v128zM384 384h896v128h128v640h-128v128h-896v-128h-128v-640h128v-128zM896 -128v128h-128v-128h128zM2176 -128v128h-128v-128h128zM2048 128v640h-128v128h-384v-384h128v-384h-384v128h-384v-128h128v-128h896v128h128z" />
+    <glyph glyph-name="_549" unicode="&#xf249;" 
+d="M1024 288v-416h-928q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h1344q40 0 68 -28t28 -68v-928h-416q-40 0 -68 -28t-28 -68zM1152 256h381q-15 -82 -65 -132l-184 -184q-50 -50 -132 -65v381z" />
+    <glyph glyph-name="_550" unicode="&#xf24a;" 
+d="M1400 256h-248v-248q29 10 41 22l185 185q12 12 22 41zM1120 384h288v896h-1280v-1280h896v288q0 40 28 68t68 28zM1536 1312v-1024q0 -40 -20 -88t-48 -76l-184 -184q-28 -28 -76 -48t-88 -20h-1024q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h1344q40 0 68 -28t28 -68
+z" />
+    <glyph glyph-name="_551" unicode="&#xf24b;" horiz-adv-x="2304" 
+d="M1951 538q0 -26 -15.5 -44.5t-38.5 -23.5q-8 -2 -18 -2h-153v140h153q10 0 18 -2q23 -5 38.5 -23.5t15.5 -44.5zM1933 751q0 -25 -15 -42t-38 -21q-3 -1 -15 -1h-139v129h139q3 0 8.5 -0.5t6.5 -0.5q23 -4 38 -21.5t15 -42.5zM728 587v308h-228v-308q0 -58 -38 -94.5
+t-105 -36.5q-108 0 -229 59v-112q53 -15 121 -23t109 -9l42 -1q328 0 328 217zM1442 403v113q-99 -52 -200 -59q-108 -8 -169 41t-61 142t61 142t169 41q101 -7 200 -58v112q-48 12 -100 19.5t-80 9.5l-28 2q-127 6 -218.5 -14t-140.5 -60t-71 -88t-22 -106t22 -106t71 -88
+t140.5 -60t218.5 -14q101 4 208 31zM2176 518q0 54 -43 88.5t-109 39.5v3q57 8 89 41.5t32 79.5q0 55 -41 88t-107 36q-3 0 -12 0.5t-14 0.5h-455v-510h491q74 0 121.5 36.5t47.5 96.5zM2304 1280v-1280q0 -52 -38 -90t-90 -38h-2048q-52 0 -90 38t-38 90v1280q0 52 38 90
+t90 38h2048q52 0 90 -38t38 -90z" />
+    <glyph glyph-name="_552" unicode="&#xf24c;" horiz-adv-x="2304" 
+d="M858 295v693q-106 -41 -172 -135.5t-66 -211.5t66 -211.5t172 -134.5zM1362 641q0 117 -66 211.5t-172 135.5v-694q106 41 172 135.5t66 211.5zM1577 641q0 -159 -78.5 -294t-213.5 -213.5t-294 -78.5q-119 0 -227.5 46.5t-187 125t-125 187t-46.5 227.5q0 159 78.5 294
+t213.5 213.5t294 78.5t294 -78.5t213.5 -213.5t78.5 -294zM1960 634q0 139 -55.5 261.5t-147.5 205.5t-213.5 131t-252.5 48h-301q-176 0 -323.5 -81t-235 -230t-87.5 -335q0 -171 87 -317.5t236 -231.5t323 -85h301q129 0 251.5 50.5t214.5 135t147.5 202.5t55.5 246z
+M2304 1280v-1280q0 -52 -38 -90t-90 -38h-2048q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h2048q52 0 90 -38t38 -90z" />
+    <glyph glyph-name="_553" unicode="&#xf24d;" horiz-adv-x="1792" 
+d="M1664 -96v1088q0 13 -9.5 22.5t-22.5 9.5h-1088q-13 0 -22.5 -9.5t-9.5 -22.5v-1088q0 -13 9.5 -22.5t22.5 -9.5h1088q13 0 22.5 9.5t9.5 22.5zM1792 992v-1088q0 -66 -47 -113t-113 -47h-1088q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1088q66 0 113 -47t47 -113
+zM1408 1376v-160h-128v160q0 13 -9.5 22.5t-22.5 9.5h-1088q-13 0 -22.5 -9.5t-9.5 -22.5v-1088q0 -13 9.5 -22.5t22.5 -9.5h160v-128h-160q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1088q66 0 113 -47t47 -113z" />
+    <glyph glyph-name="_554" unicode="&#xf24e;" horiz-adv-x="2304" 
+d="M1728 1088l-384 -704h768zM448 1088l-384 -704h768zM1269 1280q-14 -40 -45.5 -71.5t-71.5 -45.5v-1291h608q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-1344q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h608v1291q-40 14 -71.5 45.5t-45.5 71.5h-491q-14 0 -23 9t-9 23v64
+q0 14 9 23t23 9h491q21 57 70 92.5t111 35.5t111 -35.5t70 -92.5h491q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-491zM1088 1264q33 0 56.5 23.5t23.5 56.5t-23.5 56.5t-56.5 23.5t-56.5 -23.5t-23.5 -56.5t23.5 -56.5t56.5 -23.5zM2176 384q0 -73 -46.5 -131t-117.5 -91
+t-144.5 -49.5t-139.5 -16.5t-139.5 16.5t-144.5 49.5t-117.5 91t-46.5 131q0 11 35 81t92 174.5t107 195.5t102 184t56 100q18 33 56 33t56 -33q4 -7 56 -100t102 -184t107 -195.5t92 -174.5t35 -81zM896 384q0 -73 -46.5 -131t-117.5 -91t-144.5 -49.5t-139.5 -16.5
+t-139.5 16.5t-144.5 49.5t-117.5 91t-46.5 131q0 11 35 81t92 174.5t107 195.5t102 184t56 100q18 33 56 33t56 -33q4 -7 56 -100t102 -184t107 -195.5t92 -174.5t35 -81z" />
+    <glyph glyph-name="_555" unicode="&#xf250;" 
+d="M1408 1408q0 -261 -106.5 -461.5t-266.5 -306.5q160 -106 266.5 -306.5t106.5 -461.5h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-1472q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96q0 261 106.5 461.5t266.5 306.5q-160 106 -266.5 306.5t-106.5 461.5h-96q-14 0 -23 9
+t-9 23v64q0 14 9 23t23 9h1472q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-96zM874 700q77 29 149 92.5t129.5 152.5t92.5 210t35 253h-1024q0 -132 35 -253t92.5 -210t129.5 -152.5t149 -92.5q19 -7 30.5 -23.5t11.5 -36.5t-11.5 -36.5t-30.5 -23.5q-77 -29 -149 -92.5
+t-129.5 -152.5t-92.5 -210t-35 -253h1024q0 132 -35 253t-92.5 210t-129.5 152.5t-149 92.5q-19 7 -30.5 23.5t-11.5 36.5t11.5 36.5t30.5 23.5z" />
+    <glyph glyph-name="_556" unicode="&#xf251;" 
+d="M1408 1408q0 -261 -106.5 -461.5t-266.5 -306.5q160 -106 266.5 -306.5t106.5 -461.5h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-1472q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96q0 261 106.5 461.5t266.5 306.5q-160 106 -266.5 306.5t-106.5 461.5h-96q-14 0 -23 9
+t-9 23v64q0 14 9 23t23 9h1472q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-96zM1280 1408h-1024q0 -66 9 -128h1006q9 61 9 128zM1280 -128q0 130 -34 249.5t-90.5 208t-126.5 152t-146 94.5h-230q-76 -31 -146 -94.5t-126.5 -152t-90.5 -208t-34 -249.5h1024z" />
+    <glyph glyph-name="_557" unicode="&#xf252;" 
+d="M1408 1408q0 -261 -106.5 -461.5t-266.5 -306.5q160 -106 266.5 -306.5t106.5 -461.5h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-1472q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96q0 261 106.5 461.5t266.5 306.5q-160 106 -266.5 306.5t-106.5 461.5h-96q-14 0 -23 9
+t-9 23v64q0 14 9 23t23 9h1472q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-96zM1280 1408h-1024q0 -206 85 -384h854q85 178 85 384zM1223 192q-54 141 -145.5 241.5t-194.5 142.5h-230q-103 -42 -194.5 -142.5t-145.5 -241.5h910z" />
+    <glyph glyph-name="_558" unicode="&#xf253;" 
+d="M1408 1408q0 -261 -106.5 -461.5t-266.5 -306.5q160 -106 266.5 -306.5t106.5 -461.5h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-1472q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96q0 261 106.5 461.5t266.5 306.5q-160 106 -266.5 306.5t-106.5 461.5h-96q-14 0 -23 9
+t-9 23v64q0 14 9 23t23 9h1472q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-96zM874 700q77 29 149 92.5t129.5 152.5t92.5 210t35 253h-1024q0 -132 35 -253t92.5 -210t129.5 -152.5t149 -92.5q19 -7 30.5 -23.5t11.5 -36.5t-11.5 -36.5t-30.5 -23.5q-137 -51 -244 -196
+h700q-107 145 -244 196q-19 7 -30.5 23.5t-11.5 36.5t11.5 36.5t30.5 23.5z" />
+    <glyph glyph-name="_559" unicode="&#xf254;" 
+d="M1504 -64q14 0 23 -9t9 -23v-128q0 -14 -9 -23t-23 -9h-1472q-14 0 -23 9t-9 23v128q0 14 9 23t23 9h1472zM130 0q3 55 16 107t30 95t46 87t53.5 76t64.5 69.5t66 60t70.5 55t66.5 47.5t65 43q-43 28 -65 43t-66.5 47.5t-70.5 55t-66 60t-64.5 69.5t-53.5 76t-46 87
+t-30 95t-16 107h1276q-3 -55 -16 -107t-30 -95t-46 -87t-53.5 -76t-64.5 -69.5t-66 -60t-70.5 -55t-66.5 -47.5t-65 -43q43 -28 65 -43t66.5 -47.5t70.5 -55t66 -60t64.5 -69.5t53.5 -76t46 -87t30 -95t16 -107h-1276zM1504 1536q14 0 23 -9t9 -23v-128q0 -14 -9 -23t-23 -9
+h-1472q-14 0 -23 9t-9 23v128q0 14 9 23t23 9h1472z" />
+    <glyph glyph-name="_560" unicode="&#xf255;" 
+d="M768 1152q-53 0 -90.5 -37.5t-37.5 -90.5v-128h-32v93q0 48 -32 81.5t-80 33.5q-46 0 -79 -33t-33 -79v-429l-32 30v172q0 48 -32 81.5t-80 33.5q-46 0 -79 -33t-33 -79v-224q0 -47 35 -82l310 -296q39 -39 39 -102q0 -26 19 -45t45 -19h640q26 0 45 19t19 45v25
+q0 41 10 77l108 436q10 36 10 77v246q0 48 -32 81.5t-80 33.5q-46 0 -79 -33t-33 -79v-32h-32v125q0 40 -25 72.5t-64 40.5q-14 2 -23 2q-46 0 -79 -33t-33 -79v-128h-32v122q0 51 -32.5 89.5t-82.5 43.5q-5 1 -13 1zM768 1280q84 0 149 -50q57 34 123 34q59 0 111 -27
+t86 -76q27 7 59 7q100 0 170 -71.5t70 -171.5v-246q0 -51 -13 -108l-109 -436q-6 -24 -6 -71q0 -80 -56 -136t-136 -56h-640q-84 0 -138 58.5t-54 142.5l-308 296q-76 73 -76 175v224q0 99 70.5 169.5t169.5 70.5q11 0 16 -1q6 95 75.5 160t164.5 65q52 0 98 -21
+q72 69 174 69z" />
+    <glyph glyph-name="_561" unicode="&#xf256;" horiz-adv-x="1792" 
+d="M880 1408q-46 0 -79 -33t-33 -79v-656h-32v528q0 46 -33 79t-79 33t-79 -33t-33 -79v-528v-256l-154 205q-38 51 -102 51q-53 0 -90.5 -37.5t-37.5 -90.5q0 -43 26 -77l384 -512q38 -51 102 -51h688q34 0 61 22t34 56l76 405q5 32 5 59v498q0 46 -33 79t-79 33t-79 -33
+t-33 -79v-272h-32v528q0 46 -33 79t-79 33t-79 -33t-33 -79v-528h-32v656q0 46 -33 79t-79 33zM880 1536q68 0 125.5 -35.5t88.5 -96.5q19 4 42 4q99 0 169.5 -70.5t70.5 -169.5v-17q105 6 180.5 -64t75.5 -175v-498q0 -40 -8 -83l-76 -404q-14 -79 -76.5 -131t-143.5 -52
+h-688q-60 0 -114.5 27.5t-90.5 74.5l-384 512q-51 68 -51 154q0 106 75 181t181 75q78 0 128 -34v434q0 99 70.5 169.5t169.5 70.5q23 0 42 -4q31 61 88.5 96.5t125.5 35.5z" />
+    <glyph glyph-name="_562" unicode="&#xf257;" horiz-adv-x="1792" 
+d="M1073 -128h-177q-163 0 -226 141q-23 49 -23 102v5q-62 30 -98.5 88.5t-36.5 127.5q0 38 5 48h-261q-106 0 -181 75t-75 181t75 181t181 75h113l-44 17q-74 28 -119.5 93.5t-45.5 145.5q0 106 75 181t181 75q46 0 91 -17l628 -239h401q106 0 181 -75t75 -181v-668
+q0 -88 -54 -157.5t-140 -90.5l-339 -85q-92 -23 -186 -23zM1024 583l-155 -71l-163 -74q-30 -14 -48 -41.5t-18 -60.5q0 -46 33 -79t79 -33q26 0 46 10l338 154q-49 10 -80.5 50t-31.5 90v55zM1344 272q0 46 -33 79t-79 33q-26 0 -46 -10l-290 -132q-28 -13 -37 -17
+t-30.5 -17t-29.5 -23.5t-16 -29t-8 -40.5q0 -50 31.5 -82t81.5 -32q20 0 38 9l352 160q30 14 48 41.5t18 60.5zM1112 1024l-650 248q-24 8 -46 8q-53 0 -90.5 -37.5t-37.5 -90.5q0 -40 22.5 -73t59.5 -47l526 -200v-64h-640q-53 0 -90.5 -37.5t-37.5 -90.5t37.5 -90.5
+t90.5 -37.5h535l233 106v198q0 63 46 106l111 102h-69zM1073 0q82 0 155 19l339 85q43 11 70 45.5t27 78.5v668q0 53 -37.5 90.5t-90.5 37.5h-308l-136 -126q-36 -33 -36 -82v-296q0 -46 33 -77t79 -31t79 35t33 81v208h32v-208q0 -70 -57 -114q52 -8 86.5 -48.5t34.5 -93.5
+q0 -42 -23 -78t-61 -53l-310 -141h91z" />
+    <glyph glyph-name="_563" unicode="&#xf258;" horiz-adv-x="2048" 
+d="M1151 1536q61 0 116 -28t91 -77l572 -781q118 -159 118 -359v-355q0 -80 -56 -136t-136 -56h-384q-80 0 -136 56t-56 136v177l-286 143h-546q-80 0 -136 56t-56 136v32q0 119 84.5 203.5t203.5 84.5h420l42 128h-686q-100 0 -173.5 67.5t-81.5 166.5q-65 79 -65 182v32
+q0 80 56 136t136 56h959zM1920 -64v355q0 157 -93 284l-573 781q-39 52 -103 52h-959q-26 0 -45 -19t-19 -45q0 -32 1.5 -49.5t9.5 -40.5t25 -43q10 31 35.5 50t56.5 19h832v-32h-832q-26 0 -45 -19t-19 -45q0 -44 3 -58q8 -44 44 -73t81 -29h640h91q40 0 68 -28t28 -68
+q0 -15 -5 -30l-64 -192q-10 -29 -35 -47.5t-56 -18.5h-443q-66 0 -113 -47t-47 -113v-32q0 -26 19 -45t45 -19h561q16 0 29 -7l317 -158q24 -13 38.5 -36t14.5 -50v-197q0 -26 19 -45t45 -19h384q26 0 45 19t19 45z" />
+    <glyph glyph-name="_564" unicode="&#xf259;" horiz-adv-x="2048" 
+d="M459 -256q-77 0 -137.5 47.5t-79.5 122.5l-101 401q-13 57 -13 108q0 45 -5 67l-116 477q-7 27 -7 57q0 93 62 161t155 78q17 85 82.5 139t152.5 54q83 0 148 -51.5t85 -132.5l83 -348l103 428q20 81 85 132.5t148 51.5q89 0 155.5 -57.5t80.5 -144.5q92 -10 152 -79
+t60 -162q0 -24 -7 -59l-123 -512q10 7 37.5 28.5t38.5 29.5t35 23t41 20.5t41.5 11t49.5 5.5q105 0 180 -74t75 -179q0 -62 -28.5 -118t-78.5 -94l-507 -380q-68 -51 -153 -51h-694zM1104 1408q-38 0 -68.5 -24t-39.5 -62l-164 -682h-127l-145 602q-9 38 -39.5 62t-68.5 24
+q-48 0 -80 -33t-32 -80q0 -15 3 -28l132 -547h-26l-99 408q-9 37 -40 62.5t-69 25.5q-47 0 -80 -33t-33 -79q0 -14 3 -26l116 -478q7 -28 9 -86t10 -88l100 -401q8 -32 34 -52.5t59 -20.5h694q42 0 76 26l507 379q56 43 56 110q0 52 -37.5 88.5t-89.5 36.5q-43 0 -77 -26
+l-307 -230v227q0 4 32 138t68 282t39 161q4 18 4 29q0 47 -32 81t-79 34q-39 0 -69.5 -24t-39.5 -62l-116 -482h-26l150 624q3 14 3 28q0 48 -31.5 82t-79.5 34z" />
+    <glyph glyph-name="_565" unicode="&#xf25a;" horiz-adv-x="1792" 
+d="M640 1408q-53 0 -90.5 -37.5t-37.5 -90.5v-512v-384l-151 202q-41 54 -107 54q-52 0 -89 -38t-37 -90q0 -43 26 -77l384 -512q38 -51 102 -51h718q22 0 39.5 13.5t22.5 34.5l92 368q24 96 24 194v217q0 41 -28 71t-68 30t-68 -28t-28 -68h-32v61q0 48 -32 81.5t-80 33.5
+q-46 0 -79 -33t-33 -79v-64h-32v90q0 55 -37 94.5t-91 39.5q-53 0 -90.5 -37.5t-37.5 -90.5v-96h-32v570q0 55 -37 94.5t-91 39.5zM640 1536q107 0 181.5 -77.5t74.5 -184.5v-220q22 2 32 2q99 0 173 -69q47 21 99 21q113 0 184 -87q27 7 56 7q94 0 159 -67.5t65 -161.5
+v-217q0 -116 -28 -225l-92 -368q-16 -64 -68 -104.5t-118 -40.5h-718q-60 0 -114.5 27.5t-90.5 74.5l-384 512q-51 68 -51 154q0 105 74.5 180.5t179.5 75.5q71 0 130 -35v547q0 106 75 181t181 75zM768 128v384h-32v-384h32zM1024 128v384h-32v-384h32zM1280 128v384h-32
+v-384h32z" />
+    <glyph glyph-name="_566" unicode="&#xf25b;" 
+d="M1288 889q60 0 107 -23q141 -63 141 -226v-177q0 -94 -23 -186l-85 -339q-21 -86 -90.5 -140t-157.5 -54h-668q-106 0 -181 75t-75 181v401l-239 628q-17 45 -17 91q0 106 75 181t181 75q80 0 145.5 -45.5t93.5 -119.5l17 -44v113q0 106 75 181t181 75t181 -75t75 -181
+v-261q27 5 48 5q69 0 127.5 -36.5t88.5 -98.5zM1072 896q-33 0 -60.5 -18t-41.5 -48l-74 -163l-71 -155h55q50 0 90 -31.5t50 -80.5l154 338q10 20 10 46q0 46 -33 79t-79 33zM1293 761q-22 0 -40.5 -8t-29 -16t-23.5 -29.5t-17 -30.5t-17 -37l-132 -290q-10 -20 -10 -46
+q0 -46 33 -79t79 -33q33 0 60.5 18t41.5 48l160 352q9 18 9 38q0 50 -32 81.5t-82 31.5zM128 1120q0 -22 8 -46l248 -650v-69l102 111q43 46 106 46h198l106 233v535q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5v-640h-64l-200 526q-14 37 -47 59.5t-73 22.5
+q-53 0 -90.5 -37.5t-37.5 -90.5zM1180 -128q44 0 78.5 27t45.5 70l85 339q19 73 19 155v91l-141 -310q-17 -38 -53 -61t-78 -23q-53 0 -93.5 34.5t-48.5 86.5q-44 -57 -114 -57h-208v32h208q46 0 81 33t35 79t-31 79t-77 33h-296q-49 0 -82 -36l-126 -136v-308
+q0 -53 37.5 -90.5t90.5 -37.5h668z" />
+    <glyph glyph-name="_567" unicode="&#xf25c;" horiz-adv-x="1973" 
+d="M857 992v-117q0 -13 -9.5 -22t-22.5 -9h-298v-812q0 -13 -9 -22.5t-22 -9.5h-135q-13 0 -22.5 9t-9.5 23v812h-297q-13 0 -22.5 9t-9.5 22v117q0 14 9 23t23 9h793q13 0 22.5 -9.5t9.5 -22.5zM1895 995l77 -961q1 -13 -8 -24q-10 -10 -23 -10h-134q-12 0 -21 8.5
+t-10 20.5l-46 588l-189 -425q-8 -19 -29 -19h-120q-20 0 -29 19l-188 427l-45 -590q-1 -12 -10 -20.5t-21 -8.5h-135q-13 0 -23 10q-9 10 -9 24l78 961q1 12 10 20.5t21 8.5h142q20 0 29 -19l220 -520q10 -24 20 -51q3 7 9.5 24.5t10.5 26.5l221 520q9 19 29 19h141
+q13 0 22 -8.5t10 -20.5z" />
+    <glyph glyph-name="_568" unicode="&#xf25d;" horiz-adv-x="1792" 
+d="M1042 833q0 88 -60 121q-33 18 -117 18h-123v-281h162q66 0 102 37t36 105zM1094 548l205 -373q8 -17 -1 -31q-8 -16 -27 -16h-152q-20 0 -28 17l-194 365h-155v-350q0 -14 -9 -23t-23 -9h-134q-14 0 -23 9t-9 23v960q0 14 9 23t23 9h294q128 0 190 -24q85 -31 134 -109
+t49 -180q0 -92 -42.5 -165.5t-115.5 -109.5q6 -10 9 -16zM896 1376q-150 0 -286 -58.5t-234.5 -157t-157 -234.5t-58.5 -286t58.5 -286t157 -234.5t234.5 -157t286 -58.5t286 58.5t234.5 157t157 234.5t58.5 286t-58.5 286t-157 234.5t-234.5 157t-286 58.5zM1792 640
+q0 -182 -71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
+    <glyph glyph-name="_569" unicode="&#xf25e;" horiz-adv-x="1792" 
+d="M605 303q153 0 257 104q14 18 3 36l-45 82q-6 13 -24 17q-16 2 -27 -11l-4 -3q-4 -4 -11.5 -10t-17.5 -13.5t-23.5 -14.5t-28.5 -13t-33.5 -9.5t-37.5 -3.5q-76 0 -125 50t-49 127q0 76 48 125.5t122 49.5q37 0 71.5 -14t50.5 -28l16 -14q11 -11 26 -10q16 2 24 14l53 78
+q13 20 -2 39q-3 4 -11 12t-30 23.5t-48.5 28t-67.5 22.5t-86 10q-148 0 -246 -96.5t-98 -240.5q0 -146 97 -241.5t247 -95.5zM1235 303q153 0 257 104q14 18 4 36l-45 82q-8 14 -25 17q-16 2 -27 -11l-4 -3q-4 -4 -11.5 -10t-17.5 -13.5t-23.5 -14.5t-28.5 -13t-33.5 -9.5
+t-37.5 -3.5q-76 0 -125 50t-49 127q0 76 48 125.5t122 49.5q37 0 71.5 -14t50.5 -28l16 -14q11 -11 26 -10q16 2 24 14l53 78q13 20 -2 39q-3 4 -11 12t-30 23.5t-48.5 28t-67.5 22.5t-86 10q-147 0 -245.5 -96.5t-98.5 -240.5q0 -146 97 -241.5t247 -95.5zM896 1376
+q-150 0 -286 -58.5t-234.5 -157t-157 -234.5t-58.5 -286t58.5 -286t157 -234.5t234.5 -157t286 -58.5t286 58.5t234.5 157t157 234.5t58.5 286t-58.5 286t-157 234.5t-234.5 157t-286 58.5zM896 1536q182 0 348 -71t286 -191t191 -286t71 -348t-71 -348t-191 -286t-286 -191
+t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71z" />
+    <glyph glyph-name="f260" unicode="&#xf260;" horiz-adv-x="2048" 
+d="M736 736l384 -384l-384 -384l-672 672l672 672l168 -168l-96 -96l-72 72l-480 -480l480 -480l193 193l-289 287zM1312 1312l672 -672l-672 -672l-168 168l96 96l72 -72l480 480l-480 480l-193 -193l289 -287l-96 -96l-384 384z" />
+    <glyph glyph-name="f261" unicode="&#xf261;" horiz-adv-x="1792" 
+d="M717 182l271 271l-279 279l-88 -88l192 -191l-96 -96l-279 279l279 279l40 -40l87 87l-127 128l-454 -454zM1075 190l454 454l-454 454l-271 -271l279 -279l88 88l-192 191l96 96l279 -279l-279 -279l-40 40l-87 -88zM1792 640q0 -182 -71 -348t-191 -286t-286 -191
+t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
+    <glyph glyph-name="_572" unicode="&#xf262;" horiz-adv-x="2304" 
+d="M651 539q0 -39 -27.5 -66.5t-65.5 -27.5q-39 0 -66.5 27.5t-27.5 66.5q0 38 27.5 65.5t66.5 27.5q38 0 65.5 -27.5t27.5 -65.5zM1805 540q0 -39 -27.5 -66.5t-66.5 -27.5t-66.5 27.5t-27.5 66.5t27.5 66t66.5 27t66.5 -27t27.5 -66zM765 539q0 79 -56.5 136t-136.5 57
+t-136.5 -56.5t-56.5 -136.5t56.5 -136.5t136.5 -56.5t136.5 56.5t56.5 136.5zM1918 540q0 80 -56.5 136.5t-136.5 56.5q-79 0 -136 -56.5t-57 -136.5t56.5 -136.5t136.5 -56.5t136.5 56.5t56.5 136.5zM850 539q0 -116 -81.5 -197.5t-196.5 -81.5q-116 0 -197.5 82t-81.5 197
+t82 196.5t197 81.5t196.5 -81.5t81.5 -196.5zM2004 540q0 -115 -81.5 -196.5t-197.5 -81.5q-115 0 -196.5 81.5t-81.5 196.5t81.5 196.5t196.5 81.5q116 0 197.5 -81.5t81.5 -196.5zM1040 537q0 191 -135.5 326.5t-326.5 135.5q-125 0 -231 -62t-168 -168.5t-62 -231.5
+t62 -231.5t168 -168.5t231 -62q191 0 326.5 135.5t135.5 326.5zM1708 1110q-254 111 -556 111q-319 0 -573 -110q117 0 223 -45.5t182.5 -122.5t122 -183t45.5 -223q0 115 43.5 219.5t118 180.5t177.5 123t217 50zM2187 537q0 191 -135 326.5t-326 135.5t-326.5 -135.5
+t-135.5 -326.5t135.5 -326.5t326.5 -135.5t326 135.5t135 326.5zM1921 1103h383q-44 -51 -75 -114.5t-40 -114.5q110 -151 110 -337q0 -156 -77 -288t-209 -208.5t-287 -76.5q-133 0 -249 56t-196 155q-47 -56 -129 -179q-11 22 -53.5 82.5t-74.5 97.5
+q-80 -99 -196.5 -155.5t-249.5 -56.5q-155 0 -287 76.5t-209 208.5t-77 288q0 186 110 337q-9 51 -40 114.5t-75 114.5h365q149 100 355 156.5t432 56.5q224 0 421 -56t348 -157z" />
+    <glyph glyph-name="f263" unicode="&#xf263;" horiz-adv-x="1280" 
+d="M640 629q-188 0 -321 133t-133 320q0 188 133 321t321 133t321 -133t133 -321q0 -187 -133 -320t-321 -133zM640 1306q-92 0 -157.5 -65.5t-65.5 -158.5q0 -92 65.5 -157.5t157.5 -65.5t157.5 65.5t65.5 157.5q0 93 -65.5 158.5t-157.5 65.5zM1163 574q13 -27 15 -49.5
+t-4.5 -40.5t-26.5 -38.5t-42.5 -37t-61.5 -41.5q-115 -73 -315 -94l73 -72l267 -267q30 -31 30 -74t-30 -73l-12 -13q-31 -30 -74 -30t-74 30q-67 68 -267 268l-267 -268q-31 -30 -74 -30t-73 30l-12 13q-31 30 -31 73t31 74l267 267l72 72q-203 21 -317 94
+q-39 25 -61.5 41.5t-42.5 37t-26.5 38.5t-4.5 40.5t15 49.5q10 20 28 35t42 22t56 -2t65 -35q5 -4 15 -11t43 -24.5t69 -30.5t92 -24t113 -11q91 0 174 25.5t120 50.5l38 25q33 26 65 35t56 2t42 -22t28 -35z" />
+    <glyph glyph-name="_574" unicode="&#xf264;" 
+d="M927 956q0 -66 -46.5 -112.5t-112.5 -46.5t-112.5 46.5t-46.5 112.5t46.5 112.5t112.5 46.5t112.5 -46.5t46.5 -112.5zM1141 593q-10 20 -28 32t-47.5 9.5t-60.5 -27.5q-10 -8 -29 -20t-81 -32t-127 -20t-124 18t-86 36l-27 18q-31 25 -60.5 27.5t-47.5 -9.5t-28 -32
+q-22 -45 -2 -74.5t87 -73.5q83 -53 226 -67l-51 -52q-142 -142 -191 -190q-22 -22 -22 -52.5t22 -52.5l9 -9q22 -22 52.5 -22t52.5 22l191 191q114 -115 191 -191q22 -22 52.5 -22t52.5 22l9 9q22 22 22 52.5t-22 52.5l-191 190l-52 52q141 14 225 67q67 44 87 73.5t-2 74.5
+zM1092 956q0 134 -95 229t-229 95t-229 -95t-95 -229t95 -229t229 -95t229 95t95 229zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="_575" unicode="&#xf265;" horiz-adv-x="1720" 
+d="M1565 1408q65 0 110 -45.5t45 -110.5v-519q0 -176 -68 -336t-182.5 -275t-274 -182.5t-334.5 -67.5q-176 0 -335.5 67.5t-274.5 182.5t-183 275t-68 336v519q0 64 46 110t110 46h1409zM861 344q47 0 82 33l404 388q37 35 37 85q0 49 -34.5 83.5t-83.5 34.5q-47 0 -82 -33
+l-323 -310l-323 310q-35 33 -81 33q-49 0 -83.5 -34.5t-34.5 -83.5q0 -51 36 -85l405 -388q33 -33 81 -33z" />
+    <glyph glyph-name="_576" unicode="&#xf266;" horiz-adv-x="2304" 
+d="M1494 -103l-295 695q-25 -49 -158.5 -305.5t-198.5 -389.5q-1 -1 -27.5 -0.5t-26.5 1.5q-82 193 -255.5 587t-259.5 596q-21 50 -66.5 107.5t-103.5 100.5t-102 43q0 5 -0.5 24t-0.5 27h583v-50q-39 -2 -79.5 -16t-66.5 -43t-10 -64q26 -59 216.5 -499t235.5 -540
+q31 61 140 266.5t131 247.5q-19 39 -126 281t-136 295q-38 69 -201 71v50l513 -1v-47q-60 -2 -93.5 -25t-12.5 -69q33 -70 87 -189.5t86 -187.5q110 214 173 363q24 55 -10 79.5t-129 26.5q1 7 1 25v24q64 0 170.5 0.5t180 1t92.5 0.5v-49q-62 -2 -119 -33t-90 -81
+l-213 -442q13 -33 127.5 -290t121.5 -274l441 1017q-14 38 -49.5 62.5t-65 31.5t-55.5 8v50l460 -4l1 -2l-1 -44q-139 -4 -201 -145q-526 -1216 -559 -1291h-49z" />
+    <glyph glyph-name="_577" unicode="&#xf267;" horiz-adv-x="1792" 
+d="M949 643q0 -26 -16.5 -45t-41.5 -19q-26 0 -45 16.5t-19 41.5q0 26 17 45t42 19t44 -16.5t19 -41.5zM964 585l350 581q-9 -8 -67.5 -62.5t-125.5 -116.5t-136.5 -127t-117 -110.5t-50.5 -51.5l-349 -580q7 7 67 62t126 116.5t136 127t117 111t50 50.5zM1611 640
+q0 -201 -104 -371q-3 2 -17 11t-26.5 16.5t-16.5 7.5q-13 0 -13 -13q0 -10 59 -44q-74 -112 -184.5 -190.5t-241.5 -110.5l-16 67q-1 10 -15 10q-5 0 -8 -5.5t-2 -9.5l16 -68q-72 -15 -146 -15q-199 0 -372 105q1 2 13 20.5t21.5 33.5t9.5 19q0 13 -13 13q-6 0 -17 -14.5
+t-22.5 -34.5t-13.5 -23q-113 75 -192 187.5t-110 244.5l69 15q10 3 10 15q0 5 -5.5 8t-10.5 2l-68 -15q-14 72 -14 139q0 206 109 379q2 -1 18.5 -12t30 -19t17.5 -8q13 0 13 12q0 6 -12.5 15.5t-32.5 21.5l-20 12q77 112 189 189t244 107l15 -67q2 -10 15 -10q5 0 8 5.5
+t2 10.5l-15 66q71 13 134 13q204 0 379 -109q-39 -56 -39 -65q0 -13 12 -13q11 0 48 64q111 -75 187.5 -186t107.5 -241l-56 -12q-10 -2 -10 -16q0 -5 5.5 -8t9.5 -2l57 13q14 -72 14 -140zM1696 640q0 163 -63.5 311t-170.5 255t-255 170.5t-311 63.5t-311 -63.5
+t-255 -170.5t-170.5 -255t-63.5 -311t63.5 -311t170.5 -255t255 -170.5t311 -63.5t311 63.5t255 170.5t170.5 255t63.5 311zM1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71t348 -71t286 -191
+t191 -286t71 -348z" />
+    <glyph glyph-name="_578" unicode="&#xf268;" horiz-adv-x="1792" 
+d="M893 1536q240 2 451 -120q232 -134 352 -372l-742 39q-160 9 -294 -74.5t-185 -229.5l-276 424q128 159 311 245.5t383 87.5zM146 1131l337 -663q72 -143 211 -217t293 -45l-230 -451q-212 33 -385 157.5t-272.5 316t-99.5 411.5q0 267 146 491zM1732 962
+q58 -150 59.5 -310.5t-48.5 -306t-153 -272t-246 -209.5q-230 -133 -498 -119l405 623q88 131 82.5 290.5t-106.5 277.5zM896 942q125 0 213.5 -88.5t88.5 -213.5t-88.5 -213.5t-213.5 -88.5t-213.5 88.5t-88.5 213.5t88.5 213.5t213.5 88.5z" />
+    <glyph glyph-name="_579" unicode="&#xf269;" horiz-adv-x="1792" 
+d="M903 -256q-283 0 -504.5 150.5t-329.5 398.5q-58 131 -67 301t26 332.5t111 312t179 242.5l-11 -281q11 14 68 15.5t70 -15.5q42 81 160.5 138t234.5 59q-54 -45 -119.5 -148.5t-58.5 -163.5q25 -8 62.5 -13.5t63 -7.5t68 -4t50.5 -3q15 -5 9.5 -45.5t-30.5 -75.5
+q-5 -7 -16.5 -18.5t-56.5 -35.5t-101 -34l15 -189l-139 67q-18 -43 -7.5 -81.5t36 -66.5t65.5 -41.5t81 -6.5q51 9 98 34.5t83.5 45t73.5 17.5q61 -4 89.5 -33t19.5 -65q-1 -2 -2.5 -5.5t-8.5 -12.5t-18 -15.5t-31.5 -10.5t-46.5 -1q-60 -95 -144.5 -135.5t-209.5 -29.5
+q74 -61 162.5 -82.5t168.5 -6t154.5 52t128 87.5t80.5 104q43 91 39 192.5t-37.5 188.5t-78.5 125q87 -38 137 -79.5t77 -112.5q15 170 -57.5 343t-209.5 284q265 -77 412 -279.5t151 -517.5q2 -127 -40.5 -255t-123.5 -238t-189 -196t-247.5 -135.5t-288.5 -49.5z" />
+    <glyph glyph-name="_580" unicode="&#xf26a;" horiz-adv-x="1792" 
+d="M1493 1308q-165 110 -359 110q-155 0 -293 -73t-240 -200q-75 -93 -119.5 -218t-48.5 -266v-42q4 -141 48.5 -266t119.5 -218q102 -127 240 -200t293 -73q194 0 359 110q-121 -108 -274.5 -168t-322.5 -60q-29 0 -43 1q-175 8 -333 82t-272 193t-181 281t-67 339
+q0 182 71 348t191 286t286 191t348 71h3q168 -1 320.5 -60.5t273.5 -167.5zM1792 640q0 -192 -77 -362.5t-213 -296.5q-104 -63 -222 -63q-137 0 -255 84q154 56 253.5 233t99.5 405q0 227 -99 404t-253 234q119 83 254 83q119 0 226 -65q135 -125 210.5 -295t75.5 -361z
+" />
+    <glyph glyph-name="_581" unicode="&#xf26b;" horiz-adv-x="1792" 
+d="M1792 599q0 -56 -7 -104h-1151q0 -146 109.5 -244.5t257.5 -98.5q99 0 185.5 46.5t136.5 130.5h423q-56 -159 -170.5 -281t-267.5 -188.5t-321 -66.5q-187 0 -356 83q-228 -116 -394 -116q-237 0 -237 263q0 115 45 275q17 60 109 229q199 360 475 606
+q-184 -79 -427 -354q63 274 283.5 449.5t501.5 175.5q30 0 45 -1q255 117 433 117q64 0 116 -13t94.5 -40.5t66.5 -76.5t24 -115q0 -116 -75 -286q101 -182 101 -390zM1722 1239q0 83 -53 132t-137 49q-108 0 -254 -70q121 -47 222.5 -131.5t170.5 -195.5q51 135 51 216z
+M128 2q0 -86 48.5 -132.5t134.5 -46.5q115 0 266 83q-122 72 -213.5 183t-137.5 245q-98 -205 -98 -332zM632 715h728q-5 142 -113 237t-251 95q-144 0 -251.5 -95t-112.5 -237z" />
+    <glyph glyph-name="_582" unicode="&#xf26c;" horiz-adv-x="2048" 
+d="M1792 288v960q0 13 -9.5 22.5t-22.5 9.5h-1600q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h1600q13 0 22.5 9.5t9.5 22.5zM1920 1248v-960q0 -66 -47 -113t-113 -47h-736v-128h352q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-832q-14 0 -23 9t-9 23
+v64q0 14 9 23t23 9h352v128h-736q-66 0 -113 47t-47 113v960q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" />
+    <glyph glyph-name="_583" unicode="&#xf26d;" horiz-adv-x="1792" 
+d="M138 1408h197q-70 -64 -126 -149q-36 -56 -59 -115t-30 -125.5t-8.5 -120t10.5 -132t21 -126t28 -136.5q4 -19 6 -28q51 -238 81 -329q57 -171 152 -275h-272q-48 0 -82 34t-34 82v1304q0 48 34 82t82 34zM1346 1408h308q48 0 82 -34t34 -82v-1304q0 -48 -34 -82t-82 -34
+h-178q212 210 196 565l-469 -101q-2 -45 -12 -82t-31 -72t-59.5 -59.5t-93.5 -36.5q-123 -26 -199 40q-32 27 -53 61t-51.5 129t-64.5 258q-35 163 -45.5 263t-5.5 139t23 77q20 41 62.5 73t102.5 45q45 12 83.5 6.5t67 -17t54 -35t43 -48t34.5 -56.5l468 100
+q-68 175 -180 287z" />
+    <glyph glyph-name="_584" unicode="&#xf26e;" 
+d="M1401 -11l-6 -6q-113 -113 -259 -175q-154 -64 -317 -64q-165 0 -317 64q-148 63 -259 175q-113 112 -175 258q-42 103 -54 189q-4 28 48 36q51 8 56 -20q1 -1 1 -4q18 -90 46 -159q50 -124 152 -226q98 -98 226 -152q132 -56 276 -56q143 0 276 56q128 55 225 152l6 6
+q10 10 25 6q12 -3 33 -22q36 -37 17 -58zM929 604l-66 -66l63 -63q21 -21 -7 -49q-17 -17 -32 -17q-10 0 -19 10l-62 61l-66 -66q-5 -5 -15 -5q-15 0 -31 16l-2 2q-18 15 -18 29q0 7 8 17l66 65l-66 66q-16 16 14 45q18 18 31 18q6 0 13 -5l65 -66l65 65q18 17 48 -13
+q27 -27 11 -44zM1400 547q0 -118 -46 -228q-45 -105 -126 -186q-80 -80 -187 -126t-228 -46t-228 46t-187 126q-82 82 -125 186q-15 33 -15 40h-1q-9 27 43 44q50 16 60 -12q37 -99 97 -167h1v339v2q3 136 102 232q105 103 253 103q147 0 251 -103t104 -249
+q0 -147 -104.5 -251t-250.5 -104q-58 0 -112 16q-28 11 -13 61q16 51 44 43l14 -3q14 -3 33 -6t30 -3q104 0 176 71.5t72 174.5q0 101 -72 171q-71 71 -175 71q-107 0 -178 -80q-64 -72 -64 -160v-413q110 -67 242 -67q96 0 185 36.5t156 103.5t103.5 155t36.5 183
+q0 198 -141 339q-140 140 -339 140q-200 0 -340 -140q-53 -53 -77 -87l-2 -2q-8 -11 -13 -15.5t-21.5 -9.5t-38.5 3q-21 5 -36.5 16.5t-15.5 26.5v680q0 15 10.5 26.5t27.5 11.5h877q30 0 30 -55t-30 -55h-811v-483h1q40 42 102 84t108 61q109 46 231 46q121 0 228 -46
+t187 -126q81 -81 126 -186q46 -112 46 -229zM1369 1128q9 -8 9 -18t-5.5 -18t-16.5 -21q-26 -26 -39 -26q-9 0 -16 7q-106 91 -207 133q-128 56 -276 56q-133 0 -262 -49q-27 -10 -45 37q-9 25 -8 38q3 16 16 20q130 57 299 57q164 0 316 -64q137 -58 235 -152z" />
+    <glyph glyph-name="_585" unicode="&#xf270;" horiz-adv-x="1792" 
+d="M1551 60q15 6 26 3t11 -17.5t-15 -33.5q-13 -16 -44 -43.5t-95.5 -68t-141 -74t-188 -58t-229.5 -24.5q-119 0 -238 31t-209 76.5t-172.5 104t-132.5 105t-84 87.5q-8 9 -10 16.5t1 12t8 7t11.5 2t11.5 -4.5q192 -117 300 -166q389 -176 799 -90q190 40 391 135z
+M1758 175q11 -16 2.5 -69.5t-28.5 -102.5q-34 -83 -85 -124q-17 -14 -26 -9t0 24q21 45 44.5 121.5t6.5 98.5q-5 7 -15.5 11.5t-27 6t-29.5 2.5t-35 0t-31.5 -2t-31 -3t-22.5 -2q-6 -1 -13 -1.5t-11 -1t-8.5 -1t-7 -0.5h-5.5h-4.5t-3 0.5t-2 1.5l-1.5 3q-6 16 47 40t103 30
+q46 7 108 1t76 -24zM1364 618q0 -31 13.5 -64t32 -58t37.5 -46t33 -32l13 -11l-227 -224q-40 37 -79 75.5t-58 58.5l-19 20q-11 11 -25 33q-38 -59 -97.5 -102.5t-127.5 -63.5t-140 -23t-137.5 21t-117.5 65.5t-83 113t-31 162.5q0 84 28 154t72 116.5t106.5 83t122.5 57
+t130 34.5t119.5 18.5t99.5 6.5v127q0 65 -21 97q-34 53 -121 53q-6 0 -16.5 -1t-40.5 -12t-56 -29.5t-56 -59.5t-48 -96l-294 27q0 60 22 119t67 113t108 95t151.5 65.5t190.5 24.5q100 0 181 -25t129.5 -61.5t81 -83t45 -86t12.5 -73.5v-589zM692 597q0 -86 70 -133
+q66 -44 139 -22q84 25 114 123q14 45 14 101v162q-59 -2 -111 -12t-106.5 -33.5t-87 -71t-32.5 -114.5z" />
+    <glyph glyph-name="_586" unicode="&#xf271;" horiz-adv-x="1792" 
+d="M1536 1280q52 0 90 -38t38 -90v-1280q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h384v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h128zM1152 1376v-288q0 -14 9 -23t23 -9
+h64q14 0 23 9t9 23v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23zM384 1376v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23zM1536 -128v1024h-1408v-1024h1408zM896 448h224q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-224
+v-224q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v224h-224q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h224v224q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-224z" />
+    <glyph glyph-name="_587" unicode="&#xf272;" horiz-adv-x="1792" 
+d="M1152 416v-64q0 -14 -9 -23t-23 -9h-576q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h576q14 0 23 -9t9 -23zM128 -128h1408v1024h-1408v-1024zM512 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1280 1088v288q0 14 -9 23
+t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1664 1152v-1280q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h384v96q0 66 47 113t113 47h64q66 0 113 -47
+t47 -113v-96h128q52 0 90 -38t38 -90z" />
+    <glyph glyph-name="_588" unicode="&#xf273;" horiz-adv-x="1792" 
+d="M1111 151l-46 -46q-9 -9 -22 -9t-23 9l-188 189l-188 -189q-10 -9 -23 -9t-22 9l-46 46q-9 9 -9 22t9 23l189 188l-189 188q-9 10 -9 23t9 22l46 46q9 9 22 9t23 -9l188 -188l188 188q10 9 23 9t22 -9l46 -46q9 -9 9 -22t-9 -23l-188 -188l188 -188q9 -10 9 -23t-9 -22z
+M128 -128h1408v1024h-1408v-1024zM512 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1280 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1664 1152v-1280
+q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h384v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h128q52 0 90 -38t38 -90z" />
+    <glyph glyph-name="_589" unicode="&#xf274;" horiz-adv-x="1792" 
+d="M1303 572l-512 -512q-10 -9 -23 -9t-23 9l-288 288q-9 10 -9 23t9 22l46 46q9 9 22 9t23 -9l220 -220l444 444q10 9 23 9t22 -9l46 -46q9 -9 9 -22t-9 -23zM128 -128h1408v1024h-1408v-1024zM512 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23
+t23 -9h64q14 0 23 9t9 23zM1280 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1664 1152v-1280q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47
+t47 -113v-96h384v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h128q52 0 90 -38t38 -90z" />
+    <glyph glyph-name="_590" unicode="&#xf275;" horiz-adv-x="1792" 
+d="M448 1536q26 0 45 -19t19 -45v-891l536 429q17 14 40 14q26 0 45 -19t19 -45v-379l536 429q17 14 40 14q26 0 45 -19t19 -45v-1152q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v1664q0 26 19 45t45 19h384z" />
+    <glyph glyph-name="_591" unicode="&#xf276;" horiz-adv-x="1024" 
+d="M512 448q66 0 128 15v-655q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v655q62 -15 128 -15zM512 1536q212 0 362 -150t150 -362t-150 -362t-362 -150t-362 150t-150 362t150 362t362 150zM512 1312q14 0 23 9t9 23t-9 23t-23 9q-146 0 -249 -103t-103 -249
+q0 -14 9 -23t23 -9t23 9t9 23q0 119 84.5 203.5t203.5 84.5z" />
+    <glyph glyph-name="_592" unicode="&#xf277;" horiz-adv-x="1792" 
+d="M1745 1239q10 -10 10 -23t-10 -23l-141 -141q-28 -28 -68 -28h-1344q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h576v64q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-64h512q40 0 68 -28zM768 320h256v-512q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v512zM1600 768
+q26 0 45 -19t19 -45v-256q0 -26 -19 -45t-45 -19h-1344q-40 0 -68 28l-141 141q-10 10 -10 23t10 23l141 141q28 28 68 28h512v192h256v-192h576z" />
+    <glyph glyph-name="_593" unicode="&#xf278;" horiz-adv-x="2048" 
+d="M2020 1525q28 -20 28 -53v-1408q0 -20 -11 -36t-29 -23l-640 -256q-24 -11 -48 0l-616 246l-616 -246q-10 -5 -24 -5q-19 0 -36 11q-28 20 -28 53v1408q0 20 11 36t29 23l640 256q24 11 48 0l616 -246l616 246q32 13 60 -6zM736 1390v-1270l576 -230v1270zM128 1173
+v-1270l544 217v1270zM1920 107v1270l-544 -217v-1270z" />
+    <glyph glyph-name="_594" unicode="&#xf279;" horiz-adv-x="1792" 
+d="M512 1536q13 0 22.5 -9.5t9.5 -22.5v-1472q0 -20 -17 -28l-480 -256q-7 -4 -15 -4q-13 0 -22.5 9.5t-9.5 22.5v1472q0 20 17 28l480 256q7 4 15 4zM1760 1536q13 0 22.5 -9.5t9.5 -22.5v-1472q0 -20 -17 -28l-480 -256q-7 -4 -15 -4q-13 0 -22.5 9.5t-9.5 22.5v1472
+q0 20 17 28l480 256q7 4 15 4zM640 1536q8 0 14 -3l512 -256q18 -10 18 -29v-1472q0 -13 -9.5 -22.5t-22.5 -9.5q-8 0 -14 3l-512 256q-18 10 -18 29v1472q0 13 9.5 22.5t22.5 9.5z" />
+    <glyph glyph-name="_595" unicode="&#xf27a;" horiz-adv-x="1792" 
+d="M640 640q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1024 640q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1408 640q0 53 -37.5 90.5t-90.5 37.5
+t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1792 640q0 -174 -120 -321.5t-326 -233t-450 -85.5q-110 0 -211 18q-173 -173 -435 -229q-52 -10 -86 -13q-12 -1 -22 6t-13 18q-4 15 20 37q5 5 23.5 21.5t25.5 23.5t23.5 25.5t24 31.5t20.5 37
+t20 48t14.5 57.5t12.5 72.5q-146 90 -229.5 216.5t-83.5 269.5q0 174 120 321.5t326 233t450 85.5t450 -85.5t326 -233t120 -321.5z" />
+    <glyph glyph-name="_596" unicode="&#xf27b;" horiz-adv-x="1792" 
+d="M640 640q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1024 640q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1408 640q0 -53 -37.5 -90.5t-90.5 -37.5
+t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM896 1152q-204 0 -381.5 -69.5t-282 -187.5t-104.5 -255q0 -112 71.5 -213.5t201.5 -175.5l87 -50l-27 -96q-24 -91 -70 -172q152 63 275 171l43 38l57 -6q69 -8 130 -8q204 0 381.5 69.5t282 187.5
+t104.5 255t-104.5 255t-282 187.5t-381.5 69.5zM1792 640q0 -174 -120 -321.5t-326 -233t-450 -85.5q-70 0 -145 8q-198 -175 -460 -242q-49 -14 -114 -22h-5q-15 0 -27 10.5t-16 27.5v1q-3 4 -0.5 12t2 10t4.5 9.5l6 9t7 8.5t8 9q7 8 31 34.5t34.5 38t31 39.5t32.5 51
+t27 59t26 76q-157 89 -247.5 220t-90.5 281q0 130 71 248.5t191 204.5t286 136.5t348 50.5t348 -50.5t286 -136.5t191 -204.5t71 -248.5z" />
+    <glyph glyph-name="_597" unicode="&#xf27c;" horiz-adv-x="1024" 
+d="M512 345l512 295v-591l-512 -296v592zM0 640v-591l512 296zM512 1527v-591l-512 -296v591zM512 936l512 295v-591z" />
+    <glyph glyph-name="_598" unicode="&#xf27d;" horiz-adv-x="1792" 
+d="M1709 1018q-10 -236 -332 -651q-333 -431 -562 -431q-142 0 -240 263q-44 160 -132 482q-72 262 -157 262q-18 0 -127 -76l-77 98q24 21 108 96.5t130 115.5q156 138 241 146q95 9 153 -55.5t81 -203.5q44 -287 66 -373q55 -249 120 -249q51 0 154 161q101 161 109 246
+q13 139 -109 139q-57 0 -121 -26q120 393 459 382q251 -8 236 -326z" />
+    <glyph glyph-name="f27e" unicode="&#xf27e;" 
+d="M0 1408h1536v-1536h-1536v1536zM1085 293l-221 631l221 297h-634l221 -297l-221 -631l317 -304z" />
+    <glyph glyph-name="uniF280" unicode="&#xf280;" 
+d="M0 1408h1536v-1536h-1536v1536zM908 1088l-12 -33l75 -83l-31 -114l25 -25l107 57l107 -57l25 25l-31 114l75 83l-12 33h-95l-53 96h-32l-53 -96h-95zM641 925q32 0 44.5 -16t11.5 -63l174 21q0 55 -17.5 92.5t-50.5 56t-69 25.5t-85 7q-133 0 -199 -57.5t-66 -182.5v-72
+h-96v-128h76q20 0 20 -8v-382q0 -14 -5 -20t-18 -7l-73 -7v-88h448v86l-149 14q-6 1 -8.5 1.5t-3.5 2.5t-0.5 4t1 7t0.5 10v387h191l38 128h-231q-6 0 -2 6t4 9v80q0 27 1.5 40.5t7.5 28t19.5 20t36.5 5.5zM1248 96v86l-54 9q-7 1 -9.5 2.5t-2.5 3t1 7.5t1 12v520h-275
+l-23 -101l83 -22q23 -7 23 -27v-370q0 -14 -6 -18.5t-20 -6.5l-70 -9v-86h352z" />
+    <glyph glyph-name="uniF281" unicode="&#xf281;" horiz-adv-x="1792" 
+d="M1792 690q0 -58 -29.5 -105.5t-79.5 -72.5q12 -46 12 -96q0 -155 -106.5 -287t-290.5 -208.5t-400 -76.5t-399.5 76.5t-290 208.5t-106.5 287q0 47 11 94q-51 25 -82 73.5t-31 106.5q0 82 58 140.5t141 58.5q85 0 145 -63q218 152 515 162l116 521q3 13 15 21t26 5
+l369 -81q18 37 54 59.5t79 22.5q62 0 106 -43.5t44 -105.5t-44 -106t-106 -44t-105.5 43.5t-43.5 105.5l-334 74l-104 -472q300 -9 519 -160q58 61 143 61q83 0 141 -58.5t58 -140.5zM418 491q0 -62 43.5 -106t105.5 -44t106 44t44 106t-44 105.5t-106 43.5q-61 0 -105 -44
+t-44 -105zM1228 136q11 11 11 26t-11 26q-10 10 -25 10t-26 -10q-41 -42 -121 -62t-160 -20t-160 20t-121 62q-11 10 -26 10t-25 -10q-11 -10 -11 -25.5t11 -26.5q43 -43 118.5 -68t122.5 -29.5t91 -4.5t91 4.5t122.5 29.5t118.5 68zM1225 341q62 0 105.5 44t43.5 106
+q0 61 -44 105t-105 44q-62 0 -106 -43.5t-44 -105.5t44 -106t106 -44z" />
+    <glyph glyph-name="_602" unicode="&#xf282;" horiz-adv-x="1792" 
+d="M69 741h1q16 126 58.5 241.5t115 217t167.5 176t223.5 117.5t276.5 43q231 0 414 -105.5t294 -303.5q104 -187 104 -442v-188h-1125q1 -111 53.5 -192.5t136.5 -122.5t189.5 -57t213 -3t208 46.5t173.5 84.5v-377q-92 -55 -229.5 -92t-312.5 -38t-316 53
+q-189 73 -311.5 249t-124.5 372q-3 242 111 412t325 268q-48 -60 -78 -125.5t-46 -159.5h635q8 77 -8 140t-47 101.5t-70.5 66.5t-80.5 41t-75 20.5t-56 8.5l-22 1q-135 -5 -259.5 -44.5t-223.5 -104.5t-176 -140.5t-138 -163.5z" />
+    <glyph glyph-name="_603" unicode="&#xf283;" horiz-adv-x="2304" 
+d="M0 32v608h2304v-608q0 -66 -47 -113t-113 -47h-1984q-66 0 -113 47t-47 113zM640 256v-128h384v128h-384zM256 256v-128h256v128h-256zM2144 1408q66 0 113 -47t47 -113v-224h-2304v224q0 66 47 113t113 47h1984z" />
+    <glyph glyph-name="_604" unicode="&#xf284;" horiz-adv-x="1792" 
+d="M1584 246l-218 111q-74 -120 -196.5 -189t-263.5 -69q-147 0 -271 72t-196 196t-72 270q0 110 42.5 209.5t115 172t172 115t209.5 42.5q131 0 247.5 -60.5t192.5 -168.5l215 125q-110 169 -286.5 265t-378.5 96q-161 0 -308 -63t-253 -169t-169 -253t-63 -308t63 -308
+t169 -253t253 -169t308 -63q213 0 397.5 107t290.5 292zM1030 643l693 -352q-116 -253 -334.5 -400t-492.5 -147q-182 0 -348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71q260 0 470.5 -133.5t335.5 -366.5zM1543 640h-39v-160h-96v352h136q32 0 54.5 -20
+t28.5 -48t1 -56t-27.5 -48t-57.5 -20z" />
+    <glyph glyph-name="uniF285" unicode="&#xf285;" horiz-adv-x="1792" 
+d="M1427 827l-614 386l92 151h855zM405 562l-184 116v858l1183 -743zM1424 697l147 -95v-858l-532 335zM1387 718l-500 -802h-855l356 571z" />
+    <glyph glyph-name="uniF286" unicode="&#xf286;" horiz-adv-x="1792" 
+d="M640 528v224q0 16 -16 16h-96q-16 0 -16 -16v-224q0 -16 16 -16h96q16 0 16 16zM1152 528v224q0 16 -16 16h-96q-16 0 -16 -16v-224q0 -16 16 -16h96q16 0 16 16zM1664 496v-752h-640v320q0 80 -56 136t-136 56t-136 -56t-56 -136v-320h-640v752q0 16 16 16h96
+q16 0 16 -16v-112h128v624q0 16 16 16h96q16 0 16 -16v-112h128v112q0 16 16 16h96q16 0 16 -16v-112h128v112q0 6 2.5 9.5t8.5 5t9.5 2t11.5 0t9 -0.5v391q-32 15 -32 50q0 23 16.5 39t38.5 16t38.5 -16t16.5 -39q0 -35 -32 -50v-17q45 10 83 10q21 0 59.5 -7.5t54.5 -7.5
+q17 0 47 7.5t37 7.5q16 0 16 -16v-210q0 -15 -35 -21.5t-62 -6.5q-18 0 -54.5 7.5t-55.5 7.5q-40 0 -90 -12v-133q1 0 9 0.5t11.5 0t9.5 -2t8.5 -5t2.5 -9.5v-112h128v112q0 16 16 16h96q16 0 16 -16v-112h128v112q0 16 16 16h96q16 0 16 -16v-624h128v112q0 16 16 16h96
+q16 0 16 -16z" />
+    <glyph glyph-name="_607" unicode="&#xf287;" horiz-adv-x="2304" 
+d="M2288 731q16 -8 16 -27t-16 -27l-320 -192q-8 -5 -16 -5q-9 0 -16 4q-16 10 -16 28v128h-858q37 -58 83 -165q16 -37 24.5 -55t24 -49t27 -47t27 -34t31.5 -26t33 -8h96v96q0 14 9 23t23 9h320q14 0 23 -9t9 -23v-320q0 -14 -9 -23t-23 -9h-320q-14 0 -23 9t-9 23v96h-96
+q-32 0 -61 10t-51 23.5t-45 40.5t-37 46t-33.5 57t-28.5 57.5t-28 60.5q-23 53 -37 81.5t-36 65t-44.5 53.5t-46.5 17h-360q-22 -84 -91 -138t-157 -54q-106 0 -181 75t-75 181t75 181t181 75q88 0 157 -54t91 -138h104q24 0 46.5 17t44.5 53.5t36 65t37 81.5q19 41 28 60.5
+t28.5 57.5t33.5 57t37 46t45 40.5t51 23.5t61 10h107q21 57 70 92.5t111 35.5q80 0 136 -56t56 -136t-56 -136t-136 -56q-62 0 -111 35.5t-70 92.5h-107q-17 0 -33 -8t-31.5 -26t-27 -34t-27 -47t-24 -49t-24.5 -55q-46 -107 -83 -165h1114v128q0 18 16 28t32 -1z" />
+    <glyph glyph-name="_608" unicode="&#xf288;" horiz-adv-x="1792" 
+d="M1150 774q0 -56 -39.5 -95t-95.5 -39h-253v269h253q56 0 95.5 -39.5t39.5 -95.5zM1329 774q0 130 -91.5 222t-222.5 92h-433v-896h180v269h253q130 0 222 91.5t92 221.5zM1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348
+t71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
+    <glyph glyph-name="_609" unicode="&#xf289;" horiz-adv-x="2304" 
+d="M1645 438q0 59 -34 106.5t-87 68.5q-7 -45 -23 -92q-7 -24 -27.5 -38t-44.5 -14q-12 0 -24 3q-31 10 -45 38.5t-4 58.5q23 71 23 143q0 123 -61 227.5t-166 165.5t-228 61q-134 0 -247 -73t-167 -194q108 -28 188 -106q22 -23 22 -55t-22 -54t-54 -22t-55 22
+q-75 75 -180 75q-106 0 -181 -74.5t-75 -180.5t75 -180.5t181 -74.5h1046q79 0 134.5 55.5t55.5 133.5zM1798 438q0 -142 -100.5 -242t-242.5 -100h-1046q-169 0 -289 119.5t-120 288.5q0 153 100 267t249 136q62 184 221 298t354 114q235 0 408.5 -158.5t196.5 -389.5
+q116 -25 192.5 -118.5t76.5 -214.5zM2048 438q0 -175 -97 -319q-23 -33 -64 -33q-24 0 -43 13q-26 17 -32 48.5t12 57.5q71 104 71 233t-71 233q-18 26 -12 57t32 49t57.5 11.5t49.5 -32.5q97 -142 97 -318zM2304 438q0 -244 -134 -443q-23 -34 -64 -34q-23 0 -42 13
+q-26 18 -32.5 49t11.5 57q108 164 108 358q0 195 -108 357q-18 26 -11.5 57.5t32.5 48.5q26 18 57 12t49 -33q134 -198 134 -442z" />
+    <glyph glyph-name="_610" unicode="&#xf28a;" 
+d="M1500 -13q0 -89 -63 -152.5t-153 -63.5t-153.5 63.5t-63.5 152.5q0 90 63.5 153.5t153.5 63.5t153 -63.5t63 -153.5zM1267 268q-115 -15 -192.5 -102.5t-77.5 -205.5q0 -74 33 -138q-146 -78 -379 -78q-109 0 -201 21t-153.5 54.5t-110.5 76.5t-76 85t-44.5 83
+t-23.5 66.5t-6 39.5q0 19 4.5 42.5t18.5 56t36.5 58t64 43.5t94.5 18t94 -17.5t63 -41t35.5 -53t17.5 -49t4 -33.5q0 -34 -23 -81q28 -27 82 -42t93 -17l40 -1q115 0 190 51t75 133q0 26 -9 48.5t-31.5 44.5t-49.5 41t-74 44t-93.5 47.5t-119.5 56.5q-28 13 -43 20
+q-116 55 -187 100t-122.5 102t-72 125.5t-20.5 162.5q0 78 20.5 150t66 137.5t112.5 114t166.5 77t221.5 28.5q120 0 220 -26t164.5 -67t109.5 -94t64 -105.5t19 -103.5q0 -46 -15 -82.5t-36.5 -58t-48.5 -36t-49 -19.5t-39 -5h-8h-32t-39 5t-44 14t-41 28t-37 46t-24 70.5
+t-10 97.5q-15 16 -59 25.5t-81 10.5l-37 1q-68 0 -117.5 -31t-70.5 -70t-21 -76q0 -24 5 -43t24 -46t53 -51t97 -53.5t150 -58.5q76 -25 138.5 -53.5t109 -55.5t83 -59t60.5 -59.5t41 -62.5t26.5 -62t14.5 -63.5t6 -62t1 -62.5z" />
+    <glyph glyph-name="_611" unicode="&#xf28b;" 
+d="M704 352v576q0 14 -9 23t-23 9h-256q-14 0 -23 -9t-9 -23v-576q0 -14 9 -23t23 -9h256q14 0 23 9t9 23zM1152 352v576q0 14 -9 23t-23 9h-256q-14 0 -23 -9t-9 -23v-576q0 -14 9 -23t23 -9h256q14 0 23 9t9 23zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103
+t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="_612" unicode="&#xf28c;" 
+d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM768 96q148 0 273 73t198 198t73 273t-73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273
+t73 -273t198 -198t273 -73zM864 320q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-576q0 -14 -9 -23t-23 -9h-192zM480 320q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-576q0 -14 -9 -23t-23 -9h-192z" />
+    <glyph glyph-name="_613" unicode="&#xf28d;" 
+d="M1088 352v576q0 14 -9 23t-23 9h-576q-14 0 -23 -9t-9 -23v-576q0 -14 9 -23t23 -9h576q14 0 23 9t9 23zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5
+t103 -385.5z" />
+    <glyph glyph-name="_614" unicode="&#xf28e;" 
+d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM768 96q148 0 273 73t198 198t73 273t-73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273
+t73 -273t198 -198t273 -73zM480 320q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h576q14 0 23 -9t9 -23v-576q0 -14 -9 -23t-23 -9h-576z" />
+    <glyph glyph-name="_615" unicode="&#xf290;" horiz-adv-x="1792" 
+d="M1757 128l35 -313q3 -28 -16 -50q-19 -21 -48 -21h-1664q-29 0 -48 21q-19 22 -16 50l35 313h1722zM1664 967l86 -775h-1708l86 775q3 24 21 40.5t43 16.5h256v-128q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5v128h384v-128q0 -53 37.5 -90.5t90.5 -37.5
+t90.5 37.5t37.5 90.5v128h256q25 0 43 -16.5t21 -40.5zM1280 1152v-256q0 -26 -19 -45t-45 -19t-45 19t-19 45v256q0 106 -75 181t-181 75t-181 -75t-75 -181v-256q0 -26 -19 -45t-45 -19t-45 19t-19 45v256q0 159 112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5z" />
+    <glyph glyph-name="_616" unicode="&#xf291;" horiz-adv-x="2048" 
+d="M1920 768q53 0 90.5 -37.5t37.5 -90.5t-37.5 -90.5t-90.5 -37.5h-15l-115 -662q-8 -46 -44 -76t-82 -30h-1280q-46 0 -82 30t-44 76l-115 662h-15q-53 0 -90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5h1792zM485 -32q26 2 43.5 22.5t15.5 46.5l-32 416q-2 26 -22.5 43.5
+t-46.5 15.5t-43.5 -22.5t-15.5 -46.5l32 -416q2 -25 20.5 -42t43.5 -17h5zM896 32v416q0 26 -19 45t-45 19t-45 -19t-19 -45v-416q0 -26 19 -45t45 -19t45 19t19 45zM1280 32v416q0 26 -19 45t-45 19t-45 -19t-19 -45v-416q0 -26 19 -45t45 -19t45 19t19 45zM1632 27l32 416
+q2 26 -15.5 46.5t-43.5 22.5t-46.5 -15.5t-22.5 -43.5l-32 -416q-2 -26 15.5 -46.5t43.5 -22.5h5q25 0 43.5 17t20.5 42zM476 1244l-93 -412h-132l101 441q19 88 89 143.5t160 55.5h167q0 26 19 45t45 19h384q26 0 45 -19t19 -45h167q90 0 160 -55.5t89 -143.5l101 -441
+h-132l-93 412q-11 44 -45.5 72t-79.5 28h-167q0 -26 -19 -45t-45 -19h-384q-26 0 -45 19t-19 45h-167q-45 0 -79.5 -28t-45.5 -72z" />
+    <glyph glyph-name="_617" unicode="&#xf292;" horiz-adv-x="1792" 
+d="M991 512l64 256h-254l-64 -256h254zM1759 1016l-56 -224q-7 -24 -31 -24h-327l-64 -256h311q15 0 25 -12q10 -14 6 -28l-56 -224q-5 -24 -31 -24h-327l-81 -328q-7 -24 -31 -24h-224q-16 0 -26 12q-9 12 -6 28l78 312h-254l-81 -328q-7 -24 -31 -24h-225q-15 0 -25 12
+q-9 12 -6 28l78 312h-311q-15 0 -25 12q-9 12 -6 28l56 224q7 24 31 24h327l64 256h-311q-15 0 -25 12q-10 14 -6 28l56 224q5 24 31 24h327l81 328q7 24 32 24h224q15 0 25 -12q9 -12 6 -28l-78 -312h254l81 328q7 24 32 24h224q15 0 25 -12q9 -12 6 -28l-78 -312h311
+q15 0 25 -12q9 -12 6 -28z" />
+    <glyph glyph-name="_618" unicode="&#xf293;" 
+d="M841 483l148 -148l-149 -149zM840 1094l149 -149l-148 -148zM710 -130l464 464l-306 306l306 306l-464 464v-611l-255 255l-93 -93l320 -321l-320 -321l93 -93l255 255v-611zM1429 640q0 -209 -32 -365.5t-87.5 -257t-140.5 -162.5t-181.5 -86.5t-219.5 -24.5
+t-219.5 24.5t-181.5 86.5t-140.5 162.5t-87.5 257t-32 365.5t32 365.5t87.5 257t140.5 162.5t181.5 86.5t219.5 24.5t219.5 -24.5t181.5 -86.5t140.5 -162.5t87.5 -257t32 -365.5z" />
+    <glyph glyph-name="_619" unicode="&#xf294;" horiz-adv-x="1024" 
+d="M596 113l173 172l-173 172v-344zM596 823l173 172l-173 172v-344zM628 640l356 -356l-539 -540v711l-297 -296l-108 108l372 373l-372 373l108 108l297 -296v711l539 -540z" />
+    <glyph glyph-name="_620" unicode="&#xf295;" 
+d="M1280 256q0 52 -38 90t-90 38t-90 -38t-38 -90t38 -90t90 -38t90 38t38 90zM512 1024q0 52 -38 90t-90 38t-90 -38t-38 -90t38 -90t90 -38t90 38t38 90zM1536 256q0 -159 -112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5t271.5 -112.5
+t112.5 -271.5zM1440 1344q0 -20 -13 -38l-1056 -1408q-19 -26 -51 -26h-160q-26 0 -45 19t-19 45q0 20 13 38l1056 1408q19 26 51 26h160q26 0 45 -19t19 -45zM768 1024q0 -159 -112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5
+t271.5 -112.5t112.5 -271.5z" />
+    <glyph glyph-name="_621" unicode="&#xf296;" horiz-adv-x="1792" 
+d="M104 830l792 -1015l-868 630q-18 13 -25 34.5t0 42.5l101 308v0zM566 830h660l-330 -1015v0zM368 1442l198 -612h-462l198 612q8 23 33 23t33 -23zM1688 830l101 -308q7 -21 0 -42.5t-25 -34.5l-868 -630l792 1015v0zM1688 830h-462l198 612q8 23 33 23t33 -23z" />
+    <glyph glyph-name="_622" unicode="&#xf297;" horiz-adv-x="1792" 
+d="M384 704h160v224h-160v-224zM1221 372v92q-104 -36 -243 -38q-135 -1 -259.5 46.5t-220.5 122.5l1 -96q88 -80 212 -128.5t272 -47.5q129 0 238 49zM640 704h640v224h-640v-224zM1792 736q0 -187 -99 -352q89 -102 89 -229q0 -157 -129.5 -268t-313.5 -111
+q-122 0 -225 52.5t-161 140.5q-19 -1 -57 -1t-57 1q-58 -88 -161 -140.5t-225 -52.5q-184 0 -313.5 111t-129.5 268q0 127 89 229q-99 165 -99 352q0 209 120 385.5t326.5 279.5t449.5 103t449.5 -103t326.5 -279.5t120 -385.5z" />
+    <glyph glyph-name="_623" unicode="&#xf298;" 
+d="M515 625v-128h-252v128h252zM515 880v-127h-252v127h252zM1273 369v-128h-341v128h341zM1273 625v-128h-672v128h672zM1273 880v-127h-672v127h672zM1408 20v1240q0 8 -6 14t-14 6h-32l-378 -256l-210 171l-210 -171l-378 256h-32q-8 0 -14 -6t-6 -14v-1240q0 -8 6 -14
+t14 -6h1240q8 0 14 6t6 14zM553 1130l185 150h-406zM983 1130l221 150h-406zM1536 1260v-1240q0 -62 -43 -105t-105 -43h-1240q-62 0 -105 43t-43 105v1240q0 62 43 105t105 43h1240q62 0 105 -43t43 -105z" />
+    <glyph glyph-name="_624" unicode="&#xf299;" horiz-adv-x="1792" 
+d="M896 720q-104 196 -160 278q-139 202 -347 318q-34 19 -70 36q-89 40 -94 32t34 -38l39 -31q62 -43 112.5 -93.5t94.5 -116.5t70.5 -113t70.5 -131q9 -17 13 -25q44 -84 84 -153t98 -154t115.5 -150t131 -123.5t148.5 -90.5q153 -66 154 -60q1 3 -49 37q-53 36 -81 57
+q-77 58 -179 211t-185 310zM549 177q-76 60 -132.5 125t-98 143.5t-71 154.5t-58.5 186t-52 209t-60.5 252t-76.5 289q273 0 497.5 -36t379 -92t271 -144.5t185.5 -172.5t110 -198.5t56 -199.5t12.5 -198.5t-9.5 -173t-20 -143.5t-13 -107l323 -327h-104l-281 285
+q-22 -2 -91.5 -14t-121.5 -19t-138 -6t-160.5 17t-167.5 59t-179 111z" />
+    <glyph glyph-name="_625" unicode="&#xf29a;" horiz-adv-x="1792" 
+d="M1374 879q-6 26 -28.5 39.5t-48.5 7.5q-261 -62 -401 -62t-401 62q-26 6 -48.5 -7.5t-28.5 -39.5t7.5 -48.5t39.5 -28.5q194 -46 303 -58q-2 -158 -15.5 -269t-26.5 -155.5t-41 -115.5l-9 -21q-10 -25 1 -49t36 -34q9 -4 23 -4q44 0 60 41l8 20q54 139 71 259h42
+q17 -120 71 -259l8 -20q16 -41 60 -41q14 0 23 4q25 10 36 34t1 49l-9 21q-28 71 -41 115.5t-26.5 155.5t-15.5 269q109 12 303 58q26 6 39.5 28.5t7.5 48.5zM1024 1024q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5z
+M1600 640q0 -143 -55.5 -273.5t-150 -225t-225 -150t-273.5 -55.5t-273.5 55.5t-225 150t-150 225t-55.5 273.5t55.5 273.5t150 225t225 150t273.5 55.5t273.5 -55.5t225 -150t150 -225t55.5 -273.5zM896 1408q-156 0 -298 -61t-245 -164t-164 -245t-61 -298t61 -298
+t164 -245t245 -164t298 -61t298 61t245 164t164 245t61 298t-61 298t-164 245t-245 164t-298 61zM1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
+    <glyph glyph-name="_626" unicode="&#xf29b;" 
+d="M1438 723q34 -35 29 -82l-44 -551q-4 -42 -34.5 -70t-71.5 -28q-6 0 -9 1q-44 3 -72.5 36.5t-25.5 77.5l35 429l-143 -8q55 -113 55 -240q0 -216 -148 -372l-137 137q91 101 91 235q0 145 -102.5 248t-247.5 103q-134 0 -236 -92l-137 138q120 114 284 141l264 300
+l-149 87l-181 -161q-33 -30 -77 -27.5t-73 35.5t-26.5 77t34.5 73l239 213q26 23 60 26.5t64 -14.5l488 -283q36 -21 48 -68q17 -67 -26 -117l-205 -232l371 20q49 3 83 -32zM1240 1180q-74 0 -126 52t-52 126t52 126t126 52t126.5 -52t52.5 -126t-52.5 -126t-126.5 -52z
+M613 -62q106 0 196 61l139 -139q-146 -116 -335 -116q-148 0 -273.5 73t-198.5 198t-73 273q0 188 116 336l139 -139q-60 -88 -60 -197q0 -145 102.5 -247.5t247.5 -102.5z" />
+    <glyph glyph-name="_627" unicode="&#xf29c;" 
+d="M880 336v-160q0 -14 -9 -23t-23 -9h-160q-14 0 -23 9t-9 23v160q0 14 9 23t23 9h160q14 0 23 -9t9 -23zM1136 832q0 -50 -15 -90t-45.5 -69t-52 -44t-59.5 -36q-32 -18 -46.5 -28t-26 -24t-11.5 -29v-32q0 -14 -9 -23t-23 -9h-160q-14 0 -23 9t-9 23v68q0 35 10.5 64.5
+t24 47.5t39 35.5t41 25.5t44.5 21q53 25 75 43t22 49q0 42 -43.5 71.5t-95.5 29.5q-56 0 -95 -27q-29 -20 -80 -83q-9 -12 -25 -12q-11 0 -19 6l-108 82q-10 7 -12 20t5 23q122 192 349 192q129 0 238.5 -89.5t109.5 -214.5zM768 1280q-130 0 -248.5 -51t-204 -136.5
+t-136.5 -204t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5t-51 248.5t-136.5 204t-204 136.5t-248.5 51zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5
+t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="_628" unicode="&#xf29d;" horiz-adv-x="1408" 
+d="M366 1225q-64 0 -110 45.5t-46 110.5q0 64 46 109.5t110 45.5t109.5 -45.5t45.5 -109.5q0 -65 -45.5 -110.5t-109.5 -45.5zM917 583q0 -50 -30 -67.5t-63.5 -6.5t-47.5 34l-367 438q-7 12 -14 15.5t-11 1.5l-3 -3q-7 -8 4 -21l122 -139l1 -354l-161 -457
+q-67 -192 -92 -234q-15 -26 -28 -32q-50 -26 -103 -1q-29 13 -41.5 43t-9.5 57q2 17 197 618l5 416l-85 -164l35 -222q4 -24 -1 -42t-14 -27.5t-19 -16t-17 -7.5l-7 -2q-19 -3 -34.5 3t-24 16t-14 22t-7.5 19.5t-2 9.5l-46 299l211 381q23 34 113 34q75 0 107 -40l424 -521
+q7 -5 14 -17l3 -3l-1 -1q7 -13 7 -29zM514 433q43 -113 88.5 -225t69.5 -168l24 -55q36 -93 42 -125q11 -70 -36 -97q-35 -22 -66 -16t-51 22t-29 35h-1q-6 16 -8 25l-124 351zM1338 -159q31 -49 31 -57q0 -5 -3 -7q-9 -5 -14.5 0.5t-15.5 26t-16 30.5q-114 172 -423 661
+q3 -1 7 1t7 4l3 2q11 9 11 17z" />
+    <glyph glyph-name="_629" unicode="&#xf29e;" horiz-adv-x="2304" 
+d="M504 542h171l-1 265zM1530 641q0 87 -50.5 140t-146.5 53h-54v-388h52q91 0 145 57t54 138zM956 1018l1 -756q0 -14 -9.5 -24t-23.5 -10h-216q-14 0 -23.5 10t-9.5 24v62h-291l-55 -81q-10 -15 -28 -15h-267q-21 0 -30.5 18t3.5 35l556 757q9 14 27 14h332q14 0 24 -10
+t10 -24zM1783 641q0 -193 -125.5 -303t-324.5 -110h-270q-14 0 -24 10t-10 24v756q0 14 10 24t24 10h268q200 0 326 -109t126 -302zM1939 640q0 -11 -0.5 -29t-8 -71.5t-21.5 -102t-44.5 -108t-73.5 -102.5h-51q38 45 66.5 104.5t41.5 112t21 98t9 72.5l1 27q0 8 -0.5 22.5
+t-7.5 60t-20 91.5t-41 111.5t-66 124.5h43q41 -47 72 -107t45.5 -111.5t23 -96t10.5 -70.5zM2123 640q0 -11 -0.5 -29t-8 -71.5t-21.5 -102t-45 -108t-74 -102.5h-51q38 45 66.5 104.5t41.5 112t21 98t9 72.5l1 27q0 8 -0.5 22.5t-7.5 60t-19.5 91.5t-40.5 111.5t-66 124.5
+h43q41 -47 72 -107t45.5 -111.5t23 -96t10.5 -70.5zM2304 640q0 -11 -0.5 -29t-8 -71.5t-21.5 -102t-44.5 -108t-73.5 -102.5h-51q38 45 66 104.5t41 112t21 98t9 72.5l1 27q0 8 -0.5 22.5t-7.5 60t-19.5 91.5t-40.5 111.5t-66 124.5h43q41 -47 72 -107t45.5 -111.5t23 -96
+t9.5 -70.5z" />
+    <glyph glyph-name="uniF2A0" unicode="&#xf2a0;" horiz-adv-x="1408" 
+d="M617 -153q0 11 -13 58t-31 107t-20 69q-1 4 -5 26.5t-8.5 36t-13.5 21.5q-15 14 -51 14q-23 0 -70 -5.5t-71 -5.5q-34 0 -47 11q-6 5 -11 15.5t-7.5 20t-6.5 24t-5 18.5q-37 128 -37 255t37 255q1 4 5 18.5t6.5 24t7.5 20t11 15.5q13 11 47 11q24 0 71 -5.5t70 -5.5
+q36 0 51 14q9 8 13.5 21.5t8.5 36t5 26.5q2 9 20 69t31 107t13 58q0 22 -43.5 52.5t-75.5 42.5q-20 8 -45 8q-34 0 -98 -18q-57 -17 -96.5 -40.5t-71 -66t-46 -70t-45.5 -94.5q-6 -12 -9 -19q-49 -107 -68 -216t-19 -244t19 -244t68 -216q56 -122 83 -161q63 -91 179 -127
+l6 -2q64 -18 98 -18q25 0 45 8q32 12 75.5 42.5t43.5 52.5zM776 760q-26 0 -45 19t-19 45.5t19 45.5q37 37 37 90q0 52 -37 91q-19 19 -19 45t19 45t45 19t45 -19q75 -75 75 -181t-75 -181q-21 -19 -45 -19zM957 579q-27 0 -45 19q-19 19 -19 45t19 45q112 114 112 272
+t-112 272q-19 19 -19 45t19 45t45 19t45 -19q150 -150 150 -362t-150 -362q-18 -19 -45 -19zM1138 398q-27 0 -45 19q-19 19 -19 45t19 45q90 91 138.5 208t48.5 245t-48.5 245t-138.5 208q-19 19 -19 45t19 45t45 19t45 -19q109 -109 167 -249t58 -294t-58 -294t-167 -249
+q-18 -19 -45 -19z" />
+    <glyph glyph-name="uniF2A1" unicode="&#xf2a1;" horiz-adv-x="2176" 
+d="M192 352q-66 0 -113 -47t-47 -113t47 -113t113 -47t113 47t47 113t-47 113t-113 47zM704 352q-66 0 -113 -47t-47 -113t47 -113t113 -47t113 47t47 113t-47 113t-113 47zM704 864q-66 0 -113 -47t-47 -113t47 -113t113 -47t113 47t47 113t-47 113t-113 47zM1472 352
+q-66 0 -113 -47t-47 -113t47 -113t113 -47t113 47t47 113t-47 113t-113 47zM1984 352q-66 0 -113 -47t-47 -113t47 -113t113 -47t113 47t47 113t-47 113t-113 47zM1472 864q-66 0 -113 -47t-47 -113t47 -113t113 -47t113 47t47 113t-47 113t-113 47zM1984 864
+q-66 0 -113 -47t-47 -113t47 -113t113 -47t113 47t47 113t-47 113t-113 47zM1984 1376q-66 0 -113 -47t-47 -113t47 -113t113 -47t113 47t47 113t-47 113t-113 47zM384 192q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM896 192q0 -80 -56 -136
+t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM384 704q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM896 704q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM384 1216q0 -80 -56 -136t-136 -56
+t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1664 192q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM896 1216q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM2176 192q0 -80 -56 -136t-136 -56t-136 56
+t-56 136t56 136t136 56t136 -56t56 -136zM1664 704q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM2176 704q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1664 1216q0 -80 -56 -136t-136 -56t-136 56t-56 136
+t56 136t136 56t136 -56t56 -136zM2176 1216q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136z" />
+    <glyph glyph-name="uniF2A2" unicode="&#xf2a2;" horiz-adv-x="1792" 
+d="M128 -192q0 -26 -19 -45t-45 -19t-45 19t-19 45t19 45t45 19t45 -19t19 -45zM320 0q0 -26 -19 -45t-45 -19t-45 19t-19 45t19 45t45 19t45 -19t19 -45zM365 365l256 -256l-90 -90l-256 256zM704 384q0 -26 -19 -45t-45 -19t-45 19t-19 45t19 45t45 19t45 -19t19 -45z
+M1411 704q0 -59 -11.5 -108.5t-37.5 -93.5t-44 -67.5t-53 -64.5q-31 -35 -45.5 -54t-33.5 -50t-26.5 -64t-7.5 -74q0 -159 -112.5 -271.5t-271.5 -112.5q-26 0 -45 19t-19 45t19 45t45 19q106 0 181 75t75 181q0 57 11.5 105.5t37 91t43.5 66.5t52 63q40 46 59.5 72
+t37.5 74.5t18 103.5q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5q0 -26 -19 -45t-45 -19t-45 19t-19 45q0 117 45.5 223.5t123 184t184 123t223.5 45.5t223.5 -45.5t184 -123t123 -184t45.5 -223.5zM896 576q0 -26 -19 -45t-45 -19t-45 19t-19 45t19 45
+t45 19t45 -19t19 -45zM1184 704q0 -26 -19 -45t-45 -19t-45 19t-19 45q0 93 -65.5 158.5t-158.5 65.5q-92 0 -158 -65.5t-66 -158.5q0 -26 -19 -45t-45 -19t-45 19t-19 45q0 146 103 249t249 103t249 -103t103 -249zM1578 993q10 -25 -1 -49t-36 -34q-9 -4 -23 -4
+q-19 0 -35.5 11t-23.5 30q-68 178 -224 295q-21 16 -25 42t12 47q17 21 43 25t47 -12q183 -137 266 -351zM1788 1074q9 -25 -1.5 -49t-35.5 -34q-11 -4 -23 -4q-44 0 -60 41q-92 238 -297 393q-22 16 -25.5 42t12.5 47q16 22 42 25.5t47 -12.5q235 -175 341 -449z" />
+    <glyph glyph-name="uniF2A3" unicode="&#xf2a3;" horiz-adv-x="2304" 
+d="M1032 576q-59 2 -84 55q-17 34 -48 53.5t-68 19.5q-53 0 -90.5 -37.5t-37.5 -90.5q0 -56 36 -89l10 -8q34 -31 82 -31q37 0 68 19.5t48 53.5q25 53 84 55zM1600 704q0 56 -36 89l-10 8q-34 31 -82 31q-37 0 -68 -19.5t-48 -53.5q-25 -53 -84 -55q59 -2 84 -55
+q17 -34 48 -53.5t68 -19.5q53 0 90.5 37.5t37.5 90.5zM1174 925q-17 -35 -55 -48t-73 4q-62 31 -134 31q-51 0 -99 -17q3 0 9.5 0.5t9.5 0.5q92 0 170.5 -50t118.5 -133q17 -36 3.5 -73.5t-49.5 -54.5q-18 -9 -39 -9q21 0 39 -9q36 -17 49.5 -54.5t-3.5 -73.5
+q-40 -83 -118.5 -133t-170.5 -50h-6q-16 2 -44 4l-290 27l-239 -120q-14 -7 -29 -7q-40 0 -57 35l-160 320q-11 23 -4 47.5t29 37.5l209 119l148 267q17 155 91.5 291.5t195.5 236.5q31 25 70.5 21.5t64.5 -34.5t21.5 -70t-34.5 -65q-70 -59 -117 -128q123 84 267 101
+q40 5 71.5 -19t35.5 -64q5 -40 -19 -71.5t-64 -35.5q-84 -10 -159 -55q46 10 99 10q115 0 218 -50q36 -18 49 -55.5t-5 -73.5zM2137 1085l160 -320q11 -23 4 -47.5t-29 -37.5l-209 -119l-148 -267q-17 -155 -91.5 -291.5t-195.5 -236.5q-26 -22 -61 -22q-45 0 -74 35
+q-25 31 -21.5 70t34.5 65q70 59 117 128q-123 -84 -267 -101q-4 -1 -12 -1q-36 0 -63.5 24t-31.5 60q-5 40 19 71.5t64 35.5q84 10 159 55q-46 -10 -99 -10q-115 0 -218 50q-36 18 -49 55.5t5 73.5q17 35 55 48t73 -4q62 -31 134 -31q51 0 99 17q-3 0 -9.5 -0.5t-9.5 -0.5
+q-92 0 -170.5 50t-118.5 133q-17 36 -3.5 73.5t49.5 54.5q18 9 39 9q-21 0 -39 9q-36 17 -49.5 54.5t3.5 73.5q40 83 118.5 133t170.5 50h6h1q14 -2 42 -4l291 -27l239 120q14 7 29 7q40 0 57 -35z" />
+    <glyph glyph-name="uniF2A4" unicode="&#xf2a4;" horiz-adv-x="1792" 
+d="M1056 704q0 -26 19 -45t45 -19t45 19t19 45q0 146 -103 249t-249 103t-249 -103t-103 -249q0 -26 19 -45t45 -19t45 19t19 45q0 93 66 158.5t158 65.5t158 -65.5t66 -158.5zM835 1280q-117 0 -223.5 -45.5t-184 -123t-123 -184t-45.5 -223.5q0 -26 19 -45t45 -19t45 19
+t19 45q0 185 131.5 316.5t316.5 131.5t316.5 -131.5t131.5 -316.5q0 -55 -18 -103.5t-37.5 -74.5t-59.5 -72q-34 -39 -52 -63t-43.5 -66.5t-37 -91t-11.5 -105.5q0 -106 -75 -181t-181 -75q-26 0 -45 -19t-19 -45t19 -45t45 -19q159 0 271.5 112.5t112.5 271.5q0 41 7.5 74
+t26.5 64t33.5 50t45.5 54q35 41 53 64.5t44 67.5t37.5 93.5t11.5 108.5q0 117 -45.5 223.5t-123 184t-184 123t-223.5 45.5zM591 561l226 -226l-579 -579q-12 -12 -29 -12t-29 12l-168 168q-12 12 -12 29t12 29zM1612 1524l168 -168q12 -12 12 -29t-12 -30l-233 -233
+l-26 -25l-71 -71q-66 153 -195 258l91 91l207 207q13 12 30 12t29 -12z" />
+    <glyph glyph-name="uniF2A5" unicode="&#xf2a5;" 
+d="M866 1021q0 -27 -13 -94q-11 -50 -31.5 -150t-30.5 -150q-2 -11 -4.5 -12.5t-13.5 -2.5q-20 -2 -31 -2q-58 0 -84 49.5t-26 113.5q0 88 35 174t103 124q28 14 51 14q28 0 36.5 -16.5t8.5 -47.5zM1352 597q0 14 -39 75.5t-52 66.5q-21 8 -34 8q-91 0 -226 -77l-2 2
+q3 22 27.5 135t24.5 178q0 233 -242 233q-24 0 -68 -6q-94 -17 -168.5 -89.5t-111.5 -166.5t-37 -189q0 -146 80.5 -225t227.5 -79q25 0 25 -3t-1 -5q-4 -34 -26 -117q-14 -52 -51.5 -101t-82.5 -49q-42 0 -42 47q0 24 10.5 47.5t25 39.5t29.5 28.5t26 20t11 8.5q0 3 -7 10
+q-24 22 -58.5 36.5t-65.5 14.5q-35 0 -63.5 -34t-41 -75t-12.5 -75q0 -88 51.5 -142t138.5 -54q82 0 155 53t117.5 126t65.5 153q6 22 15.5 66.5t14.5 66.5q3 12 14 18q118 60 227 60q48 0 127 -18q1 -1 4 -1q5 0 9.5 4.5t4.5 8.5zM1536 1120v-960q0 -119 -84.5 -203.5
+t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="uniF2A6" unicode="&#xf2a6;" horiz-adv-x="1535" 
+d="M744 1231q0 24 -2 38.5t-8.5 30t-21 23t-37.5 7.5q-39 0 -78 -23q-105 -58 -159 -190.5t-54 -269.5q0 -44 8.5 -85.5t26.5 -80.5t52.5 -62.5t81.5 -23.5q4 0 18 -0.5t20 0t16 3t15 8.5t7 16q16 77 48 231.5t48 231.5q19 91 19 146zM1498 575q0 -7 -7.5 -13.5t-15.5 -6.5
+l-6 1q-22 3 -62 11t-72 12.5t-63 4.5q-167 0 -351 -93q-15 -8 -21 -27q-10 -36 -24.5 -105.5t-22.5 -100.5q-23 -91 -70 -179.5t-112.5 -164.5t-154.5 -123t-185 -47q-135 0 -214.5 83.5t-79.5 219.5q0 53 19.5 117t63 116.5t97.5 52.5q38 0 120 -33.5t83 -61.5
+q0 -1 -16.5 -12.5t-39.5 -31t-46 -44.5t-39 -61t-16 -74q0 -33 16.5 -53t48.5 -20q45 0 85 31.5t66.5 78t48 105.5t32.5 107t16 90v9q0 2 -3.5 3.5t-8.5 1.5h-10t-10 -0.5t-6 -0.5q-227 0 -352 122.5t-125 348.5q0 108 34.5 221t96 210t156 167.5t204.5 89.5q52 9 106 9
+q374 0 374 -360q0 -98 -38 -273t-43 -211l3 -3q101 57 182.5 88t167.5 31q22 0 53 -13q19 -7 80 -102.5t61 -116.5z" />
+    <glyph glyph-name="uniF2A7" unicode="&#xf2a7;" horiz-adv-x="1664" 
+d="M831 863q32 0 59 -18l222 -148q61 -40 110 -97l146 -170q40 -46 29 -106l-72 -413q-6 -32 -29.5 -53.5t-55.5 -25.5l-527 -56l-352 -32h-9q-39 0 -67.5 28t-28.5 68q0 37 27 64t65 32l260 32h-448q-41 0 -69.5 30t-26.5 71q2 39 32 65t69 26l442 1l-521 64q-41 5 -66 37
+t-19 73q6 35 34.5 57.5t65.5 22.5h10l481 -60l-351 94q-38 10 -62 41.5t-18 68.5q6 36 33 58.5t62 22.5q6 0 20 -2l448 -96l217 -37q1 0 3 -0.5t3 -0.5q23 0 30.5 23t-12.5 36l-186 125q-35 23 -42 63.5t18 73.5q27 38 76 38zM761 661l186 -125l-218 37l-5 2l-36 38
+l-238 262q-1 1 -2.5 3.5t-2.5 3.5q-24 31 -18.5 70t37.5 64q31 23 68 17.5t64 -33.5l142 -147q-2 -1 -5 -3.5t-4 -4.5q-32 -45 -23 -99t55 -85zM1648 1115l15 -266q4 -73 -11 -147l-48 -219q-12 -59 -67 -87l-106 -54q2 62 -39 109l-146 170q-53 61 -117 103l-222 148
+q-34 23 -76 23q-51 0 -88 -37l-235 312q-25 33 -18 73.5t41 63.5q33 22 71.5 14t62.5 -40l266 -352l-262 455q-21 35 -10.5 75t47.5 59q35 18 72.5 6t57.5 -46l241 -420l-136 337q-15 35 -4.5 74t44.5 56q37 19 76 6t56 -51l193 -415l101 -196q8 -15 23 -17.5t27 7.5t11 26
+l-12 224q-2 41 26 71t69 31q39 0 67 -28.5t30 -67.5z" />
+    <glyph glyph-name="uniF2A8" unicode="&#xf2a8;" horiz-adv-x="1792" 
+d="M335 180q-2 0 -6 2q-86 57 -168.5 145t-139.5 180q-21 30 -21 69q0 9 2 19t4 18t7 18t8.5 16t10.5 17t10 15t12 15.5t11 14.5q184 251 452 365q-110 198 -110 211q0 19 17 29q116 64 128 64q18 0 28 -16l124 -229q92 19 192 19q266 0 497.5 -137.5t378.5 -369.5
+q20 -31 20 -69t-20 -69q-91 -142 -218.5 -253.5t-278.5 -175.5q110 -198 110 -211q0 -20 -17 -29q-116 -64 -127 -64q-19 0 -29 16l-124 229l-64 119l-444 820l7 7q-58 -24 -99 -47q3 -5 127 -234t243 -449t119 -223q0 -7 -9 -9q-13 -3 -72 -3q-57 0 -60 7l-456 841
+q-39 -28 -82 -68q24 -43 214 -393.5t190 -354.5q0 -10 -11 -10q-14 0 -82.5 22t-72.5 28l-106 197l-224 413q-44 -53 -78 -106q2 -3 18 -25t23 -34l176 -327q0 -10 -10 -10zM1165 282l49 -91q273 111 450 385q-180 277 -459 389q67 -64 103 -148.5t36 -176.5
+q0 -106 -47 -200.5t-132 -157.5zM848 896q0 -20 14 -34t34 -14q86 0 147 -61t61 -147q0 -20 14 -34t34 -14t34 14t14 34q0 126 -89 215t-215 89q-20 0 -34 -14t-14 -34zM1214 961l-9 4l7 -7z" />
+    <glyph glyph-name="uniF2A9" unicode="&#xf2a9;" horiz-adv-x="1280" 
+d="M1050 430q0 -215 -147 -374q-148 -161 -378 -161q-232 0 -378 161q-147 159 -147 374q0 147 68 270.5t189 196.5t268 73q96 0 182 -31q-32 -62 -39 -126q-66 28 -143 28q-167 0 -280.5 -123t-113.5 -291q0 -170 112.5 -288.5t281.5 -118.5t281 118.5t112 288.5
+q0 89 -32 166q66 13 123 49q41 -98 41 -212zM846 619q0 -192 -79.5 -345t-238.5 -253l-14 -1q-29 0 -62 5q83 32 146.5 102.5t99.5 154.5t58.5 189t30 192.5t7.5 178.5q0 69 -3 103q55 -160 55 -326zM791 947v-2q-73 214 -206 440q88 -59 142.5 -186.5t63.5 -251.5z
+M1035 744q-83 0 -160 75q218 120 290 247q19 37 21 56q-42 -94 -139.5 -166.5t-204.5 -97.5q-35 54 -35 113q0 37 17 79t43 68q46 44 157 74q59 16 106 58.5t74 100.5q74 -105 74 -253q0 -109 -24 -170q-32 -77 -88.5 -130.5t-130.5 -53.5z" />
+    <glyph glyph-name="uniF2AA" unicode="&#xf2aa;" 
+d="M1050 495q0 78 -28 147q-41 -25 -85 -34q22 -50 22 -114q0 -117 -77 -198.5t-193 -81.5t-193.5 81.5t-77.5 198.5q0 115 78 199.5t193 84.5q53 0 98 -19q4 43 27 87q-60 21 -125 21q-154 0 -257.5 -108.5t-103.5 -263.5t103.5 -261t257.5 -106t257.5 106.5t103.5 260.5z
+M872 850q2 -24 2 -71q0 -63 -5 -123t-20.5 -132.5t-40.5 -130t-68.5 -106t-100.5 -70.5q21 -3 42 -3h10q219 139 219 411q0 116 -38 225zM872 850q-4 80 -44 171.5t-98 130.5q92 -156 142 -302zM1207 955q0 102 -51 174q-41 -86 -124 -109q-69 -19 -109 -53.5t-40 -99.5
+q0 -40 24 -77q74 17 140.5 67t95.5 115q-4 -52 -74.5 -111.5t-138.5 -97.5q52 -52 110 -52q51 0 90 37t60 90q17 42 17 117zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5
+t84.5 -203.5z" />
+    <glyph glyph-name="uniF2AB" unicode="&#xf2ab;" 
+d="M1279 388q0 22 -22 27q-67 15 -118 59t-80 108q-7 19 -7 25q0 15 19.5 26t43 17t43 20.5t19.5 36.5q0 19 -18.5 31.5t-38.5 12.5q-12 0 -32 -8t-31 -8q-4 0 -12 2q5 95 5 114q0 79 -17 114q-36 78 -103 121.5t-152 43.5q-199 0 -275 -165q-17 -35 -17 -114q0 -19 5 -114
+q-4 -2 -14 -2q-12 0 -32 7.5t-30 7.5q-21 0 -38.5 -12t-17.5 -32q0 -21 19.5 -35.5t43 -20.5t43 -17t19.5 -26q0 -6 -7 -25q-64 -138 -198 -167q-22 -5 -22 -27q0 -46 137 -68q2 -5 6 -26t11.5 -30.5t23.5 -9.5q12 0 37.5 4.5t39.5 4.5q35 0 67 -15t54 -32.5t57.5 -32.5
+t76.5 -15q43 0 79 15t57.5 32.5t53.5 32.5t67 15q14 0 39.5 -4t38.5 -4q16 0 23 10t11 30t6 25q137 22 137 68zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5
+t103 -385.5z" />
+    <glyph glyph-name="uniF2AC" unicode="&#xf2ac;" horiz-adv-x="1664" 
+d="M848 1408q134 1 240.5 -68.5t163.5 -192.5q27 -58 27 -179q0 -47 -9 -191q14 -7 28 -7q18 0 51 13.5t51 13.5q29 0 56 -18t27 -46q0 -32 -31.5 -54t-69 -31.5t-69 -29t-31.5 -47.5q0 -15 12 -43q37 -82 102.5 -150t144.5 -101q28 -12 80 -23q28 -6 28 -35
+q0 -70 -219 -103q-7 -11 -11 -39t-14 -46.5t-33 -18.5q-20 0 -62 6.5t-64 6.5q-37 0 -62 -5q-32 -5 -63 -22.5t-58 -38t-58 -40.5t-76 -33.5t-99 -13.5q-52 0 -96.5 13.5t-75 33.5t-57.5 40.5t-58 38t-62 22.5q-26 5 -63 5q-24 0 -65.5 -7.5t-58.5 -7.5q-25 0 -35 18.5
+t-14 47.5t-11 40q-219 33 -219 103q0 29 28 35q52 11 80 23q78 32 144.5 101t102.5 150q12 28 12 43q0 28 -31.5 47.5t-69.5 29.5t-69.5 31.5t-31.5 52.5q0 27 26 45.5t55 18.5q15 0 48 -13t53 -13q18 0 32 7q-9 142 -9 190q0 122 27 180q64 137 172 198t264 63z" />
+    <glyph glyph-name="uniF2AD" unicode="&#xf2ad;" 
+d="M1280 388q0 22 -22 27q-67 14 -118 58t-80 109q-7 14 -7 25q0 15 19.5 26t42.5 17t42.5 20.5t19.5 36.5q0 19 -18.5 31.5t-38.5 12.5q-11 0 -31 -8t-32 -8q-4 0 -12 2q5 63 5 115q0 78 -17 114q-36 78 -102.5 121.5t-152.5 43.5q-198 0 -275 -165q-18 -38 -18 -115
+q0 -38 6 -114q-10 -2 -15 -2q-11 0 -31.5 8t-30.5 8q-20 0 -37.5 -12.5t-17.5 -32.5q0 -21 19.5 -35.5t42.5 -20.5t42.5 -17t19.5 -26q0 -11 -7 -25q-64 -138 -198 -167q-22 -5 -22 -27q0 -47 138 -69q2 -5 6 -26t11 -30.5t23 -9.5q13 0 38.5 5t38.5 5q35 0 67.5 -15
+t54.5 -32.5t57.5 -32.5t76.5 -15q43 0 79 15t57.5 32.5t54 32.5t67.5 15q13 0 39 -4.5t39 -4.5q15 0 22.5 9.5t11.5 31t5 24.5q138 22 138 69zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960
+q119 0 203.5 -84.5t84.5 -203.5z" />
+    <glyph glyph-name="uniF2AE" unicode="&#xf2ae;" horiz-adv-x="2304" 
+d="M2304 1536q-69 -46 -125 -92t-89 -81t-59.5 -71.5t-37.5 -57.5t-22 -44.5t-14 -29.5q-10 -18 -35.5 -136.5t-48.5 -164.5q-15 -29 -50 -60.5t-67.5 -50.5t-72.5 -41t-48 -28q-47 -31 -151 -231q-341 14 -630 -158q-92 -53 -303 -179q47 16 86 31t55 22l15 7
+q71 27 163 64.5t133.5 53.5t108 34.5t142.5 31.5q186 31 465 -7q1 0 10 -3q11 -6 14 -17t-3 -22l-194 -345q-15 -29 -47 -22q-128 24 -354 24q-146 0 -402 -44.5t-392 -46.5q-82 -1 -149 13t-107 37t-61 40t-33 34l-1 1v2q0 6 6 6q138 0 371 55q192 366 374.5 524t383.5 158
+q5 0 14.5 -0.5t38 -5t55 -12t61.5 -24.5t63 -39.5t54 -59t40 -82.5l102 177q2 4 21 42.5t44.5 86.5t61 109.5t84 133.5t100.5 137q66 82 128 141.5t121.5 96.5t92.5 53.5t88 39.5z" />
+    <glyph glyph-name="uniF2B0" unicode="&#xf2b0;" 
+d="M1322 640q0 -45 -5 -76l-236 14l224 -78q-19 -73 -58 -141l-214 103l177 -158q-44 -61 -107 -108l-157 178l103 -215q-61 -37 -140 -59l-79 228l14 -240q-38 -6 -76 -6t-76 6l14 238l-78 -226q-74 19 -140 59l103 215l-157 -178q-59 43 -108 108l178 158l-214 -104
+q-39 69 -58 141l224 79l-237 -14q-5 42 -5 76q0 35 5 77l238 -14l-225 79q19 73 58 140l214 -104l-177 159q46 61 107 108l158 -178l-103 215q67 39 140 58l77 -224l-13 236q36 6 75 6q38 0 76 -6l-14 -237l78 225q74 -19 140 -59l-103 -214l158 178q61 -47 107 -108
+l-177 -159l213 104q37 -62 58 -141l-224 -78l237 14q5 -31 5 -77zM1352 640q0 160 -78.5 295.5t-213 214t-292.5 78.5q-119 0 -227 -46.5t-186.5 -125t-124.5 -187.5t-46 -229q0 -119 46 -228t124.5 -187.5t186.5 -125t227 -46.5q158 0 292.5 78.5t213 214t78.5 294.5z
+M1425 1023v-766l-657 -383l-657 383v766l657 383zM768 -183l708 412v823l-708 411l-708 -411v-823zM1536 1088v-896l-768 -448l-768 448v896l768 448z" />
+    <glyph glyph-name="uniF2B1" unicode="&#xf2b1;" horiz-adv-x="1664" 
+d="M339 1318h691l-26 -72h-665q-110 0 -188.5 -79t-78.5 -189v-771q0 -95 60.5 -169.5t153.5 -93.5q23 -5 98 -5v-72h-45q-140 0 -239.5 100t-99.5 240v771q0 140 99.5 240t239.5 100zM1190 1536h247l-482 -1294q-23 -61 -40.5 -103.5t-45 -98t-54 -93.5t-64.5 -78.5
+t-79.5 -65t-95.5 -41t-116 -18.5v195q163 26 220 182q20 52 20 105q0 54 -20 106l-285 733h228l187 -585zM1664 978v-1111h-795q37 55 45 73h678v1038q0 85 -49.5 155t-129.5 99l25 67q101 -34 163.5 -123.5t62.5 -197.5z" />
+    <glyph glyph-name="uniF2B2" unicode="&#xf2b2;" horiz-adv-x="1792" 
+d="M852 1227q0 -29 -17 -52.5t-45 -23.5t-45 23.5t-17 52.5t17 52.5t45 23.5t45 -23.5t17 -52.5zM688 -149v114q0 30 -20.5 51.5t-50.5 21.5t-50 -21.5t-20 -51.5v-114q0 -30 20.5 -52t49.5 -22q30 0 50.5 22t20.5 52zM860 -149v114q0 30 -20 51.5t-50 21.5t-50.5 -21.5
+t-20.5 -51.5v-114q0 -30 20.5 -52t50.5 -22q29 0 49.5 22t20.5 52zM1034 -149v114q0 30 -20.5 51.5t-50.5 21.5t-50.5 -21.5t-20.5 -51.5v-114q0 -30 20.5 -52t50.5 -22t50.5 22t20.5 52zM1208 -149v114q0 30 -20.5 51.5t-50.5 21.5t-50.5 -21.5t-20.5 -51.5v-114
+q0 -30 20.5 -52t50.5 -22t50.5 22t20.5 52zM1476 535q-84 -160 -232 -259.5t-323 -99.5q-123 0 -229.5 51.5t-178.5 137t-113 197.5t-41 232q0 88 21 174q-104 -175 -104 -390q0 -162 65 -312t185 -251q30 57 91 57q56 0 86 -50q32 50 87 50q56 0 86 -50q32 50 87 50t87 -50
+q30 50 86 50q28 0 52.5 -15.5t37.5 -40.5q112 94 177 231.5t73 287.5zM1326 564q0 75 -72 75q-17 0 -47 -6q-95 -19 -149 -19q-226 0 -226 243q0 86 30 204q-83 -127 -83 -275q0 -150 89 -260.5t235 -110.5q111 0 210 70q13 48 13 79zM884 1223q0 50 -32 89.5t-81 39.5
+t-81 -39.5t-32 -89.5q0 -51 31.5 -90.5t81.5 -39.5t81.5 39.5t31.5 90.5zM1513 884q0 96 -37.5 179t-113 137t-173.5 54q-77 0 -149 -35t-127 -94q-48 -159 -48 -268q0 -104 45.5 -157t147.5 -53q53 0 142 19q36 6 53 6q51 0 77.5 -28t26.5 -80q0 -26 -4 -46
+q75 68 117.5 165.5t42.5 200.5zM1792 667q0 -111 -33.5 -249.5t-93.5 -204.5q-58 -64 -195 -142.5t-228 -104.5l-4 -1v-114q0 -43 -29.5 -75t-72.5 -32q-56 0 -86 50q-32 -50 -87 -50t-87 50q-30 -50 -86 -50q-55 0 -87 50q-30 -50 -86 -50q-47 0 -75 33.5t-28 81.5
+q-90 -68 -198 -68q-118 0 -211 80q54 1 106 20q-113 31 -182 127q32 -7 71 -7q89 0 164 46q-192 192 -240 306q-24 56 -24 160q0 57 9 125.5t31.5 146.5t55 141t86.5 105t120 42q59 0 81 -52q19 29 42 54q2 3 12 13t13 16q10 15 23 38t25 42t28 39q87 111 211.5 177
+t260.5 66q35 0 62 -4q59 64 146 64q83 0 140 -57q5 -5 5 -12q0 -5 -6 -13.5t-12.5 -16t-16 -17l-10.5 -10.5q17 -6 36 -18t19 -24q0 -6 -16 -25q157 -138 197 -378q25 30 60 30q45 0 100 -49q90 -80 90 -279z" />
+    <glyph glyph-name="uniF2B3" unicode="&#xf2b3;" 
+d="M917 631q0 33 -6 64h-362v-132h217q-12 -76 -74.5 -120.5t-142.5 -44.5q-99 0 -169 71.5t-70 170.5t70 170.5t169 71.5q93 0 153 -59l104 101q-108 100 -257 100q-160 0 -272 -112.5t-112 -271.5t112 -271.5t272 -112.5q165 0 266.5 105t101.5 270zM1262 585h109v110
+h-109v110h-110v-110h-110v-110h110v-110h110v110zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+    <glyph glyph-name="uniF2B4" unicode="&#xf2b4;" 
+d="M1536 1024v-839q0 -48 -49 -62q-174 -52 -338 -52q-73 0 -215.5 29.5t-227.5 29.5q-164 0 -370 -48v-338h-160v1368q-63 25 -101 81t-38 124q0 91 64 155t155 64t155 -64t64 -155q0 -68 -38 -124t-101 -81v-68q190 44 343 44q99 0 198 -15q14 -2 111.5 -22.5t149.5 -20.5
+q77 0 165 18q11 2 80 21t89 19q26 0 45 -19t19 -45z" />
+    <glyph glyph-name="uniF2B5" unicode="&#xf2b5;" horiz-adv-x="2304" 
+d="M192 384q40 0 56 32t0 64t-56 32t-56 -32t0 -64t56 -32zM1665 442q-10 13 -38.5 50t-41.5 54t-38 49t-42.5 53t-40.5 47t-45 49l-125 -140q-83 -94 -208.5 -92t-205.5 98q-57 69 -56.5 158t58.5 157l177 206q-22 11 -51 16.5t-47.5 6t-56.5 -0.5t-49 -1q-92 0 -158 -66
+l-158 -158h-155v-544q5 0 21 0.5t22 0t19.5 -2t20.5 -4.5t17.5 -8.5t18.5 -13.5l297 -292q115 -111 227 -111q78 0 125 47q57 -20 112.5 8t72.5 85q74 -6 127 44q20 18 36 45.5t14 50.5q10 -10 43 -10q43 0 77 21t49.5 53t12 71.5t-30.5 73.5zM1824 384h96v512h-93l-157 180
+q-66 76 -169 76h-167q-89 0 -146 -67l-209 -243q-28 -33 -28 -75t27 -75q43 -51 110 -52t111 49l193 218q25 23 53.5 21.5t47 -27t8.5 -56.5q16 -19 56 -63t60 -68q29 -36 82.5 -105.5t64.5 -84.5q52 -66 60 -140zM2112 384q40 0 56 32t0 64t-56 32t-56 -32t0 -64t56 -32z
+M2304 960v-640q0 -26 -19 -45t-45 -19h-434q-27 -65 -82 -106.5t-125 -51.5q-33 -48 -80.5 -81.5t-102.5 -45.5q-42 -53 -104.5 -81.5t-128.5 -24.5q-60 -34 -126 -39.5t-127.5 14t-117 53.5t-103.5 81l-287 282h-358q-26 0 -45 19t-19 45v672q0 26 19 45t45 19h421
+q14 14 47 48t47.5 48t44 40t50.5 37.5t51 25.5t62 19.5t68 5.5h117q99 0 181 -56q82 56 181 56h167q35 0 67 -6t56.5 -14.5t51.5 -26.5t44.5 -31t43 -39.5t39 -42t41 -48t41.5 -48.5h355q26 0 45 -19t19 -45z" />
+    <glyph glyph-name="uniF2B6" unicode="&#xf2b6;" horiz-adv-x="1792" 
+d="M1792 882v-978q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v978q0 15 11 24q8 7 39 34.5t41.5 36t45.5 37.5t70 55.5t96 73t143.5 107t192.5 140.5q5 4 52.5 40t71.5 52.5t64 35t69 18.5t69 -18.5t65 -35.5t71 -52t52 -40q110 -80 192.5 -140.5t143.5 -107
+t96 -73t70 -55.5t45.5 -37.5t41.5 -36t39 -34.5q11 -9 11 -24zM1228 297q263 191 345 252q11 8 12.5 20.5t-6.5 23.5l-38 52q-8 11 -21 12.5t-24 -6.5q-231 -169 -343 -250q-5 -3 -52 -39t-71.5 -52.5t-64.5 -35t-69 -18.5t-69 18.5t-64.5 35t-71.5 52.5t-52 39
+q-186 134 -343 250q-11 8 -24 6.5t-21 -12.5l-38 -52q-8 -11 -6.5 -23.5t12.5 -20.5q82 -61 345 -252q10 -8 50 -38t65 -47t64 -39.5t77.5 -33.5t75.5 -11t75.5 11t79 34.5t64.5 39.5t65 47.5t48 36.5z" />
+    <glyph glyph-name="uniF2B7" unicode="&#xf2b7;" horiz-adv-x="1792" 
+d="M1474 623l39 -51q8 -11 6.5 -23.5t-11.5 -20.5q-43 -34 -126.5 -98.5t-146.5 -113t-67 -51.5q-39 -32 -60 -48t-60.5 -41t-76.5 -36.5t-74 -11.5h-1h-1q-37 0 -74 11.5t-76 36.5t-61 41.5t-60 47.5q-5 4 -65 50.5t-143.5 111t-122.5 94.5q-11 8 -12.5 20.5t6.5 23.5
+l37 52q8 11 21.5 13t24.5 -7q94 -73 306 -236q5 -4 43.5 -35t60.5 -46.5t56.5 -32.5t58.5 -17h1h1q24 0 58.5 17t56.5 32.5t60.5 46.5t43.5 35q258 198 313 242q11 8 24 6.5t21 -12.5zM1664 -96v928q-90 83 -159 139q-91 74 -389 304q-3 2 -43 35t-61 48t-56 32.5t-59 17.5
+h-1h-1q-24 0 -59 -17.5t-56 -32.5t-61 -48t-43 -35q-215 -166 -315.5 -245.5t-129.5 -104t-82 -74.5q-14 -12 -21 -19v-928q0 -13 9.5 -22.5t22.5 -9.5h1472q13 0 22.5 9.5t9.5 22.5zM1792 832v-928q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v928q0 56 41 94
+q123 114 350 290.5t233 181.5q36 30 59 47.5t61.5 42t76 36.5t74.5 12h1h1q37 0 74.5 -12t76 -36.5t61.5 -42t59 -47.5q43 -36 156 -122t226 -177t201 -173q41 -38 41 -94z" />
+    <glyph glyph-name="uniF2B8" unicode="&#xf2b8;" 
+d="M330 1l202 -214l-34 236l-216 213zM556 -225l274 218l-11 245l-300 -215zM245 413l227 -213l-48 327l-245 204zM495 189l317 214l-14 324l-352 -200zM843 178l95 -80l-2 239l-103 79q0 -1 1 -8.5t0 -12t-5 -7.5l-78 -52l85 -70q7 -6 7 -88zM138 930l256 -200l-68 465
+l-279 173zM1173 267l15 234l-230 -164l2 -240zM417 722l373 194l-19 441l-423 -163zM1270 357l20 233l-226 142l-2 -105l144 -95q6 -4 4 -9l-7 -119zM1461 496l30 222l-179 -128l-20 -228zM1273 329l-71 49l-8 -117q0 -5 -4 -8l-234 -187q-7 -5 -14 0l-98 83l7 -161
+q0 -5 -4 -8l-293 -234q-4 -2 -6 -2q-8 2 -8 3l-228 242q-4 4 -59 277q-2 7 5 11l61 37q-94 86 -95 92l-72 351q-2 7 6 12l94 45q-133 100 -135 108l-96 466q-2 10 7 13l433 135q5 0 8 -1l317 -153q6 -4 6 -9l20 -463q0 -7 -6 -10l-118 -61l126 -85q5 -2 5 -8l5 -123l121 74
+q5 4 11 0l84 -56l3 110q0 6 5 9l206 126q6 3 11 0l245 -135q4 -4 5 -7t-6.5 -60t-17.5 -124.5t-10 -70.5q0 -5 -4 -7l-191 -153q-6 -5 -13 0z" />
+    <glyph glyph-name="uniF2B9" unicode="&#xf2b9;" horiz-adv-x="1664" 
+d="M1201 298q0 57 -5.5 107t-21 100.5t-39.5 86t-64 58t-91 22.5q-6 -4 -33.5 -20.5t-42.5 -24.5t-40.5 -20t-49 -17t-46.5 -5t-46.5 5t-49 17t-40.5 20t-42.5 24.5t-33.5 20.5q-51 0 -91 -22.5t-64 -58t-39.5 -86t-21 -100.5t-5.5 -107q0 -73 42 -121.5t103 -48.5h576
+q61 0 103 48.5t42 121.5zM1028 892q0 108 -76.5 184t-183.5 76t-183.5 -76t-76.5 -184q0 -107 76.5 -183t183.5 -76t183.5 76t76.5 183zM1664 352v-192q0 -14 -9 -23t-23 -9h-96v-224q0 -66 -47 -113t-113 -47h-1216q-66 0 -113 47t-47 113v1472q0 66 47 113t113 47h1216
+q66 0 113 -47t47 -113v-224h96q14 0 23 -9t9 -23v-192q0 -14 -9 -23t-23 -9h-96v-128h96q14 0 23 -9t9 -23v-192q0 -14 -9 -23t-23 -9h-96v-128h96q14 0 23 -9t9 -23z" />
+    <glyph glyph-name="uniF2BA" unicode="&#xf2ba;" horiz-adv-x="1664" 
+d="M1028 892q0 -107 -76.5 -183t-183.5 -76t-183.5 76t-76.5 183q0 108 76.5 184t183.5 76t183.5 -76t76.5 -184zM980 672q46 0 82.5 -17t60 -47.5t39.5 -67t24 -81t11.5 -82.5t3.5 -79q0 -67 -39.5 -118.5t-105.5 -51.5h-576q-66 0 -105.5 51.5t-39.5 118.5q0 48 4.5 93.5
+t18.5 98.5t36.5 91.5t63 64.5t93.5 26h5q7 -4 32 -19.5t35.5 -21t33 -17t37 -16t35 -9t39.5 -4.5t39.5 4.5t35 9t37 16t33 17t35.5 21t32 19.5zM1664 928q0 -13 -9.5 -22.5t-22.5 -9.5h-96v-128h96q13 0 22.5 -9.5t9.5 -22.5v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-96v-128h96
+q13 0 22.5 -9.5t9.5 -22.5v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-96v-224q0 -66 -47 -113t-113 -47h-1216q-66 0 -113 47t-47 113v1472q0 66 47 113t113 47h1216q66 0 113 -47t47 -113v-224h96q13 0 22.5 -9.5t9.5 -22.5v-192zM1408 -96v1472q0 13 -9.5 22.5t-22.5 9.5h-1216
+q-13 0 -22.5 -9.5t-9.5 -22.5v-1472q0 -13 9.5 -22.5t22.5 -9.5h1216q13 0 22.5 9.5t9.5 22.5z" />
+    <glyph glyph-name="uniF2BB" unicode="&#xf2bb;" horiz-adv-x="2048" 
+d="M1024 405q0 64 -9 117.5t-29.5 103t-60.5 78t-97 28.5q-6 -4 -30 -18t-37.5 -21.5t-35.5 -17.5t-43 -14.5t-42 -4.5t-42 4.5t-43 14.5t-35.5 17.5t-37.5 21.5t-30 18q-57 0 -97 -28.5t-60.5 -78t-29.5 -103t-9 -117.5t37 -106.5t91 -42.5h512q54 0 91 42.5t37 106.5z
+M867 925q0 94 -66.5 160.5t-160.5 66.5t-160.5 -66.5t-66.5 -160.5t66.5 -160.5t160.5 -66.5t160.5 66.5t66.5 160.5zM1792 416v64q0 14 -9 23t-23 9h-576q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h576q14 0 23 9t9 23zM1792 676v56q0 15 -10.5 25.5t-25.5 10.5h-568
+q-15 0 -25.5 -10.5t-10.5 -25.5v-56q0 -15 10.5 -25.5t25.5 -10.5h568q15 0 25.5 10.5t10.5 25.5zM1792 928v64q0 14 -9 23t-23 9h-576q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h576q14 0 23 9t9 23zM2048 1248v-1216q0 -66 -47 -113t-113 -47h-352v96q0 14 -9 23t-23 9
+h-64q-14 0 -23 -9t-9 -23v-96h-768v96q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-96h-352q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1728q66 0 113 -47t47 -113z" />
+    <glyph glyph-name="uniF2BC" unicode="&#xf2bc;" horiz-adv-x="2048" 
+d="M1024 405q0 -64 -37 -106.5t-91 -42.5h-512q-54 0 -91 42.5t-37 106.5t9 117.5t29.5 103t60.5 78t97 28.5q6 -4 30 -18t37.5 -21.5t35.5 -17.5t43 -14.5t42 -4.5t42 4.5t43 14.5t35.5 17.5t37.5 21.5t30 18q57 0 97 -28.5t60.5 -78t29.5 -103t9 -117.5zM867 925
+q0 -94 -66.5 -160.5t-160.5 -66.5t-160.5 66.5t-66.5 160.5t66.5 160.5t160.5 66.5t160.5 -66.5t66.5 -160.5zM1792 480v-64q0 -14 -9 -23t-23 -9h-576q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h576q14 0 23 -9t9 -23zM1792 732v-56q0 -15 -10.5 -25.5t-25.5 -10.5h-568
+q-15 0 -25.5 10.5t-10.5 25.5v56q0 15 10.5 25.5t25.5 10.5h568q15 0 25.5 -10.5t10.5 -25.5zM1792 992v-64q0 -14 -9 -23t-23 -9h-576q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h576q14 0 23 -9t9 -23zM1920 32v1216q0 13 -9.5 22.5t-22.5 9.5h-1728q-13 0 -22.5 -9.5
+t-9.5 -22.5v-1216q0 -13 9.5 -22.5t22.5 -9.5h352v96q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-96h768v96q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-96h352q13 0 22.5 9.5t9.5 22.5zM2048 1248v-1216q0 -66 -47 -113t-113 -47h-1728q-66 0 -113 47t-47 113v1216q0 66 47 113
+t113 47h1728q66 0 113 -47t47 -113z" />
+    <glyph glyph-name="uniF2BD" unicode="&#xf2bd;" horiz-adv-x="1792" 
+d="M1523 197q-22 155 -87.5 257.5t-184.5 118.5q-67 -74 -159.5 -115.5t-195.5 -41.5t-195.5 41.5t-159.5 115.5q-119 -16 -184.5 -118.5t-87.5 -257.5q106 -150 271 -237.5t356 -87.5t356 87.5t271 237.5zM1280 896q0 159 -112.5 271.5t-271.5 112.5t-271.5 -112.5
+t-112.5 -271.5t112.5 -271.5t271.5 -112.5t271.5 112.5t112.5 271.5zM1792 640q0 -182 -71 -347.5t-190.5 -286t-285.5 -191.5t-349 -71q-182 0 -348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
+    <glyph glyph-name="uniF2BE" unicode="&#xf2be;" horiz-adv-x="1792" 
+d="M896 1536q182 0 348 -71t286 -191t191 -286t71 -348q0 -181 -70.5 -347t-190.5 -286t-286 -191.5t-349 -71.5t-349 71t-285.5 191.5t-190.5 286t-71 347.5t71 348t191 286t286 191t348 71zM1515 185q149 205 149 455q0 156 -61 298t-164 245t-245 164t-298 61t-298 -61
+t-245 -164t-164 -245t-61 -298q0 -250 149 -455q66 327 306 327q131 -128 313 -128t313 128q240 0 306 -327zM1280 832q0 159 -112.5 271.5t-271.5 112.5t-271.5 -112.5t-112.5 -271.5t112.5 -271.5t271.5 -112.5t271.5 112.5t112.5 271.5z" />
+    <glyph glyph-name="uniF2C0" unicode="&#xf2c0;" 
+d="M1201 752q47 -14 89.5 -38t89 -73t79.5 -115.5t55 -172t22 -236.5q0 -154 -100 -263.5t-241 -109.5h-854q-141 0 -241 109.5t-100 263.5q0 131 22 236.5t55 172t79.5 115.5t89 73t89.5 38q-79 125 -79 272q0 104 40.5 198.5t109.5 163.5t163.5 109.5t198.5 40.5
+t198.5 -40.5t163.5 -109.5t109.5 -163.5t40.5 -198.5q0 -147 -79 -272zM768 1408q-159 0 -271.5 -112.5t-112.5 -271.5t112.5 -271.5t271.5 -112.5t271.5 112.5t112.5 271.5t-112.5 271.5t-271.5 112.5zM1195 -128q88 0 150.5 71.5t62.5 173.5q0 239 -78.5 377t-225.5 145
+q-145 -127 -336 -127t-336 127q-147 -7 -225.5 -145t-78.5 -377q0 -102 62.5 -173.5t150.5 -71.5h854z" />
+    <glyph glyph-name="uniF2C1" unicode="&#xf2c1;" horiz-adv-x="1280" 
+d="M1024 278q0 -64 -37 -107t-91 -43h-512q-54 0 -91 43t-37 107t9 118t29.5 104t61 78.5t96.5 28.5q80 -75 188 -75t188 75q56 0 96.5 -28.5t61 -78.5t29.5 -104t9 -118zM870 797q0 -94 -67.5 -160.5t-162.5 -66.5t-162.5 66.5t-67.5 160.5t67.5 160.5t162.5 66.5
+t162.5 -66.5t67.5 -160.5zM1152 -96v1376h-1024v-1376q0 -13 9.5 -22.5t22.5 -9.5h960q13 0 22.5 9.5t9.5 22.5zM1280 1376v-1472q0 -66 -47 -113t-113 -47h-960q-66 0 -113 47t-47 113v1472q0 66 47 113t113 47h352v-96q0 -14 9 -23t23 -9h192q14 0 23 9t9 23v96h352
+q66 0 113 -47t47 -113z" />
+    <glyph glyph-name="uniF2C2" unicode="&#xf2c2;" horiz-adv-x="2048" 
+d="M896 324q0 54 -7.5 100.5t-24.5 90t-51 68.5t-81 25q-64 -64 -156 -64t-156 64q-47 0 -81 -25t-51 -68.5t-24.5 -90t-7.5 -100.5q0 -55 31.5 -93.5t75.5 -38.5h426q44 0 75.5 38.5t31.5 93.5zM768 768q0 80 -56 136t-136 56t-136 -56t-56 -136t56 -136t136 -56t136 56
+t56 136zM1792 288v64q0 14 -9 23t-23 9h-704q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h704q14 0 23 9t9 23zM1408 544v64q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1792 544v64q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23
+v-64q0 -14 9 -23t23 -9h192q14 0 23 9t9 23zM1792 800v64q0 14 -9 23t-23 9h-704q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h704q14 0 23 9t9 23zM128 1152h1792v96q0 14 -9 23t-23 9h-1728q-14 0 -23 -9t-9 -23v-96zM2048 1248v-1216q0 -66 -47 -113t-113 -47h-1728
+q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1728q66 0 113 -47t47 -113z" />
+    <glyph glyph-name="uniF2C3" unicode="&#xf2c3;" horiz-adv-x="2048" 
+d="M896 324q0 -55 -31.5 -93.5t-75.5 -38.5h-426q-44 0 -75.5 38.5t-31.5 93.5q0 54 7.5 100.5t24.5 90t51 68.5t81 25q64 -64 156 -64t156 64q47 0 81 -25t51 -68.5t24.5 -90t7.5 -100.5zM768 768q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136z
+M1792 352v-64q0 -14 -9 -23t-23 -9h-704q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h704q14 0 23 -9t9 -23zM1408 608v-64q0 -14 -9 -23t-23 -9h-320q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h320q14 0 23 -9t9 -23zM1792 608v-64q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v64
+q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1792 864v-64q0 -14 -9 -23t-23 -9h-704q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h704q14 0 23 -9t9 -23zM1920 32v1120h-1792v-1120q0 -13 9.5 -22.5t22.5 -9.5h1728q13 0 22.5 9.5t9.5 22.5zM2048 1248v-1216q0 -66 -47 -113t-113 -47
+h-1728q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1728q66 0 113 -47t47 -113z" />
+    <glyph glyph-name="uniF2C4" unicode="&#xf2c4;" horiz-adv-x="1792" 
+d="M1255 749q0 318 -105 474.5t-330 156.5q-222 0 -326 -157t-104 -474q0 -316 104 -471.5t326 -155.5q74 0 131 17q-22 43 -39 73t-44 65t-53.5 56.5t-63 36t-77.5 14.5q-46 0 -79 -16l-49 97q105 91 276 91q132 0 215.5 -54t150.5 -155q67 149 67 402zM1645 117h117
+q3 -27 -2 -67t-26.5 -95t-58 -100.5t-107 -78t-162.5 -32.5q-71 0 -130.5 19t-105.5 56t-79 78t-66 96q-97 -27 -205 -27q-150 0 -292.5 58t-253 158.5t-178 249t-67.5 317.5q0 170 67.5 319.5t178.5 250.5t253.5 159t291.5 58q121 0 238.5 -36t217 -106t176 -164.5
+t119.5 -219t43 -261.5q0 -190 -80.5 -347.5t-218.5 -264.5q47 -70 93.5 -106.5t104.5 -36.5q61 0 94 37.5t38 85.5z" />
+    <glyph glyph-name="uniF2C5" unicode="&#xf2c5;" horiz-adv-x="2304" 
+d="M453 -101q0 -21 -16 -37.5t-37 -16.5q-1 0 -13 3q-63 15 -162 140q-225 284 -225 676q0 341 213 614q39 51 95 103.5t94 52.5q19 0 35 -13.5t16 -32.5q0 -27 -63 -90q-98 -102 -147 -184q-119 -199 -119 -449q0 -281 123 -491q50 -85 136 -173q2 -3 14.5 -16t19.5 -21
+t17 -20.5t14.5 -23.5t4.5 -21zM1796 33q0 -29 -17.5 -48.5t-46.5 -19.5h-1081q-26 0 -45 19t-19 45q0 29 17.5 48.5t46.5 19.5h1081q26 0 45 -19t19 -45zM1581 644q0 -134 -67 -233q-25 -38 -69.5 -78.5t-83.5 -60.5q-16 -10 -27 -10q-7 0 -15 6t-8 12q0 9 19 30t42 46
+t42 67.5t19 88.5q0 76 -35 130q-29 42 -46 42q-3 0 -3 -5q0 -12 7.5 -35.5t7.5 -36.5q0 -22 -21.5 -35t-44.5 -13q-66 0 -66 76q0 15 1.5 44t1.5 44q0 25 -10 46q-13 25 -42 53.5t-51 28.5q-5 0 -7 -0.5t-3.5 -2.5t-1.5 -6q0 -2 16 -26t16 -54q0 -37 -19 -68t-46 -54
+t-53.5 -46t-45.5 -54t-19 -68q0 -98 42 -160q29 -43 79 -63q16 -5 17 -10q1 -2 1 -5q0 -16 -18 -16q-6 0 -33 11q-119 43 -195 139.5t-76 218.5q0 55 24.5 115.5t60 115t70.5 108.5t59.5 113.5t24.5 111.5q0 53 -25 94q-29 48 -56 64q-19 9 -19 21q0 20 41 20q50 0 110 -29
+q41 -19 71 -44.5t49.5 -51t33.5 -62.5t22 -69t16 -80q0 -1 3 -17.5t4.5 -25t5.5 -25t9 -27t11 -21.5t14.5 -16.5t18.5 -5.5q23 0 37 14t14 37q0 25 -20 67t-20 52t10 10q27 0 93 -70q72 -76 102.5 -156t30.5 -186zM2304 615q0 -274 -138 -503q-19 -32 -48 -72t-68 -86.5
+t-81 -77t-74 -30.5q-16 0 -31 15.5t-15 31.5q0 15 29 50.5t68.5 77t48.5 52.5q183 230 183 531q0 131 -20.5 235t-72.5 211q-58 119 -163 228q-2 3 -13 13.5t-16.5 16.5t-15 17.5t-15 20t-9.5 18.5t-4 19q0 19 16 35.5t35 16.5q70 0 196 -169q98 -131 146 -273t60 -314
+q2 -42 2 -64z" />
+    <glyph glyph-name="uniF2C6" unicode="&#xf2c6;" horiz-adv-x="1792" 
+d="M1189 229l147 693q9 44 -10.5 63t-51.5 7l-864 -333q-29 -11 -39.5 -25t-2.5 -26.5t32 -19.5l221 -69l513 323q21 14 32 6q7 -5 -4 -15l-415 -375v0v0l-16 -228q23 0 45 22l108 104l224 -165q64 -36 81 38zM1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71
+t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
+    <glyph glyph-name="uniF2C7" unicode="&#xf2c7;" horiz-adv-x="1024" 
+d="M640 192q0 -80 -56 -136t-136 -56t-136 56t-56 136q0 60 35 110t93 71v907h128v-907q58 -21 93 -71t35 -110zM768 192q0 77 -34 144t-94 112v768q0 80 -56 136t-136 56t-136 -56t-56 -136v-768q-60 -45 -94 -112t-34 -144q0 -133 93.5 -226.5t226.5 -93.5t226.5 93.5
+t93.5 226.5zM896 192q0 -185 -131.5 -316.5t-316.5 -131.5t-316.5 131.5t-131.5 316.5q0 182 128 313v711q0 133 93.5 226.5t226.5 93.5t226.5 -93.5t93.5 -226.5v-711q128 -131 128 -313zM1024 768v-128h-192v128h192zM1024 1024v-128h-192v128h192zM1024 1280v-128h-192
+v128h192z" />
+    <glyph glyph-name="uniF2C8" unicode="&#xf2c8;" horiz-adv-x="1024" 
+d="M640 192q0 -80 -56 -136t-136 -56t-136 56t-56 136q0 60 35 110t93 71v651h128v-651q58 -21 93 -71t35 -110zM768 192q0 77 -34 144t-94 112v768q0 80 -56 136t-136 56t-136 -56t-56 -136v-768q-60 -45 -94 -112t-34 -144q0 -133 93.5 -226.5t226.5 -93.5t226.5 93.5
+t93.5 226.5zM896 192q0 -185 -131.5 -316.5t-316.5 -131.5t-316.5 131.5t-131.5 316.5q0 182 128 313v711q0 133 93.5 226.5t226.5 93.5t226.5 -93.5t93.5 -226.5v-711q128 -131 128 -313zM1024 768v-128h-192v128h192zM1024 1024v-128h-192v128h192zM1024 1280v-128h-192
+v128h192z" />
+    <glyph glyph-name="uniF2C9" unicode="&#xf2c9;" horiz-adv-x="1024" 
+d="M640 192q0 -80 -56 -136t-136 -56t-136 56t-56 136q0 60 35 110t93 71v395h128v-395q58 -21 93 -71t35 -110zM768 192q0 77 -34 144t-94 112v768q0 80 -56 136t-136 56t-136 -56t-56 -136v-768q-60 -45 -94 -112t-34 -144q0 -133 93.5 -226.5t226.5 -93.5t226.5 93.5
+t93.5 226.5zM896 192q0 -185 -131.5 -316.5t-316.5 -131.5t-316.5 131.5t-131.5 316.5q0 182 128 313v711q0 133 93.5 226.5t226.5 93.5t226.5 -93.5t93.5 -226.5v-711q128 -131 128 -313zM1024 768v-128h-192v128h192zM1024 1024v-128h-192v128h192zM1024 1280v-128h-192
+v128h192z" />
+    <glyph glyph-name="uniF2CA" unicode="&#xf2ca;" horiz-adv-x="1024" 
+d="M640 192q0 -80 -56 -136t-136 -56t-136 56t-56 136q0 60 35 110t93 71v139h128v-139q58 -21 93 -71t35 -110zM768 192q0 77 -34 144t-94 112v768q0 80 -56 136t-136 56t-136 -56t-56 -136v-768q-60 -45 -94 -112t-34 -144q0 -133 93.5 -226.5t226.5 -93.5t226.5 93.5
+t93.5 226.5zM896 192q0 -185 -131.5 -316.5t-316.5 -131.5t-316.5 131.5t-131.5 316.5q0 182 128 313v711q0 133 93.5 226.5t226.5 93.5t226.5 -93.5t93.5 -226.5v-711q128 -131 128 -313zM1024 768v-128h-192v128h192zM1024 1024v-128h-192v128h192zM1024 1280v-128h-192
+v128h192z" />
+    <glyph glyph-name="uniF2CB" unicode="&#xf2cb;" horiz-adv-x="1024" 
+d="M640 192q0 -80 -56 -136t-136 -56t-136 56t-56 136q0 79 56 135.5t136 56.5t136 -56.5t56 -135.5zM768 192q0 77 -34 144t-94 112v768q0 80 -56 136t-136 56t-136 -56t-56 -136v-768q-60 -45 -94 -112t-34 -144q0 -133 93.5 -226.5t226.5 -93.5t226.5 93.5t93.5 226.5z
+M896 192q0 -185 -131.5 -316.5t-316.5 -131.5t-316.5 131.5t-131.5 316.5q0 182 128 313v711q0 133 93.5 226.5t226.5 93.5t226.5 -93.5t93.5 -226.5v-711q128 -131 128 -313zM1024 768v-128h-192v128h192zM1024 1024v-128h-192v128h192zM1024 1280v-128h-192v128h192z" />
+    <glyph glyph-name="uniF2CC" unicode="&#xf2cc;" horiz-adv-x="1920" 
+d="M1433 1287q10 -10 10 -23t-10 -23l-626 -626q-10 -10 -23 -10t-23 10l-82 82q-10 10 -10 23t10 23l44 44q-72 91 -81.5 207t46.5 215q-74 71 -176 71q-106 0 -181 -75t-75 -181v-1280h-256v1280q0 104 40.5 198.5t109.5 163.5t163.5 109.5t198.5 40.5q106 0 201 -41
+t166 -115q94 39 197 24.5t185 -79.5l44 44q10 10 23 10t23 -10zM1344 1024q26 0 45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45t19 45t45 19zM1600 896q-26 0 -45 19t-19 45t19 45t45 19t45 -19t19 -45t-19 -45t-45 -19zM1856 1024q26 0 45 -19t19 -45t-19 -45t-45 -19
+t-45 19t-19 45t19 45t45 19zM1216 896q26 0 45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45t19 45t45 19zM1408 832q0 26 19 45t45 19t45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45zM1728 896q26 0 45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45t19 45t45 19zM1088 768
+q26 0 45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45t19 45t45 19zM1344 640q-26 0 -45 19t-19 45t19 45t45 19t45 -19t19 -45t-19 -45t-45 -19zM1600 768q26 0 45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45t19 45t45 19zM1216 512q-26 0 -45 19t-19 45t19 45t45 19t45 -19
+t19 -45t-19 -45t-45 -19zM1472 640q26 0 45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45t19 45t45 19zM1088 512q26 0 45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45t19 45t45 19zM1344 512q26 0 45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45t19 45t45 19zM1216 384
+q26 0 45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45t19 45t45 19zM1088 256q26 0 45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45t19 45t45 19z" />
+    <glyph glyph-name="uniF2CD" unicode="&#xf2cd;" horiz-adv-x="1792" 
+d="M1664 448v-192q0 -169 -128 -286v-194q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v118q-63 -22 -128 -22h-768q-65 0 -128 22v-110q0 -17 -9.5 -28.5t-22.5 -11.5h-64q-13 0 -22.5 11.5t-9.5 28.5v186q-128 117 -128 286v192h1536zM704 864q0 -14 -9 -23t-23 -9t-23 9
+t-9 23t9 23t23 9t23 -9t9 -23zM768 928q0 -14 -9 -23t-23 -9t-23 9t-9 23t9 23t23 9t23 -9t9 -23zM704 992q0 -14 -9 -23t-23 -9t-23 9t-9 23t9 23t23 9t23 -9t9 -23zM832 992q0 -14 -9 -23t-23 -9t-23 9t-9 23t9 23t23 9t23 -9t9 -23zM768 1056q0 -14 -9 -23t-23 -9t-23 9
+t-9 23t9 23t23 9t23 -9t9 -23zM704 1120q0 -14 -9 -23t-23 -9t-23 9t-9 23t9 23t23 9t23 -9t9 -23zM1792 608v-64q0 -14 -9 -23t-23 -9h-1728q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96v640q0 106 75 181t181 75q108 0 184 -78q46 19 98 12t93 -39l22 22q11 11 22 0l42 -42
+q11 -11 0 -22l-314 -314q-11 -11 -22 0l-42 42q-11 11 0 22l22 22q-36 46 -40.5 104t23.5 108q-37 35 -88 35q-53 0 -90.5 -37.5t-37.5 -90.5v-640h1504q14 0 23 -9t9 -23zM896 1056q0 -14 -9 -23t-23 -9t-23 9t-9 23t9 23t23 9t23 -9t9 -23zM832 1120q0 -14 -9 -23t-23 -9
+t-23 9t-9 23t9 23t23 9t23 -9t9 -23zM768 1184q0 -14 -9 -23t-23 -9t-23 9t-9 23t9 23t23 9t23 -9t9 -23zM960 1120q0 -14 -9 -23t-23 -9t-23 9t-9 23t9 23t23 9t23 -9t9 -23zM896 1184q0 -14 -9 -23t-23 -9t-23 9t-9 23t9 23t23 9t23 -9t9 -23zM832 1248q0 -14 -9 -23
+t-23 -9t-23 9t-9 23t9 23t23 9t23 -9t9 -23zM1024 1184q0 -14 -9 -23t-23 -9t-23 9t-9 23t9 23t23 9t23 -9t9 -23zM960 1248q0 -14 -9 -23t-23 -9t-23 9t-9 23t9 23t23 9t23 -9t9 -23zM1088 1248q0 -14 -9 -23t-23 -9t-23 9t-9 23t9 23t23 9t23 -9t9 -23z" />
+    <glyph glyph-name="uniF2CE" unicode="&#xf2ce;" 
+d="M994 344q0 -86 -17 -197q-31 -215 -55 -313q-22 -90 -152 -90t-152 90q-24 98 -55 313q-17 110 -17 197q0 168 224 168t224 -168zM1536 768q0 -240 -134 -434t-350 -280q-8 -3 -15 3t-6 15q7 48 10 66q4 32 6 47q1 9 9 12q159 81 255.5 234t96.5 337q0 180 -91 330.5
+t-247 234.5t-337 74q-124 -7 -237 -61t-193.5 -140.5t-128 -202t-46.5 -240.5q1 -184 99 -336.5t257 -231.5q7 -3 9 -12q3 -21 6 -45q1 -9 5 -32.5t6 -35.5q1 -9 -6.5 -15t-15.5 -2q-148 58 -261 169.5t-173.5 264t-52.5 319.5q7 143 66 273.5t154.5 227t225 157.5t272.5 70
+q164 10 315.5 -46.5t261 -160.5t175 -250.5t65.5 -308.5zM994 800q0 -93 -65.5 -158.5t-158.5 -65.5t-158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5t158.5 -65.5t65.5 -158.5zM1282 768q0 -122 -53.5 -228.5t-146.5 -177.5q-8 -6 -16 -2t-10 14q-6 52 -29 92q-7 10 3 20
+q58 54 91 127t33 155q0 111 -58.5 204t-157.5 141.5t-212 36.5q-133 -15 -229 -113t-109 -231q-10 -92 23.5 -176t98.5 -144q10 -10 3 -20q-24 -41 -29 -93q-2 -9 -10 -13t-16 2q-95 74 -148.5 183t-51.5 234q3 131 69 244t177 181.5t241 74.5q144 7 268 -60t196.5 -187.5
+t72.5 -263.5z" />
+    <glyph glyph-name="uniF2D0" unicode="&#xf2d0;" horiz-adv-x="1792" 
+d="M256 128h1280v768h-1280v-768zM1792 1248v-1216q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1472q66 0 113 -47t47 -113z" />
+    <glyph glyph-name="uniF2D1" unicode="&#xf2d1;" horiz-adv-x="1792" 
+d="M1792 224v-192q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v192q0 66 47 113t113 47h1472q66 0 113 -47t47 -113z" />
+    <glyph glyph-name="uniF2D2" unicode="&#xf2d2;" horiz-adv-x="2048" 
+d="M256 0h768v512h-768v-512zM1280 512h512v768h-768v-256h96q66 0 113 -47t47 -113v-352zM2048 1376v-960q0 -66 -47 -113t-113 -47h-608v-352q0 -66 -47 -113t-113 -47h-960q-66 0 -113 47t-47 113v960q0 66 47 113t113 47h608v352q0 66 47 113t113 47h960q66 0 113 -47
+t47 -113z" />
+    <glyph glyph-name="uniF2D3" unicode="&#xf2d3;" horiz-adv-x="1792" 
+d="M1175 215l146 146q10 10 10 23t-10 23l-233 233l233 233q10 10 10 23t-10 23l-146 146q-10 10 -23 10t-23 -10l-233 -233l-233 233q-10 10 -23 10t-23 -10l-146 -146q-10 -10 -10 -23t10 -23l233 -233l-233 -233q-10 -10 -10 -23t10 -23l146 -146q10 -10 23 -10t23 10
+l233 233l233 -233q10 -10 23 -10t23 10zM1792 1248v-1216q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1472q66 0 113 -47t47 -113z" />
+    <glyph glyph-name="uniF2D4" unicode="&#xf2d4;" horiz-adv-x="1792" 
+d="M1257 425l-146 -146q-10 -10 -23 -10t-23 10l-169 169l-169 -169q-10 -10 -23 -10t-23 10l-146 146q-10 10 -10 23t10 23l169 169l-169 169q-10 10 -10 23t10 23l146 146q10 10 23 10t23 -10l169 -169l169 169q10 10 23 10t23 -10l146 -146q10 -10 10 -23t-10 -23
+l-169 -169l169 -169q10 -10 10 -23t-10 -23zM256 128h1280v1024h-1280v-1024zM1792 1248v-1216q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1472q66 0 113 -47t47 -113z" />
+    <glyph glyph-name="uniF2D5" unicode="&#xf2d5;" horiz-adv-x="1792" 
+d="M1070 358l306 564h-654l-306 -564h654zM1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
+    <glyph glyph-name="uniF2D6" unicode="&#xf2d6;" horiz-adv-x="1794" 
+d="M1291 1060q-15 17 -35 8.5t-26 -28.5t5 -38q14 -17 40 -14.5t34 20.5t-18 52zM895 814q-8 -8 -19.5 -8t-18.5 8q-8 8 -8 19t8 18q7 8 18.5 8t19.5 -8q7 -7 7 -18t-7 -19zM1060 740l-35 -35q-12 -13 -29.5 -13t-30.5 13l-38 38q-12 13 -12 30t12 30l35 35q12 12 29.5 12
+t30.5 -12l38 -39q12 -12 12 -29.5t-12 -29.5zM951 870q-7 -8 -18.5 -8t-19.5 8q-7 8 -7 19t7 19q8 8 19 8t19 -8t8 -19t-8 -19zM1354 968q-34 -64 -107.5 -85.5t-127.5 16.5q-38 28 -61 66.5t-21 87.5t39 92t75.5 53t70.5 -5t70 -51q2 -2 13 -12.5t14.5 -13.5t13 -13.5
+t12.5 -15.5t10 -15.5t8.5 -18t4 -18.5t1 -21t-5 -22t-9.5 -24zM1555 486q3 20 -8.5 34.5t-27.5 21.5t-33 17t-23 20q-40 71 -84 98.5t-113 11.5q19 13 40 18.5t33 4.5l12 -1q2 45 -34 90q6 20 6.5 40.5t-2.5 30.5l-3 10q43 24 71 65t34 91q10 84 -43 150.5t-137 76.5
+q-60 7 -114 -18.5t-82 -74.5q-30 -51 -33.5 -101t14.5 -87t43.5 -64t56.5 -42q-45 4 -88 36t-57 88q-28 108 32 222q-16 21 -29 32q-50 0 -89 -19q19 24 42 37t36 14l13 1q0 50 -13 78q-10 21 -32.5 28.5t-47 -3.5t-37.5 -40q2 4 4 7q-7 -28 -6.5 -75.5t19 -117t48.5 -122.5
+q-25 -14 -47 -36q-35 -16 -85.5 -70.5t-84.5 -101.5l-33 -46q-90 -34 -181 -125.5t-75 -162.5q1 -16 11 -27q-15 -12 -30 -30q-21 -25 -21 -54t21.5 -40t63.5 6q41 19 77 49.5t55 60.5q-2 2 -6.5 5t-20.5 7.5t-33 3.5q23 5 51 12.5t40 10t27.5 6t26 4t23.5 0.5q14 -7 22 34
+q7 37 7 90q0 102 -40 150q106 -103 101 -219q-1 -29 -15 -50t-27 -27l-13 -6q-4 -7 -19 -32t-26 -45.5t-26.5 -52t-25 -61t-17 -63t-6.5 -66.5t10 -63q-35 54 -37 80q-22 -24 -34.5 -39t-33.5 -42t-30.5 -46t-16.5 -41t-0.5 -38t25.5 -27q45 -25 144 64t190.5 221.5
+t122.5 228.5q86 52 145 115.5t86 119.5q47 -93 154 -178q104 -83 167 -80q39 2 46 43zM1794 640q0 -182 -71 -348t-191 -286t-286.5 -191t-348.5 -71t-348.5 71t-286.5 191t-191 286t-71 348t71 348t191 286t286.5 191t348.5 71t348.5 -71t286.5 -191t191 -286t71 -348z" />
+    <glyph glyph-name="uniF2D7" unicode="&#xf2d7;" 
+d="M518 1353v-655q103 -1 191.5 1.5t125.5 5.5l37 3q68 2 90.5 24.5t39.5 94.5l33 142h103l-14 -322l7 -319h-103l-29 127q-15 68 -45 93t-84 26q-87 8 -352 8v-556q0 -78 43.5 -115.5t133.5 -37.5h357q35 0 59.5 2t55 7.5t54 18t48.5 32t46 50.5t39 73l93 216h89
+q-6 -37 -31.5 -252t-30.5 -276q-146 5 -263.5 8t-162.5 4h-44h-628l-376 -12v102l127 25q67 13 91.5 37t25.5 79l8 643q3 402 -8 645q-2 61 -25.5 84t-91.5 36l-127 24v102l376 -12h702q139 0 374 27q-6 -68 -14 -194.5t-12 -219.5l-5 -92h-93l-32 124q-31 121 -74 179.5
+t-113 58.5h-548q-28 0 -35.5 -8.5t-7.5 -30.5z" />
+    <glyph glyph-name="uniF2D8" unicode="&#xf2d8;" 
+d="M922 739v-182q0 -4 0.5 -15t0 -15l-1.5 -12t-3.5 -11.5t-6.5 -7.5t-11 -5.5t-16 -1.5v309q9 0 16 -1t11 -5t6.5 -5.5t3.5 -9.5t1 -10.5v-13.5v-14zM1238 643v-121q0 -1 0.5 -12.5t0 -15.5t-2.5 -11.5t-7.5 -10.5t-13.5 -3q-9 0 -14 9q-4 10 -4 165v7v8.5v9t1.5 8.5l3.5 7
+t5 5.5t8 1.5q6 0 10 -1.5t6.5 -4.5t4 -6t2 -8.5t0.5 -8v-9.5v-9zM180 407h122v472h-122v-472zM614 407h106v472h-159l-28 -221q-20 148 -32 221h-158v-472h107v312l45 -312h76l43 319v-319zM1039 712q0 67 -5 90q-3 16 -11 28.5t-17 20.5t-25 14t-26.5 8.5t-31 4t-29 1.5
+h-29.5h-12h-91v-472h56q169 -1 197 24.5t25 180.5q-1 62 -1 100zM1356 515v133q0 29 -2 45t-9.5 33.5t-24.5 25t-46 7.5q-46 0 -77 -34v154h-117v-472h110l7 30q30 -36 77 -36q50 0 66 30.5t16 83.5zM1536 1248v-1216q0 -66 -47 -113t-113 -47h-1216q-66 0 -113 47t-47 113
+v1216q0 66 47 113t113 47h1216q66 0 113 -47t47 -113z" />
+    <glyph glyph-name="uniF2D9" unicode="&#xf2d9;" horiz-adv-x="2176" 
+d="M1143 -197q-6 1 -11 4q-13 8 -36 23t-86 65t-116.5 104.5t-112 140t-89.5 172.5q-17 3 -175 37q66 -213 235 -362t391 -184zM502 409l168 -28q-25 76 -41 167.5t-19 145.5l-4 53q-84 -82 -121 -224q5 -65 17 -114zM612 1018q-43 -64 -77 -148q44 46 74 68zM2049 584
+q0 161 -62 307t-167.5 252t-250.5 168.5t-304 62.5q-147 0 -281 -52.5t-240 -148.5q-30 -58 -45 -160q60 51 143 83.5t158.5 43t143 13.5t108.5 -1l40 -3q33 -1 53 -15.5t24.5 -33t6.5 -37t-1 -28.5q-126 11 -227.5 0.5t-183 -43.5t-142.5 -71.5t-131 -98.5
+q4 -36 11.5 -92.5t35.5 -178t62 -179.5q123 -6 247.5 14.5t214.5 53.5t162.5 67t109.5 59l37 24q22 16 39.5 20.5t30.5 -5t17 -34.5q14 -97 -39 -121q-208 -97 -467 -134q-135 -20 -317 -16q41 -96 110 -176.5t137 -127t130.5 -79t101.5 -43.5l39 -12q143 -23 263 15
+q195 99 314 289t119 418zM2123 621q-14 -135 -40 -212q-70 -208 -181.5 -346.5t-318.5 -253.5q-48 -33 -82 -44q-72 -26 -163 -16q-36 -3 -73 -3q-283 0 -504.5 173t-295.5 442q-1 0 -4 0.5t-5 0.5q-6 -50 2.5 -112.5t26 -115t36 -98t31.5 -71.5l14 -26q8 -12 54 -82
+q-71 38 -124.5 106.5t-78.5 140t-39.5 137t-17.5 107.5l-2 42q-5 2 -33.5 12.5t-48.5 18t-53 20.5t-57.5 25t-50 25.5t-42.5 27t-25 25.5q19 -10 50.5 -25.5t113 -45.5t145.5 -38l2 32q11 149 94 290q41 202 176 365q28 115 81 214q15 28 32 45t49 32q158 74 303.5 104
+t302 11t306.5 -97q220 -115 333 -336t87 -474z" />
+    <glyph glyph-name="uniF2DA" unicode="&#xf2da;" horiz-adv-x="1792" 
+d="M1341 752q29 44 -6.5 129.5t-121.5 142.5q-58 39 -125.5 53.5t-118 4.5t-68.5 -37q-12 -23 -4.5 -28t42.5 -10q23 -3 38.5 -5t44.5 -9.5t56 -17.5q36 -13 67.5 -31.5t53 -37t40 -38.5t30.5 -38t22 -34.5t16.5 -28.5t12 -18.5t10.5 -6t11 9.5zM1704 178
+q-52 -127 -148.5 -220t-214.5 -141.5t-253 -60.5t-266 13.5t-251 91t-210 161.5t-141.5 235.5t-46.5 303.5q1 41 8.5 84.5t12.5 64t24 80.5t23 73q-51 -208 1 -397t173 -318t291 -206t346 -83t349 74.5t289 244.5q20 27 18 14q0 -4 -4 -14zM1465 627q0 -104 -40.5 -199
+t-108.5 -164t-162 -109.5t-198 -40.5t-198 40.5t-162 109.5t-108.5 164t-40.5 199t40.5 199t108.5 164t162 109.5t198 40.5t198 -40.5t162 -109.5t108.5 -164t40.5 -199zM1752 915q-65 147 -180.5 251t-253 153.5t-292 53.5t-301 -36.5t-275.5 -129t-220 -211.5t-131 -297
+t-10 -373q-49 161 -51.5 311.5t35.5 272.5t109 227t165.5 180.5t207 126t232 71t242.5 9t236 -54t216 -124.5t178 -197q33 -50 62 -121t31 -112zM1690 573q12 244 -136.5 416t-396.5 240q-8 0 -10 5t24 8q125 -4 230 -50t173 -120t116 -168.5t58.5 -199t-1 -208
+t-61.5 -197.5t-122.5 -167t-185 -117.5t-248.5 -46.5q108 30 201.5 80t174 123t129.5 176.5t55 225.5z" />
+    <glyph glyph-name="uniF2DB" unicode="&#xf2db;" 
+d="M192 256v-128h-112q-16 0 -16 16v16h-48q-16 0 -16 16v32q0 16 16 16h48v16q0 16 16 16h112zM192 512v-128h-112q-16 0 -16 16v16h-48q-16 0 -16 16v32q0 16 16 16h48v16q0 16 16 16h112zM192 768v-128h-112q-16 0 -16 16v16h-48q-16 0 -16 16v32q0 16 16 16h48v16
+q0 16 16 16h112zM192 1024v-128h-112q-16 0 -16 16v16h-48q-16 0 -16 16v32q0 16 16 16h48v16q0 16 16 16h112zM192 1280v-128h-112q-16 0 -16 16v16h-48q-16 0 -16 16v32q0 16 16 16h48v16q0 16 16 16h112zM1280 1440v-1472q0 -40 -28 -68t-68 -28h-832q-40 0 -68 28
+t-28 68v1472q0 40 28 68t68 28h832q40 0 68 -28t28 -68zM1536 208v-32q0 -16 -16 -16h-48v-16q0 -16 -16 -16h-112v128h112q16 0 16 -16v-16h48q16 0 16 -16zM1536 464v-32q0 -16 -16 -16h-48v-16q0 -16 -16 -16h-112v128h112q16 0 16 -16v-16h48q16 0 16 -16zM1536 720v-32
+q0 -16 -16 -16h-48v-16q0 -16 -16 -16h-112v128h112q16 0 16 -16v-16h48q16 0 16 -16zM1536 976v-32q0 -16 -16 -16h-48v-16q0 -16 -16 -16h-112v128h112q16 0 16 -16v-16h48q16 0 16 -16zM1536 1232v-32q0 -16 -16 -16h-48v-16q0 -16 -16 -16h-112v128h112q16 0 16 -16v-16
+h48q16 0 16 -16z" />
+    <glyph glyph-name="uniF2DC" unicode="&#xf2dc;" horiz-adv-x="1664" 
+d="M1566 419l-167 -33l186 -107q23 -13 29.5 -38.5t-6.5 -48.5q-14 -23 -39 -29.5t-48 6.5l-186 106l55 -160q13 -38 -12 -63.5t-60.5 -20.5t-48.5 42l-102 300l-271 156v-313l208 -238q16 -18 17 -39t-11 -36.5t-28.5 -25t-37 -5.5t-36.5 22l-112 128v-214q0 -26 -19 -45
+t-45 -19t-45 19t-19 45v214l-112 -128q-16 -18 -36.5 -22t-37 5.5t-28.5 25t-11 36.5t17 39l208 238v313l-271 -156l-102 -300q-13 -37 -48.5 -42t-60.5 20.5t-12 63.5l55 160l-186 -106q-23 -13 -48 -6.5t-39 29.5q-13 23 -6.5 48.5t29.5 38.5l186 107l-167 33
+q-29 6 -42 29t-8.5 46.5t25.5 40t50 10.5l310 -62l271 157l-271 157l-310 -62q-4 -1 -13 -1q-27 0 -44 18t-19 40t11 43t40 26l167 33l-186 107q-23 13 -29.5 38.5t6.5 48.5t39 30t48 -7l186 -106l-55 160q-13 38 12 63.5t60.5 20.5t48.5 -42l102 -300l271 -156v313
+l-208 238q-16 18 -17 39t11 36.5t28.5 25t37 5.5t36.5 -22l112 -128v214q0 26 19 45t45 19t45 -19t19 -45v-214l112 128q16 18 36.5 22t37 -5.5t28.5 -25t11 -36.5t-17 -39l-208 -238v-313l271 156l102 300q13 37 48.5 42t60.5 -20.5t12 -63.5l-55 -160l186 106
+q23 13 48 6.5t39 -29.5q13 -23 6.5 -48.5t-29.5 -38.5l-186 -107l167 -33q27 -5 40 -26t11 -43t-19 -40t-44 -18q-9 0 -13 1l-310 62l-271 -157l271 -157l310 62q29 6 50 -10.5t25.5 -40t-8.5 -46.5t-42 -29z" />
+    <glyph glyph-name="uniF2DD" unicode="&#xf2dd;" horiz-adv-x="1792" 
+d="M1473 607q7 118 -33 226.5t-113 189t-177 131t-221 57.5q-116 7 -225.5 -32t-192 -110.5t-135 -175t-59.5 -220.5q-7 -118 33 -226.5t113 -189t177.5 -131t221.5 -57.5q155 -9 293 59t224 195.5t94 283.5zM1792 1536l-349 -348q120 -117 180.5 -272t50.5 -321
+q-11 -183 -102 -339t-241 -255.5t-332 -124.5l-999 -132l347 347q-120 116 -180.5 271.5t-50.5 321.5q11 184 102 340t241.5 255.5t332.5 124.5q167 22 500 66t500 66z" />
+    <glyph glyph-name="uniF2DE" unicode="&#xf2de;" horiz-adv-x="1792" 
+d="M948 508l163 -329h-51l-175 350l-171 -350h-49l179 374l-78 33l21 49l240 -102l-21 -50zM563 1100l304 -130l-130 -304l-304 130zM907 915l240 -103l-103 -239l-239 102zM1188 765l191 -81l-82 -190l-190 81zM1680 640q0 159 -62 304t-167.5 250.5t-250.5 167.5t-304 62
+t-304 -62t-250.5 -167.5t-167.5 -250.5t-62 -304t62 -304t167.5 -250.5t250.5 -167.5t304 -62t304 62t250.5 167.5t167.5 250.5t62 304zM1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71t348 -71
+t286 -191t191 -286t71 -348z" />
+    <glyph glyph-name="uniF2E0" unicode="&#xf2e0;" horiz-adv-x="1920" 
+d="M1334 302q-4 24 -27.5 34t-49.5 10.5t-48.5 12.5t-25.5 38q-5 47 33 139.5t75 181t32 127.5q-14 101 -117 103q-45 1 -75 -16l-3 -2l-5 -2.5t-4.5 -2t-5 -2t-5 -0.5t-6 1.5t-6 3.5t-6.5 5q-3 2 -9 8.5t-9 9t-8.5 7.5t-9.5 7.5t-9.5 5.5t-11 4.5t-11.5 2.5q-30 5 -48 -3
+t-45 -31q-1 -1 -9 -8.5t-12.5 -11t-15 -10t-16.5 -5.5t-17 3q-54 27 -84 40q-41 18 -94 -5t-76 -65q-16 -28 -41 -98.5t-43.5 -132.5t-40 -134t-21.5 -73q-22 -69 18.5 -119t110.5 -46q30 2 50.5 15t38.5 46q7 13 79 199.5t77 194.5q6 11 21.5 18t29.5 0q27 -15 21 -53
+q-2 -18 -51 -139.5t-50 -132.5q-6 -38 19.5 -56.5t60.5 -7t55 49.5q4 8 45.5 92t81.5 163.5t46 88.5q20 29 41 28q29 0 25 -38q-2 -16 -65.5 -147.5t-70.5 -159.5q-12 -53 13 -103t74 -74q17 -9 51 -15.5t71.5 -8t62.5 14t20 48.5zM383 86q3 -15 -5 -27.5t-23 -15.5
+q-14 -3 -26.5 5t-15.5 23q-3 14 5 27t22 16t27 -5t16 -23zM953 -177q12 -17 8.5 -37.5t-20.5 -32.5t-37.5 -8t-32.5 21q-11 17 -7.5 37.5t20.5 32.5t37.5 8t31.5 -21zM177 635q-18 -27 -49.5 -33t-57.5 13q-26 18 -32 50t12 58q18 27 49.5 33t57.5 -12q26 -19 32 -50.5
+t-12 -58.5zM1467 -42q19 -28 13 -61.5t-34 -52.5t-60.5 -13t-51.5 34t-13 61t33 53q28 19 60.5 13t52.5 -34zM1579 562q69 -113 42.5 -244.5t-134.5 -207.5q-90 -63 -199 -60q-20 -80 -84.5 -127t-143.5 -44.5t-140 57.5q-12 -9 -13 -10q-103 -71 -225 -48.5t-193 126.5
+q-50 73 -53 164q-83 14 -142.5 70.5t-80.5 128t-2 152t81 138.5q-36 60 -38 128t24.5 125t79.5 98.5t121 50.5q32 85 99 148t146.5 91.5t168 17t159.5 -66.5q72 21 140 17.5t128.5 -36t104.5 -80t67.5 -115t17.5 -140.5q52 -16 87 -57t45.5 -89t-5.5 -99.5t-58 -87.5z
+M455 1222q14 -20 9.5 -44.5t-24.5 -38.5q-19 -14 -43.5 -9.5t-37.5 24.5q-14 20 -9.5 44.5t24.5 38.5q19 14 43.5 9.5t37.5 -24.5zM614 1503q4 -16 -5 -30.5t-26 -18.5t-31 5.5t-18 26.5q-3 17 6.5 31t25.5 18q17 4 31 -5.5t17 -26.5zM1800 555q4 -20 -6.5 -37t-30.5 -21
+q-19 -4 -36 6.5t-21 30.5t6.5 37t30.5 22q20 4 36.5 -7.5t20.5 -30.5zM1136 1448q16 -27 8.5 -58.5t-35.5 -47.5q-27 -16 -57.5 -8.5t-46.5 34.5q-16 28 -8.5 59t34.5 48t58 9t47 -36zM1882 792q4 -15 -4 -27.5t-23 -16.5q-15 -3 -27.5 5.5t-15.5 22.5q-3 15 5 28t23 16
+q14 3 26.5 -5t15.5 -23zM1691 1033q15 -22 10.5 -49t-26.5 -43q-22 -15 -49 -10t-42 27t-10 49t27 43t48.5 11t41.5 -28z" />
+    <glyph glyph-name="uniF2E1" unicode="&#xf2e1;" horiz-adv-x="1792" 
+ />
+    <glyph glyph-name="uniF2E2" unicode="&#xf2e2;" horiz-adv-x="1792" 
+ />
+    <glyph glyph-name="uniF2E3" unicode="&#xf2e3;" horiz-adv-x="1792" 
+ />
+    <glyph glyph-name="uniF2E4" unicode="&#xf2e4;" horiz-adv-x="1792" 
+ />
+    <glyph glyph-name="uniF2E5" unicode="&#xf2e5;" horiz-adv-x="1792" 
+ />
+    <glyph glyph-name="uniF2E6" unicode="&#xf2e6;" horiz-adv-x="1792" 
+ />
+    <glyph glyph-name="uniF2E7" unicode="&#xf2e7;" horiz-adv-x="1792" 
+ />
+    <glyph glyph-name="_698" unicode="&#xf2e8;" horiz-adv-x="1792" 
+ />
+    <glyph glyph-name="uniF2E9" unicode="&#xf2e9;" horiz-adv-x="1792" 
+ />
+    <glyph glyph-name="uniF2EA" unicode="&#xf2ea;" horiz-adv-x="1792" 
+ />
+    <glyph glyph-name="uniF2EB" unicode="&#xf2eb;" horiz-adv-x="1792" 
+ />
+    <glyph glyph-name="uniF2EC" unicode="&#xf2ec;" horiz-adv-x="1792" 
+ />
+    <glyph glyph-name="uniF2ED" unicode="&#xf2ed;" horiz-adv-x="1792" 
+ />
+    <glyph glyph-name="uniF2EE" unicode="&#xf2ee;" horiz-adv-x="1792" 
+ />
+    <glyph glyph-name="lessequal" unicode="&#xf500;" horiz-adv-x="1792" 
+ />
+  </font>
+</defs></svg>
diff --git a/themes/bootstrap3/css/fonts/fontawesome-webfont.ttf b/themes/bootstrap3/css/fonts/fontawesome-webfont.ttf
index f221e50a2ef60738ba30932d834530cdfe55cb3e..35acda2fa1196aad98c2adf4378a7611dd713aa3 100644
Binary files a/themes/bootstrap3/css/fonts/fontawesome-webfont.ttf and b/themes/bootstrap3/css/fonts/fontawesome-webfont.ttf differ
diff --git a/themes/bootstrap3/css/fonts/fontawesome-webfont.woff b/themes/bootstrap3/css/fonts/fontawesome-webfont.woff
index 6e7483cf61b490c08ed644d6ef802c69472eb247..400014a4b06eee3d0c0d54402a47ab2601b2862b 100644
Binary files a/themes/bootstrap3/css/fonts/fontawesome-webfont.woff and b/themes/bootstrap3/css/fonts/fontawesome-webfont.woff differ
diff --git a/themes/bootstrap3/css/fonts/fontawesome-webfont.woff2 b/themes/bootstrap3/css/fonts/fontawesome-webfont.woff2
index 7eb74fd127ee5eddf3b95fee6a20dc1684b0963b..4d13fc60404b91e398a37200c4a77b645cfd9586 100644
Binary files a/themes/bootstrap3/css/fonts/fontawesome-webfont.woff2 and b/themes/bootstrap3/css/fonts/fontawesome-webfont.woff2 differ
diff --git a/themes/bootstrap3/css/lib/channel-slider.css b/themes/bootstrap3/css/lib/channel-slider.css
new file mode 100644
index 0000000000000000000000000000000000000000..8b49574400df6395ded0086bda94225ef582f258
--- /dev/null
+++ b/themes/bootstrap3/css/lib/channel-slider.css
@@ -0,0 +1,63 @@
+.channel-slider {
+  position: relative;
+  max-width: 1000px;
+  height: 300px;
+  margin: 50px auto;
+  border: 1px solid #aaa;
+}
+.slider-bounds {
+  position: relative;
+  width: 100%;
+  height: 100%;
+  overflow: hidden;
+}
+.slider-screen {
+  position: absolute;
+  top: 0;
+  left: 0;
+  display: block;
+  width: 9999px;
+  height: 300px;
+}
+.slider-screen::after {
+  display: table;
+  clear: both;
+  content: "";
+}
+.slider-screen .slide {
+  float: left;
+  display: table;
+  max-width: 150px;
+  margin: 5px;
+  padding: 5px;
+  user-select: none;
+}
+.slider-screen .slide .thumb {
+  max-width: 100%;
+  max-height: 160px;
+}
+.slider-screen .slide img {
+  display: block;
+  max-width: 100%;
+  max-height: 100%;
+  margin: auto;
+}
+.slider-menu {
+  position: absolute;
+  bottom: 0;
+  width: 100%;
+  padding: 4px;
+  border-top: 1px solid #aaa;
+  background-color: #fff;
+}
+.slider-menu .scroll-bar {
+  position: absolute;
+  top: -10px;
+  left: 0;
+  z-index: 10;
+  width: 50px;
+  height: 8px;
+  background: #aaa;
+  color: transparent;
+  border-radius: 1px;
+}
\ No newline at end of file
diff --git a/themes/bootstrap3/css/vendor/bootstrap-slider.min.css b/themes/bootstrap3/css/vendor/bootstrap-slider.min.css
index 4ddddf82f707d92707f855a8e08efa1f81fe923d..1c7127442fe33a5d22be07b280e51257f1de2862 100644
--- a/themes/bootstrap3/css/vendor/bootstrap-slider.min.css
+++ b/themes/bootstrap3/css/vendor/bootstrap-slider.min.css
@@ -1,5 +1,5 @@
 /*! =======================================================
-                      VERSION  7.1.1
+                      VERSION  9.7.0              
 ========================================================= */
 /*! =========================================================
  * bootstrap-slider.js
@@ -13,16 +13,29 @@
  *			- Github:  rovolution
  *
  * =========================================================
+  *
+ * bootstrap-slider is released under the MIT License
+ * Copyright (c) 2017 Kyle Kemp, Rohit Kalkur, and contributors
+ * 
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ * 
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
  *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================================================= */.slider{display:inline-block;vertical-align:middle;position:relative}.slider.slider-horizontal{width:210px;height:20px}.slider.slider-horizontal .slider-track{height:10px;width:100%;margin-top:-5px;top:50%;left:0}.slider.slider-horizontal .slider-selection,.slider.slider-horizontal .slider-track-low,.slider.slider-horizontal .slider-track-high{height:100%;top:0;bottom:0}.slider.slider-horizontal .slider-tick,.slider.slider-horizontal .slider-handle{margin-left:-10px;margin-top:-5px}.slider.slider-horizontal .slider-tick.triangle,.slider.slider-horizontal .slider-handle.triangle{border-width:0 10px 10px 10px;width:0;height:0;border-bottom-color:#0480be;margin-top:0}.slider.slider-horizontal .slider-tick-label-container{white-space:nowrap;margin-top:20px}.slider.slider-horizontal .slider-tick-label-container .slider-tick-label{padding-top:4px;display:inline-block;text-align:center}.slider.slider-vertical{height:210px;width:20px}.slider.slider-vertical .slider-track{width:10px;height:100%;margin-left:-5px;left:50%;top:0}.slider.slider-vertical .slider-selection{width:100%;left:0;top:0;bottom:0}.slider.slider-vertical .slider-track-low,.slider.slider-vertical .slider-track-high{width:100%;left:0;right:0}.slider.slider-vertical .slider-tick,.slider.slider-vertical .slider-handle{margin-left:-5px;margin-top:-10px}.slider.slider-vertical .slider-tick.triangle,.slider.slider-vertical .slider-handle.triangle{border-width:10px 0 10px 10px;width:1px;height:1px;border-left-color:#0480be;margin-left:0}.slider.slider-vertical .slider-tick-label-container{white-space:nowrap}.slider.slider-vertical .slider-tick-label-container .slider-tick-label{padding-left:4px}.slider.slider-disabled .slider-handle{background-image:-webkit-linear-gradient(top,#dfdfdf 0,#bebebe 100%);background-image:-o-linear-gradient(top,#dfdfdf 0,#bebebe 100%);background-image:linear-gradient(to bottom,#dfdfdf 0,#bebebe 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdfdfdf',endColorstr='#ffbebebe',GradientType=0)}.slider.slider-disabled .slider-track{background-image:-webkit-linear-gradient(top,#e5e5e5 0,#e9e9e9 100%);background-image:-o-linear-gradient(top,#e5e5e5 0,#e9e9e9 100%);background-image:linear-gradient(to bottom,#e5e5e5 0,#e9e9e9 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe5e5e5',endColorstr='#ffe9e9e9',GradientType=0);cursor:not-allowed}.slider input{display:none}.slider .tooltip.top{margin-top:-36px}.slider .tooltip-inner{white-space:nowrap;max-width:none}.slider .hide{display:none}.slider-track{position:absolute;cursor:pointer;background-image:-webkit-linear-gradient(top,#f5f5f5 0,#f9f9f9 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#f9f9f9 100%);background-image:linear-gradient(to bottom,#f5f5f5 0,#f9f9f9 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5',endColorstr='#fff9f9f9',GradientType=0);-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);border-radius:4px}.slider-selection{position:absolute;background-image:-webkit-linear-gradient(top,#f9f9f9 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#f9f9f9 0,#f5f5f5 100%);background-image:linear-gradient(to bottom,#f9f9f9 0,#f5f5f5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff9f9f9',endColorstr='#fff5f5f5',GradientType=0);-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;border-radius:4px}.slider-selection.tick-slider-selection{background-image:-webkit-linear-gradient(top,#89cdef 0,#81bfde 100%);background-image:-o-linear-gradient(top,#89cdef 0,#81bfde 100%);background-image:linear-gradient(to bottom,#89cdef 0,#81bfde 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff89cdef',endColorstr='#ff81bfde',GradientType=0)}.slider-track-low,.slider-track-high{position:absolute;background:transparent;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;border-radius:4px}.slider-handle{position:absolute;width:20px;height:20px;background-color:#337ab7;background-image:-webkit-linear-gradient(top,#149bdf 0,#0480be 100%);background-image:-o-linear-gradient(top,#149bdf 0,#0480be 100%);background-image:linear-gradient(to bottom,#149bdf 0,#0480be 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf',endColorstr='#ff0480be',GradientType=0);filter:none;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.2),0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.2),0 1px 2px rgba(0,0,0,.05);border:0 solid transparent}.slider-handle.round{border-radius:50%}.slider-handle.triangle{background:transparent none}.slider-handle.custom{background:transparent none}.slider-handle.custom::before{line-height:20px;font-size:20px;content:'\2605';color:#726204}.slider-tick{position:absolute;width:20px;height:20px;background-image:-webkit-linear-gradient(top,#f9f9f9 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#f9f9f9 0,#f5f5f5 100%);background-image:linear-gradient(to bottom,#f9f9f9 0,#f5f5f5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff9f9f9',endColorstr='#fff5f5f5',GradientType=0);-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;filter:none;opacity:.8;border:0 solid transparent}.slider-tick.round{border-radius:50%}.slider-tick.triangle{background:transparent none}.slider-tick.custom{background:transparent none}.slider-tick.custom::before{line-height:20px;font-size:20px;content:'\2605';color:#726204}.slider-tick.in-selection{background-image:-webkit-linear-gradient(top,#89cdef 0,#81bfde 100%);background-image:-o-linear-gradient(top,#89cdef 0,#81bfde 100%);background-image:linear-gradient(to bottom,#89cdef 0,#81bfde 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff89cdef',endColorstr='#ff81bfde',GradientType=0);opacity:1}
\ No newline at end of file
+ * ========================================================= */.slider{display:inline-block;vertical-align:middle;position:relative}.slider.slider-horizontal{width:210px;height:20px}.slider.slider-horizontal .slider-track{height:10px;width:100%;margin-top:-5px;top:50%;left:0}.slider.slider-horizontal .slider-selection,.slider.slider-horizontal .slider-track-low,.slider.slider-horizontal .slider-track-high{height:100%;top:0;bottom:0}.slider.slider-horizontal .slider-tick,.slider.slider-horizontal .slider-handle{margin-left:-10px}.slider.slider-horizontal .slider-tick.triangle,.slider.slider-horizontal .slider-handle.triangle{position:relative;top:50%;transform:translateY(-50%);border-width:0 10px 10px 10px;width:0;height:0;border-bottom-color:#0480be;margin-top:0}.slider.slider-horizontal .slider-tick-container{white-space:nowrap;position:absolute;top:0;left:0;width:100%}.slider.slider-horizontal .slider-tick-label-container{white-space:nowrap;margin-top:20px}.slider.slider-horizontal .slider-tick-label-container .slider-tick-label{padding-top:4px;display:inline-block;text-align:center}.slider.slider-horizontal.slider-rtl .slider-track{left:initial;right:0}.slider.slider-horizontal.slider-rtl .slider-tick,.slider.slider-horizontal.slider-rtl .slider-handle{margin-left:initial;margin-right:-10px}.slider.slider-horizontal.slider-rtl .slider-tick-container{left:initial;right:0}.slider.slider-vertical{height:210px;width:20px}.slider.slider-vertical .slider-track{width:10px;height:100%;left:25%;top:0}.slider.slider-vertical .slider-selection{width:100%;left:0;top:0;bottom:0}.slider.slider-vertical .slider-track-low,.slider.slider-vertical .slider-track-high{width:100%;left:0;right:0}.slider.slider-vertical .slider-tick,.slider.slider-vertical .slider-handle{margin-top:-10px}.slider.slider-vertical .slider-tick.triangle,.slider.slider-vertical .slider-handle.triangle{border-width:10px 0 10px 10px;width:1px;height:1px;border-left-color:#0480be;border-right-color:#0480be;margin-left:0;margin-right:0}.slider.slider-vertical .slider-tick-label-container{white-space:nowrap}.slider.slider-vertical .slider-tick-label-container .slider-tick-label{padding-left:4px}.slider.slider-vertical.slider-rtl .slider-track{left:initial;right:25%}.slider.slider-vertical.slider-rtl .slider-selection{left:initial;right:0}.slider.slider-vertical.slider-rtl .slider-tick.triangle,.slider.slider-vertical.slider-rtl .slider-handle.triangle{border-width:10px 10px 10px 0}.slider.slider-vertical.slider-rtl .slider-tick-label-container .slider-tick-label{padding-left:initial;padding-right:4px}.slider.slider-disabled .slider-handle{background-image:-webkit-linear-gradient(top,#dfdfdf 0,#bebebe 100%);background-image:-o-linear-gradient(top,#dfdfdf 0,#bebebe 100%);background-image:linear-gradient(to bottom,#dfdfdf 0,#bebebe 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdfdfdf',endColorstr='#ffbebebe',GradientType=0)}.slider.slider-disabled .slider-track{background-image:-webkit-linear-gradient(top,#e5e5e5 0,#e9e9e9 100%);background-image:-o-linear-gradient(top,#e5e5e5 0,#e9e9e9 100%);background-image:linear-gradient(to bottom,#e5e5e5 0,#e9e9e9 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe5e5e5',endColorstr='#ffe9e9e9',GradientType=0);cursor:not-allowed}.slider input{display:none}.slider .tooltip.top{margin-top:-36px}.slider .tooltip-inner{white-space:nowrap;max-width:none}.slider .hide{display:none}.slider-track{position:absolute;cursor:pointer;background-image:-webkit-linear-gradient(top,#f5f5f5 0,#f9f9f9 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#f9f9f9 100%);background-image:linear-gradient(to bottom,#f5f5f5 0,#f9f9f9 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5',endColorstr='#fff9f9f9',GradientType=0);-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);border-radius:4px}.slider-selection{position:absolute;background-image:-webkit-linear-gradient(top,#f9f9f9 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#f9f9f9 0,#f5f5f5 100%);background-image:linear-gradient(to bottom,#f9f9f9 0,#f5f5f5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff9f9f9',endColorstr='#fff5f5f5',GradientType=0);-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;border-radius:4px}.slider-selection.tick-slider-selection{background-image:-webkit-linear-gradient(top,#89cdef 0,#81bfde 100%);background-image:-o-linear-gradient(top,#89cdef 0,#81bfde 100%);background-image:linear-gradient(to bottom,#89cdef 0,#81bfde 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff89cdef',endColorstr='#ff81bfde',GradientType=0)}.slider-track-low,.slider-track-high{position:absolute;background:transparent;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;border-radius:4px}.slider-handle{position:absolute;top:0;width:20px;height:20px;background-color:#337ab7;background-image:-webkit-linear-gradient(top,#149bdf 0,#0480be 100%);background-image:-o-linear-gradient(top,#149bdf 0,#0480be 100%);background-image:linear-gradient(to bottom,#149bdf 0,#0480be 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf',endColorstr='#ff0480be',GradientType=0);filter:none;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.2),0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.2),0 1px 2px rgba(0,0,0,.05);border:0 solid transparent}.slider-handle.round{border-radius:50%}.slider-handle.triangle{background:transparent none}.slider-handle.custom{background:transparent none}.slider-handle.custom::before{line-height:20px;font-size:20px;content:'\2605';color:#726204}.slider-tick{position:absolute;width:20px;height:20px;background-image:-webkit-linear-gradient(top,#f9f9f9 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#f9f9f9 0,#f5f5f5 100%);background-image:linear-gradient(to bottom,#f9f9f9 0,#f5f5f5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff9f9f9',endColorstr='#fff5f5f5',GradientType=0);-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;filter:none;opacity:.8;border:0 solid transparent}.slider-tick.round{border-radius:50%}.slider-tick.triangle{background:transparent none}.slider-tick.custom{background:transparent none}.slider-tick.custom::before{line-height:20px;font-size:20px;content:'\2605';color:#726204}.slider-tick.in-selection{background-image:-webkit-linear-gradient(top,#89cdef 0,#81bfde 100%);background-image:-o-linear-gradient(top,#89cdef 0,#81bfde 100%);background-image:linear-gradient(to bottom,#89cdef 0,#81bfde 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff89cdef',endColorstr='#ff81bfde',GradientType=0);opacity:1}
\ No newline at end of file
diff --git a/themes/bootstrap3/css/vendor/font-awesome.min.css b/themes/bootstrap3/css/vendor/font-awesome.min.css
index 9b27f8ea8f8da544b622a801c4a47f73e3865929..540440ce89f2a408aa699b65100e18f15e0f09ca 100644
--- a/themes/bootstrap3/css/vendor/font-awesome.min.css
+++ b/themes/bootstrap3/css/vendor/font-awesome.min.css
@@ -1,4 +1,4 @@
 /*!
- *  Font Awesome 4.6.3 by @davegandy - http://fontawesome.io - @fontawesome
+ *  Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome
  *  License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)
- */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.6.3');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.6.3') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff2?v=4.6.3') format('woff2'),url('../fonts/fontawesome-webfont.woff?v=4.6.3') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.6.3') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.6.3#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-remove:before,.fa-close:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook-f:before,.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-feed:before,.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before,.fa-gratipay:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-resistance:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-y-combinator-square:before,.fa-yc-square:before,.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"}.fa-buysellads:before{content:"\f20d"}.fa-connectdevelop:before{content:"\f20e"}.fa-dashcube:before{content:"\f210"}.fa-forumbee:before{content:"\f211"}.fa-leanpub:before{content:"\f212"}.fa-sellsy:before{content:"\f213"}.fa-shirtsinbulk:before{content:"\f214"}.fa-simplybuilt:before{content:"\f215"}.fa-skyatlas:before{content:"\f216"}.fa-cart-plus:before{content:"\f217"}.fa-cart-arrow-down:before{content:"\f218"}.fa-diamond:before{content:"\f219"}.fa-ship:before{content:"\f21a"}.fa-user-secret:before{content:"\f21b"}.fa-motorcycle:before{content:"\f21c"}.fa-street-view:before{content:"\f21d"}.fa-heartbeat:before{content:"\f21e"}.fa-venus:before{content:"\f221"}.fa-mars:before{content:"\f222"}.fa-mercury:before{content:"\f223"}.fa-intersex:before,.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-venus-double:before{content:"\f226"}.fa-mars-double:before{content:"\f227"}.fa-venus-mars:before{content:"\f228"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-neuter:before{content:"\f22c"}.fa-genderless:before{content:"\f22d"}.fa-facebook-official:before{content:"\f230"}.fa-pinterest-p:before{content:"\f231"}.fa-whatsapp:before{content:"\f232"}.fa-server:before{content:"\f233"}.fa-user-plus:before{content:"\f234"}.fa-user-times:before{content:"\f235"}.fa-hotel:before,.fa-bed:before{content:"\f236"}.fa-viacoin:before{content:"\f237"}.fa-train:before{content:"\f238"}.fa-subway:before{content:"\f239"}.fa-medium:before{content:"\f23a"}.fa-yc:before,.fa-y-combinator:before{content:"\f23b"}.fa-optin-monster:before{content:"\f23c"}.fa-opencart:before{content:"\f23d"}.fa-expeditedssl:before{content:"\f23e"}.fa-battery-4:before,.fa-battery-full:before{content:"\f240"}.fa-battery-3:before,.fa-battery-three-quarters:before{content:"\f241"}.fa-battery-2:before,.fa-battery-half:before{content:"\f242"}.fa-battery-1:before,.fa-battery-quarter:before{content:"\f243"}.fa-battery-0:before,.fa-battery-empty:before{content:"\f244"}.fa-mouse-pointer:before{content:"\f245"}.fa-i-cursor:before{content:"\f246"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-sticky-note:before{content:"\f249"}.fa-sticky-note-o:before{content:"\f24a"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-diners-club:before{content:"\f24c"}.fa-clone:before{content:"\f24d"}.fa-balance-scale:before{content:"\f24e"}.fa-hourglass-o:before{content:"\f250"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\f251"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\f253"}.fa-hourglass:before{content:"\f254"}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:"\f255"}.fa-hand-stop-o:before,.fa-hand-paper-o:before{content:"\f256"}.fa-hand-scissors-o:before{content:"\f257"}.fa-hand-lizard-o:before{content:"\f258"}.fa-hand-spock-o:before{content:"\f259"}.fa-hand-pointer-o:before{content:"\f25a"}.fa-hand-peace-o:before{content:"\f25b"}.fa-trademark:before{content:"\f25c"}.fa-registered:before{content:"\f25d"}.fa-creative-commons:before{content:"\f25e"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-tripadvisor:before{content:"\f262"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-get-pocket:before{content:"\f265"}.fa-wikipedia-w:before{content:"\f266"}.fa-safari:before{content:"\f267"}.fa-chrome:before{content:"\f268"}.fa-firefox:before{content:"\f269"}.fa-opera:before{content:"\f26a"}.fa-internet-explorer:before{content:"\f26b"}.fa-tv:before,.fa-television:before{content:"\f26c"}.fa-contao:before{content:"\f26d"}.fa-500px:before{content:"\f26e"}.fa-amazon:before{content:"\f270"}.fa-calendar-plus-o:before{content:"\f271"}.fa-calendar-minus-o:before{content:"\f272"}.fa-calendar-times-o:before{content:"\f273"}.fa-calendar-check-o:before{content:"\f274"}.fa-industry:before{content:"\f275"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-map-o:before{content:"\f278"}.fa-map:before{content:"\f279"}.fa-commenting:before{content:"\f27a"}.fa-commenting-o:before{content:"\f27b"}.fa-houzz:before{content:"\f27c"}.fa-vimeo:before{content:"\f27d"}.fa-black-tie:before{content:"\f27e"}.fa-fonticons:before{content:"\f280"}.fa-reddit-alien:before{content:"\f281"}.fa-edge:before{content:"\f282"}.fa-credit-card-alt:before{content:"\f283"}.fa-codiepie:before{content:"\f284"}.fa-modx:before{content:"\f285"}.fa-fort-awesome:before{content:"\f286"}.fa-usb:before{content:"\f287"}.fa-product-hunt:before{content:"\f288"}.fa-mixcloud:before{content:"\f289"}.fa-scribd:before{content:"\f28a"}.fa-pause-circle:before{content:"\f28b"}.fa-pause-circle-o:before{content:"\f28c"}.fa-stop-circle:before{content:"\f28d"}.fa-stop-circle-o:before{content:"\f28e"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-hashtag:before{content:"\f292"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-percent:before{content:"\f295"}.fa-gitlab:before{content:"\f296"}.fa-wpbeginner:before{content:"\f297"}.fa-wpforms:before{content:"\f298"}.fa-envira:before{content:"\f299"}.fa-universal-access:before{content:"\f29a"}.fa-wheelchair-alt:before{content:"\f29b"}.fa-question-circle-o:before{content:"\f29c"}.fa-blind:before{content:"\f29d"}.fa-audio-description:before{content:"\f29e"}.fa-volume-control-phone:before{content:"\f2a0"}.fa-braille:before{content:"\f2a1"}.fa-assistive-listening-systems:before{content:"\f2a2"}.fa-asl-interpreting:before,.fa-american-sign-language-interpreting:before{content:"\f2a3"}.fa-deafness:before,.fa-hard-of-hearing:before,.fa-deaf:before{content:"\f2a4"}.fa-glide:before{content:"\f2a5"}.fa-glide-g:before{content:"\f2a6"}.fa-signing:before,.fa-sign-language:before{content:"\f2a7"}.fa-low-vision:before{content:"\f2a8"}.fa-viadeo:before{content:"\f2a9"}.fa-viadeo-square:before{content:"\f2aa"}.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-ghost:before{content:"\f2ac"}.fa-snapchat-square:before{content:"\f2ad"}.fa-pied-piper:before{content:"\f2ae"}.fa-first-order:before{content:"\f2b0"}.fa-yoast:before{content:"\f2b1"}.fa-themeisle:before{content:"\f2b2"}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:"\f2b3"}.fa-fa:before,.fa-font-awesome:before{content:"\f2b4"}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}
+ */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.7.0');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.7.0') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff2?v=4.7.0') format('woff2'),url('../fonts/fontawesome-webfont.woff?v=4.7.0') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.7.0') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-remove:before,.fa-close:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook-f:before,.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-feed:before,.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before,.fa-gratipay:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-resistance:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-y-combinator-square:before,.fa-yc-square:before,.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"}.fa-buysellads:before{content:"\f20d"}.fa-connectdevelop:before{content:"\f20e"}.fa-dashcube:before{content:"\f210"}.fa-forumbee:before{content:"\f211"}.fa-leanpub:before{content:"\f212"}.fa-sellsy:before{content:"\f213"}.fa-shirtsinbulk:before{content:"\f214"}.fa-simplybuilt:before{content:"\f215"}.fa-skyatlas:before{content:"\f216"}.fa-cart-plus:before{content:"\f217"}.fa-cart-arrow-down:before{content:"\f218"}.fa-diamond:before{content:"\f219"}.fa-ship:before{content:"\f21a"}.fa-user-secret:before{content:"\f21b"}.fa-motorcycle:before{content:"\f21c"}.fa-street-view:before{content:"\f21d"}.fa-heartbeat:before{content:"\f21e"}.fa-venus:before{content:"\f221"}.fa-mars:before{content:"\f222"}.fa-mercury:before{content:"\f223"}.fa-intersex:before,.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-venus-double:before{content:"\f226"}.fa-mars-double:before{content:"\f227"}.fa-venus-mars:before{content:"\f228"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-neuter:before{content:"\f22c"}.fa-genderless:before{content:"\f22d"}.fa-facebook-official:before{content:"\f230"}.fa-pinterest-p:before{content:"\f231"}.fa-whatsapp:before{content:"\f232"}.fa-server:before{content:"\f233"}.fa-user-plus:before{content:"\f234"}.fa-user-times:before{content:"\f235"}.fa-hotel:before,.fa-bed:before{content:"\f236"}.fa-viacoin:before{content:"\f237"}.fa-train:before{content:"\f238"}.fa-subway:before{content:"\f239"}.fa-medium:before{content:"\f23a"}.fa-yc:before,.fa-y-combinator:before{content:"\f23b"}.fa-optin-monster:before{content:"\f23c"}.fa-opencart:before{content:"\f23d"}.fa-expeditedssl:before{content:"\f23e"}.fa-battery-4:before,.fa-battery:before,.fa-battery-full:before{content:"\f240"}.fa-battery-3:before,.fa-battery-three-quarters:before{content:"\f241"}.fa-battery-2:before,.fa-battery-half:before{content:"\f242"}.fa-battery-1:before,.fa-battery-quarter:before{content:"\f243"}.fa-battery-0:before,.fa-battery-empty:before{content:"\f244"}.fa-mouse-pointer:before{content:"\f245"}.fa-i-cursor:before{content:"\f246"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-sticky-note:before{content:"\f249"}.fa-sticky-note-o:before{content:"\f24a"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-diners-club:before{content:"\f24c"}.fa-clone:before{content:"\f24d"}.fa-balance-scale:before{content:"\f24e"}.fa-hourglass-o:before{content:"\f250"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\f251"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\f253"}.fa-hourglass:before{content:"\f254"}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:"\f255"}.fa-hand-stop-o:before,.fa-hand-paper-o:before{content:"\f256"}.fa-hand-scissors-o:before{content:"\f257"}.fa-hand-lizard-o:before{content:"\f258"}.fa-hand-spock-o:before{content:"\f259"}.fa-hand-pointer-o:before{content:"\f25a"}.fa-hand-peace-o:before{content:"\f25b"}.fa-trademark:before{content:"\f25c"}.fa-registered:before{content:"\f25d"}.fa-creative-commons:before{content:"\f25e"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-tripadvisor:before{content:"\f262"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-get-pocket:before{content:"\f265"}.fa-wikipedia-w:before{content:"\f266"}.fa-safari:before{content:"\f267"}.fa-chrome:before{content:"\f268"}.fa-firefox:before{content:"\f269"}.fa-opera:before{content:"\f26a"}.fa-internet-explorer:before{content:"\f26b"}.fa-tv:before,.fa-television:before{content:"\f26c"}.fa-contao:before{content:"\f26d"}.fa-500px:before{content:"\f26e"}.fa-amazon:before{content:"\f270"}.fa-calendar-plus-o:before{content:"\f271"}.fa-calendar-minus-o:before{content:"\f272"}.fa-calendar-times-o:before{content:"\f273"}.fa-calendar-check-o:before{content:"\f274"}.fa-industry:before{content:"\f275"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-map-o:before{content:"\f278"}.fa-map:before{content:"\f279"}.fa-commenting:before{content:"\f27a"}.fa-commenting-o:before{content:"\f27b"}.fa-houzz:before{content:"\f27c"}.fa-vimeo:before{content:"\f27d"}.fa-black-tie:before{content:"\f27e"}.fa-fonticons:before{content:"\f280"}.fa-reddit-alien:before{content:"\f281"}.fa-edge:before{content:"\f282"}.fa-credit-card-alt:before{content:"\f283"}.fa-codiepie:before{content:"\f284"}.fa-modx:before{content:"\f285"}.fa-fort-awesome:before{content:"\f286"}.fa-usb:before{content:"\f287"}.fa-product-hunt:before{content:"\f288"}.fa-mixcloud:before{content:"\f289"}.fa-scribd:before{content:"\f28a"}.fa-pause-circle:before{content:"\f28b"}.fa-pause-circle-o:before{content:"\f28c"}.fa-stop-circle:before{content:"\f28d"}.fa-stop-circle-o:before{content:"\f28e"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-hashtag:before{content:"\f292"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-percent:before{content:"\f295"}.fa-gitlab:before{content:"\f296"}.fa-wpbeginner:before{content:"\f297"}.fa-wpforms:before{content:"\f298"}.fa-envira:before{content:"\f299"}.fa-universal-access:before{content:"\f29a"}.fa-wheelchair-alt:before{content:"\f29b"}.fa-question-circle-o:before{content:"\f29c"}.fa-blind:before{content:"\f29d"}.fa-audio-description:before{content:"\f29e"}.fa-volume-control-phone:before{content:"\f2a0"}.fa-braille:before{content:"\f2a1"}.fa-assistive-listening-systems:before{content:"\f2a2"}.fa-asl-interpreting:before,.fa-american-sign-language-interpreting:before{content:"\f2a3"}.fa-deafness:before,.fa-hard-of-hearing:before,.fa-deaf:before{content:"\f2a4"}.fa-glide:before{content:"\f2a5"}.fa-glide-g:before{content:"\f2a6"}.fa-signing:before,.fa-sign-language:before{content:"\f2a7"}.fa-low-vision:before{content:"\f2a8"}.fa-viadeo:before{content:"\f2a9"}.fa-viadeo-square:before{content:"\f2aa"}.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-ghost:before{content:"\f2ac"}.fa-snapchat-square:before{content:"\f2ad"}.fa-pied-piper:before{content:"\f2ae"}.fa-first-order:before{content:"\f2b0"}.fa-yoast:before{content:"\f2b1"}.fa-themeisle:before{content:"\f2b2"}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:"\f2b3"}.fa-fa:before,.fa-font-awesome:before{content:"\f2b4"}.fa-handshake-o:before{content:"\f2b5"}.fa-envelope-open:before{content:"\f2b6"}.fa-envelope-open-o:before{content:"\f2b7"}.fa-linode:before{content:"\f2b8"}.fa-address-book:before{content:"\f2b9"}.fa-address-book-o:before{content:"\f2ba"}.fa-vcard:before,.fa-address-card:before{content:"\f2bb"}.fa-vcard-o:before,.fa-address-card-o:before{content:"\f2bc"}.fa-user-circle:before{content:"\f2bd"}.fa-user-circle-o:before{content:"\f2be"}.fa-user-o:before{content:"\f2c0"}.fa-id-badge:before{content:"\f2c1"}.fa-drivers-license:before,.fa-id-card:before{content:"\f2c2"}.fa-drivers-license-o:before,.fa-id-card-o:before{content:"\f2c3"}.fa-quora:before{content:"\f2c4"}.fa-free-code-camp:before{content:"\f2c5"}.fa-telegram:before{content:"\f2c6"}.fa-thermometer-4:before,.fa-thermometer:before,.fa-thermometer-full:before{content:"\f2c7"}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:"\f2c8"}.fa-thermometer-2:before,.fa-thermometer-half:before{content:"\f2c9"}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:"\f2ca"}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:"\f2cb"}.fa-shower:before{content:"\f2cc"}.fa-bathtub:before,.fa-s15:before,.fa-bath:before{content:"\f2cd"}.fa-podcast:before{content:"\f2ce"}.fa-window-maximize:before{content:"\f2d0"}.fa-window-minimize:before{content:"\f2d1"}.fa-window-restore:before{content:"\f2d2"}.fa-times-rectangle:before,.fa-window-close:before{content:"\f2d3"}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:"\f2d4"}.fa-bandcamp:before{content:"\f2d5"}.fa-grav:before{content:"\f2d6"}.fa-etsy:before{content:"\f2d7"}.fa-imdb:before{content:"\f2d8"}.fa-ravelry:before{content:"\f2d9"}.fa-eercast:before{content:"\f2da"}.fa-microchip:before{content:"\f2db"}.fa-snowflake-o:before{content:"\f2dc"}.fa-superpowers:before{content:"\f2dd"}.fa-wpexplorer:before{content:"\f2de"}.fa-meetup:before{content:"\f2e0"}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}
diff --git a/themes/bootstrap3/js/advanced_search.js b/themes/bootstrap3/js/advanced_search.js
index af944a0c8820df20791938079d150fb5e387a1a0..379df9584533652257f37cb1d82f52af0e880cca 100644
--- a/themes/bootstrap3/js/advanced_search.js
+++ b/themes/bootstrap3/js/advanced_search.js
@@ -12,22 +12,22 @@ function addSearch(group, _fieldValues) {
   $newSearch.find('input.form-control')
     .attr('id', 'search_lookfor' + inputID)
     .attr('name', 'lookfor' + group + '[]')
-    .attr('value', '');
-  $newSearch.find('select.type option:first-child').attr('selected', 1);
-  $newSearch.find('select.type')
+    .val('');
+  $newSearch.find('select.adv-term-type option:first-child').attr('selected', 1);
+  $newSearch.find('select.adv-term-type')
     .attr('id', 'search_type' + inputID)
     .attr('name', 'type' + group + '[]');
-  $newSearch.find('.close a')
-    .attr('onClick', 'deleteSearch(' + group + ',' + groupLength[group] + ')');
+  $newSearch.find('.adv-term-remove')
+    .attr('onClick', 'return deleteSearch(' + group + ',' + groupLength[group] + ')');
   // Preset Values
   if (typeof fieldValues.term !== "undefined") {
-    $newSearch.find('input.form-control').attr('value', fieldValues.term);
+    $newSearch.find('input.form-control').val(fieldValues.term);
   }
   if (typeof fieldValues.field !== "undefined") {
-    $newSearch.find('select.type option[value="' + fieldValues.field + '"]').attr('selected', 1);
+    $newSearch.find('select.adv-term-type option[value="' + fieldValues.field + '"]').attr('selected', 1);
   }
   if (typeof fieldValues.op !== "undefined") {
-    $newSearch.find('select.op option[value="' + fieldValues.op + '"]').attr('selected', 1);
+    $newSearch.find('select.adv-term-op option[value="' + fieldValues.op + '"]').attr('selected', 1);
   }
   // Insert it
   $("#group" + group + "Holder").before($newSearch);
@@ -36,18 +36,19 @@ function addSearch(group, _fieldValues) {
     $newSearch.find('.first-op')
       .attr('name', 'op' + group + '[]')
       .removeClass('hidden');
-    $newSearch.find('select.op').remove();
+    $newSearch.find('select.adv-term-op').remove();
   } else {
-    $newSearch.find('select.op')
+    $newSearch.find('select.adv-term-op')
       .attr('id', 'search_op' + group + '_' + groupLength[group])
       .attr('name', 'op' + group + '[]')
       .removeClass('hidden');
     $newSearch.find('.first-op').remove();
     $newSearch.find('label').remove();
     // Show x if we have more than one search inputs
-    $('#group' + group + ' .search .close').removeClass('hidden');
+    $('#group' + group + ' .adv-term-remove').removeClass('hidden');
   }
   groupLength[group]++;
+  return false;
 }
 
 function deleteSearch(group, sindex) {
@@ -63,9 +64,10 @@ function deleteSearch(group, sindex) {
     groupLength[group]--;
     $('#search' + group + '_' + groupLength[group]).remove();
     if (groupLength[group] === 1) {
-      $('#group' + group + ' .search .close').addClass('hidden'); // Hide x
+      $('#group' + group + ' .adv-term-remove').addClass('hidden'); // Hide x
     }
   }
+  return false;
 }
 
 function addGroup(_firstTerm, _firstField, _join) {
@@ -80,10 +82,10 @@ function addGroup(_firstTerm, _firstField, _join) {
     .removeClass('hidden');
   $newGroup.find('.add_search_link')
     .attr('id', 'add_search_link_' + nextGroup)
-    .attr('onClick', 'addSearch(' + nextGroup + ')')
+    .attr('onClick', 'return addSearch(' + nextGroup + ')')
     .removeClass('hidden');
-  $newGroup.find('.group-close')
-    .attr('onClick', 'deleteGroup(' + nextGroup + ')');
+  $newGroup.find('.adv-group-close')
+    .attr('onClick', 'return deleteGroup(' + nextGroup + ')');
   $newGroup.find('select.form-control')
     .attr('id', 'search_bool' + nextGroup)
     .attr('name', 'bool' + nextGroup + '[]');
@@ -101,7 +103,7 @@ function addGroup(_firstTerm, _firstField, _join) {
   if (nextGroup > 0) {
     $('#groupJoin').removeClass('hidden');
     // Show x
-    $('.group .group-close').removeClass('hidden');
+    $('.adv-group-close').removeClass('hidden');
   }
   return nextGroup++;
 }
@@ -110,12 +112,13 @@ function deleteGroup(group) {
   // Find the group and remove it
   $("#group" + group).remove();
   // If the last group was removed, add an empty group
-  if ($('.group').length === 0) {
+  if ($('.adv-group').length === 0) {
     addGroup();
-  } else if ($('#advSearchForm .group').length === 1) {
+  } else if ($('#advSearchForm .adv-group').length === 1) {
     $('#groupJoin').addClass('hidden'); // Hide join menu
-    $('.group .group-close').addClass('hidden'); // Hide x
+    $('.adv-group .adv-group-close').addClass('hidden'); // Hide x
   }
+  return false;
 }
 
 $(document).ready(function advSearchReady() {
diff --git a/themes/bootstrap3/js/autocomplete.js b/themes/bootstrap3/js/autocomplete.js
deleted file mode 100644
index 731b6b63c3609da6dec562f46e1484c1a2e72c2b..0000000000000000000000000000000000000000
--- a/themes/bootstrap3/js/autocomplete.js
+++ /dev/null
@@ -1,279 +0,0 @@
-/**
- * crhallberg/autocomplete.js 0.15.1
- * ~ @crhallberg
- */
-(function autocomplete( $ ) {
-  var cache = {},
-    element = false,
-    options = {
-      ajaxDelay: 200,
-      cache: true,
-      hidingClass: 'hidden',
-      highlight: true,
-      loadingString: 'Loading...',
-      maxResults: 20,
-      minLength: 3
-    };
-
-  var xhr = false;
-
-  function align(input) {
-    var position = input.offset();
-    element.css({
-      top: position.top + input.outerHeight(),
-      left: position.left,
-      minWidth: input.width(),
-      maxWidth: Math.max(input.width(), input.closest('form').width())
-    });
-  }
-
-  function show() {
-    element.removeClass(options.hidingClass);
-  }
-  function hide() {
-    element.addClass(options.hidingClass);
-  }
-
-  function populate(data, input, eventType) {
-    input.val(data.value);
-    input.data('selection', data);
-    if (options.callback) {
-      options.callback(data, input, eventType);
-    }
-    hide();
-  }
-
-  function createList(fulldata, input) {
-    // Limit results
-    var data = fulldata.slice(0, Math.min(options.maxResults, fulldata.length));
-    input.data('length', data.length);
-    // highlighting setup
-    // escape term for regex - https://github.com/sindresorhus/escape-string-regexp/blob/master/index.js
-    var escapedTerm = input.val().replace(/[|\\{}()\[\]\^$+*?.]/g, '\\$&');
-    var regex = new RegExp('(' + escapedTerm + ')', 'ig');
-    var shell = $('<div/>');
-    for (var i = 0; i < data.length; i++) {
-      if (typeof data[i] === 'string') {
-        data[i] = {value: data[i]};
-      }
-      var content = data[i].label || data[i].value;
-      if (options.highlight) {
-        content = content.replace(regex, '<b>$1</b>');
-      }
-      var item = typeof data[i].href === 'undefined'
-        ? $('<div/>')
-        : $('<a/>').attr('href', data[i].href);
-      // Data
-      item.data(data[i])
-          .addClass('item')
-          .html(content);
-      if (typeof data[i].description !== 'undefined') {
-        item.append($('<small/>').html(
-          options.highlight
-            ? data[i].description.replace(regex, '<b>$1</b>')
-            : data[i].description
-        ));
-      }
-      shell.append(item);
-    }
-    element.html(shell);
-    element.find('.item').mousedown(function acItemClick() {
-      populate($(this).data(), input, {mouse: true});
-      setTimeout(function acClickDelay() {
-        input.focus();
-        hide();
-      }, 10);
-    });
-    align(input);
-  }
-
-  function search(input) {
-    if (xhr) { xhr.abort(); }
-    if (input.val().length >= options.minLength) {
-      element.html('<i class="item loading">' + options.loadingString + '</i>');
-      show();
-      align(input);
-      var term = input.val();
-      var cid = input.data('cache-id');
-      if (options.cache && typeof cache[cid][term] !== "undefined") {
-        if (cache[cid][term].length === 0) {
-          hide();
-        } else {
-          createList(cache[cid][term], input);
-        }
-      } else {
-        options.handler(input, function achandlerCallback(data) {
-          cache[cid][term] = data;
-          if (data.length === 0) {
-            hide();
-          } else {
-            createList(data, input);
-          }
-        });
-      }
-      input.data('selected', -1);
-    } else {
-      hide();
-    }
-  }
-
-  function setup(input) {
-    if ($('.autocomplete-results').length === 0) {
-      element = $('<div/>')
-        .addClass('autocomplete-results hidden')
-        .html('<i class="item loading">' + options.loadingString + '</i>');
-      align(input);
-      $(document.body).append(element);
-    }
-
-    input.data('selected', -1);
-    input.data('length', 0);
-
-    if (options.cache) {
-      var cid = Math.floor(Math.random() * 1000);
-      input.data('cache-id', cid);
-      cache[cid] = {};
-    }
-
-    input.blur(function acinputBlur(e) {
-      if (e.target.acitem) {
-        setTimeout(hide, 10);
-      } else {
-        hide();
-      }
-    });
-    input.click(function acinputClick() {
-      search(input, element);
-    });
-    input.focus(function acinputFocus() {
-      search(input, element);
-    });
-    input.keyup(function acinputKeyup(event) {
-      // Ignore navigation keys
-      // - Ignore control functions
-      if (event.ctrlKey || event.which === 17) {
-        return;
-      }
-      // - Function keys (F1 - F15)
-      if (112 <= event.which && event.which <= 126) {
-        return;
-      }
-      switch (event.which) {
-      case 9:    // tab
-      case 13:   // enter
-      case 16:   // shift
-      case 20:   // caps lock
-      case 27:   // esc
-      case 33:   // page up
-      case 34:   // page down
-      case 35:   // end
-      case 36:   // home
-      case 37:   // arrows
-      case 38:
-      case 39:
-      case 40:
-      case 45:   // insert
-      case 144:  // num lock
-      case 145:  // scroll lock
-      case 19:   // pause/break
-        return;
-      default:
-        search(input, element);
-      }
-    });
-    input.keydown(function acinputKeydown(event) {
-      // - Ignore control functions
-      if (event.ctrlKey || event.which === 17) {
-        return;
-      }
-      var position = $(this).data('selected');
-      switch (event.which) {
-        // arrow keys through items
-      case 38: // up key
-        event.preventDefault();
-        element.find('.item.selected').removeClass('selected');
-        if (position-- > 0) {
-          element.find('.item:eq(' + position + ')').addClass('selected');
-        }
-        $(this).data('selected', position);
-        break;
-      case 40: // down key
-        event.preventDefault();
-        if (element.hasClass(options.hidingClass)) {
-          search(input, element);
-        } else if (position < input.data('length') - 1) {
-          position++;
-          element.find('.item.selected').removeClass('selected');
-          element.find('.item:eq(' + position + ')').addClass('selected');
-          $(this).data('selected', position);
-        }
-        break;
-        // enter to nav or populate
-      case 9:
-      case 13:
-        var selected = element.find('.item.selected');
-        if (selected.length > 0) {
-          event.preventDefault();
-          if (event.which === 13 && selected.attr('href')) {
-            window.location.assign(selected.attr('href'));
-          } else {
-            populate(selected.data(), $(this), {key: true});
-            element.find('.item.selected').removeClass('selected');
-            $(this).data('selected', -1);
-          }
-        }
-        break;
-        // hide on escape
-      case 27:
-        hide();
-        $(this).data('selected', -1);
-        break;
-      }
-    });
-
-    window.addEventListener("resize", hide, false);
-
-    return element;
-  }
-
-  $.fn.autocomplete = function acJQuery(settings) {
-
-    return this.each(function acJQueryEach() {
-
-      var input = $(this);
-
-      if (typeof settings === "string") {
-        if (settings === "show") {
-          show();
-          align(input);
-        } else if (settings === "hide") {
-          hide();
-        } else if (options.cache && settings === "clear cache") {
-          var cid = parseInt(input.data('cache-id'), 10);
-          cache[cid] = {};
-        }
-        return input;
-      } else if ('undefined' == typeof settings.handler) {
-        console.error('handler function not provided for autocomplete');
-        return this;
-      } else {
-        options = $.extend( {}, options, settings );
-        setup(input);
-      }
-
-      return input;
-
-    });
-  };
-
-  var timer = false;
-  $.fn.autocomplete.ajax = function acAjax(ops) {
-    if (timer) { clearTimeout(timer); }
-    if (xhr) { xhr.abort(); }
-    timer = setTimeout(
-      function acajaxDelay() { xhr = $.ajax(ops); },
-      options.ajaxDelay
-    );
-  };
-
-}( jQuery ));
\ No newline at end of file
diff --git a/themes/bootstrap3/js/cart.js b/themes/bootstrap3/js/cart.js
index ca69eea6e9d1770f5880f43364e731b69fe1b57b..bafd28296266eeff7f230395b82662d3089f8810 100644
--- a/themes/bootstrap3/js/cart.js
+++ b/themes/bootstrap3/js/cart.js
@@ -53,6 +53,26 @@ VuFind.register('cart', function Cart() {
     return full;
   }
 
+  function hasItem(id, _source) {
+    var source = _source || VuFind.defaultSearchBackend;
+    return _getItems().indexOf(String.fromCharCode(65 + _getSources().indexOf(source)) + id) > -1;
+  }
+
+  function _refreshToggles() {
+    var $toggleBtns = $('.btn-bookbag-toggle');
+    if ($toggleBtns.length > 0) {
+      $toggleBtns.each(function cartIdEach() {
+        var $this = $(this);
+        $this.find('.cart-add,.cart-remove').addClass('hidden');
+        if (hasItem($this.data('cart-id'), $this.data('cart-source'))) {
+          $this.find('.cart-remove').removeClass('hidden');
+        } else {
+          $this.find('.cart-add').removeClass('hidden');
+        }
+      });
+    }
+  }
+
   function updateCount() {
     var items = VuFind.cart.getFullItems();
     $('#cartItems strong').html(items.length);
@@ -61,6 +81,7 @@ VuFind.register('cart', function Cart() {
     } else {
       $('#cartItems .full').addClass('hidden');
     }
+    _refreshToggles();
   }
 
   function addItem(id, _source) {
@@ -127,80 +148,93 @@ VuFind.register('cart', function Cart() {
   }
 
   var _cartNotificationTimeout = false;
-  function _registerUpdate($form) {
-    if ($form) {
-      $("#updateCart, #bottom_updateCart").unbind('click').click(function cartUpdate() {
-        var elId = this.id;
-        var selectedBoxes = $("input[name='ids[]']:checked", $form);
-        var selected = [];
-        $(selectedBoxes).each(function cartCheckboxValues(i) {
-          selected[i] = this.value;
+  function _registerUpdate(_form) {
+    var $form = typeof _form === 'undefined'
+      ? $('form[name="bulkActionForm"]')
+      : $(_form);
+    $("#updateCart, #bottom_updateCart").unbind('click').click(function cartUpdate() {
+      var elId = this.id;
+      var selected = [];
+      var selectedInForm = $form.find('input[name="ids[]"]:checked');
+      var selectedFormAttr = $('input[form="' + $form.attr('id') + '"][name="ids[]"]:checked');
+      $(selectedInForm).each(function cartFormCheckboxValues() {
+        selected.push(this.value);
+      });
+      $(selectedFormAttr).each(function cartAttrCheckboxValues() {
+        selected.push(this.value);
+      });
+      if (selected.length > 0) {
+        var msg = "";
+        var orig = getFullItems();
+        $(selected).each(function cartCheckedItemsAdd() {
+          var data = this.split('|');
+          addItem(data[1], data[0]);
         });
-        if (selected.length > 0) {
-          var msg = "";
-          var orig = getFullItems();
-          $(selected).each(function cartCheckedItemsAdd() {
-            var data = this.split('|');
-            addItem(data[1], data[0]);
-          });
-          var updated = getFullItems();
-          var added = updated.length - orig.length;
-          var inCart = selected.length - added;
-          msg += added + " " + VuFind.translate('itemsAddBag');
-          if (updated.length >= parseInt(VuFind.translate('bookbagMax'), 10)) {
-            msg += "<br/>" + VuFind.translate('bookbagFull');
-          }
-          if (inCart > 0 && orig.length > 0) {
-            msg += "<br/>" + inCart + " " + VuFind.translate('itemsInBag');
-          }
-          $('#' + elId).data('bs.popover').options.content = msg;
-          $('#cartItems strong').html(updated.length);
-        } else {
-          $('#' + elId).data('bs.popover').options.content = VuFind.translate('bulk_noitems_advice');
+        var updated = getFullItems();
+        var added = updated.length - orig.length;
+        var inCart = selected.length - added;
+        msg += VuFind.translate('itemsAddBag', {'%%count%%': added});
+        if (updated.length >= parseInt(VuFind.translate('bookbagMax'), 10)) {
+          msg += "<br/>" + VuFind.translate('bookbagFull');
         }
-        $('#' + elId).popover('show');
-        if (_cartNotificationTimeout !== false) {
-          clearTimeout(_cartNotificationTimeout);
+        if (inCart > 0 && orig.length > 0) {
+          msg += "<br/>" + VuFind.translate('itemsInBag', {'%%count%%': inCart});
         }
-        _cartNotificationTimeout = setTimeout(function notificationHide() {
-          $('#' + elId).popover('hide');
-        }, 5000);
-        return false;
-      });
-    }
+        $('#' + elId).data('bs.popover').options.content = msg;
+        $('#cartItems strong').html(updated.length);
+      } else {
+        $('#' + elId).data('bs.popover').options.content = VuFind.translate('bulk_noitems_advice');
+      }
+      $('#' + elId).popover('show');
+      if (_cartNotificationTimeout !== false) {
+        clearTimeout(_cartNotificationTimeout);
+      }
+      _cartNotificationTimeout = setTimeout(function notificationHide() {
+        $('#' + elId).popover('hide');
+      }, 5000);
+      return false;
+    });
   }
 
-  function init() {
-    // Record buttons
-    var $cartId = $('.cartId');
-    if ($cartId.length > 0) {
-      $cartId.each(function cartIdEach() {
-        var cartId = this.value.split('|');
-        var currentId = cartId[1];
-        var currentSource = cartId[0];
-        var $parent = $(this).parent();
-        $parent.find('.cart-add.correct,.cart-remove.correct').removeClass('correct hidden');
-        $parent.find('.cart-add').click(function cartAddClick() {
+  function _registerToggles() {
+    var $toggleBtns = $('.btn-bookbag-toggle');
+    if ($toggleBtns.length > 0) {
+      $toggleBtns.each(function cartIdEach() {
+        var $this = $(this);
+        var currentId = $this.data('cart-id');
+        var currentSource = $this.data('cart-source');
+        $this.find('.correct').removeClass('correct hidden');
+        $this.find('.cart-add').click(function cartAddClick() {
           if (addItem(currentId, currentSource)) {
-            $parent.find('.cart-add,.cart-remove').toggleClass('hidden');
+            $this.find('.cart-add').addClass('hidden');
+            $this.find('.cart-remove').removeClass('hidden');
           } else {
-            $parent.popover({content: VuFind.translate('bookbagFull')});
+            $this.popover({content: VuFind.translate('bookbagFull')});
             setTimeout(function recordCartFullHide() {
-              $parent.popover('hide');
+              $this.popover('hide');
             }, 5000);
           }
         });
-        $parent.find('.cart-remove').click(function cartRemoveClick() {
+        $this.find('.cart-remove').click(function cartRemoveClick() {
           removeItem(currentId, currentSource);
-          $parent.find('.cart-add,.cart-remove').toggleClass('hidden');
+          $this.find('.cart-add').removeClass('hidden');
+          $this.find('.cart-remove').addClass('hidden');
         });
       });
-    } else {
-      // Search results
-      var $form = $('form[name="bulkActionForm"]');
-      _registerUpdate($form);
     }
-    $("#updateCart, #bottom_updateCart").popover({content: '', html: true, trigger: 'manual'});
+  }
+
+  function init() {
+    // Record buttons
+    _registerToggles();
+    // Search results
+    _registerUpdate();
+    $("#updateCart, #bottom_updateCart").popover({
+      content: '',
+      html: true,
+      trigger: 'manual',
+      placement: $(document.body).hasClass('rtl') ? 'left' : 'right'
+    });
     updateCount();
   }
 
@@ -208,11 +242,12 @@ VuFind.register('cart', function Cart() {
   return {
     // Methods
     addItem: addItem,
-    removeItem: removeItem,
     getFullItems: getFullItems,
-    updateCount: updateCount,
-    setDomain: setDomain,
+    hasItem: hasItem,
+    removeItem: removeItem,
     setCookiePath: setCookiePath,
+    setDomain: setDomain,
+    updateCount: updateCount,
     // Init
     init: init
   };
diff --git a/themes/bootstrap3/js/channels.js b/themes/bootstrap3/js/channels.js
new file mode 100644
index 0000000000000000000000000000000000000000..734f2531c2645f8150181693531b3279972a1c28
--- /dev/null
+++ b/themes/bootstrap3/js/channels.js
@@ -0,0 +1,125 @@
+/*global ChannelSlider, getUrlRoot, htmlEncode, VuFind */
+/*exported channelAddLinkButtons */
+
+function channelAddLinkButtons(elem) {
+  var links = JSON.parse(elem.dataset.linkJson);
+  var $cont = $('<div class="channel-links pull-left"></div>');
+  for (var i = 0; i < links.length; i++) {
+    $cont.append(
+      $('<a/> ', {
+        'href': links[i].url,
+        'class': links[i].label + " btn btn-default",
+        'html': '<i class="fa ' + links[i].icon + '"></i> ' + VuFind.translate(links[i].label)
+      })
+    );
+  }
+  $('#' + elem.id + ' .slider-menu').append($cont);
+}
+
+function setupChannelSlider(i, op) {
+  if (ChannelSlider(op)) {
+    $(op).find('.thumb').each(function thumbnailBackgrounds(index, thumb) {
+      var img = $(thumb).find('img');
+      $(thumb).css('background-image', 'url(' + img.attr('src') + ')');
+      img.remove();
+    });
+    // truncate long titles and add hover
+    $(op).find('.channel-record').dotdotdot({
+      callback: function dddcallback(istrunc, orig) {
+        if (istrunc) {
+          $(this).attr('title', $(orig).text());
+        }
+      }
+    });
+    $('.channel-record').unbind('click').click(function channelRecord(event) {
+      var record = $(event.delegateTarget);
+      if (record.data('popover')) {
+        if (record.attr('aria-describedby')) {
+          record.popover('hide');
+        } else {
+          $('[aria-describedby]').popover('hide');
+          record.popover('show');
+        }
+      } else {
+        record.data('popover', true);
+        record.popover({
+          content: VuFind.translate('loading') + '...',
+          html: true,
+          placement: 'bottom',
+          trigger: 'focus',
+          container: '#' + record.closest('.channel').attr('id')
+        });
+        $('[aria-describedby]').popover('hide');
+        record.popover('show');
+        $.ajax({
+          url: VuFind.path + getUrlRoot(record.attr('href')) + '/AjaxTab',
+          type: 'POST',
+          data: {tab: 'description'}
+        })
+        .done(function channelPopoverDone(data) {
+          record.data('bs.popover').options.content = '<h2>' + htmlEncode(record.text()) + '</h2>'
+            + '<div class="btn-group btn-group-justified">'
+            + '<a href="' + VuFind.path + '/Channels/Record?'
+              + 'id=' + encodeURIComponent(record.attr('data-record-id'))
+              + '&source=' + encodeURIComponent(record.attr('data-record-source'))
+            + '" class="btn btn-default">' + VuFind.translate('channel_expand') + '</a>'
+            + '<a href="' + record.attr('href') + '" class="btn btn-default">' + VuFind.translate('View Record') + '</a>'
+            + '</div>'
+            + data;
+          record.popover('show');
+        });
+      }
+      return false;
+    });
+    // Channel add buttons
+    channelAddLinkButtons(op);
+    $('.channel-add-menu[data-group="' + op.dataset.group + '"].hidden')
+      .clone()
+      .addClass('pull-right')
+      .removeClass('hidden')
+      .appendTo($(op).find('.slider-menu'));
+  }
+}
+
+function bindChannelAddMenu(iteration, scope) {
+  $(scope).find('.channel-add-menu .dropdown-menu a').click(function selectAddedChannel(e) {
+    $.ajax(e.target.href).done(function addChannelAjaxDone(data) {
+      var list = $(e.target).closest('.dropdown-menu');
+      var $testEl = $(data);
+      // Make sure the channel has content
+      if ($testEl.find('.channel-record').length === 0) {
+        $(e.target).closest('.channel').after(
+          '<div class="channel-title no-results">'
+          + '<h2>' + $testEl.find('h2').html() + '</h2>'
+          + VuFind.translate('nohit_heading')
+          + '</div>'
+        );
+      } else {
+        $(e.target).closest('.channel').after(data);
+        $('.channel').each(setupChannelSlider);
+        $('.channel').each(bindChannelAddMenu);
+      }
+      // Remove dropdown link
+      $('[data-token="' + e.target.dataset.token + '"]').parent().remove();
+
+      if (list.children().length === 0) {
+        $('.channel-add-menu[data-group="' + list.closest('.channel-add-menu').data('group') + '"]').remove();
+      }
+    });
+    return false;
+  });
+  $(scope).find('.channel-add-menu .add-btn').click(function addChannels(e) {
+    var links = $(e.target).closest('.channel-add-menu').find('.dropdown-menu a');
+    for (var i = 0; i < links.length && i < 2; i++) {
+      links[i].click();
+    }
+  });
+}
+
+$(document).ready(function channelReady() {
+  $('.channel').each(setupChannelSlider);
+  $('.channel').each(bindChannelAddMenu);
+  $('.channel').on('dragStart', function channelDrag() {
+    $('[aria-describedby]').popover('hide');
+  });
+});
diff --git a/themes/bootstrap3/js/check_save_statuses.js b/themes/bootstrap3/js/check_save_statuses.js
index 411b88d8cec72b6ff4d56e2dad5b2fbd1498839f..d8ee5dc8689af94604ac8668f1a60970a0b7b650 100644
--- a/themes/bootstrap3/js/check_save_statuses.js
+++ b/themes/bootstrap3/js/check_save_statuses.js
@@ -1,4 +1,5 @@
 /*global htmlEncode, userIsLoggedIn, VuFind */
+/*exported checkSaveStatuses, checkSaveStatusesCallback */
 
 function checkSaveStatuses(_container) {
   if (!userIsLoggedIn) {
@@ -48,13 +49,18 @@ function checkSaveStatuses(_container) {
               + htmlEncode(response.data[sel][i].list_title) + '</a></li>';
           }
           html += '</ul>';
-          list.html(html).removeClass('hidden');
+          list.html(html).addClass('loaded');
         }
       }
     });
   }
 }
 
+function checkSaveStatusesCallback() {
+  // Make sure no event parameter etc. is passed to checkSaveStatuses()
+  checkSaveStatuses();
+}
+
 $(document).ready(function checkSaveStatusFail() {
   checkSaveStatuses();
 });
diff --git a/themes/bootstrap3/js/common.js b/themes/bootstrap3/js/common.js
index 3ab48e620494ccc57962867d4841af81c7d1076c..41ff50830c4c30799b32adc8338501b6d7244d13 100644
--- a/themes/bootstrap3/js/common.js
+++ b/themes/bootstrap3/js/common.js
@@ -1,5 +1,5 @@
 /*global grecaptcha, isPhoneNumberValid */
-/*exported VuFind, htmlEncode, deparam, moreFacets, lessFacets, phoneNumberFormHandler, recaptchaOnLoad, bulkFormHandler */
+/*exported VuFind, htmlEncode, deparam, moreFacets, lessFacets, getUrlRoot, phoneNumberFormHandler, recaptchaOnLoad, resetCaptcha, bulkFormHandler */
 
 // IE 9< console polyfill
 window.console = window.console || {log: function polyfillLog() {}};
@@ -37,8 +37,17 @@ var VuFind = (function VuFind() {
       }
     }
   };
-  var translate = function translate(op) {
-    return _translations[op] || op;
+  var translate = function translate(op, _replacements) {
+    var replacements = _replacements || [];
+    var translation = _translations[op] || op;
+    if (replacements) {
+      for (var key in replacements) {
+        if (replacements.hasOwnProperty(key)) {
+          translation = translation.replace(key, replacements[key]);
+        }
+      }
+    }
+    return translation;
   };
 
   /**
@@ -130,6 +139,26 @@ function lessFacets(id) {
   $('#more-' + id).removeClass('hidden');
   return false;
 }
+function getUrlRoot(url) {
+  // Parse out the base URL for the current record:
+  var urlroot = null;
+  var urlParts = url.split(/[?#]/);
+  var urlWithoutFragment = urlParts[0];
+  if (VuFind.path === '') {
+    // special case -- VuFind installed at site root:
+    var chunks = urlWithoutFragment.split('/');
+    urlroot = '/' + chunks[3] + '/' + chunks[4];
+  } else {
+    // standard case -- VuFind has its own path under site:
+    var slashSlash = urlWithoutFragment.indexOf('//');
+    var pathInUrl = slashSlash > -1
+      ? urlWithoutFragment.indexOf(VuFind.path, slashSlash + 2)
+      : urlWithoutFragment.indexOf(VuFind.path);
+    var parts = urlWithoutFragment.substring(pathInUrl + VuFind.path.length + 1).split('/');
+    urlroot = '/' + parts[0] + '/' + parts[1];
+  }
+  return urlroot;
+}
 function facetSessionStorage(e) {
   var source = $('#result0 .hiddenSource').val();
   var id = e.target.id;
@@ -170,6 +199,14 @@ function recaptchaOnLoad() {
     }
   }
 }
+function resetCaptcha($form) {
+  if (typeof grecaptcha !== 'undefined') {
+    var captcha = $form.find('.g-recaptcha');
+    if (captcha.length > 0) {
+      grecaptcha.reset(captcha.data('captchaId'));
+    }
+  }
+}
 
 function bulkFormHandler(event, data) {
   if ($('.checkbox-select-item:checked,checkbox-select-all:checked').length === 0) {
@@ -205,46 +242,43 @@ function setupOffcanvas() {
 
 function setupAutocomplete() {
   // Search autocomplete
-  $('.autocomplete').each(function autocompleteSetup(i, op) {
-    $(op).autocomplete({
-      maxResults: 10,
-      loadingString: VuFind.translate('loading') + '...',
-      handler: function vufindACHandler(input, cb) {
-        var query = input.val();
-        var searcher = extractClassParams(input);
-        var hiddenFilters = [];
-        $(input).closest('.searchForm').find('input[name="hiddenFilters[]"]').each(function hiddenFiltersEach() {
-          hiddenFilters.push($(this).val());
-        });
-        $.fn.autocomplete.ajax({
-          url: VuFind.path + '/AJAX/JSON',
-          data: {
-            q: query,
-            method: 'getACSuggestions',
-            searcher: searcher.searcher,
-            type: searcher.type ? searcher.type : $(input).closest('.searchForm').find('.searchForm_type').val(),
-            hiddenFilters: hiddenFilters
-          },
-          dataType: 'json',
-          success: function autocompleteJSON(json) {
-            if (json.data.length > 0) {
-              var datums = [];
-              for (var j = 0; j < json.data.length; j++) {
-                datums.push(json.data[j]);
-              }
-              cb(datums);
-            } else {
-              cb([]);
+  $('#searchForm_lookfor').autocomplete({
+    maxResults: 10,
+    loadingString: VuFind.translate('loading') + '...',
+    handler: function vufindACHandler(input, cb) {
+      var query = input.val();
+      var searcher = extractClassParams(input);
+      var hiddenFilters = [];
+      $('#searchForm').find('input[name="hiddenFilters[]"]').each(function hiddenFiltersEach() {
+        hiddenFilters.push($(this).val());
+      });
+      $.fn.autocomplete.ajax({
+        url: VuFind.path + '/AJAX/JSON',
+        data: {
+          q: query,
+          method: 'getACSuggestions',
+          searcher: searcher.searcher,
+          type: searcher.type ? searcher.type : $('#searchForm_type').val(),
+          hiddenFilters: hiddenFilters
+        },
+        dataType: 'json',
+        success: function autocompleteJSON(json) {
+          if (json.data.length > 0) {
+            var datums = [];
+            for (var j = 0; j < json.data.length; j++) {
+              datums.push(json.data[j]);
             }
+            cb(datums);
+          } else {
+            cb([]);
           }
-        });
-      }
-    });
+        }
+      });
+    }
   });
   // Update autocomplete on type change
-  $('.searchForm_type').change(function searchTypeChange() {
-    var $lookfor = $(this).closest('.searchForm').find('.searchForm_lookfor[name]');
-    $lookfor.autocomplete('clear cache');
+  $('#searchForm_type').change(function searchTypeChange() {
+    $('#searchForm_lookfor').autocomplete('clear cache');
   });
 }
 
@@ -252,7 +286,7 @@ function setupAutocomplete() {
  * Handle arrow keys to jump to next record
  */
 function keyboardShortcuts() {
-  var $searchform = $('.searchForm_lookfor');
+  var $searchform = $('#searchForm_lookfor');
   if ($('.pager').length > 0) {
     $(window).keydown(function shortcutKeyDown(e) {
       if (!$searchform.is(':focus')) {
@@ -295,12 +329,12 @@ function keyboardShortcuts() {
 function setupFacets() {
   // Advanced facets
   $('.facetAND a,.facetOR a').click(function facetBlocking() {
-    $(this).closest('.collapse').html('<div class="list-group-item">' + VuFind.translate('loading') + '...</div>');
+    $(this).closest('.collapse').html('<div class="facet">' + VuFind.translate('loading') + '...</div>');
     window.location.assign($(this).attr('href'));
   });
 
   // Side facet status saving
-  $('.facet.list-group .collapse').each(function openStoredFacets(index, item) {
+  $('.facet-group .collapse').each(function openStoredFacets(index, item) {
     var source = $('#result0 .hiddenSource').val();
     var storedItem = sessionStorage.getItem('sidefacet-' + source + item.id);
     if (storedItem) {
@@ -313,12 +347,12 @@ function setupFacets() {
           $(item).collapse('hide');
         }
       } finally {
-        $.support.transition = saveTransition;    
+        $.support.transition = saveTransition;
       }
     }
   });
-  $('.facet.list-group .collapse').on('shown.bs.collapse', facetSessionStorage);
-  $('.facet.list-group .collapse').on('hidden.bs.collapse', facetSessionStorage);
+  $('.facet-group').on('shown.bs.collapse', facetSessionStorage);
+  $('.facet-group').on('hidden.bs.collapse', facetSessionStorage);
 }
 
 function setupIeSupport() {
@@ -346,10 +380,19 @@ $(document).ready(function commonDocReady() {
 
   // Checkbox select all
   $('.checkbox-select-all').change(function selectAllCheckboxes() {
-    $(this).closest('form').find('.checkbox-select-item').prop('checked', this.checked);
+    var $form = this.form ? $(this.form) : $(this).closest('form');
+    $form.find('.checkbox-select-item').prop('checked', this.checked);
+    $('[form="' + $form.attr('id') + '"]').prop('checked', this.checked);
+    $form.find('.checkbox-select-all').prop('checked', this.checked);
+    $('.checkbox-select-all[form="' + $form.attr('id') + '"]').prop('checked', this.checked);
   });
   $('.checkbox-select-item').change(function selectAllDisable() {
-    $(this).closest('form').find('.checkbox-select-all').prop('checked', false);
+    var $form = this.form ? $(this.form) : $(this).closest('form');
+    if ($form.length === 0) {
+      return;
+    }
+    $form.find('.checkbox-select-all').prop('checked', false);
+    $('.checkbox-select-all[form="' + $form.attr('id') + '"]').prop('checked', false);
   });
 
   // handle QR code links
@@ -390,7 +433,7 @@ $(document).ready(function commonDocReady() {
   if (sessionStorage.getItem('vufind_retain_filters')) {
     var state = (sessionStorage.getItem('vufind_retain_filters') === 'true');
     $('.searchFormKeepFilters').prop('checked', state);
-    $('.applied-filter').prop('checked', state);
+    $('#applied-filter').prop('checked', state);
   }
 
   setupIeSupport();
diff --git a/themes/bootstrap3/js/embedded_record.js b/themes/bootstrap3/js/embedded_record.js
index 7140732402195b9bbefb9232e65bf4dfff2b0c62..596729e83ba87219cd209593e7b955a6857705e5 100644
--- a/themes/bootstrap3/js/embedded_record.js
+++ b/themes/bootstrap3/js/embedded_record.js
@@ -93,26 +93,30 @@ VuFind.register('embedded', function embedded() {
     }
     var result = $link.closest('.result');
     var mediaBody = result.find('.media-body');
-    var shortNode = mediaBody.find('.short-view');
+    var shortNode = mediaBody.find('.result-body');
+    var linksNode = mediaBody.find('.result-links');
     var longNode = mediaBody.find('.long-view');
     // Insert new elements
     if (!$link.hasClass('js-setup')) {
       $link.prependTo(mediaBody);
       result.addClass('embedded');
-      mediaBody.find('.short-view').addClass('collapse');
+      shortNode.addClass('collapse');
+      linksNode.addClass('collapse');
       longNode = $('<div class="long-view collapse"></div>');
       // Add loading status
       shortNode
         .before('<div class="loading hidden"><i class="fa fa-spin fa-spinner"></i> '
                 + VuFind.translate('loading') + '...</div>')
         .before(longNode);
-      $link.addClass('js-setup');
       longNode.on('show.bs.collapse', function embeddedExpand() {
         $link.addClass('expanded');
       });
-      longNode.on('hidden.bs.collapse', function embeddedCollapsed() {
-        $link.removeClass('expanded');
+      longNode.on('hidden.bs.collapse', function embeddedCollapsed(e) {
+        if ($(e.target).hasClass('long-view')) {
+          $link.removeClass('expanded');
+        }
       });
+      $link.addClass('expanded js-setup');
     }
     // Gather information
     var divID = result.find('.hiddenId')[0].value;
@@ -177,6 +181,7 @@ VuFind.register('embedded', function embedded() {
         longNode.collapse('show');
       }
       shortNode.collapse('hide');
+      linksNode.collapse('hide');
       if (!$link.hasClass('auto')) {
         addToStorage(divID, $(longNode).find('.list-tab-toggle.active').attr('id'));
       } else {
@@ -184,6 +189,7 @@ VuFind.register('embedded', function embedded() {
       }
     } else {
       shortNode.collapse('show');
+      linksNode.collapse('show');
       longNode.collapse('hide');
       removeFromStorage(divID);
     }
diff --git a/themes/bootstrap3/js/hierarchyTree.js b/themes/bootstrap3/js/hierarchyTree.js
index 316d26ddd47ba152db06d548b32c7b2e21b6ee28..edc1d72cb67c0bf0c0ef71eaf0096849c2209abc 100644
--- a/themes/bootstrap3/js/hierarchyTree.js
+++ b/themes/bootstrap3/js/hierarchyTree.js
@@ -31,7 +31,7 @@ function getRecord(id) {
     dataType: 'html'
   })
   .done(function getRecordDone(response) {
-    $('#hierarchyRecord').html(html_entity_decode(response));
+    $('#tree-preview').html(html_entity_decode(response));
     // Remove the old path highlighting
     $('#hierarchyTree a').removeClass("jstree-highlight");
     // Add Current path highlighting
diff --git a/themes/bootstrap3/js/lib/autocomplete.js b/themes/bootstrap3/js/lib/autocomplete.js
new file mode 100644
index 0000000000000000000000000000000000000000..727b0d4ca7f848e6cb7a71345a5c71697e809506
--- /dev/null
+++ b/themes/bootstrap3/js/lib/autocomplete.js
@@ -0,0 +1,390 @@
+/* https://github.com/vufind-org/autocomplete.js 1.0b */
+(function autocomplete( $ ) {
+  var element = false,
+    xhr = false;
+
+  function Factory(_input, settings) {
+    return (function acClosure() {
+      var input = $(this),
+        cache = {},
+        options;
+
+      var _align = function _align() {
+        var position = input.offset();
+        element.css({
+          top: position.top + input.outerHeight(),
+          left: position.left,
+          minWidth: input.width()
+        });
+      }
+
+      var show = function show() {
+        element.removeClass(options.hidingClass);
+      }
+      var hide = function hide() {
+        element.addClass(options.hidingClass);
+      }
+
+      var _populate = function _populate(item, eventType) {
+        if (options.callback) {
+          if (options.callback(item, input, eventType) === true && typeof item.href !== 'undefined') {
+            return window.location.assign(item.href);
+          }
+        } else if (typeof item.href !== 'undefined') {
+          return window.location.assign(item.href);
+        }
+        input.val(item.value);
+        // Reset
+        element.find('.ac-item.selected').removeClass('selected');
+        $(this).data('selected', -1);
+        setTimeout(function acPopulateDelay() {
+          input.focus();
+          hide();
+        }, 10);
+      }
+
+      var _listToHTML = function _listToHTML(list, regex) {
+        var shell = $('<div/>');
+        for (var i = 0; i < list.length; i++) {
+          if (typeof list[i] === 'string') {
+            list[i] = {value: list[i]};
+          }
+          var content = list[i].label || list[i].value;
+          if (options.highlight) {
+            content = content.replace(regex, '<b>$1</b>');
+          }
+          var item = typeof list[i].href === 'undefined'
+            ? $('<div/>')
+            : $('<a/>').attr('href', list[i].href);
+          // list
+          item.data(list[i])
+              .addClass('ac-item')
+              .html(content);
+          if (typeof list[i].description !== 'undefined') {
+            item.append($('<small/>').html(
+              options.highlight
+                ? list[i].description.replace(regex, '<b>$1</b>')
+                : list[i].description
+            ));
+          }
+          shell.append(item);
+        }
+        return shell;
+      }
+      var _createList = function _createList(data) {
+        // highlighting setup
+        // escape term for regex - https://github.com/sindresorhus/escape-string-regexp/blob/master/index.js
+        var escapedTerm = input.val().replace(/[|\\{}()\[\]\^$+*?.]/g, '\\$&');
+        var regex = new RegExp('(' + escapedTerm + ')', 'ig');
+        var shell;
+        if (typeof data.groups === 'undefined') {
+          shell = _listToHTML(data, regex);
+        } else {
+          shell = $('<div/>');
+          for (var i = 0; i < data.groups.length; i++) {
+            if (typeof data.groups[i].label !== 'undefined' || i > 0) {
+              shell.append($('<hr/>', { class: 'ac-section-divider' }));
+            }
+            if (typeof data.groups[i].label !== 'undefined') {
+              shell.append($('<header>', {
+                class: 'ac-section-header',
+                html: data.groups[i].label
+              }));
+            }
+            if (typeof data.groups[i].label !== 'undefined' && data.groups[i].items.length > 0) {
+              shell.append(_listToHTML(data.groups[i].items, regex));
+            } else if (data.groups[i].length > 0) {
+              shell.append(_listToHTML(data.groups[i], regex));
+            }
+          }
+        }
+        element.html(shell);
+        input.data('length', shell.find('.ac-item').length);
+        element.find('.ac-item').mousedown(function acItemClick() {
+          _populate($(this).data(), {mouse: true});
+        });
+        _align();
+      }
+
+      var _handleResults = function _handleResults(term, _data) {
+        // Limit results
+        var data = typeof _data.groups === 'undefined'
+          ? _data.slice(0, Math.min(options.maxResults, _data.length))
+          : _data;
+        var cid = input.data('cacheId');
+        cache[cid][term] = data;
+        if (data.length === 0 || (typeof data.groups !== 'undefined' && data.groups.length === 0)) {
+          hide();
+        } else {
+          _createList(data);
+        }
+      }
+      var _defaultStaticSort = function _defaultStaticSort(a, b) { // .bind(lcterm)
+        return a.match.indexOf(this) - b.match.indexOf(this);
+      }
+      var _staticGroups = function _staticGroups(lcterm) {
+        var matches = [];
+        for (var i = 0; i < options.static.groups.length; i++) {
+          if (typeof options.static.groups[i].label !== 'undefined') {
+            var mitems = options.static.groups[i].items.filter(function staticLabelledGroupFilter(_item) {
+              return _item.match.match(lcterm);
+            });
+            if (mitems.length > 0) {
+              if (typeof options.staticSort === 'function') {
+                mitems.sort(options.staticSort);
+              } else {
+                mitems.sort(_defaultStaticSort.bind(lcterm));
+              }
+              matches.push({
+                label: options.static.groups[i].label,
+                items: mitems
+              });
+            }
+          } else {
+            var ms = options.static.groups[i].filter(function staticGroupFilter(_item) {
+              return _item.match.match(lcterm);
+            });
+            if (ms.length > 0) {
+              if (typeof options.staticSort === 'function') {
+                ms.sort(options.staticSort);
+              } else {
+                ms.sort(_defaultStaticSort.bind(lcterm));
+              }
+              matches.push(ms);
+            }
+          }
+        }
+        return matches;
+      }
+      var search = function search() {
+        if (xhr) { xhr.abort(); }
+        if (input.val().length >= options.minLength) {
+          element.html('<i class="ac-item loading">' + options.loadingString + '</i>');
+          show();
+          _align();
+          input.data('selected', -1);
+          var term = input.val();
+          // Check cache (only for handler-based setups)
+          var cid = input.data('cacheId');
+          if (options.cache && typeof cache[cid][term] !== "undefined") {
+            if (cache[cid][term].length === 0) {
+              hide();
+            } else {
+              _createList(cache[cid][term]);
+            }
+          // Check for static list
+          } else if (typeof options.static !== 'undefined') {
+            var lcterm = term.toLowerCase();
+            var matches;
+            if (typeof options.static.groups !== 'undefined') {
+              matches = { groups: _staticGroups(lcterm) };
+            } else {
+              matches = options.static.filter(function staticFilter(_item) {
+                return _item.match.match(lcterm);
+              });
+              if (typeof options.staticSort === 'function') {
+                matches.sort(options.staticSort);
+              } else {
+                matches.sort(_defaultStaticSort.bind(lcterm));
+              }
+            }
+            _handleResults(term, matches);
+          // Call handler
+          } else {
+            options.handler(input, function achandlerCallback(data) {
+              _handleResults(term, data);
+            });
+          }
+        } else {
+          hide();
+        }
+      }
+
+      function preprocessStatic(_item) {
+        var item = typeof _item === 'string'
+          ? { value: _item }
+          : _item;
+        item.match = (item.label || item.value).toLowerCase();
+        return item;
+      }
+      var _setup = function _setup() {
+        element = $('.autocomplete-results');
+        if (element.length === 0) {
+          element = $('<div/>')
+            .addClass('autocomplete-results ' + options.hidingClass)
+            .html('<i class="item loading">' + options.loadingString + '</i>');
+          _align();
+          $(document.body).append(element);
+        }
+
+        input.data('selected', -1);
+        input.data('length', 0);
+
+        if (options.cache) {
+          var cid = Math.floor(Math.random() * 1000);
+          input.data('cacheId', cid);
+          cache[cid] = {};
+        }
+
+        input.blur(function acinputBlur(e) {
+          if (e.target.acitem) {
+            setTimeout(hide, 10);
+          } else {
+            hide();
+          }
+        });
+        input.click(function acinputClick() {
+          search();
+        });
+        input.focus(function acinputFocus() {
+          search();
+        });
+        input.keyup(function acinputKeyup(event) {
+          // Ignore navigation keys
+          // - Ignore control functions
+          if (event.ctrlKey || event.which === 17) {
+            return;
+          }
+          // - Function keys (F1 - F15)
+          if (112 <= event.which && event.which <= 126) {
+            return;
+          }
+          switch (event.which) {
+          case 9:    // tab
+          case 13:   // enter
+          case 16:   // shift
+          case 20:   // caps lock
+          case 27:   // esc
+          case 33:   // page up
+          case 34:   // page down
+          case 35:   // end
+          case 36:   // home
+          case 37:   // arrows
+          case 38:
+          case 39:
+          case 40:
+          case 45:   // insert
+          case 144:  // num lock
+          case 145:  // scroll lock
+          case 19:   // pause/break
+            return;
+          default:
+            search();
+          }
+        });
+        input.keydown(function acinputKeydown(event) {
+          // - Ignore control functions
+          if (event.ctrlKey || event.which === 17) {
+            return;
+          }
+          var position = $(this).data('selected');
+          switch (event.which) {
+            // arrow keys through items
+          case 38: // up key
+            event.preventDefault();
+            element.find('.ac-item.selected').removeClass('selected');
+            if (position > -1) {
+              if (position-- > 0) {
+                element.find('.ac-item:eq(' + position + ')').addClass('selected');
+              }
+              $(this).data('selected', position);
+            }
+            break;
+          case 40: // down key
+            event.preventDefault();
+            if (element.hasClass(options.hidingClass)) {
+              search();
+            } else if (position < input.data('length') - 1) {
+              position++;
+              element.find('.ac-item.selected').removeClass('selected');
+              element.find('.ac-item:eq(' + position + ')').addClass('selected');
+              $(this).data('selected', position);
+            }
+            break;
+            // enter to nav or populate
+          case 9:
+          case 13:
+            var selected = element.find('.ac-item.selected');
+            if (selected.length > 0) {
+              event.preventDefault();
+              if (event.which === 13 && selected.attr('href')) {
+                return window.location.assign(selected.attr('href'));
+              } else {
+                _populate(selected.data(), $(this), {key: true});
+              }
+            }
+            break;
+            // hide on escape
+          case 27:
+            hide();
+            $(this).data('selected', -1);
+            break;
+          }
+        });
+
+        window.addEventListener("resize", hide, false);
+      }
+
+      if (typeof settings === "string") {
+        if (settings === "show") {
+          show();
+          _align();
+        } else if (settings === "hide") {
+          hide();
+        } else if (options.cache && settings === "clear cache") {
+          var cid = parseInt(input.data('cacheId'), 10);
+          cache[cid] = {};
+        }
+        return input;
+      } else if (typeof settings.handler === 'undefined' && typeof settings.static === 'undefined') {
+        console.error('Neither handler function nor static result list provided for autocomplete');
+        return input;
+      } else {
+        if (typeof settings.static !== 'undefined') {
+          // Preprocess strings into items
+          if (typeof settings.static.groups !== 'undefined') {
+            for (var i = 0; i < settings.static.groups.length; i++) {
+              if (typeof settings.static.groups[i].label !== 'undefined') {
+                settings.static.groups[i].items = settings.static.groups[i].items.map(preprocessStatic);
+              } else {
+                settings.static.groups[i] = settings.static.groups[i].map(preprocessStatic);
+              }
+            }
+          } else {
+            settings.static = settings.static.map(preprocessStatic);
+          }
+        }
+        options = $.extend( {}, $.fn.autocomplete.defaults, settings );
+        _setup();
+      }
+
+      return input;
+    }.bind(_input))();
+  }
+
+  $.fn.autocomplete = function acJQuery(settings) {
+    return this.each(function acJQueryEach() {
+      return Factory(this, settings);
+    });
+  };
+
+  $.fn.autocomplete.defaults = {
+    cache: true,
+    hidingClass: 'hidden',
+    highlight: true,
+    loadingString: 'Loading...',
+    maxResults: 20,
+    minLength: 3
+  };
+
+  var timer = false;
+  $.fn.autocomplete.ajax = function acAjax(ops) {
+    if (timer) { clearTimeout(timer); }
+    if (xhr) { xhr.abort(); }
+    timer = setTimeout(
+      function acajaxDelay() { xhr = $.ajax(ops); },
+      200
+    );
+  };
+
+}( jQuery ));
diff --git a/themes/bootstrap3/js/lib/channel-slider.js b/themes/bootstrap3/js/lib/channel-slider.js
new file mode 100644
index 0000000000000000000000000000000000000000..9d6f59b047606f263303ff0cfe50dea062d3b46c
--- /dev/null
+++ b/themes/bootstrap3/js/lib/channel-slider.js
@@ -0,0 +1,178 @@
+function ChannelSlider(el) {
+  return (function Slider() {
+    // Elements
+    var _container; // Entire element
+    var _slider;    // Moving, too-wide element
+    var _menu;
+    var _leftbtn;
+    var _rightbtn;
+    var _scrollbar;
+    // Data
+    var _slidePositions;
+    var _xpos = 0;
+    var _maxpos = false;
+    var _targetx = 0;
+    var _current = 0;
+
+    var _setupWrappers = function _setupWrappers() {
+      var bounds = $('<div class="slider-bounds"></div>');
+      _slider = $('<div class="slider-screen"></div>');
+      _container.children().appendTo(_slider);
+      bounds.append(_slider);
+      _container.append(bounds);
+    };
+    var _addMenu = function _addMenu() {
+      _menu = $('<nav class="slider-menu"></nav>');
+      var group = $('<div class="btn-group pull-left"></div>');
+      _leftbtn = $('<button class="btn btn-default" disabled><i class="fa fa-arrow-left"></i></button>').click(pageLeft);
+      _rightbtn = $('<button class="btn btn-default"><i class="fa fa-arrow-right"></i></button>').click(pageRight);
+      _scrollbar = $('<div class="scroll-bar"></div>');
+      group.append(_leftbtn);
+      group.append(_rightbtn);
+      _menu.append(group);
+      _menu.append(_scrollbar);
+      _container.append(_menu);
+    };
+
+    var _adjustWidth = function _adjustWidth() {
+      // Make the slider ridiculously wide
+      _slider.css('width', 1e6);
+      // Grab slide positions
+      var slides = _slider.find('.slide');
+      var farLeft = slides[0].getBoundingClientRect().left;
+      _slidePositions = slides.map(function slidePositionsMap(i, op) {
+        var box = op.getBoundingClientRect();
+        if (i === 0) {
+          return {
+            left: 0,
+            right: box.width
+          };
+        }
+        return {
+          left: box.left - farLeft,
+          right: box.right - farLeft
+        }
+      });
+      // Reign it in
+      _slider.css('width', _slidePositions[_slidePositions.length - 1].right + 100);
+      _scrollbar.css('width', _container.width() / _slidePositions.length);
+      _maxpos = _slidePositions[_slidePositions.length - 1].right - _container.width() + 10;
+    };
+    var _move = function _move(newpos) {
+      _targetx = Math.max(0, Math.min(newpos, _maxpos));
+      _animate();
+      // If we're running into the end, we need a new current
+      if (_targetx === _maxpos) {
+        _leftbtn.removeAttr('disabled');
+        _rightbtn.attr('disabled', 1);
+        for (var i = 0; i < _slidePositions.length; i++) {
+          if (_slidePositions[i].left >= _maxpos) {
+            _current = i + 1;
+            break;
+          }
+        }
+      } else if (_targetx === 0) {
+        _leftbtn.attr('disabled', 1);
+        _rightbtn.removeAttr('disabled');
+      } else {
+        _leftbtn.removeAttr('disabled');
+        _rightbtn.removeAttr('disabled');
+      }
+    };
+    var _animate = function _animate() {
+      _xpos += (_targetx - _xpos) / 10;
+      if (Math.abs(_xpos - _targetx) < 1) {
+        _xpos = _targetx;
+      } else {
+        requestAnimationFrame(_animate);
+      }
+      _slider.css('left', 0 - Math.round(_xpos));
+      var barMax = _container.width() - _scrollbar.width();
+      _scrollbar.css('left', Math.max(0, Math.min(barMax, (_xpos / _maxpos) * barMax)));
+    };
+    var _moveToClosest = function _moveToClosest(threshold) {
+      for (var i = 0; i < _slidePositions.length; i++) {
+        if (_slidePositions[i].right >= threshold) {
+          _current = i;
+          _move(_slidePositions[i].left);
+          break;
+        }
+      }
+    };
+    var pageLeft = function pageLeft() {
+      _moveToClosest(_slidePositions[_current].right - _container.width());
+    };
+    var pageRight = function pageRight() {
+      _moveToClosest(_xpos + _container.width());
+    };
+
+    /* --- Setup --- */
+    if (typeof el.dataset.slider !== 'undefined') {
+      return false;
+    }
+    _container = $(el);
+    _container.attr('data-slider', true);
+    _setupWrappers();
+    _addMenu();
+    // Image loading listeners
+    _slider.find('img').on('load', _adjustWidth);
+    // Adjust width
+    _adjustWidth();
+
+    var _touchX = null;
+    var _draggingScrollbar = false;
+    var _sliderDragStart = function _sliderDragStart(e) {
+      _touchX = e.clientX || e.originalEvent.touches[0].clientX;
+      _draggingScrollbar = false;
+    };
+    var _scrollbarDragStart = function _scrollbarDragStart(e) {
+      _touchX = e.clientX || e.originalEvent.touches[0].clientX;
+      _draggingScrollbar = true;
+    };
+    var _sliderDragMove = function _sliderDrag(e) {
+      if (_touchX === null) {
+        return;
+      }
+      var x = e.clientX || e.originalEvent.touches[0].clientX;
+      if (_draggingScrollbar) {
+        _targetx = _maxpos * (x - _container.offset().left) / _container.width();
+        _animate();
+      } else {
+        var diffX = _touchX - x;
+        if (Math.abs(diffX) > 100) {
+          if (diffX < 0) {
+            pageLeft();
+          } else {
+            pageRight();
+          }
+          _touchX = null;
+        }
+      }
+    };
+    var _dragEnd = function _dragEnd() {
+      _touchX = null;
+      // Move to true closest
+      if (_draggingScrollbar) {
+        var mindist = Math.abs(_slidePositions[0].left - _xpos);
+        var closest = 0;
+        for (var i = 1; i < _slidePositions.length; i++) {
+          var d = Math.abs(_slidePositions[i].left - _xpos);
+          if (d < mindist) {
+            mindist = d;
+            closest = i;
+          }
+        }
+        _move(_slidePositions[closest].left);
+      }
+    };
+    _slider.on('mousedown', _sliderDragStart);
+    _scrollbar.on('mousedown', _scrollbarDragStart);
+    _slider.on('touchstart', _sliderDragStart);
+    _slider.on('touchmove', _sliderDragMove);
+    _container.on('mousemove', _sliderDragMove);
+    $(document).on('mouseup', _dragEnd);
+    $(document).on('touchend', _dragEnd);
+
+    return true;
+  })();
+}
diff --git a/themes/bootstrap3/js/lib/form-attr-polyfill.js b/themes/bootstrap3/js/lib/form-attr-polyfill.js
new file mode 100644
index 0000000000000000000000000000000000000000..000a63e44a514347257609c804fc854fa0afbb94
--- /dev/null
+++ b/themes/bootstrap3/js/lib/form-attr-polyfill.js
@@ -0,0 +1,68 @@
+/**
+ * From http://stackoverflow.com/questions/17742275/polyfill-html5-input-form-attribute/26696165#26696165
+ * Recommended by https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-browser-Polyfills
+ * Adapted to eslint styling and updated detection by Chris Hallberg (@crhallberg) for VuFind
+ */
+(function formAttrPolyfill($) {
+  /**
+   * polyfill for html5 form attr
+   */
+
+  // every browser supports except IE
+  if (typeof document.documentMode == 'undefined') {
+    // any other browser? skip
+    return;
+  }
+
+  function resetFormAttr(form) {
+    var $form = $(form);
+    $form.find('.js-form-attr').remove();
+    return $form;
+  }
+  function makeFieldElement(data) {
+    return $('<input/>', data)
+      .addClass('js-form-attr')
+      .attr('type', 'hidden');
+  }
+
+  $(document).ready(function formAttrReady() {
+    /**
+     * Find all input fields with form attribute point to jQuery object
+     *
+     */
+    $('form[id]').submit(function locateFormAttr(/*e*/) {
+      // serialize data
+      var data = $('[form=' + this.id + ']').serializeArray();
+      // append data to form
+      var $form = resetFormAttr(this);
+      for (var i=0; i<data.length; i++) {
+        $form.append(makeFieldElement(data[i]));
+      }
+      return true;
+    }).each(function locateFormAttrEach() {
+      var form = this,
+        $fields = $('[form=' + this.id + ']');
+
+      $fields.filter('button, input').filter('[type=reset],[type=submit]').click(function formAttrButtonSubmit() {
+        var type = this.type.toLowerCase();
+        if (type === 'reset') {
+          // reset form
+          form.reset();
+          // for elements outside form
+          $fields.each(function formAttrGatherFieldData() {
+            this.value = this.defaultValue;
+            this.checked = this.defaultChecked;
+          }).filter('select').each(function formAttrGatherSelectData() {
+            $(this).find('option').each(function formAttrGatherOptionData() {
+              this.selected = this.defaultSelected;
+            });
+          });
+        } else if (type.match(/^submit|image$/i)) {
+          var $form = resetFormAttr(form);
+          $form.append( makeFieldElement({name: this.name, value: this.value}) ).submit();
+        }
+      });
+    });
+  });
+
+})(jQuery);
diff --git a/themes/bootstrap3/js/lightbox.js b/themes/bootstrap3/js/lightbox.js
index 9c82c9d3a86d16d5755d6f1b2a194bc136703bfb..51393a46e4a0eda8aedd1eb6ecbe0e8bc2ace01f 100644
--- a/themes/bootstrap3/js/lightbox.js
+++ b/themes/bootstrap3/js/lightbox.js
@@ -1,10 +1,11 @@
-/*global grecaptcha, recaptchaOnLoad, VuFind */
+/*global grecaptcha, recaptchaOnLoad, resetCaptcha, VuFind */
 VuFind.register('lightbox', function Lightbox() {
   // State
   var _originalUrl = false;
   var _currentUrl = false;
   var _lightboxTitle = '';
   var refreshOnClose = false;
+  var _modalParams = {};
   // Elements
   var _modal, _modalBody, _clickedButton = null;
   // Utilities
@@ -64,20 +65,23 @@ VuFind.register('lightbox', function Lightbox() {
    */
   var _constrainLink; // function declarations to avoid style warnings
   var _formSubmit;    // about circular references
-  function _update(content) {
+  function render(content) {
     if (!content.match) {
       return;
     }
     // Isolate successes
     var htmlDiv = $('<div/>').html(content);
-    var alerts = htmlDiv.find('.flash-message.alert-success');
+    var alerts = htmlDiv.find('.flash-message.alert-success:not([data-lightbox-ignore])');
     if (alerts.length > 0) {
+      var msgs = alerts.toArray().map(function getSuccessHtml(el) {
+        return el.innerHTML;
+      }).join('<br/>');
       var href = alerts.find('.download').attr('href');
       if (typeof href !== 'undefined') {
         location.href = href;
         _modal.modal('hide');
       } else {
-        showAlert(alerts[0].innerHTML, 'success');
+        showAlert(msgs, 'success');
       }
       return;
     }
@@ -88,7 +92,7 @@ VuFind.register('lightbox', function Lightbox() {
     }
     // Fill HTML
     _html(finalHTML);
-    _modal.modal('show');
+    VuFind.modal('show');
     // Attach capturing events
     _modalBody.find('a').click(_constrainLink);
     // Handle submit buttons attached to a form as well as those in a form. Store
@@ -136,21 +140,25 @@ VuFind.register('lightbox', function Lightbox() {
           VuFind.refreshPage();
           return;
         }
+        var testDiv = $('<div/>').html(content);
+        var errorMsgs = testDiv.find('.flash-message.alert-danger:not([data-lightbox-ignore])');
         // Place Hold error isolation
-        if (obj.url.match(/\/Record/) && (obj.url.match(/Hold\?/) || obj.url.match(/Request\?/))) {
-          var testDiv = $('<div/>').html(content);
-          var error = testDiv.find('.flash-message.alert-danger');
-          if (error.length && testDiv.find('.record').length) {
-            showAlert(error[0].innerHTML, 'danger');
+        if (obj.url.match(/\/Record\/.*(Hold|Request)\?/)) {
+          if (errorMsgs.length && testDiv.find('.record').length) {
+            var msgs = errorMsgs.toArray().map(function getAlertHtml(el) {
+              return el.innerHTML;
+            }).join('<br/>');
+            showAlert(msgs, 'danger');
             return false;
           }
         }
         if ( // Close the lightbox after deliberate login
-          obj.method                                                                 // is a form
-          && ((obj.url.match(/MyResearch/) && !obj.url.match(/Bulk/) && !obj.url.match(/Delete/)) // that matches login/create account
-            || obj.url.match(/catalogLogin/))                                        // or catalog login for holds
-          && $('<div/>').html(content).find('.flash-message.alert-danger').length === 0 // skip failed logins
+          obj.method && (                                            // is a form
+            obj.url.match(/catalogLogin/)                            // catalog login for holds
+            || obj.url.match(/MyResearch\/(?!Bulk|Delete|Recover)/)  // or that matches login/create account
+          ) && errorMsgs.length === 0                                // skip failed logins
         ) {
+
           var eventResult = _emit('VuFind.lightbox.login', {
             originalUrl: _originalUrl,
             formUrl: obj.url
@@ -165,7 +173,7 @@ VuFind.register('lightbox', function Lightbox() {
           }
           _currentUrl = _originalUrl; // Now that we're logged in, where were we?
         }
-        _update(content);
+        render(content);
       })
       .fail(function lbAjaxFail(deferred, errorType, msg) {
         showAlert(VuFind.translate('error_occurred') + '<br/>' + msg, 'danger');
@@ -182,9 +190,23 @@ VuFind.register('lightbox', function Lightbox() {
   function _evalCallback(callback, event, data) {
     if ('function' === typeof window[callback]) {
       return window[callback](event, data);
-    } else {
-      return eval('(function(event, data) {' + callback + '}())'); // inline code
     }
+    var parts = callback.split('.');
+    if (typeof window[parts[0]] === 'object') {
+      var obj = window[parts[0]];
+      for (var i = 1; i < parts.length; i++) {
+        if (typeof obj[parts[i]] === 'undefined') {
+          obj = false;
+          break;
+        }
+        obj = obj[parts[i]];
+      }
+      if ('function' === typeof obj) {
+        return obj(event, data);
+      }
+    }
+    console.error('Lightbox callback function not found.');
+    return null;
   }
 
   /**
@@ -209,9 +231,10 @@ VuFind.register('lightbox', function Lightbox() {
         obj.data = $(this).data('lightboxPost');
       }
       _lightboxTitle = $(this).data('lightboxTitle') || '';
+      _modalParams = $(this).data();
+      VuFind.modal('show');
       ajax(obj);
       _currentUrl = this.href;
-      VuFind.modal('show');
       return false;
     }
   };
@@ -272,7 +295,7 @@ VuFind.register('lightbox', function Lightbox() {
       }, false);
     }
     // Loading
-    _modalBody.prepend('<i class="fa fa-spinner fa-spin pull-right" title="' + VuFind.translate('loading') + '"></i>');
+    _modalBody.prepend('<i class="modal-loading fa fa-spinner fa-spin" title="' + VuFind.translate('loading') + '"></i>');
     // Prevent multiple submission of submit button in lightbox
     if (submit.closest(_modal).length > 0) {
       submit.attr('disabled', 'disabled');
@@ -285,9 +308,7 @@ VuFind.register('lightbox', function Lightbox() {
       method: $(form).attr('method') || 'GET',
       data: data
     }).done(function recaptchaReset() {
-      if (typeof grecaptcha !== 'undefined') {
-        grecaptcha.reset($(form).find('.g-recaptcha').data('captchaId'));
-      }
+      resetCaptcha($(form));
     });
 
     VuFind.modal('show');
@@ -307,7 +328,10 @@ VuFind.register('lightbox', function Lightbox() {
     // Handle submit buttons attached to a form as well as those in a form. Store
     // information about which button was clicked here as checking focused button
     // doesn't work on all browsers and platforms.
-    $('form[data-lightbox] [type=submit]').click(_storeClickedStatus);
+    $('form[data-lightbox]').each(function bindFormSubmitsLightbox(i, form) {
+      $(form).find('[type=submit]').click(_storeClickedStatus);
+      $('[type="submit"][form="' + form.id + '"]').click(_storeClickedStatus);
+    });
   }
 
   function reset() {
@@ -315,6 +339,7 @@ VuFind.register('lightbox', function Lightbox() {
     _originalUrl = false;
     _currentUrl = false;
     _lightboxTitle = '';
+    _modalParams = {};
   }
   function init() {
     _modal = $('#modal');
@@ -330,7 +355,13 @@ VuFind.register('lightbox', function Lightbox() {
       _emit('VuFind.lightbox.closed');
     });
 
-    VuFind.modal = function modalShortcut(cmd) { _modal.modal(cmd); };
+    VuFind.modal = function modalShortcut(cmd) {
+      if (cmd === 'show') {
+        _modal.modal($.extend({ show: true }, _modalParams));
+      } else {
+        _modal.modal(cmd);
+      }
+    };
     bind();
   }
 
@@ -345,6 +376,7 @@ VuFind.register('lightbox', function Lightbox() {
     bind: bind,
     flashMessage: flashMessage,
     reload: reload,
+    render: render,
     // Reset
     reset: reset,
     // Init
diff --git a/themes/bootstrap3/js/map_selection.js b/themes/bootstrap3/js/map_selection.js
index a3abce25c15408f702cd7e15ad4c6afe59a7775c..fe2159cb0b78f0dfeea4d5c9cb76a7ff8eac4540 100644
--- a/themes/bootstrap3/js/map_selection.js
+++ b/themes/bootstrap3/js/map_selection.js
@@ -191,6 +191,10 @@ function loadMapSelection(geoField, boundingBox, baseURL, homeURL, searchParams,
         }
       }
     });
+    // close popup if zoom in / out occurs
+    map.getView().on('change:resolution', function closePopupsOnZoom() {
+      $(element).popover('destroy');
+    });
   };
   function addInteraction() {
     draw = new ol.interaction.Draw ({
diff --git a/themes/bootstrap3/js/map_tab_ol.js b/themes/bootstrap3/js/map_tab_ol.js
index 1e26b2f073a464dd8acb62d1d751f1993e600d88..bf3e4c435c90d9721603a2a2faa45d01350fac8d 100644
--- a/themes/bootstrap3/js/map_tab_ol.js
+++ b/themes/bootstrap3/js/map_tab_ol.js
@@ -78,10 +78,25 @@ function loadMapTab(mapData, popupTitle) {
         iconFeature.setStyle(iconStyle);
         vectorSource.addFeature(iconFeature);
       } else if (mapData[i][4] === 4) { // It's a polygon feature //
-        var point1 = ol.proj.transform([mapData[i][0], mapData[i][3]], srcProj, dstProj);
-        var point2 = ol.proj.transform([mapData[i][0], mapData[i][1]], srcProj, dstProj);
-        var point3 = ol.proj.transform([mapData[i][2], mapData[i][1]], srcProj, dstProj);
-        var point4 = ol.proj.transform([mapData[i][2], mapData[i][3]], srcProj, dstProj);
+        var west = mapData[i][0];
+        var east = mapData[i][2];
+        var north = mapData[i][3];
+        var south = mapData[i][1];
+        // handle dateline crossing
+        if (west > east) {
+          var wpt = 180 - west;
+          var ept = 180 + east;
+          east = west + wpt + ept;
+        }
+        // move S90 off the poles so ol will map it
+        if (south === -90) {
+          south = south + 0.5;
+        }
+        var point1 = ol.proj.transform([west, north], srcProj, dstProj);
+        var point2 = ol.proj.transform([west, south], srcProj, dstProj);
+        var point3 = ol.proj.transform([east, south], srcProj, dstProj);
+        var point4 = ol.proj.transform([east, north], srcProj, dstProj);
+
         var polyFeature = new ol.Feature({
           geometry: new ol.geom.Polygon([
             [point1, point2, point3, point4, point1]
@@ -171,6 +186,10 @@ function loadMapTab(mapData, popupTitle) {
           document.getElementById(target).style.cursor = "default";
         }
       });
+      // close popup if zoom in / out occurs
+      map.getView().on('change:resolution', function closePopupsOnZoom() {
+        $(element).popover('destroy');
+      });
     }
   };
   init();
diff --git a/themes/bootstrap3/js/preview.js b/themes/bootstrap3/js/preview.js
index a94d594462efb87fc4c6bbdf565a76f6a91b579f..8d71e1bf15c61e5a6fe8af49ddba8a8f49e9448d 100644
--- a/themes/bootstrap3/js/preview.js
+++ b/themes/bootstrap3/js/preview.js
@@ -38,12 +38,14 @@ function getHTPreviews(keys) {
 }
 
 function applyPreviewUrl($link, url) {
-    // Update the preview button:
-  $link.attr('href', url).removeClass('hidden');
+  // Update the preview button:
+  $link.attr('href', url).removeClass('hidden')
+       .attr('rel', 'noopener'); // Performance improvement
 
-    // Update associated record thumbnail, if any:
+  // Update associated record thumbnail, if any:
   $link.parents('.result,.record')
-        .find('.recordcover[data-linkpreview="true"]').parents('a').attr('href', url);
+       .find('.recordcover[data-linkpreview="true"]').parents('a').attr('href', url)
+       .attr('rel', 'noopener');
 }
 
 function processBookInfo(booksInfo, previewClass, viewOptions) {
diff --git a/themes/bootstrap3/js/record.js b/themes/bootstrap3/js/record.js
index 34749a9f4dc47c29ef5348a7463f8d192102e36e..07dfebbf637a91d562429e51d5995825facf398c 100644
--- a/themes/bootstrap3/js/record.js
+++ b/themes/bootstrap3/js/record.js
@@ -1,4 +1,4 @@
-/*global deparam, grecaptcha, recaptchaOnLoad, syn_get_widget, userIsLoggedIn, VuFind */
+/*global deparam, getUrlRoot, grecaptcha, recaptchaOnLoad, resetCaptcha, syn_get_widget, userIsLoggedIn, VuFind */
 /*exported ajaxTagUpdate, recordDocReady */
 
 /**
@@ -78,9 +78,7 @@ function refreshCommentList($target, recordId, recordSource) {
       return false;
     });
     $target.find('.comment-form input[type="submit"]').button('reset');
-    if (typeof grecaptcha !== 'undefined') {
-      grecaptcha.reset();
-    }
+    resetCaptcha($target);
   });
 }
 
@@ -109,16 +107,15 @@ function registerAjaxCommentRecord() {
       dataType: 'json'
     })
     .done(function addCommentDone(/*response, textStatus*/) {
-      var $tab = $(form).closest('.list-tab-content');
+      var $form = $(form);
+      var $tab = $form.closest('.list-tab-content');
       if (!$tab.length) {
-        $tab = $(form).closest('.tab-pane');
+        $tab = $form.closest('.tab-pane');
       }
       refreshCommentList($tab, id, recordSource);
-      $(form).find('textarea[name="comment"]').val('');
-      $(form).find('input[type="submit"]').button('loading');
-      if (typeof grecaptcha !== 'undefined') {
-        grecaptcha.reset($(form).find('.g-recaptcha').data('captchaId'));
-      }
+      $form.find('textarea[name="comment"]').val('');
+      $form.find('input[type="submit"]').button('loading');
+      resetCaptcha($form);
     })
     .fail(function addCommentFail(response, textStatus) {
       if (textStatus === 'abort' || typeof response.responseJSON === 'undefined') { return; }
@@ -152,31 +149,28 @@ function registerTabEvents() {
   VuFind.lightbox.bind('.tab-pane.active');
 }
 
-function ajaxLoadTab($newTab, tabid, setHash) {
-  // Parse out the base URL for the current record:
-  var urlParts = document.URL.split(/[?#]/);
-  var urlWithoutFragment = urlParts[0];
-  var path = VuFind.path;
-  var urlroot = null;
-  if (path === '') {
-    // special case -- VuFind installed at site root:
-    var chunks = urlWithoutFragment.split('/');
-    urlroot = '/' + chunks[3] + '/' + chunks[4];
+function removeHashFromLocation() {
+  if (window.history.replaceState) {
+    var href = window.location.href.split('#');
+    window.history.replaceState({}, document.title, href[0]);
   } else {
-    // standard case -- VuFind has its own path under site:
-    var pathInUrl = urlWithoutFragment.indexOf(path, urlWithoutFragment.indexOf('//') + 2);
-    var parts = urlWithoutFragment.substring(pathInUrl + path.length + 1).split('/');
-    urlroot = '/' + parts[0] + '/' + parts[1];
+    window.location.hash = '#';
   }
+}
 
+function ajaxLoadTab($newTab, tabid, setHash) {
   // Request the tab via AJAX:
   $.ajax({
-    url: path + urlroot + '/AjaxTab',
+    url: VuFind.path + getUrlRoot(document.URL) + '/AjaxTab',
     type: 'POST',
     data: {tab: tabid}
   })
-  .done(function ajaxLoadTabDone(data) {
-    $newTab.html(data);
+  .always(function ajaxLoadTabDone(data) {
+    if (typeof data === 'object') {
+      $newTab.html(data.responseText ? data.responseText : VuFind.translate('error_occurred'));
+    } else {
+      $newTab.html(data);
+    }
     registerTabEvents();
     if (typeof syn_get_widget === "function") {
       syn_get_widget();
@@ -266,15 +260,6 @@ function applyRecordTabHash() {
   }
 }
 
-function removeHashFromLocation() {
-  if (window.history.replaceState) {
-    var href = window.location.href.split('#');
-    window.history.replaceState({}, document.title, href[0]);  
-  } else {
-    window.location.hash = '#';  
-  }
-}
-
 $(window).on('hashchange', applyRecordTabHash);
 
 function recordDocReady() {
diff --git a/themes/bootstrap3/js/vendor/bootstrap-slider.js b/themes/bootstrap3/js/vendor/bootstrap-slider.js
deleted file mode 100644
index 8694ee7f38bbee3416a94673497827b49138bb86..0000000000000000000000000000000000000000
--- a/themes/bootstrap3/js/vendor/bootstrap-slider.js
+++ /dev/null
@@ -1,29 +0,0 @@
-/*! =======================================================
-                      VERSION  7.1.1
-========================================================= */
-"use strict";function _typeof(a){return a&&"undefined"!=typeof Symbol&&a.constructor===Symbol?"symbol":typeof a}/*! =========================================================
- * bootstrap-slider.js
- *
- * Maintainers:
- *		Kyle Kemp
- *			- Twitter: @seiyria
- *			- Github:  seiyria
- *		Rohit Kalkur
- *			- Twitter: @Rovolutionary
- *			- Github:  rovolution
- *
- * =========================================================
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================================================= */
-!function(a){if("function"==typeof define&&define.amd)try{define(["jquery"],a)}catch(b){define([],a)}else if("object"===("undefined"==typeof module?"undefined":_typeof(module))&&module.exports){var c;try{c=require("jquery")}catch(b){c=null}module.exports=a(c)}else window&&(window.Slider=a(window.jQuery))}(function(a){var b;return function(a){function b(){}function c(a){function c(b){b.prototype.option||(b.prototype.option=function(b){a.isPlainObject(b)&&(this.options=a.extend(!0,this.options,b))})}function e(b,c){a.fn[b]=function(e){if("string"==typeof e){for(var g=d.call(arguments,1),h=0,i=this.length;i>h;h++){var j=this[h],k=a.data(j,b);if(k)if(a.isFunction(k[e])&&"_"!==e.charAt(0)){var l=k[e].apply(k,g);if(void 0!==l&&l!==k)return l}else f("no such method '"+e+"' for "+b+" instance");else f("cannot call methods on "+b+" prior to initialization; attempted to call '"+e+"'")}return this}var m=this.map(function(){var d=a.data(this,b);return d?(d.option(e),d._init()):(d=new c(this,e),a.data(this,b,d)),a(this)});return!m||m.length>1?m:m[0]}}if(a){var f="undefined"==typeof console?b:function(a){console.error(a)};return a.bridget=function(a,b){c(b),e(a,b)},a.bridget}}var d=Array.prototype.slice;c(a)}(a),function(a){function c(b,c){function d(a,b){var c="data-slider-"+b.replace(/_/g,"-"),d=a.getAttribute(c);try{return JSON.parse(d)}catch(e){return d}}this._state={value:null,enabled:null,offset:null,size:null,percentage:null,inDrag:!1,over:!1},"string"==typeof b?this.element=document.querySelector(b):b instanceof HTMLElement&&(this.element=b),c=c?c:{};for(var f=Object.keys(this.defaultOptions),g=0;g<f.length;g++){var h=f[g],i=c[h];i="undefined"!=typeof i?i:d(this.element,h),i=null!==i?i:this.defaultOptions[h],this.options||(this.options={}),this.options[h]=i}"vertical"!==this.options.orientation||"top"!==this.options.tooltip_position&&"bottom"!==this.options.tooltip_position?"horizontal"!==this.options.orientation||"left"!==this.options.tooltip_position&&"right"!==this.options.tooltip_position||(this.options.tooltip_position="top"):this.options.tooltip_position="right";var j,k,l,m,n,o=this.element.style.width,p=!1,q=this.element.parentNode;if(this.sliderElem)p=!0;else{this.sliderElem=document.createElement("div"),this.sliderElem.className="slider";var r=document.createElement("div");r.className="slider-track",k=document.createElement("div"),k.className="slider-track-low",j=document.createElement("div"),j.className="slider-selection",l=document.createElement("div"),l.className="slider-track-high",m=document.createElement("div"),m.className="slider-handle min-slider-handle",m.setAttribute("role","slider"),m.setAttribute("aria-valuemin",this.options.min),m.setAttribute("aria-valuemax",this.options.max),n=document.createElement("div"),n.className="slider-handle max-slider-handle",n.setAttribute("role","slider"),n.setAttribute("aria-valuemin",this.options.min),n.setAttribute("aria-valuemax",this.options.max),r.appendChild(k),r.appendChild(j),r.appendChild(l);var s=Array.isArray(this.options.labelledby);if(s&&this.options.labelledby[0]&&m.setAttribute("aria-labelledby",this.options.labelledby[0]),s&&this.options.labelledby[1]&&n.setAttribute("aria-labelledby",this.options.labelledby[1]),!s&&this.options.labelledby&&(m.setAttribute("aria-labelledby",this.options.labelledby),n.setAttribute("aria-labelledby",this.options.labelledby)),this.ticks=[],Array.isArray(this.options.ticks)&&this.options.ticks.length>0){for(g=0;g<this.options.ticks.length;g++){var t=document.createElement("div");t.className="slider-tick",this.ticks.push(t),r.appendChild(t)}j.className+=" tick-slider-selection"}if(r.appendChild(m),r.appendChild(n),this.tickLabels=[],Array.isArray(this.options.ticks_labels)&&this.options.ticks_labels.length>0)for(this.tickLabelContainer=document.createElement("div"),this.tickLabelContainer.className="slider-tick-label-container",g=0;g<this.options.ticks_labels.length;g++){var u=document.createElement("div"),v=0===this.options.ticks_positions.length,w=this.options.reversed&&v?this.options.ticks_labels.length-(g+1):g;u.className="slider-tick-label",u.innerHTML=this.options.ticks_labels[w],this.tickLabels.push(u),this.tickLabelContainer.appendChild(u)}var x=function(a){var b=document.createElement("div");b.className="tooltip-arrow";var c=document.createElement("div");c.className="tooltip-inner",a.appendChild(b),a.appendChild(c)},y=document.createElement("div");y.className="tooltip tooltip-main",y.setAttribute("role","presentation"),x(y);var z=document.createElement("div");z.className="tooltip tooltip-min",z.setAttribute("role","presentation"),x(z);var A=document.createElement("div");A.className="tooltip tooltip-max",A.setAttribute("role","presentation"),x(A),this.sliderElem.appendChild(r),this.sliderElem.appendChild(y),this.sliderElem.appendChild(z),this.sliderElem.appendChild(A),this.tickLabelContainer&&this.sliderElem.appendChild(this.tickLabelContainer),q.insertBefore(this.sliderElem,this.element),this.element.style.display="none"}if(a&&(this.$element=a(this.element),this.$sliderElem=a(this.sliderElem)),this.eventToCallbackMap={},this.sliderElem.id=this.options.id,this.touchCapable="ontouchstart"in window||window.DocumentTouch&&document instanceof window.DocumentTouch,this.touchX=0,this.touchY=0,this.tooltip=this.sliderElem.querySelector(".tooltip-main"),this.tooltipInner=this.tooltip.querySelector(".tooltip-inner"),this.tooltip_min=this.sliderElem.querySelector(".tooltip-min"),this.tooltipInner_min=this.tooltip_min.querySelector(".tooltip-inner"),this.tooltip_max=this.sliderElem.querySelector(".tooltip-max"),this.tooltipInner_max=this.tooltip_max.querySelector(".tooltip-inner"),e[this.options.scale]&&(this.options.scale=e[this.options.scale]),p===!0&&(this._removeClass(this.sliderElem,"slider-horizontal"),this._removeClass(this.sliderElem,"slider-vertical"),this._removeClass(this.tooltip,"hide"),this._removeClass(this.tooltip_min,"hide"),this._removeClass(this.tooltip_max,"hide"),["left","top","width","height"].forEach(function(a){this._removeProperty(this.trackLow,a),this._removeProperty(this.trackSelection,a),this._removeProperty(this.trackHigh,a)},this),[this.handle1,this.handle2].forEach(function(a){this._removeProperty(a,"left"),this._removeProperty(a,"top")},this),[this.tooltip,this.tooltip_min,this.tooltip_max].forEach(function(a){this._removeProperty(a,"left"),this._removeProperty(a,"top"),this._removeProperty(a,"margin-left"),this._removeProperty(a,"margin-top"),this._removeClass(a,"right"),this._removeClass(a,"top")},this)),"vertical"===this.options.orientation?(this._addClass(this.sliderElem,"slider-vertical"),this.stylePos="top",this.mousePos="pageY",this.sizePos="offsetHeight"):(this._addClass(this.sliderElem,"slider-horizontal"),this.sliderElem.style.width=o,this.options.orientation="horizontal",this.stylePos="left",this.mousePos="pageX",this.sizePos="offsetWidth"),this._setTooltipPosition(),Array.isArray(this.options.ticks)&&this.options.ticks.length>0&&(this.options.max=Math.max.apply(Math,this.options.ticks),this.options.min=Math.min.apply(Math,this.options.ticks)),Array.isArray(this.options.value)?(this.options.range=!0,this._state.value=this.options.value):this.options.range?this._state.value=[this.options.value,this.options.max]:this._state.value=this.options.value,this.trackLow=k||this.trackLow,this.trackSelection=j||this.trackSelection,this.trackHigh=l||this.trackHigh,"none"===this.options.selection&&(this._addClass(this.trackLow,"hide"),this._addClass(this.trackSelection,"hide"),this._addClass(this.trackHigh,"hide")),this.handle1=m||this.handle1,this.handle2=n||this.handle2,p===!0)for(this._removeClass(this.handle1,"round triangle"),this._removeClass(this.handle2,"round triangle hide"),g=0;g<this.ticks.length;g++)this._removeClass(this.ticks[g],"round triangle hide");var B=["round","triangle","custom"],C=-1!==B.indexOf(this.options.handle);if(C)for(this._addClass(this.handle1,this.options.handle),this._addClass(this.handle2,this.options.handle),g=0;g<this.ticks.length;g++)this._addClass(this.ticks[g],this.options.handle);this._state.offset=this._offset(this.sliderElem),this._state.size=this.sliderElem[this.sizePos],this.setValue(this._state.value),this.handle1Keydown=this._keydown.bind(this,0),this.handle1.addEventListener("keydown",this.handle1Keydown,!1),this.handle2Keydown=this._keydown.bind(this,1),this.handle2.addEventListener("keydown",this.handle2Keydown,!1),this.mousedown=this._mousedown.bind(this),this.touchstart=this._touchstart.bind(this),this.touchmove=this._touchmove.bind(this),this.touchCapable&&(this.sliderElem.addEventListener("touchstart",this.touchstart,!1),this.sliderElem.addEventListener("touchmove",this.touchmove,!1)),this.sliderElem.addEventListener("mousedown",this.mousedown,!1),this.resize=this._resize.bind(this),window.addEventListener("resize",this.resize,!1),"hide"===this.options.tooltip?(this._addClass(this.tooltip,"hide"),this._addClass(this.tooltip_min,"hide"),this._addClass(this.tooltip_max,"hide")):"always"===this.options.tooltip?(this._showTooltip(),this._alwaysShowTooltip=!0):(this.showTooltip=this._showTooltip.bind(this),this.hideTooltip=this._hideTooltip.bind(this),this.sliderElem.addEventListener("mouseenter",this.showTooltip,!1),this.sliderElem.addEventListener("mouseleave",this.hideTooltip,!1),this.handle1.addEventListener("focus",this.showTooltip,!1),this.handle1.addEventListener("blur",this.hideTooltip,!1),this.handle2.addEventListener("focus",this.showTooltip,!1),this.handle2.addEventListener("blur",this.hideTooltip,!1)),this.options.enabled?this.enable():this.disable()}var d={formatInvalidInputErrorMsg:function(a){return"Invalid input value '"+a+"' passed in"},callingContextNotSliderInstance:"Calling context element does not have instance of Slider bound to it. Check your code to make sure the JQuery object returned from the call to the slider() initializer is calling the method"},e={linear:{toValue:function(a){var b=a/100*(this.options.max-this.options.min),c=!0;if(this.options.ticks_positions.length>0){for(var d,e,f,g=0,h=1;h<this.options.ticks_positions.length;h++)if(a<=this.options.ticks_positions[h]){d=this.options.ticks[h-1],f=this.options.ticks_positions[h-1],e=this.options.ticks[h],g=this.options.ticks_positions[h];break}var i=(a-f)/(g-f);b=d+i*(e-d),c=!1}var j=c?this.options.min:0,k=j+Math.round(b/this.options.step)*this.options.step;return k<this.options.min?this.options.min:k>this.options.max?this.options.max:k},toPercentage:function(a){if(this.options.max===this.options.min)return 0;if(this.options.ticks_positions.length>0){for(var b,c,d,e=0,f=0;f<this.options.ticks.length;f++)if(a<=this.options.ticks[f]){b=f>0?this.options.ticks[f-1]:0,d=f>0?this.options.ticks_positions[f-1]:0,c=this.options.ticks[f],e=this.options.ticks_positions[f];break}if(f>0){var g=(a-b)/(c-b);return d+g*(e-d)}}return 100*(a-this.options.min)/(this.options.max-this.options.min)}},logarithmic:{toValue:function(a){var b=0===this.options.min?0:Math.log(this.options.min),c=Math.log(this.options.max),d=Math.exp(b+(c-b)*a/100);return d=this.options.min+Math.round((d-this.options.min)/this.options.step)*this.options.step,d<this.options.min?this.options.min:d>this.options.max?this.options.max:d},toPercentage:function(a){if(this.options.max===this.options.min)return 0;var b=Math.log(this.options.max),c=0===this.options.min?0:Math.log(this.options.min),d=0===a?0:Math.log(a);return 100*(d-c)/(b-c)}}};if(b=function(a,b){return c.call(this,a,b),this},b.prototype={_init:function(){},constructor:b,defaultOptions:{id:"",min:0,max:10,step:1,precision:0,orientation:"horizontal",value:5,range:!1,selection:"before",tooltip:"show",tooltip_split:!1,handle:"round",reversed:!1,enabled:!0,formatter:function(a){return Array.isArray(a)?a[0]+" : "+a[1]:a},natural_arrow_keys:!1,ticks:[],ticks_positions:[],ticks_labels:[],ticks_snap_bounds:0,scale:"linear",focus:!1,tooltip_position:null,labelledby:null},getElement:function(){return this.sliderElem},getValue:function(){return this.options.range?this._state.value:this._state.value[0]},setValue:function(a,b,c){a||(a=0);var d=this.getValue();this._state.value=this._validateInputValue(a);var e=this._applyPrecision.bind(this);this.options.range?(this._state.value[0]=e(this._state.value[0]),this._state.value[1]=e(this._state.value[1]),this._state.value[0]=Math.max(this.options.min,Math.min(this.options.max,this._state.value[0])),this._state.value[1]=Math.max(this.options.min,Math.min(this.options.max,this._state.value[1]))):(this._state.value=e(this._state.value),this._state.value=[Math.max(this.options.min,Math.min(this.options.max,this._state.value))],this._addClass(this.handle2,"hide"),"after"===this.options.selection?this._state.value[1]=this.options.max:this._state.value[1]=this.options.min),this.options.max>this.options.min?this._state.percentage=[this._toPercentage(this._state.value[0]),this._toPercentage(this._state.value[1]),100*this.options.step/(this.options.max-this.options.min)]:this._state.percentage=[0,0,100],this._layout();var f=this.options.range?this._state.value:this._state.value[0];return this._setDataVal(f),b===!0&&this._trigger("slide",f),d!==f&&c===!0&&this._trigger("change",{oldValue:d,newValue:f}),this},destroy:function(){this._removeSliderEventHandlers(),this.sliderElem.parentNode.removeChild(this.sliderElem),this.element.style.display="",this._cleanUpEventCallbacksMap(),this.element.removeAttribute("data"),a&&(this._unbindJQueryEventHandlers(),this.$element.removeData("slider"))},disable:function(){return this._state.enabled=!1,this.handle1.removeAttribute("tabindex"),this.handle2.removeAttribute("tabindex"),this._addClass(this.sliderElem,"slider-disabled"),this._trigger("slideDisabled"),this},enable:function(){return this._state.enabled=!0,this.handle1.setAttribute("tabindex",0),this.handle2.setAttribute("tabindex",0),this._removeClass(this.sliderElem,"slider-disabled"),this._trigger("slideEnabled"),this},toggle:function(){return this._state.enabled?this.disable():this.enable(),this},isEnabled:function(){return this._state.enabled},on:function(a,b){return this._bindNonQueryEventHandler(a,b),this},off:function(b,c){a?(this.$element.off(b,c),this.$sliderElem.off(b,c)):this._unbindNonQueryEventHandler(b,c)},getAttribute:function(a){return a?this.options[a]:this.options},setAttribute:function(a,b){return this.options[a]=b,this},refresh:function(){return this._removeSliderEventHandlers(),c.call(this,this.element,this.options),a&&a.data(this.element,"slider",this),this},relayout:function(){return this._resize(),this._layout(),this},_removeSliderEventHandlers:function(){this.handle1.removeEventListener("keydown",this.handle1Keydown,!1),this.handle2.removeEventListener("keydown",this.handle2Keydown,!1),this.showTooltip&&(this.handle1.removeEventListener("focus",this.showTooltip,!1),this.handle2.removeEventListener("focus",this.showTooltip,!1)),this.hideTooltip&&(this.handle1.removeEventListener("blur",this.hideTooltip,!1),this.handle2.removeEventListener("blur",this.hideTooltip,!1)),this.showTooltip&&this.sliderElem.removeEventListener("mouseenter",this.showTooltip,!1),this.hideTooltip&&this.sliderElem.removeEventListener("mouseleave",this.hideTooltip,!1),this.sliderElem.removeEventListener("touchstart",this.touchstart,!1),this.sliderElem.removeEventListener("touchmove",this.touchmove,!1),this.sliderElem.removeEventListener("mousedown",this.mousedown,!1),window.removeEventListener("resize",this.resize,!1)},_bindNonQueryEventHandler:function(a,b){void 0===this.eventToCallbackMap[a]&&(this.eventToCallbackMap[a]=[]),this.eventToCallbackMap[a].push(b)},_unbindNonQueryEventHandler:function(a,b){var c=this.eventToCallbackMap[a];if(void 0!==c)for(var d=0;d<c.length;d++)if(c[d]===b){c.splice(d,1);break}},_cleanUpEventCallbacksMap:function(){for(var a=Object.keys(this.eventToCallbackMap),b=0;b<a.length;b++){var c=a[b];this.eventToCallbackMap[c]=null}},_showTooltip:function(){this.options.tooltip_split===!1?(this._addClass(this.tooltip,"in"),this.tooltip_min.style.display="none",this.tooltip_max.style.display="none"):(this._addClass(this.tooltip_min,"in"),this._addClass(this.tooltip_max,"in"),this.tooltip.style.display="none"),this._state.over=!0},_hideTooltip:function(){this._state.inDrag===!1&&this.alwaysShowTooltip!==!0&&(this._removeClass(this.tooltip,"in"),this._removeClass(this.tooltip_min,"in"),this._removeClass(this.tooltip_max,"in")),this._state.over=!1},_layout:function(){var a;if(a=this.options.reversed?[100-this._state.percentage[0],this.options.range?100-this._state.percentage[1]:this._state.percentage[1]]:[this._state.percentage[0],this._state.percentage[1]],this.handle1.style[this.stylePos]=a[0]+"%",this.handle1.setAttribute("aria-valuenow",this._state.value[0]),this.handle2.style[this.stylePos]=a[1]+"%",this.handle2.setAttribute("aria-valuenow",this._state.value[1]),Array.isArray(this.options.ticks)&&this.options.ticks.length>0){var b="vertical"===this.options.orientation?"height":"width",c="vertical"===this.options.orientation?"marginTop":"marginLeft",d=this._state.size/(this.options.ticks.length-1);if(this.tickLabelContainer){var e=0;if(0===this.options.ticks_positions.length)"vertical"!==this.options.orientation&&(this.tickLabelContainer.style[c]=-d/2+"px"),e=this.tickLabelContainer.offsetHeight;else for(f=0;f<this.tickLabelContainer.childNodes.length;f++)this.tickLabelContainer.childNodes[f].offsetHeight>e&&(e=this.tickLabelContainer.childNodes[f].offsetHeight);"horizontal"===this.options.orientation&&(this.sliderElem.style.marginBottom=e+"px")}for(var f=0;f<this.options.ticks.length;f++){var g=this.options.ticks_positions[f]||this._toPercentage(this.options.ticks[f]);this.options.reversed&&(g=100-g),this.ticks[f].style[this.stylePos]=g+"%",this._removeClass(this.ticks[f],"in-selection"),this.options.range?g>=a[0]&&g<=a[1]&&this._addClass(this.ticks[f],"in-selection"):"after"===this.options.selection&&g>=a[0]?this._addClass(this.ticks[f],"in-selection"):"before"===this.options.selection&&g<=a[0]&&this._addClass(this.ticks[f],"in-selection"),this.tickLabels[f]&&(this.tickLabels[f].style[b]=d+"px","vertical"!==this.options.orientation&&void 0!==this.options.ticks_positions[f]?(this.tickLabels[f].style.position="absolute",this.tickLabels[f].style[this.stylePos]=g+"%",this.tickLabels[f].style[c]=-d/2+"px"):"vertical"===this.options.orientation&&(this.tickLabels[f].style.marginLeft=this.sliderElem.offsetWidth+"px",this.tickLabelContainer.style.marginTop=this.sliderElem.offsetWidth/2*-1+"px"))}}var h;if(this.options.range){h=this.options.formatter(this._state.value),this._setText(this.tooltipInner,h),this.tooltip.style[this.stylePos]=(a[1]+a[0])/2+"%","vertical"===this.options.orientation?this._css(this.tooltip,"margin-top",-this.tooltip.offsetHeight/2+"px"):this._css(this.tooltip,"margin-left",-this.tooltip.offsetWidth/2+"px"),"vertical"===this.options.orientation?this._css(this.tooltip,"margin-top",-this.tooltip.offsetHeight/2+"px"):this._css(this.tooltip,"margin-left",-this.tooltip.offsetWidth/2+"px");var i=this.options.formatter(this._state.value[0]);this._setText(this.tooltipInner_min,i);var j=this.options.formatter(this._state.value[1]);this._setText(this.tooltipInner_max,j),this.tooltip_min.style[this.stylePos]=a[0]+"%","vertical"===this.options.orientation?this._css(this.tooltip_min,"margin-top",-this.tooltip_min.offsetHeight/2+"px"):this._css(this.tooltip_min,"margin-left",-this.tooltip_min.offsetWidth/2+"px"),this.tooltip_max.style[this.stylePos]=a[1]+"%","vertical"===this.options.orientation?this._css(this.tooltip_max,"margin-top",-this.tooltip_max.offsetHeight/2+"px"):this._css(this.tooltip_max,"margin-left",-this.tooltip_max.offsetWidth/2+"px")}else h=this.options.formatter(this._state.value[0]),this._setText(this.tooltipInner,h),this.tooltip.style[this.stylePos]=a[0]+"%","vertical"===this.options.orientation?this._css(this.tooltip,"margin-top",-this.tooltip.offsetHeight/2+"px"):this._css(this.tooltip,"margin-left",-this.tooltip.offsetWidth/2+"px");if("vertical"===this.options.orientation)this.trackLow.style.top="0",this.trackLow.style.height=Math.min(a[0],a[1])+"%",this.trackSelection.style.top=Math.min(a[0],a[1])+"%",this.trackSelection.style.height=Math.abs(a[0]-a[1])+"%",this.trackHigh.style.bottom="0",this.trackHigh.style.height=100-Math.min(a[0],a[1])-Math.abs(a[0]-a[1])+"%";else{this.trackLow.style.left="0",this.trackLow.style.width=Math.min(a[0],a[1])+"%",this.trackSelection.style.left=Math.min(a[0],a[1])+"%",this.trackSelection.style.width=Math.abs(a[0]-a[1])+"%",this.trackHigh.style.right="0",this.trackHigh.style.width=100-Math.min(a[0],a[1])-Math.abs(a[0]-a[1])+"%";var k=this.tooltip_min.getBoundingClientRect(),l=this.tooltip_max.getBoundingClientRect();"bottom"===this.options.tooltip_position?k.right>l.left?(this._removeClass(this.tooltip_max,"bottom"),this._addClass(this.tooltip_max,"top"),this.tooltip_max.style.top="",this.tooltip_max.style.bottom="22px"):(this._removeClass(this.tooltip_max,"top"),this._addClass(this.tooltip_max,"bottom"),this.tooltip_max.style.top=this.tooltip_min.style.top,this.tooltip_max.style.bottom=""):k.right>l.left?(this._removeClass(this.tooltip_max,"top"),this._addClass(this.tooltip_max,"bottom"),this.tooltip_max.style.top="18px"):(this._removeClass(this.tooltip_max,"bottom"),this._addClass(this.tooltip_max,"top"),this.tooltip_max.style.top=this.tooltip_min.style.top)}},_resize:function(a){this._state.offset=this._offset(this.sliderElem),this._state.size=this.sliderElem[this.sizePos],this._layout()},_removeProperty:function(a,b){a.style.removeProperty?a.style.removeProperty(b):a.style.removeAttribute(b)},_mousedown:function(a){if(!this._state.enabled)return!1;this._state.offset=this._offset(this.sliderElem),this._state.size=this.sliderElem[this.sizePos];var b=this._getPercentage(a);if(this.options.range){var c=Math.abs(this._state.percentage[0]-b),d=Math.abs(this._state.percentage[1]-b);this._state.dragged=d>c?0:1,this._adjustPercentageForRangeSliders(b)}else this._state.dragged=0;this._state.percentage[this._state.dragged]=b,this._layout(),this.touchCapable&&(document.removeEventListener("touchmove",this.mousemove,!1),document.removeEventListener("touchend",this.mouseup,!1)),this.mousemove&&document.removeEventListener("mousemove",this.mousemove,!1),this.mouseup&&document.removeEventListener("mouseup",this.mouseup,!1),this.mousemove=this._mousemove.bind(this),this.mouseup=this._mouseup.bind(this),this.touchCapable&&(document.addEventListener("touchmove",this.mousemove,!1),document.addEventListener("touchend",this.mouseup,!1)),document.addEventListener("mousemove",this.mousemove,!1),document.addEventListener("mouseup",this.mouseup,!1),this._state.inDrag=!0;var e=this._calculateValue();return this._trigger("slideStart",e),this._setDataVal(e),this.setValue(e,!1,!0),this._pauseEvent(a),this.options.focus&&this._triggerFocusOnHandle(this._state.dragged),!0},_touchstart:function(a){if(void 0===a.changedTouches)return void this._mousedown(a);var b=a.changedTouches[0];this.touchX=b.pageX,this.touchY=b.pageY},_triggerFocusOnHandle:function(a){0===a&&this.handle1.focus(),1===a&&this.handle2.focus()},_keydown:function(a,b){if(!this._state.enabled)return!1;var c;switch(b.keyCode){case 37:case 40:c=-1;break;case 39:case 38:c=1}if(c){if(this.options.natural_arrow_keys){var d="vertical"===this.options.orientation&&!this.options.reversed,e="horizontal"===this.options.orientation&&this.options.reversed;(d||e)&&(c=-c)}var f=this._state.value[a]+c*this.options.step;return this.options.range&&(f=[a?this._state.value[0]:f,a?f:this._state.value[1]]),this._trigger("slideStart",f),this._setDataVal(f),this.setValue(f,!0,!0),this._setDataVal(f),this._trigger("slideStop",f),this._layout(),this._pauseEvent(b),!1}},_pauseEvent:function(a){a.stopPropagation&&a.stopPropagation(),a.preventDefault&&a.preventDefault(),a.cancelBubble=!0,a.returnValue=!1},_mousemove:function(a){if(!this._state.enabled)return!1;var b=this._getPercentage(a);this._adjustPercentageForRangeSliders(b),this._state.percentage[this._state.dragged]=b,this._layout();var c=this._calculateValue(!0);return this.setValue(c,!0,!0),!1},_touchmove:function(a){if(void 0!==a.changedTouches){var b=a.changedTouches[0],c=b.pageX-this.touchX,d=b.pageY-this.touchY;this._state.inDrag||("vertical"===this.options.orientation&&5>=c&&c>=-5&&(d>=15||-15>=d)?this._mousedown(a):5>=d&&d>=-5&&(c>=15||-15>=c)&&this._mousedown(a))}},_adjustPercentageForRangeSliders:function(a){if(this.options.range){var b=this._getNumDigitsAfterDecimalPlace(a);b=b?b-1:0;var c=this._applyToFixedAndParseFloat(a,b);0===this._state.dragged&&this._applyToFixedAndParseFloat(this._state.percentage[1],b)<c?(this._state.percentage[0]=this._state.percentage[1],this._state.dragged=1):1===this._state.dragged&&this._applyToFixedAndParseFloat(this._state.percentage[0],b)>c&&(this._state.percentage[1]=this._state.percentage[0],this._state.dragged=0)}},_mouseup:function(){if(!this._state.enabled)return!1;this.touchCapable&&(document.removeEventListener("touchmove",this.mousemove,!1),document.removeEventListener("touchend",this.mouseup,!1)),document.removeEventListener("mousemove",this.mousemove,!1),document.removeEventListener("mouseup",this.mouseup,!1),this._state.inDrag=!1,this._state.over===!1&&this._hideTooltip();var a=this._calculateValue(!0);return this._layout(),this._setDataVal(a),this._trigger("slideStop",a),!1},_calculateValue:function(a){var b;if(this.options.range?(b=[this.options.min,this.options.max],0!==this._state.percentage[0]&&(b[0]=this._toValue(this._state.percentage[0]),b[0]=this._applyPrecision(b[0])),100!==this._state.percentage[1]&&(b[1]=this._toValue(this._state.percentage[1]),b[1]=this._applyPrecision(b[1]))):(b=this._toValue(this._state.percentage[0]),b=parseFloat(b),b=this._applyPrecision(b)),a){for(var c=[b,1/0],d=0;d<this.options.ticks.length;d++){var e=Math.abs(this.options.ticks[d]-b);e<=c[1]&&(c=[this.options.ticks[d],e])}if(c[1]<=this.options.ticks_snap_bounds)return c[0]}return b},_applyPrecision:function(a){var b=this.options.precision||this._getNumDigitsAfterDecimalPlace(this.options.step);return this._applyToFixedAndParseFloat(a,b)},_getNumDigitsAfterDecimalPlace:function(a){var b=(""+a).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);return b?Math.max(0,(b[1]?b[1].length:0)-(b[2]?+b[2]:0)):0},_applyToFixedAndParseFloat:function(a,b){var c=a.toFixed(b);return parseFloat(c)},_getPercentage:function(a){!this.touchCapable||"touchstart"!==a.type&&"touchmove"!==a.type||(a=a.touches[0]);var b=a[this.mousePos],c=this._state.offset[this.stylePos],d=b-c,e=d/this._state.size*100;return e=Math.round(e/this._state.percentage[2])*this._state.percentage[2],this.options.reversed&&(e=100-e),Math.max(0,Math.min(100,e))},_validateInputValue:function(a){if("number"==typeof a)return a;if(Array.isArray(a))return this._validateArray(a),a;throw new Error(d.formatInvalidInputErrorMsg(a))},_validateArray:function(a){for(var b=0;b<a.length;b++){var c=a[b];if("number"!=typeof c)throw new Error(d.formatInvalidInputErrorMsg(c))}},_setDataVal:function(a){this.element.setAttribute("data-value",a),this.element.setAttribute("value",a),this.element.value=a},_trigger:function(b,c){c=c||0===c?c:void 0;var d=this.eventToCallbackMap[b];if(d&&d.length)for(var e=0;e<d.length;e++){var f=d[e];f(c)}a&&this._triggerJQueryEvent(b,c)},_triggerJQueryEvent:function(a,b){var c={type:a,value:b};this.$element.trigger(c),this.$sliderElem.trigger(c)},_unbindJQueryEventHandlers:function(){this.$element.off(),this.$sliderElem.off()},_setText:function(a,b){"undefined"!=typeof a.textContent?a.textContent=b:"undefined"!=typeof a.innerText&&(a.innerText=b)},_removeClass:function(a,b){for(var c=b.split(" "),d=a.className,e=0;e<c.length;e++){var f=c[e],g=new RegExp("(?:\\s|^)"+f+"(?:\\s|$)");d=d.replace(g," ")}a.className=d.trim()},_addClass:function(a,b){for(var c=b.split(" "),d=a.className,e=0;e<c.length;e++){var f=c[e],g=new RegExp("(?:\\s|^)"+f+"(?:\\s|$)"),h=g.test(d);h||(d+=" "+f)}a.className=d.trim()},_offsetLeft:function(a){return a.getBoundingClientRect().left},_offsetTop:function(a){for(var b=a.offsetTop;(a=a.offsetParent)&&!isNaN(a.offsetTop);)b+=a.offsetTop,"BODY"!==a.tagName&&(b-=a.scrollTop);return b},_offset:function(a){return{left:this._offsetLeft(a),top:this._offsetTop(a)}},_css:function(b,c,d){if(a)a.style(b,c,d);else{var e=c.replace(/^-ms-/,"ms-").replace(/-([\da-z])/gi,function(a,b){return b.toUpperCase()});b.style[e]=d}},_toValue:function(a){return this.options.scale.toValue.apply(this,[a])},_toPercentage:function(a){return this.options.scale.toPercentage.apply(this,[a])},_setTooltipPosition:function(){var a=[this.tooltip,this.tooltip_min,this.tooltip_max];if("vertical"===this.options.orientation){var b=this.options.tooltip_position||"right",c="left"===b?"right":"left";a.forEach(function(a){this._addClass(a,b),a.style[c]="100%"}.bind(this))}else"bottom"===this.options.tooltip_position?a.forEach(function(a){this._addClass(a,"bottom"),a.style.top="22px"}.bind(this)):a.forEach(function(a){this._addClass(a,"top"),a.style.top=-this.tooltip.outerHeight-14+"px"}.bind(this))}},a){var f=a.fn.slider?"bootstrapSlider":"slider";a.bridget(f,b),a(function(){a("input[data-provide=slider]")[f]()})}}(a),b});
\ No newline at end of file
diff --git a/themes/bootstrap3/js/vendor/bootstrap-slider.min.js b/themes/bootstrap3/js/vendor/bootstrap-slider.min.js
new file mode 100644
index 0000000000000000000000000000000000000000..efeb7b1916eb0187ad26f129175754a312189760
--- /dev/null
+++ b/themes/bootstrap3/js/vendor/bootstrap-slider.min.js
@@ -0,0 +1,5 @@
+/*! =======================================================
+                      VERSION  9.7.0              
+========================================================= */
+"use strict";var _typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(a){return typeof a}:function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a},windowIsDefined="object"===("undefined"==typeof window?"undefined":_typeof(window));!function(a){if("function"==typeof define&&define.amd)define(["jquery"],a);else if("object"===("undefined"==typeof module?"undefined":_typeof(module))&&module.exports){var b;try{b=require("jquery")}catch(c){b=null}module.exports=a(b)}else window&&(window.Slider=a(window.jQuery))}(function(a){var b="slider",c="bootstrapSlider";windowIsDefined&&!window.console&&(window.console={}),windowIsDefined&&!window.console.log&&(window.console.log=function(){}),windowIsDefined&&!window.console.warn&&(window.console.warn=function(){});var d;return function(a){function b(){}function c(a){function c(b){b.prototype.option||(b.prototype.option=function(b){a.isPlainObject(b)&&(this.options=a.extend(!0,this.options,b))})}function e(b,c){a.fn[b]=function(e){if("string"==typeof e){for(var g=d.call(arguments,1),h=0,i=this.length;i>h;h++){var j=this[h],k=a.data(j,b);if(k)if(a.isFunction(k[e])&&"_"!==e.charAt(0)){var l=k[e].apply(k,g);if(void 0!==l&&l!==k)return l}else f("no such method '"+e+"' for "+b+" instance");else f("cannot call methods on "+b+" prior to initialization; attempted to call '"+e+"'")}return this}var m=this.map(function(){var d=a.data(this,b);return d?(d.option(e),d._init()):(d=new c(this,e),a.data(this,b,d)),a(this)});return!m||m.length>1?m:m[0]}}if(a){var f="undefined"==typeof console?b:function(a){console.error(a)};return a.bridget=function(a,b){c(b),e(a,b)},a.bridget}}var d=Array.prototype.slice;c(a)}(a),function(a){function e(b,c){function d(a,b){var c="data-slider-"+b.replace(/_/g,"-"),d=a.getAttribute(c);try{return JSON.parse(d)}catch(e){return d}}this._state={value:null,enabled:null,offset:null,size:null,percentage:null,inDrag:!1,over:!1},this.ticksCallbackMap={},this.handleCallbackMap={},"string"==typeof b?this.element=document.querySelector(b):b instanceof HTMLElement&&(this.element=b),c=c?c:{};for(var e=Object.keys(this.defaultOptions),f=0;f<e.length;f++){var h=e[f],i=c[h];i="undefined"!=typeof i?i:d(this.element,h),i=null!==i?i:this.defaultOptions[h],this.options||(this.options={}),this.options[h]=i}"auto"===this.options.rtl&&(this.options.rtl="rtl"===window.getComputedStyle(this.element).direction),"vertical"!==this.options.orientation||"top"!==this.options.tooltip_position&&"bottom"!==this.options.tooltip_position?"horizontal"!==this.options.orientation||"left"!==this.options.tooltip_position&&"right"!==this.options.tooltip_position||(this.options.tooltip_position="top"):this.options.rtl?this.options.tooltip_position="left":this.options.tooltip_position="right";var j,k,l,m,n,o=this.element.style.width,p=!1,q=this.element.parentNode;if(this.sliderElem)p=!0;else{this.sliderElem=document.createElement("div"),this.sliderElem.className="slider";var r=document.createElement("div");if(r.className="slider-track",k=document.createElement("div"),k.className="slider-track-low",j=document.createElement("div"),j.className="slider-selection",l=document.createElement("div"),l.className="slider-track-high",m=document.createElement("div"),m.className="slider-handle min-slider-handle",m.setAttribute("role","slider"),m.setAttribute("aria-valuemin",this.options.min),m.setAttribute("aria-valuemax",this.options.max),n=document.createElement("div"),n.className="slider-handle max-slider-handle",n.setAttribute("role","slider"),n.setAttribute("aria-valuemin",this.options.min),n.setAttribute("aria-valuemax",this.options.max),r.appendChild(k),r.appendChild(j),r.appendChild(l),this.rangeHighlightElements=[],Array.isArray(this.options.rangeHighlights)&&this.options.rangeHighlights.length>0)for(var s=0;s<this.options.rangeHighlights.length;s++){var t=document.createElement("div");t.className="slider-rangeHighlight slider-selection",this.rangeHighlightElements.push(t),r.appendChild(t)}var u=Array.isArray(this.options.labelledby);if(u&&this.options.labelledby[0]&&m.setAttribute("aria-labelledby",this.options.labelledby[0]),u&&this.options.labelledby[1]&&n.setAttribute("aria-labelledby",this.options.labelledby[1]),!u&&this.options.labelledby&&(m.setAttribute("aria-labelledby",this.options.labelledby),n.setAttribute("aria-labelledby",this.options.labelledby)),this.ticks=[],Array.isArray(this.options.ticks)&&this.options.ticks.length>0){for(this.ticksContainer=document.createElement("div"),this.ticksContainer.className="slider-tick-container",f=0;f<this.options.ticks.length;f++){var v=document.createElement("div");if(v.className="slider-tick",this.options.ticks_tooltip){var w=this._addTickListener(),x=w.addMouseEnter(this,v,f),y=w.addMouseLeave(this,v);this.ticksCallbackMap[f]={mouseEnter:x,mouseLeave:y}}this.ticks.push(v),this.ticksContainer.appendChild(v)}j.className+=" tick-slider-selection"}if(this.tickLabels=[],Array.isArray(this.options.ticks_labels)&&this.options.ticks_labels.length>0)for(this.tickLabelContainer=document.createElement("div"),this.tickLabelContainer.className="slider-tick-label-container",f=0;f<this.options.ticks_labels.length;f++){var z=document.createElement("div"),A=0===this.options.ticks_positions.length,B=this.options.reversed&&A?this.options.ticks_labels.length-(f+1):f;z.className="slider-tick-label",z.innerHTML=this.options.ticks_labels[B],this.tickLabels.push(z),this.tickLabelContainer.appendChild(z)}var C=function(a){var b=document.createElement("div");b.className="tooltip-arrow";var c=document.createElement("div");c.className="tooltip-inner",a.appendChild(b),a.appendChild(c)},D=document.createElement("div");D.className="tooltip tooltip-main",D.setAttribute("role","presentation"),C(D);var E=document.createElement("div");E.className="tooltip tooltip-min",E.setAttribute("role","presentation"),C(E);var F=document.createElement("div");F.className="tooltip tooltip-max",F.setAttribute("role","presentation"),C(F),this.sliderElem.appendChild(r),this.sliderElem.appendChild(D),this.sliderElem.appendChild(E),this.sliderElem.appendChild(F),this.tickLabelContainer&&this.sliderElem.appendChild(this.tickLabelContainer),this.ticksContainer&&this.sliderElem.appendChild(this.ticksContainer),this.sliderElem.appendChild(m),this.sliderElem.appendChild(n),q.insertBefore(this.sliderElem,this.element),this.element.style.display="none"}if(a&&(this.$element=a(this.element),this.$sliderElem=a(this.sliderElem)),this.eventToCallbackMap={},this.sliderElem.id=this.options.id,this.touchCapable="ontouchstart"in window||window.DocumentTouch&&document instanceof window.DocumentTouch,this.touchX=0,this.touchY=0,this.tooltip=this.sliderElem.querySelector(".tooltip-main"),this.tooltipInner=this.tooltip.querySelector(".tooltip-inner"),this.tooltip_min=this.sliderElem.querySelector(".tooltip-min"),this.tooltipInner_min=this.tooltip_min.querySelector(".tooltip-inner"),this.tooltip_max=this.sliderElem.querySelector(".tooltip-max"),this.tooltipInner_max=this.tooltip_max.querySelector(".tooltip-inner"),g[this.options.scale]&&(this.options.scale=g[this.options.scale]),p===!0&&(this._removeClass(this.sliderElem,"slider-horizontal"),this._removeClass(this.sliderElem,"slider-vertical"),this._removeClass(this.sliderElem,"slider-rtl"),this._removeClass(this.tooltip,"hide"),this._removeClass(this.tooltip_min,"hide"),this._removeClass(this.tooltip_max,"hide"),["left","right","top","width","height"].forEach(function(a){this._removeProperty(this.trackLow,a),this._removeProperty(this.trackSelection,a),this._removeProperty(this.trackHigh,a)},this),[this.handle1,this.handle2].forEach(function(a){this._removeProperty(a,"left"),this._removeProperty(a,"right"),this._removeProperty(a,"top")},this),[this.tooltip,this.tooltip_min,this.tooltip_max].forEach(function(a){this._removeProperty(a,"left"),this._removeProperty(a,"right"),this._removeProperty(a,"top"),this._removeProperty(a,"margin-left"),this._removeProperty(a,"margin-right"),this._removeProperty(a,"margin-top"),this._removeClass(a,"right"),this._removeClass(a,"left"),this._removeClass(a,"top")},this)),"vertical"===this.options.orientation?(this._addClass(this.sliderElem,"slider-vertical"),this.stylePos="top",this.mousePos="pageY",this.sizePos="offsetHeight"):(this._addClass(this.sliderElem,"slider-horizontal"),this.sliderElem.style.width=o,this.options.orientation="horizontal",this.options.rtl?this.stylePos="right":this.stylePos="left",this.mousePos="pageX",this.sizePos="offsetWidth"),this.options.rtl&&this._addClass(this.sliderElem,"slider-rtl"),this._setTooltipPosition(),Array.isArray(this.options.ticks)&&this.options.ticks.length>0&&(this.options.max=Math.max.apply(Math,this.options.ticks),this.options.min=Math.min.apply(Math,this.options.ticks)),Array.isArray(this.options.value)?(this.options.range=!0,this._state.value=this.options.value):this.options.range?this._state.value=[this.options.value,this.options.max]:this._state.value=this.options.value,this.trackLow=k||this.trackLow,this.trackSelection=j||this.trackSelection,this.trackHigh=l||this.trackHigh,"none"===this.options.selection?(this._addClass(this.trackLow,"hide"),this._addClass(this.trackSelection,"hide"),this._addClass(this.trackHigh,"hide")):("after"===this.options.selection||"before"===this.options.selection)&&(this._removeClass(this.trackLow,"hide"),this._removeClass(this.trackSelection,"hide"),this._removeClass(this.trackHigh,"hide")),this.handle1=m||this.handle1,this.handle2=n||this.handle2,p===!0)for(this._removeClass(this.handle1,"round triangle"),this._removeClass(this.handle2,"round triangle hide"),f=0;f<this.ticks.length;f++)this._removeClass(this.ticks[f],"round triangle hide");var G=["round","triangle","custom"],H=-1!==G.indexOf(this.options.handle);if(H)for(this._addClass(this.handle1,this.options.handle),this._addClass(this.handle2,this.options.handle),f=0;f<this.ticks.length;f++)this._addClass(this.ticks[f],this.options.handle);if(this._state.offset=this._offset(this.sliderElem),this._state.size=this.sliderElem[this.sizePos],this.setValue(this._state.value),this.handle1Keydown=this._keydown.bind(this,0),this.handle1.addEventListener("keydown",this.handle1Keydown,!1),this.handle2Keydown=this._keydown.bind(this,1),this.handle2.addEventListener("keydown",this.handle2Keydown,!1),this.mousedown=this._mousedown.bind(this),this.touchstart=this._touchstart.bind(this),this.touchmove=this._touchmove.bind(this),this.touchCapable){var I=!1;try{var J=Object.defineProperty({},"passive",{get:function(){I=!0}});window.addEventListener("test",null,J)}catch(K){}var L=I?{passive:!0}:!1;this.sliderElem.addEventListener("touchstart",this.touchstart,L),this.sliderElem.addEventListener("touchmove",this.touchmove,L)}if(this.sliderElem.addEventListener("mousedown",this.mousedown,!1),this.resize=this._resize.bind(this),window.addEventListener("resize",this.resize,!1),"hide"===this.options.tooltip)this._addClass(this.tooltip,"hide"),this._addClass(this.tooltip_min,"hide"),this._addClass(this.tooltip_max,"hide");else if("always"===this.options.tooltip)this._showTooltip(),this._alwaysShowTooltip=!0;else{if(this.showTooltip=this._showTooltip.bind(this),this.hideTooltip=this._hideTooltip.bind(this),this.options.ticks_tooltip){var M=this._addTickListener(),N=M.addMouseEnter(this,this.handle1),O=M.addMouseLeave(this,this.handle1);this.handleCallbackMap.handle1={mouseEnter:N,mouseLeave:O},N=M.addMouseEnter(this,this.handle2),O=M.addMouseLeave(this,this.handle2),this.handleCallbackMap.handle2={mouseEnter:N,mouseLeave:O}}else this.sliderElem.addEventListener("mouseenter",this.showTooltip,!1),this.sliderElem.addEventListener("mouseleave",this.hideTooltip,!1);this.handle1.addEventListener("focus",this.showTooltip,!1),this.handle1.addEventListener("blur",this.hideTooltip,!1),this.handle2.addEventListener("focus",this.showTooltip,!1),this.handle2.addEventListener("blur",this.hideTooltip,!1)}this.options.enabled?this.enable():this.disable()}var f={formatInvalidInputErrorMsg:function(a){return"Invalid input value '"+a+"' passed in"},callingContextNotSliderInstance:"Calling context element does not have instance of Slider bound to it. Check your code to make sure the JQuery object returned from the call to the slider() initializer is calling the method"},g={linear:{toValue:function(a){var b=a/100*(this.options.max-this.options.min),c=!0;if(this.options.ticks_positions.length>0){for(var d,e,f,g=0,h=1;h<this.options.ticks_positions.length;h++)if(a<=this.options.ticks_positions[h]){d=this.options.ticks[h-1],f=this.options.ticks_positions[h-1],e=this.options.ticks[h],g=this.options.ticks_positions[h];break}var i=(a-f)/(g-f);b=d+i*(e-d),c=!1}var j=c?this.options.min:0,k=j+Math.round(b/this.options.step)*this.options.step;return k<this.options.min?this.options.min:k>this.options.max?this.options.max:k},toPercentage:function(a){if(this.options.max===this.options.min)return 0;if(this.options.ticks_positions.length>0){for(var b,c,d,e=0,f=0;f<this.options.ticks.length;f++)if(a<=this.options.ticks[f]){b=f>0?this.options.ticks[f-1]:0,d=f>0?this.options.ticks_positions[f-1]:0,c=this.options.ticks[f],e=this.options.ticks_positions[f];break}if(f>0){var g=(a-b)/(c-b);return d+g*(e-d)}}return 100*(a-this.options.min)/(this.options.max-this.options.min)}},logarithmic:{toValue:function(a){var b=0===this.options.min?0:Math.log(this.options.min),c=Math.log(this.options.max),d=Math.exp(b+(c-b)*a/100);return d=this.options.min+Math.round((d-this.options.min)/this.options.step)*this.options.step,d<this.options.min?this.options.min:d>this.options.max?this.options.max:d},toPercentage:function(a){if(this.options.max===this.options.min)return 0;var b=Math.log(this.options.max),c=0===this.options.min?0:Math.log(this.options.min),d=0===a?0:Math.log(a);return 100*(d-c)/(b-c)}}};d=function(a,b){return e.call(this,a,b),this},d.prototype={_init:function(){},constructor:d,defaultOptions:{id:"",min:0,max:10,step:1,precision:0,orientation:"horizontal",value:5,range:!1,selection:"before",tooltip:"show",tooltip_split:!1,handle:"round",reversed:!1,rtl:"auto",enabled:!0,formatter:function(a){return Array.isArray(a)?a[0]+" : "+a[1]:a},natural_arrow_keys:!1,ticks:[],ticks_positions:[],ticks_labels:[],ticks_snap_bounds:0,ticks_tooltip:!1,scale:"linear",focus:!1,tooltip_position:null,labelledby:null,rangeHighlights:[]},getElement:function(){return this.sliderElem},getValue:function(){return this.options.range?this._state.value:this._state.value[0]},setValue:function(a,b,c){a||(a=0);var d=this.getValue();this._state.value=this._validateInputValue(a);var e=this._applyPrecision.bind(this);this.options.range?(this._state.value[0]=e(this._state.value[0]),this._state.value[1]=e(this._state.value[1]),this._state.value[0]=Math.max(this.options.min,Math.min(this.options.max,this._state.value[0])),this._state.value[1]=Math.max(this.options.min,Math.min(this.options.max,this._state.value[1]))):(this._state.value=e(this._state.value),this._state.value=[Math.max(this.options.min,Math.min(this.options.max,this._state.value))],this._addClass(this.handle2,"hide"),"after"===this.options.selection?this._state.value[1]=this.options.max:this._state.value[1]=this.options.min),this.options.max>this.options.min?this._state.percentage=[this._toPercentage(this._state.value[0]),this._toPercentage(this._state.value[1]),100*this.options.step/(this.options.max-this.options.min)]:this._state.percentage=[0,0,100],this._layout();var f=this.options.range?this._state.value:this._state.value[0];return this._setDataVal(f),b===!0&&this._trigger("slide",f),d!==f&&c===!0&&this._trigger("change",{oldValue:d,newValue:f}),this},destroy:function(){this._removeSliderEventHandlers(),this.sliderElem.parentNode.removeChild(this.sliderElem),this.element.style.display="",this._cleanUpEventCallbacksMap(),this.element.removeAttribute("data"),a&&(this._unbindJQueryEventHandlers(),this.$element.removeData("slider"))},disable:function(){return this._state.enabled=!1,this.handle1.removeAttribute("tabindex"),this.handle2.removeAttribute("tabindex"),this._addClass(this.sliderElem,"slider-disabled"),this._trigger("slideDisabled"),this},enable:function(){return this._state.enabled=!0,this.handle1.setAttribute("tabindex",0),this.handle2.setAttribute("tabindex",0),this._removeClass(this.sliderElem,"slider-disabled"),this._trigger("slideEnabled"),this},toggle:function(){return this._state.enabled?this.disable():this.enable(),this},isEnabled:function(){return this._state.enabled},on:function(a,b){return this._bindNonQueryEventHandler(a,b),this},off:function(b,c){a?(this.$element.off(b,c),this.$sliderElem.off(b,c)):this._unbindNonQueryEventHandler(b,c)},getAttribute:function(a){return a?this.options[a]:this.options},setAttribute:function(a,b){return this.options[a]=b,this},refresh:function(){return this._removeSliderEventHandlers(),e.call(this,this.element,this.options),a&&a.data(this.element,"slider",this),this},relayout:function(){return this._resize(),this._layout(),this},_removeSliderEventHandlers:function(){if(this.handle1.removeEventListener("keydown",this.handle1Keydown,!1),this.handle2.removeEventListener("keydown",this.handle2Keydown,!1),this.options.ticks_tooltip){for(var a=this.ticksContainer.getElementsByClassName("slider-tick"),b=0;b<a.length;b++)a[b].removeEventListener("mouseenter",this.ticksCallbackMap[b].mouseEnter,!1),a[b].removeEventListener("mouseleave",this.ticksCallbackMap[b].mouseLeave,!1);this.handle1.removeEventListener("mouseenter",this.handleCallbackMap.handle1.mouseEnter,!1),this.handle2.removeEventListener("mouseenter",this.handleCallbackMap.handle2.mouseEnter,!1),this.handle1.removeEventListener("mouseleave",this.handleCallbackMap.handle1.mouseLeave,!1),this.handle2.removeEventListener("mouseleave",this.handleCallbackMap.handle2.mouseLeave,!1)}this.handleCallbackMap=null,this.ticksCallbackMap=null,this.showTooltip&&(this.handle1.removeEventListener("focus",this.showTooltip,!1),this.handle2.removeEventListener("focus",this.showTooltip,!1)),this.hideTooltip&&(this.handle1.removeEventListener("blur",this.hideTooltip,!1),this.handle2.removeEventListener("blur",this.hideTooltip,!1)),this.showTooltip&&this.sliderElem.removeEventListener("mouseenter",this.showTooltip,!1),this.hideTooltip&&this.sliderElem.removeEventListener("mouseleave",this.hideTooltip,!1),this.sliderElem.removeEventListener("touchstart",this.touchstart,!1),this.sliderElem.removeEventListener("touchmove",this.touchmove,!1),this.sliderElem.removeEventListener("mousedown",this.mousedown,!1),window.removeEventListener("resize",this.resize,!1)},_bindNonQueryEventHandler:function(a,b){void 0===this.eventToCallbackMap[a]&&(this.eventToCallbackMap[a]=[]),this.eventToCallbackMap[a].push(b)},_unbindNonQueryEventHandler:function(a,b){var c=this.eventToCallbackMap[a];if(void 0!==c)for(var d=0;d<c.length;d++)if(c[d]===b){c.splice(d,1);break}},_cleanUpEventCallbacksMap:function(){for(var a=Object.keys(this.eventToCallbackMap),b=0;b<a.length;b++){var c=a[b];delete this.eventToCallbackMap[c]}},_showTooltip:function(){this.options.tooltip_split===!1?(this._addClass(this.tooltip,"in"),this.tooltip_min.style.display="none",this.tooltip_max.style.display="none"):(this._addClass(this.tooltip_min,"in"),this._addClass(this.tooltip_max,"in"),this.tooltip.style.display="none"),this._state.over=!0},_hideTooltip:function(){this._state.inDrag===!1&&this.alwaysShowTooltip!==!0&&(this._removeClass(this.tooltip,"in"),this._removeClass(this.tooltip_min,"in"),this._removeClass(this.tooltip_max,"in")),this._state.over=!1},_setToolTipOnMouseOver:function(a){function b(a,b){return b?[100-a.percentage[0],this.options.range?100-a.percentage[1]:a.percentage[1]]:[a.percentage[0],a.percentage[1]]}var c=this.options.formatter(a?a.value[0]:this._state.value[0]),d=a?b(a,this.options.reversed):b(this._state,this.options.reversed);this._setText(this.tooltipInner,c),this.tooltip.style[this.stylePos]=d[0]+"%","vertical"===this.options.orientation?this._css(this.tooltip,"margin-"+this.stylePos,-this.tooltip.offsetHeight/2+"px"):this._css(this.tooltip,"margin-"+this.stylePos,-this.tooltip.offsetWidth/2+"px")},_addTickListener:function(){return{addMouseEnter:function(a,b,c){var d=function(){var b=a._state,d=c>=0?c:this.attributes["aria-valuenow"].value,e=parseInt(d,10);b.value[0]=e,b.percentage[0]=a.options.ticks_positions[e],a._setToolTipOnMouseOver(b),a._showTooltip()};return b.addEventListener("mouseenter",d,!1),d},addMouseLeave:function(a,b){var c=function(){a._hideTooltip()};return b.addEventListener("mouseleave",c,!1),c}}},_layout:function(){var a;if(a=this.options.reversed?[100-this._state.percentage[0],this.options.range?100-this._state.percentage[1]:this._state.percentage[1]]:[this._state.percentage[0],this._state.percentage[1]],this.handle1.style[this.stylePos]=a[0]+"%",this.handle1.setAttribute("aria-valuenow",this._state.value[0]),isNaN(this.options.formatter(this._state.value[0]))&&this.handle1.setAttribute("aria-valuetext",this.options.formatter(this._state.value[0])),this.handle2.style[this.stylePos]=a[1]+"%",this.handle2.setAttribute("aria-valuenow",this._state.value[1]),isNaN(this.options.formatter(this._state.value[1]))&&this.handle2.setAttribute("aria-valuetext",this.options.formatter(this._state.value[1])),this.rangeHighlightElements.length>0&&Array.isArray(this.options.rangeHighlights)&&this.options.rangeHighlights.length>0)for(var b=0;b<this.options.rangeHighlights.length;b++){var c=this._toPercentage(this.options.rangeHighlights[b].start),d=this._toPercentage(this.options.rangeHighlights[b].end);if(this.options.reversed){var e=100-d;d=100-c,c=e}var f=this._createHighlightRange(c,d);f?"vertical"===this.options.orientation?(this.rangeHighlightElements[b].style.top=f.start+"%",this.rangeHighlightElements[b].style.height=f.size+"%"):(this.options.rtl?this.rangeHighlightElements[b].style.right=f.start+"%":this.rangeHighlightElements[b].style.left=f.start+"%",this.rangeHighlightElements[b].style.width=f.size+"%"):this.rangeHighlightElements[b].style.display="none"}if(Array.isArray(this.options.ticks)&&this.options.ticks.length>0){var g,h="vertical"===this.options.orientation?"height":"width";g="vertical"===this.options.orientation?"marginTop":this.options.rtl?"marginRight":"marginLeft";var i=this._state.size/(this.options.ticks.length-1);if(this.tickLabelContainer){var j=0;if(0===this.options.ticks_positions.length)"vertical"!==this.options.orientation&&(this.tickLabelContainer.style[g]=-i/2+"px"),j=this.tickLabelContainer.offsetHeight;else for(k=0;k<this.tickLabelContainer.childNodes.length;k++)this.tickLabelContainer.childNodes[k].offsetHeight>j&&(j=this.tickLabelContainer.childNodes[k].offsetHeight);"horizontal"===this.options.orientation&&(this.sliderElem.style.marginBottom=j+"px")}for(var k=0;k<this.options.ticks.length;k++){var l=this.options.ticks_positions[k]||this._toPercentage(this.options.ticks[k]);this.options.reversed&&(l=100-l),this.ticks[k].style[this.stylePos]=l+"%",this._removeClass(this.ticks[k],"in-selection"),this.options.range?l>=a[0]&&l<=a[1]&&this._addClass(this.ticks[k],"in-selection"):"after"===this.options.selection&&l>=a[0]?this._addClass(this.ticks[k],"in-selection"):"before"===this.options.selection&&l<=a[0]&&this._addClass(this.ticks[k],"in-selection"),this.tickLabels[k]&&(this.tickLabels[k].style[h]=i+"px","vertical"!==this.options.orientation&&void 0!==this.options.ticks_positions[k]?(this.tickLabels[k].style.position="absolute",this.tickLabels[k].style[this.stylePos]=l+"%",this.tickLabels[k].style[g]=-i/2+"px"):"vertical"===this.options.orientation&&(this.options.rtl?this.tickLabels[k].style.marginRight=this.sliderElem.offsetWidth+"px":this.tickLabels[k].style.marginLeft=this.sliderElem.offsetWidth+"px",this.tickLabelContainer.style[g]=this.sliderElem.offsetWidth/2*-1+"px"))}}var m;if(this.options.range){m=this.options.formatter(this._state.value),this._setText(this.tooltipInner,m),this.tooltip.style[this.stylePos]=(a[1]+a[0])/2+"%","vertical"===this.options.orientation?this._css(this.tooltip,"margin-"+this.stylePos,-this.tooltip.offsetHeight/2+"px"):this._css(this.tooltip,"margin-"+this.stylePos,-this.tooltip.offsetWidth/2+"px");var n=this.options.formatter(this._state.value[0]);this._setText(this.tooltipInner_min,n);var o=this.options.formatter(this._state.value[1]);this._setText(this.tooltipInner_max,o),this.tooltip_min.style[this.stylePos]=a[0]+"%","vertical"===this.options.orientation?this._css(this.tooltip_min,"margin-"+this.stylePos,-this.tooltip_min.offsetHeight/2+"px"):this._css(this.tooltip_min,"margin-"+this.stylePos,-this.tooltip_min.offsetWidth/2+"px"),this.tooltip_max.style[this.stylePos]=a[1]+"%","vertical"===this.options.orientation?this._css(this.tooltip_max,"margin-"+this.stylePos,-this.tooltip_max.offsetHeight/2+"px"):this._css(this.tooltip_max,"margin-"+this.stylePos,-this.tooltip_max.offsetWidth/2+"px")}else m=this.options.formatter(this._state.value[0]),this._setText(this.tooltipInner,m),this.tooltip.style[this.stylePos]=a[0]+"%","vertical"===this.options.orientation?this._css(this.tooltip,"margin-"+this.stylePos,-this.tooltip.offsetHeight/2+"px"):this._css(this.tooltip,"margin-"+this.stylePos,-this.tooltip.offsetWidth/2+"px");if("vertical"===this.options.orientation)this.trackLow.style.top="0",this.trackLow.style.height=Math.min(a[0],a[1])+"%",this.trackSelection.style.top=Math.min(a[0],a[1])+"%",this.trackSelection.style.height=Math.abs(a[0]-a[1])+"%",this.trackHigh.style.bottom="0",this.trackHigh.style.height=100-Math.min(a[0],a[1])-Math.abs(a[0]-a[1])+"%";else{"right"===this.stylePos?this.trackLow.style.right="0":this.trackLow.style.left="0",this.trackLow.style.width=Math.min(a[0],a[1])+"%","right"===this.stylePos?this.trackSelection.style.right=Math.min(a[0],a[1])+"%":this.trackSelection.style.left=Math.min(a[0],a[1])+"%",this.trackSelection.style.width=Math.abs(a[0]-a[1])+"%","right"===this.stylePos?this.trackHigh.style.left="0":this.trackHigh.style.right="0",this.trackHigh.style.width=100-Math.min(a[0],a[1])-Math.abs(a[0]-a[1])+"%";var p=this.tooltip_min.getBoundingClientRect(),q=this.tooltip_max.getBoundingClientRect();"bottom"===this.options.tooltip_position?p.right>q.left?(this._removeClass(this.tooltip_max,"bottom"),this._addClass(this.tooltip_max,"top"),this.tooltip_max.style.top="",this.tooltip_max.style.bottom="22px"):(this._removeClass(this.tooltip_max,"top"),this._addClass(this.tooltip_max,"bottom"),this.tooltip_max.style.top=this.tooltip_min.style.top,this.tooltip_max.style.bottom=""):p.right>q.left?(this._removeClass(this.tooltip_max,"top"),this._addClass(this.tooltip_max,"bottom"),this.tooltip_max.style.top="18px"):(this._removeClass(this.tooltip_max,"bottom"),this._addClass(this.tooltip_max,"top"),this.tooltip_max.style.top=this.tooltip_min.style.top)}},_createHighlightRange:function(a,b){return this._isHighlightRange(a,b)?a>b?{start:b,size:a-b}:{start:a,size:b-a}:null},_isHighlightRange:function(a,b){return a>=0&&100>=a&&b>=0&&100>=b?!0:!1},_resize:function(a){this._state.offset=this._offset(this.sliderElem),this._state.size=this.sliderElem[this.sizePos],this._layout()},_removeProperty:function(a,b){a.style.removeProperty?a.style.removeProperty(b):a.style.removeAttribute(b)},_mousedown:function(a){if(!this._state.enabled)return!1;this._state.offset=this._offset(this.sliderElem),this._state.size=this.sliderElem[this.sizePos];var b=this._getPercentage(a);if(this.options.range){var c=Math.abs(this._state.percentage[0]-b),d=Math.abs(this._state.percentage[1]-b);this._state.dragged=d>c?0:1,this._adjustPercentageForRangeSliders(b)}else this._state.dragged=0;this._state.percentage[this._state.dragged]=b,this._layout(),this.touchCapable&&(document.removeEventListener("touchmove",this.mousemove,!1),document.removeEventListener("touchend",this.mouseup,!1)),this.mousemove&&document.removeEventListener("mousemove",this.mousemove,!1),this.mouseup&&document.removeEventListener("mouseup",this.mouseup,!1),this.mousemove=this._mousemove.bind(this),this.mouseup=this._mouseup.bind(this),this.touchCapable&&(document.addEventListener("touchmove",this.mousemove,!1),document.addEventListener("touchend",this.mouseup,!1)),document.addEventListener("mousemove",this.mousemove,!1),document.addEventListener("mouseup",this.mouseup,!1),this._state.inDrag=!0;var e=this._calculateValue();return this._trigger("slideStart",e),this._setDataVal(e),this.setValue(e,!1,!0),a.returnValue=!1,this.options.focus&&this._triggerFocusOnHandle(this._state.dragged),!0},_touchstart:function(a){if(void 0===a.changedTouches)return void this._mousedown(a);var b=a.changedTouches[0];this.touchX=b.pageX,this.touchY=b.pageY},_triggerFocusOnHandle:function(a){0===a&&this.handle1.focus(),1===a&&this.handle2.focus()},_keydown:function(a,b){if(!this._state.enabled)return!1;var c;switch(b.keyCode){case 37:case 40:c=-1;break;case 39:case 38:c=1}if(c){if(this.options.natural_arrow_keys){var d="vertical"===this.options.orientation&&!this.options.reversed,e="horizontal"===this.options.orientation&&this.options.reversed;(d||e)&&(c=-c)}var f=this._state.value[a]+c*this.options.step;return this.options.range&&(f=[a?this._state.value[0]:f,a?f:this._state.value[1]]),this._trigger("slideStart",f),this._setDataVal(f),this.setValue(f,!0,!0),this._setDataVal(f),this._trigger("slideStop",f),this._layout(),this._pauseEvent(b),!1}},_pauseEvent:function(a){a.stopPropagation&&a.stopPropagation(),a.preventDefault&&a.preventDefault(),a.cancelBubble=!0,a.returnValue=!1},_mousemove:function(a){if(!this._state.enabled)return!1;var b=this._getPercentage(a);this._adjustPercentageForRangeSliders(b),this._state.percentage[this._state.dragged]=b,this._layout();var c=this._calculateValue(!0);return this.setValue(c,!0,!0),!1},_touchmove:function(a){if(void 0!==a.changedTouches){var b=a.changedTouches[0],c=b.pageX-this.touchX,d=b.pageY-this.touchY;this._state.inDrag||("vertical"===this.options.orientation&&5>=c&&c>=-5&&(d>=15||-15>=d)?this._mousedown(a):5>=d&&d>=-5&&(c>=15||-15>=c)&&this._mousedown(a))}},_adjustPercentageForRangeSliders:function(a){if(this.options.range){var b=this._getNumDigitsAfterDecimalPlace(a);b=b?b-1:0;var c=this._applyToFixedAndParseFloat(a,b);0===this._state.dragged&&this._applyToFixedAndParseFloat(this._state.percentage[1],b)<c?(this._state.percentage[0]=this._state.percentage[1],this._state.dragged=1):1===this._state.dragged&&this._applyToFixedAndParseFloat(this._state.percentage[0],b)>c&&(this._state.percentage[1]=this._state.percentage[0],this._state.dragged=0)}},_mouseup:function(){if(!this._state.enabled)return!1;this.touchCapable&&(document.removeEventListener("touchmove",this.mousemove,!1),document.removeEventListener("touchend",this.mouseup,!1)),document.removeEventListener("mousemove",this.mousemove,!1),document.removeEventListener("mouseup",this.mouseup,!1),this._state.inDrag=!1,this._state.over===!1&&this._hideTooltip();var a=this._calculateValue(!0);return this._layout(),this._setDataVal(a),this._trigger("slideStop",a),!1},_calculateValue:function(a){var b;if(this.options.range?(b=[this.options.min,this.options.max],0!==this._state.percentage[0]&&(b[0]=this._toValue(this._state.percentage[0]),b[0]=this._applyPrecision(b[0])),100!==this._state.percentage[1]&&(b[1]=this._toValue(this._state.percentage[1]),b[1]=this._applyPrecision(b[1]))):(b=this._toValue(this._state.percentage[0]),b=parseFloat(b),b=this._applyPrecision(b)),a){for(var c=[b,1/0],d=0;d<this.options.ticks.length;d++){var e=Math.abs(this.options.ticks[d]-b);e<=c[1]&&(c=[this.options.ticks[d],e])}if(c[1]<=this.options.ticks_snap_bounds)return c[0]}return b},_applyPrecision:function(a){var b=this.options.precision||this._getNumDigitsAfterDecimalPlace(this.options.step);return this._applyToFixedAndParseFloat(a,b)},_getNumDigitsAfterDecimalPlace:function(a){var b=(""+a).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);return b?Math.max(0,(b[1]?b[1].length:0)-(b[2]?+b[2]:0)):0},_applyToFixedAndParseFloat:function(a,b){
+var c=a.toFixed(b);return parseFloat(c)},_getPercentage:function(a){!this.touchCapable||"touchstart"!==a.type&&"touchmove"!==a.type||(a=a.touches[0]);var b=a[this.mousePos],c=this._state.offset[this.stylePos],d=b-c;"right"===this.stylePos&&(d=-d);var e=d/this._state.size*100;return e=Math.round(e/this._state.percentage[2])*this._state.percentage[2],this.options.reversed&&(e=100-e),Math.max(0,Math.min(100,e))},_validateInputValue:function(a){if(isNaN(+a)){if(Array.isArray(a))return this._validateArray(a),a;throw new Error(f.formatInvalidInputErrorMsg(a))}return+a},_validateArray:function(a){for(var b=0;b<a.length;b++){var c=a[b];if("number"!=typeof c)throw new Error(f.formatInvalidInputErrorMsg(c))}},_setDataVal:function(a){this.element.setAttribute("data-value",a),this.element.setAttribute("value",a),this.element.value=a},_trigger:function(b,c){c=c||0===c?c:void 0;var d=this.eventToCallbackMap[b];if(d&&d.length)for(var e=0;e<d.length;e++){var f=d[e];f(c)}a&&this._triggerJQueryEvent(b,c)},_triggerJQueryEvent:function(a,b){var c={type:a,value:b};this.$element.trigger(c),this.$sliderElem.trigger(c)},_unbindJQueryEventHandlers:function(){this.$element.off(),this.$sliderElem.off()},_setText:function(a,b){"undefined"!=typeof a.textContent?a.textContent=b:"undefined"!=typeof a.innerText&&(a.innerText=b)},_removeClass:function(a,b){for(var c=b.split(" "),d=a.className,e=0;e<c.length;e++){var f=c[e],g=new RegExp("(?:\\s|^)"+f+"(?:\\s|$)");d=d.replace(g," ")}a.className=d.trim()},_addClass:function(a,b){for(var c=b.split(" "),d=a.className,e=0;e<c.length;e++){var f=c[e],g=new RegExp("(?:\\s|^)"+f+"(?:\\s|$)"),h=g.test(d);h||(d+=" "+f)}a.className=d.trim()},_offsetLeft:function(a){return a.getBoundingClientRect().left},_offsetRight:function(a){return a.getBoundingClientRect().right},_offsetTop:function(a){for(var b=a.offsetTop;(a=a.offsetParent)&&!isNaN(a.offsetTop);)b+=a.offsetTop,"BODY"!==a.tagName&&(b-=a.scrollTop);return b},_offset:function(a){return{left:this._offsetLeft(a),right:this._offsetRight(a),top:this._offsetTop(a)}},_css:function(b,c,d){if(a)a.style(b,c,d);else{var e=c.replace(/^-ms-/,"ms-").replace(/-([\da-z])/gi,function(a,b){return b.toUpperCase()});b.style[e]=d}},_toValue:function(a){return this.options.scale.toValue.apply(this,[a])},_toPercentage:function(a){return this.options.scale.toPercentage.apply(this,[a])},_setTooltipPosition:function(){var a=[this.tooltip,this.tooltip_min,this.tooltip_max];if("vertical"===this.options.orientation){var b;b=this.options.tooltip_position?this.options.tooltip_position:this.options.rtl?"left":"right";var c="left"===b?"right":"left";a.forEach(function(a){this._addClass(a,b),a.style[c]="100%"}.bind(this))}else"bottom"===this.options.tooltip_position?a.forEach(function(a){this._addClass(a,"bottom"),a.style.top="22px"}.bind(this)):a.forEach(function(a){this._addClass(a,"top"),a.style.top=-this.tooltip.outerHeight-14+"px"}.bind(this))}},a&&!function(){var e=void 0;a.fn.slider?(windowIsDefined&&window.console.warn("bootstrap-slider.js - WARNING: $.fn.slider namespace is already bound. Use the $.fn.bootstrapSlider namespace instead."),e=c):(a.bridget(b,d),e=b),a.bridget(c,d),a(function(){a("input[data-provide=slider]")[e]()})}()}(a),d});
\ No newline at end of file
diff --git a/themes/bootstrap3/js/vendor/d3.js b/themes/bootstrap3/js/vendor/d3.js
index 71b0b37d57e9b549390a34a302b614c89ceab3c3..8cfc9ef3f4917b76800f6783d33197cd8d618f33 100644
--- a/themes/bootstrap3/js/vendor/d3.js
+++ b/themes/bootstrap3/js/vendor/d3.js
@@ -1,8 +1,5 @@
-// https://d3js.org Version 4.1.0. Copyright 2016 Mike Bostock.
-!function(t,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n(t.d3=t.d3||{})}(this,function(t){"use strict";function n(t,n){return t<n?-1:t>n?1:t>=n?0:NaN}function e(t){return 1===t.length&&(t=r(t)),{left:function(n,e,r,i){for(null==r&&(r=0),null==i&&(i=n.length);r<i;){var o=r+i>>>1;t(n[o],e)<0?r=o+1:i=o}return r},right:function(n,e,r,i){for(null==r&&(r=0),null==i&&(i=n.length);r<i;){var o=r+i>>>1;t(n[o],e)>0?i=o:r=o+1}return r}}}function r(t){return function(e,r){return n(t(e),r)}}function i(t,n){return n<t?-1:n>t?1:n>=t?0:NaN}function o(t){return null===t?NaN:+t}function u(t,n){var e,r,i=t.length,u=0,a=0,c=-1,s=0;if(null==n)for(;++c<i;)isNaN(e=o(t[c]))||(r=e-u,u+=r/++s,a+=r*(e-u));else for(;++c<i;)isNaN(e=o(n(t[c],c,t)))||(r=e-u,u+=r/++s,a+=r*(e-u));if(s>1)return a/(s-1)}function a(t,n){var e=u(t,n);return e?Math.sqrt(e):e}function c(t,n){var e,r,i,o=-1,u=t.length;if(null==n){for(;++o<u;)if(null!=(r=t[o])&&r>=r){e=i=r;break}for(;++o<u;)null!=(r=t[o])&&(e>r&&(e=r),i<r&&(i=r))}else{for(;++o<u;)if(null!=(r=n(t[o],o,t))&&r>=r){e=i=r;break}for(;++o<u;)null!=(r=n(t[o],o,t))&&(e>r&&(e=r),i<r&&(i=r))}return[e,i]}function s(t){return function(){return t}}function f(t){return t}function l(t,n,e){t=+t,n=+n,e=(i=arguments.length)<2?(n=t,t=0,1):i<3?1:+e;for(var r=-1,i=0|Math.max(0,Math.ceil((n-t)/e)),o=new Array(i);++r<i;)o[r]=t+r*e;return o}function h(t,n,e){var r=p(t,n,e);return l(Math.ceil(t/r)*r,Math.floor(n/r)*r+r/2,r)}function p(t,n,e){var r=Math.abs(n-t)/Math.max(0,e),i=Math.pow(10,Math.floor(Math.log(r)/Math.LN10)),o=r/i;return o>=Pd?i*=10:o>=qd?i*=5:o>=Ld&&(i*=2),n<t?-i:i}function d(t){return Math.ceil(Math.log(t.length)/Math.LN2)+1}function v(){function t(t){var i,o,u=t.length,a=new Array(u);for(i=0;i<u;++i)a[i]=n(t[i],i,t);var c=e(a),s=c[0],f=c[1],l=r(a,s,f);Array.isArray(l)||(l=h(s,f,l));for(var p=l.length;l[0]<=s;)l.shift(),--p;for(;l[p-1]>=f;)l.pop(),--p;var d,v=new Array(p+1);for(i=0;i<=p;++i)d=v[i]=[],d.x0=i>0?l[i-1]:s,d.x1=i<p?l[i]:f;for(i=0;i<u;++i)o=a[i],s<=o&&o<=f&&v[Sd(l,o,0,p)].push(t[i]);return v}var n=f,e=c,r=d;return t.value=function(e){return arguments.length?(n="function"==typeof e?e:s(e),t):n},t.domain=function(n){return arguments.length?(e="function"==typeof n?n:s([n[0],n[1]]),t):e},t.thresholds=function(n){return arguments.length?(r="function"==typeof n?n:s(Array.isArray(n)?Cd.call(n):n),t):r},t}function _(t,n,e){if(null==e&&(e=o),r=t.length){if((n=+n)<=0||r<2)return+e(t[0],0,t);if(n>=1)return+e(t[r-1],r-1,t);var r,i=(r-1)*n,u=Math.floor(i),a=+e(t[u],u,t),c=+e(t[u+1],u+1,t);return a+(c-a)*(i-u)}}function y(t,e,r){return t=zd.call(t,o).sort(n),Math.ceil((r-e)/(2*(_(t,.75)-_(t,.25))*Math.pow(t.length,-1/3)))}function g(t,n,e){return Math.ceil((e-n)/(3.5*a(t)*Math.pow(t.length,-1/3)))}function m(t,n){var e,r,i=-1,o=t.length;if(null==n){for(;++i<o;)if(null!=(r=t[i])&&r>=r){e=r;break}for(;++i<o;)null!=(r=t[i])&&r>e&&(e=r)}else{for(;++i<o;)if(null!=(r=n(t[i],i,t))&&r>=r){e=r;break}for(;++i<o;)null!=(r=n(t[i],i,t))&&r>e&&(e=r)}return e}function x(t,n){var e,r=0,i=t.length,u=-1,a=i;if(null==n)for(;++u<i;)isNaN(e=o(t[u]))?--a:r+=e;else for(;++u<i;)isNaN(e=o(n(t[u],u,t)))?--a:r+=e;if(a)return r/a}function b(t,e){var r,i=[],u=t.length,a=-1;if(null==e)for(;++a<u;)isNaN(r=o(t[a]))||i.push(r);else for(;++a<u;)isNaN(r=o(e(t[a],a,t)))||i.push(r);return _(i.sort(n),.5)}function w(t){for(var n,e,r,i=t.length,o=-1,u=0;++o<i;)u+=t[o].length;for(e=new Array(u);--i>=0;)for(r=t[i],n=r.length;--n>=0;)e[--u]=r[n];return e}function M(t,n){var e,r,i=-1,o=t.length;if(null==n){for(;++i<o;)if(null!=(r=t[i])&&r>=r){e=r;break}for(;++i<o;)null!=(r=t[i])&&e>r&&(e=r)}else{for(;++i<o;)if(null!=(r=n(t[i],i,t))&&r>=r){e=r;break}for(;++i<o;)null!=(r=n(t[i],i,t))&&e>r&&(e=r)}return e}function T(t){for(var n=0,e=t.length-1,r=t[0],i=new Array(e<0?0:e);n<e;)i[n]=[r,r=t[++n]];return i}function k(t,n){for(var e=n.length,r=new Array(e);e--;)r[e]=t[n[e]];return r}function N(t,e){if(r=t.length){var r,i,o=0,u=0,a=t[u];for(e||(e=n);++o<r;)(e(i=t[o],a)<0||0!==e(a,a))&&(a=i,u=o);return 0===e(a,a)?u:void 0}}function S(t,n,e){for(var r,i,o=(null==e?t.length:e)-(n=null==n?0:+n);o;)i=Math.random()*o--|0,r=t[o+n],t[o+n]=t[i+n],t[i+n]=r;return t}function A(t,n){var e,r=0,i=t.length,o=-1;if(null==n)for(;++o<i;)(e=+t[o])&&(r+=e);else for(;++o<i;)(e=+n(t[o],o,t))&&(r+=e);return r}function E(t){if(!(i=t.length))return[];for(var n=-1,e=M(t,C),r=new Array(e);++n<e;)for(var i,o=-1,u=r[n]=new Array(i);++o<i;)u[o]=t[o][n];return r}function C(t){return t.length}function z(){return E(arguments)}function P(){}function q(t,n){var e=new P;if(t instanceof P)t.each(function(t,n){e.set(n,t)});else if(Array.isArray(t)){var r,i=-1,o=t.length;if(null==n)for(;++i<o;)e.set(i,t[i]);else for(;++i<o;)e.set(n(r=t[i],i,t),r)}else if(t)for(var u in t)e.set(u,t[u]);return e}function L(){function t(n,i,u,a){if(i>=o.length)return null!=r?r(n):null!=e?n.sort(e):n;for(var c,s,f,l=-1,h=n.length,p=o[i++],d=q(),v=u();++l<h;)(f=d.get(c=p(s=n[l])+""))?f.push(s):d.set(c,[s]);return d.each(function(n,e){a(v,e,t(n,i,u,a))}),v}function n(t,e){if(++e>o.length)return t;var i,a=u[e-1];return null!=r&&e>=o.length?i=t.entries():(i=[],t.each(function(t,r){i.push({key:r,values:n(t,e)})})),null!=a?i.sort(function(t,n){return a(t.key,n.key)}):i}var e,r,i,o=[],u=[];return i={object:function(n){return t(n,0,R,U)},map:function(n){return t(n,0,D,O)},entries:function(e){return n(t(e,0,D,O),0)},key:function(t){return o.push(t),i},sortKeys:function(t){return u[o.length-1]=t,i},sortValues:function(t){return e=t,i},rollup:function(t){return r=t,i}}}function R(){return{}}function U(t,n,e){t[n]=e}function D(){return q()}function O(t,n,e){t.set(n,e)}function F(){}function I(t,n){var e=new F;if(t instanceof F)t.each(function(t){e.add(t)});else if(t){var r=-1,i=t.length;if(null==n)for(;++r<i;)e.add(t[r]);else for(;++r<i;)e.add(n(t[r],r,t))}return e}function Y(t){var n=[];for(var e in t)n.push(e);return n}function B(t){var n=[];for(var e in t)n.push(t[e]);return n}function j(t){var n=[];for(var e in t)n.push({key:e,value:t[e]});return n}function H(t,n){return t=null==t?0:+t,n=null==n?1:+n,1===arguments.length?(n=t,t=0):n-=t,function(){return Math.random()*n+t}}function X(t,n){var e,r;return t=null==t?0:+t,n=null==n?1:+n,function(){var i;if(null!=e)i=e,e=null;else do e=2*Math.random()-1,i=2*Math.random()-1,r=e*e+i*i;while(!r||r>1);return t+n*i*Math.sqrt(-2*Math.log(r)/r)}}function V(){var t=X.apply(this,arguments);return function(){return Math.exp(t())}}function W(t){return function(){for(var n=0,e=0;e<t;++e)n+=Math.random();return n}}function $(t){var n=W(t);return function(){return n()/t}}function Z(t){return function(){return-Math.log(1-Math.random())/t}}function G(t){return+t}function J(t){return t*t}function Q(t){return t*(2-t)}function K(t){return((t*=2)<=1?t*t:--t*(2-t)+1)/2}function tt(t){return t*t*t}function nt(t){return--t*t*t+1}function et(t){return((t*=2)<=1?t*t*t:(t-=2)*t*t+2)/2}function rt(t){return 1-Math.cos(t*Bd)}function it(t){return Math.sin(t*Bd)}function ot(t){return(1-Math.cos(Yd*t))/2}function ut(t){return Math.pow(2,10*t-10)}function at(t){return 1-Math.pow(2,-10*t)}function ct(t){return((t*=2)<=1?Math.pow(2,10*t-10):2-Math.pow(2,10-10*t))/2}function st(t){return 1-Math.sqrt(1-t*t)}function ft(t){return Math.sqrt(1- --t*t)}function lt(t){return((t*=2)<=1?1-Math.sqrt(1-t*t):Math.sqrt(1-(t-=2)*t)+1)/2}function ht(t){return 1-pt(1-t)}function pt(t){return(t=+t)<jd?Qd*t*t:t<Xd?Qd*(t-=Hd)*t+Vd:t<$d?Qd*(t-=Wd)*t+Zd:Qd*(t-=Gd)*t+Jd}function dt(t){return((t*=2)<=1?1-pt(1-t):pt(t-1)+1)/2}function vt(t){for(var n,e=-1,r=t.length,i=t[r-1],o=0;++e<r;)n=i,i=t[e],o+=n[1]*i[0]-n[0]*i[1];return o/2}function _t(t){for(var n,e,r=-1,i=t.length,o=0,u=0,a=t[i-1],c=0;++r<i;)n=a,a=t[r],c+=e=n[0]*a[1]-a[0]*n[1],o+=(n[0]+a[0])*e,u+=(n[1]+a[1])*e;return c*=3,[o/c,u/c]}function yt(t,n,e){return(n[0]-t[0])*(e[1]-t[1])-(n[1]-t[1])*(e[0]-t[0])}function gt(t,n){return t[0]-n[0]||t[1]-n[1]}function mt(t){for(var n=t.length,e=[0,1],r=2,i=2;i<n;++i){for(;r>1&&yt(t[e[r-2]],t[e[r-1]],t[i])<=0;)--r;e[r++]=i}return e.slice(0,r)}function xt(t){if((e=t.length)<3)return null;var n,e,r=new Array(e),i=new Array(e);for(n=0;n<e;++n)r[n]=[+t[n][0],+t[n][1],n];for(r.sort(gt),n=0;n<e;++n)i[n]=[r[n][0],-r[n][1]];var o=mt(r),u=mt(i),a=u[0]===o[0],c=u[u.length-1]===o[o.length-1],s=[];for(n=o.length-1;n>=0;--n)s.push(t[r[o[n]][2]]);for(n=+a;n<u.length-c;++n)s.push(t[r[u[n]][2]]);return s}function bt(t,n){for(var e,r,i=t.length,o=t[i-1],u=n[0],a=n[1],c=o[0],s=o[1],f=!1,l=0;l<i;++l)o=t[l],e=o[0],r=o[1],r>a!=s>a&&u<(c-e)*(a-r)/(s-r)+e&&(f=!f),c=e,s=r;return f}function wt(t){for(var n,e,r=-1,i=t.length,o=t[i-1],u=o[0],a=o[1],c=0;++r<i;)n=u,e=a,o=t[r],u=o[0],a=o[1],n-=u,e-=a,c+=Math.sqrt(n*n+e*e);return c}function Mt(){this._x0=this._y0=this._x1=this._y1=null,this._=[]}function Tt(){return new Mt}function kt(t){var n=+this._x.call(null,t),e=+this._y.call(null,t);return Nt(this.cover(n,e),n,e,t)}function Nt(t,n,e,r){if(isNaN(n)||isNaN(e))return t;var i,o,u,a,c,s,f,l,h,p=t._root,d={data:r},v=t._x0,_=t._y0,y=t._x1,g=t._y1;if(!p)return t._root=d,t;for(;p.length;)if((s=n>=(o=(v+y)/2))?v=o:y=o,(f=e>=(u=(_+g)/2))?_=u:g=u,i=p,!(p=p[l=f<<1|s]))return i[l]=d,t;if(a=+t._x.call(null,p.data),c=+t._y.call(null,p.data),n===a&&e===c)return d.next=p,i?i[l]=d:t._root=d,t;do i=i?i[l]=new Array(4):t._root=new Array(4),(s=n>=(o=(v+y)/2))?v=o:y=o,(f=e>=(u=(_+g)/2))?_=u:g=u;while((l=f<<1|s)===(h=(c>=u)<<1|a>=o));return i[h]=p,i[l]=d,t}function St(t){var n,e,r,i,o=t.length,u=new Array(o),a=new Array(o),c=1/0,s=1/0,f=-(1/0),l=-(1/0);for(e=0;e<o;++e)isNaN(r=+this._x.call(null,n=t[e]))||isNaN(i=+this._y.call(null,n))||(u[e]=r,a[e]=i,r<c&&(c=r),r>f&&(f=r),i<s&&(s=i),i>l&&(l=i));for(f<c&&(c=this._x0,f=this._x1),l<s&&(s=this._y0,l=this._y1),this.cover(c,s).cover(f,l),e=0;e<o;++e)Nt(this,u[e],a[e],t[e]);return this}function At(t,n){if(isNaN(t=+t)||isNaN(n=+n))return this;var e=this._x0,r=this._y0,i=this._x1,o=this._y1;if(isNaN(e))i=(e=Math.floor(t))+1,o=(r=Math.floor(n))+1;else{if(!(e>t||t>i||r>n||n>o))return this;var u,a,c=i-e,s=this._root;switch(a=(n<(r+o)/2)<<1|t<(e+i)/2){case 0:do u=new Array(4),u[a]=s,s=u;while(c*=2,i=e+c,o=r+c,t>i||n>o);break;case 1:do u=new Array(4),u[a]=s,s=u;while(c*=2,e=i-c,o=r+c,e>t||n>o);break;case 2:do u=new Array(4),u[a]=s,s=u;while(c*=2,i=e+c,r=o-c,t>i||r>n);break;case 3:do u=new Array(4),u[a]=s,s=u;while(c*=2,e=i-c,r=o-c,e>t||r>n)}this._root&&this._root.length&&(this._root=s)}return this._x0=e,this._y0=r,this._x1=i,this._y1=o,this}function Et(){var t=[];return this.visit(function(n){if(!n.length)do t.push(n.data);while(n=n.next)}),t}function Ct(t){return arguments.length?this.cover(+t[0][0],+t[0][1]).cover(+t[1][0],+t[1][1]):isNaN(this._x0)?void 0:[[this._x0,this._y0],[this._x1,this._y1]]}function zt(t,n,e,r,i){this.node=t,this.x0=n,this.y0=e,this.x1=r,this.y1=i}function Pt(t,n,e){var r,i,o,u,a,c,s,f=this._x0,l=this._y0,h=this._x1,p=this._y1,d=[],v=this._root;for(v&&d.push(new zt(v,f,l,h,p)),null==e?e=1/0:(f=t-e,l=n-e,h=t+e,p=n+e,e*=e);c=d.pop();)if(!(!(v=c.node)||(i=c.x0)>h||(o=c.y0)>p||(u=c.x1)<f||(a=c.y1)<l))if(v.length){var _=(i+u)/2,y=(o+a)/2;d.push(new zt(v[3],_,y,u,a),new zt(v[2],i,y,_,a),new zt(v[1],_,o,u,y),new zt(v[0],i,o,_,y)),(s=(n>=y)<<1|t>=_)&&(c=d[d.length-1],d[d.length-1]=d[d.length-1-s],d[d.length-1-s]=c)}else{var g=t-+this._x.call(null,v.data),m=n-+this._y.call(null,v.data),x=g*g+m*m;if(x<e){var b=Math.sqrt(e=x);f=t-b,l=n-b,h=t+b,p=n+b,r=v.data}}return r}function qt(t){if(isNaN(o=+this._x.call(null,t))||isNaN(u=+this._y.call(null,t)))return this;var n,e,r,i,o,u,a,c,s,f,l,h,p=this._root,d=this._x0,v=this._y0,_=this._x1,y=this._y1;if(!p)return this;if(p.length)for(;;){if((s=o>=(a=(d+_)/2))?d=a:_=a,(f=u>=(c=(v+y)/2))?v=c:y=c,n=p,!(p=p[l=f<<1|s]))return this;if(!p.length)break;(n[l+1&3]||n[l+2&3]||n[l+3&3])&&(e=n,h=l)}for(;p.data!==t;)if(r=p,!(p=p.next))return this;return(i=p.next)&&delete p.next,r?(i?r.next=i:delete r.next,this):n?(i?n[l]=i:delete n[l],(p=n[0]||n[1]||n[2]||n[3])&&p===(n[3]||n[2]||n[1]||n[0])&&!p.length&&(e?e[h]=p:this._root=p),this):(this._root=i,this)}function Lt(t){for(var n=0,e=t.length;n<e;++n)this.remove(t[n]);return this}function Rt(){return this._root}function Ut(){var t=0;return this.visit(function(n){if(!n.length)do++t;while(n=n.next)}),t}function Dt(t){var n,e,r,i,o,u,a=[],c=this._root;for(c&&a.push(new zt(c,this._x0,this._y0,this._x1,this._y1));n=a.pop();)if(!t(c=n.node,r=n.x0,i=n.y0,o=n.x1,u=n.y1)&&c.length){var s=(r+o)/2,f=(i+u)/2;(e=c[3])&&a.push(new zt(e,s,f,o,u)),(e=c[2])&&a.push(new zt(e,r,f,s,u)),(e=c[1])&&a.push(new zt(e,s,i,o,f)),(e=c[0])&&a.push(new zt(e,r,i,s,f))}return this}function Ot(t){var n,e=[],r=[];for(this._root&&e.push(new zt(this._root,this._x0,this._y0,this._x1,this._y1));n=e.pop();){var i=n.node;if(i.length){var o,u=n.x0,a=n.y0,c=n.x1,s=n.y1,f=(u+c)/2,l=(a+s)/2;(o=i[0])&&e.push(new zt(o,u,a,f,l)),(o=i[1])&&e.push(new zt(o,f,a,c,l)),(o=i[2])&&e.push(new zt(o,u,l,f,s)),(o=i[3])&&e.push(new zt(o,f,l,c,s))}r.push(n)}for(;n=r.pop();)t(n.node,n.x0,n.y0,n.x1,n.y1);return this}function Ft(t){return t[0]}function It(t){return arguments.length?(this._x=t,this):this._x}function Yt(t){return t[1]}function Bt(t){return arguments.length?(this._y=t,this):this._y}function jt(t,n,e){var r=new Ht(null==n?Ft:n,null==e?Yt:e,NaN,NaN,NaN,NaN);return null==t?r:r.addAll(t)}function Ht(t,n,e,r,i,o){this._x=t,this._y=n,this._x0=e,this._y0=r,this._x1=i,this._y1=o,this._root=void 0}function Xt(t){for(var n={data:t.data},e=n;t=t.next;)e=e.next={data:t.data};return n}function Vt(t){if(!(t>=1))throw new Error;this._size=t,this._call=this._error=null,this._tasks=[],this._data=[],this._waiting=this._active=this._ended=this._start=0}function Wt(t){if(!t._start)try{$t(t)}catch(n){t._tasks[t._ended+t._active-1]&&Gt(t,n)}}function $t(t){for(;t._start=t._waiting&&t._active<t._size;){var n=t._ended+t._active,e=t._tasks[n],r=e.length-1,i=e[r];e[r]=Zt(t,n),--t._waiting,++t._active,e=i.apply(null,e),t._tasks[n]&&(t._tasks[n]=e||vv)}}function Zt(t,n){return function(e,r){t._tasks[n]&&(--t._active,++t._ended,t._tasks[n]=null,null==t._error&&(null!=e?Gt(t,e):(t._data[n]=r,t._waiting?Wt(t):Jt(t))))}}function Gt(t,n){var e,r=t._tasks.length;for(t._error=n,t._data=void 0,t._waiting=NaN;--r>=0;)if((e=t._tasks[r])&&(t._tasks[r]=null,e.abort))try{e.abort()}catch(n){}t._active=NaN,Jt(t)}function Jt(t){!t._active&&t._call&&t._call(t._error,t._data)}function Qt(t){return new Vt(arguments.length?+t:1/0)}function Kt(t){return function(){return t}}function tn(t){return t.innerRadius}function nn(t){return t.outerRadius}function en(t){return t.startAngle}function rn(t){return t.endAngle}function on(t){return t&&t.padAngle}function un(t){return t>=1?gv:t<=-1?-gv:Math.asin(t)}function an(t,n,e,r,i,o,u,a){var c=e-t,s=r-n,f=u-i,l=a-o,h=(f*(n-o)-l*(t-i))/(l*c-f*s);return[t+h*c,n+h*s]}function cn(t,n,e,r,i,o,u){var a=t-e,c=n-r,s=(u?o:-o)/Math.sqrt(a*a+c*c),f=s*c,l=-s*a,h=t+f,p=n+l,d=e+f,v=r+l,_=(h+d)/2,y=(p+v)/2,g=d-h,m=v-p,x=g*g+m*m,b=i-o,w=h*v-d*p,M=(m<0?-1:1)*Math.sqrt(Math.max(0,b*b*x-w*w)),T=(w*m-g*M)/x,k=(-w*g-m*M)/x,N=(w*m+g*M)/x,S=(-w*g+m*M)/x,A=T-_,E=k-y,C=N-_,z=S-y;return A*A+E*E>C*C+z*z&&(T=N,k=S),{cx:T,cy:k,x01:-f,y01:-l,x11:T*(i/b-1),y11:k*(i/b-1)}}function sn(){function t(){var t,s,f=+n.apply(this,arguments),l=+e.apply(this,arguments),h=o.apply(this,arguments)-gv,p=u.apply(this,arguments)-gv,d=Math.abs(p-h),v=p>h;if(c||(c=t=Tt()),l<f&&(s=l,l=f,f=s),l>_v)if(d>mv-_v)c.moveTo(l*Math.cos(h),l*Math.sin(h)),c.arc(0,0,l,h,p,!v),f>_v&&(c.moveTo(f*Math.cos(p),f*Math.sin(p)),c.arc(0,0,f,p,h,v));else{var _,y,g=h,m=p,x=h,b=p,w=d,M=d,T=a.apply(this,arguments)/2,k=T>_v&&(i?+i.apply(this,arguments):Math.sqrt(f*f+l*l)),N=Math.min(Math.abs(l-f)/2,+r.apply(this,arguments)),S=N,A=N;if(k>_v){var E=un(k/f*Math.sin(T)),C=un(k/l*Math.sin(T));(w-=2*E)>_v?(E*=v?1:-1,x+=E,b-=E):(w=0,x=b=(h+p)/2),(M-=2*C)>_v?(C*=v?1:-1,g+=C,m-=C):(M=0,g=m=(h+p)/2)}var z=l*Math.cos(g),P=l*Math.sin(g),q=f*Math.cos(b),L=f*Math.sin(b);if(N>_v){var R=l*Math.cos(m),U=l*Math.sin(m),D=f*Math.cos(x),O=f*Math.sin(x);if(d<yv){var F=w>_v?an(z,P,D,O,R,U,q,L):[q,L],I=z-F[0],Y=P-F[1],B=R-F[0],j=U-F[1],H=1/Math.sin(Math.acos((I*B+Y*j)/(Math.sqrt(I*I+Y*Y)*Math.sqrt(B*B+j*j)))/2),X=Math.sqrt(F[0]*F[0]+F[1]*F[1]);S=Math.min(N,(f-X)/(H-1)),A=Math.min(N,(l-X)/(H+1))}}M>_v?A>_v?(_=cn(D,O,z,P,l,A,v),y=cn(R,U,q,L,l,A,v),c.moveTo(_.cx+_.x01,_.cy+_.y01),A<N?c.arc(_.cx,_.cy,A,Math.atan2(_.y01,_.x01),Math.atan2(y.y01,y.x01),!v):(c.arc(_.cx,_.cy,A,Math.atan2(_.y01,_.x01),Math.atan2(_.y11,_.x11),!v),c.arc(0,0,l,Math.atan2(_.cy+_.y11,_.cx+_.x11),Math.atan2(y.cy+y.y11,y.cx+y.x11),!v),c.arc(y.cx,y.cy,A,Math.atan2(y.y11,y.x11),Math.atan2(y.y01,y.x01),!v))):(c.moveTo(z,P),c.arc(0,0,l,g,m,!v)):c.moveTo(z,P),f>_v&&w>_v?S>_v?(_=cn(q,L,R,U,f,-S,v),y=cn(z,P,D,O,f,-S,v),c.lineTo(_.cx+_.x01,_.cy+_.y01),S<N?c.arc(_.cx,_.cy,S,Math.atan2(_.y01,_.x01),Math.atan2(y.y01,y.x01),!v):(c.arc(_.cx,_.cy,S,Math.atan2(_.y01,_.x01),Math.atan2(_.y11,_.x11),!v),c.arc(0,0,f,Math.atan2(_.cy+_.y11,_.cx+_.x11),Math.atan2(y.cy+y.y11,y.cx+y.x11),v),c.arc(y.cx,y.cy,S,Math.atan2(y.y11,y.x11),Math.atan2(y.y01,y.x01),!v))):c.arc(0,0,f,b,x,v):c.lineTo(q,L)}else c.moveTo(0,0);if(c.closePath(),t)return c=null,t+""||null}var n=tn,e=nn,r=Kt(0),i=null,o=en,u=rn,a=on,c=null;return t.centroid=function(){var t=(+n.apply(this,arguments)+ +e.apply(this,arguments))/2,r=(+o.apply(this,arguments)+ +u.apply(this,arguments))/2-yv/2;return[Math.cos(r)*t,Math.sin(r)*t]},t.innerRadius=function(e){return arguments.length?(n="function"==typeof e?e:Kt(+e),t):n},t.outerRadius=function(n){return arguments.length?(e="function"==typeof n?n:Kt(+n),t):e},t.cornerRadius=function(n){return arguments.length?(r="function"==typeof n?n:Kt(+n),t):r},t.padRadius=function(n){return arguments.length?(i=null==n?null:"function"==typeof n?n:Kt(+n),t):i},t.startAngle=function(n){return arguments.length?(o="function"==typeof n?n:Kt(+n),t):o},t.endAngle=function(n){return arguments.length?(u="function"==typeof n?n:Kt(+n),t):u},t.padAngle=function(n){return arguments.length?(a="function"==typeof n?n:Kt(+n),t):a},t.context=function(n){return arguments.length?(c=null==n?null:n,t):c},t}function fn(t){this._context=t}function ln(t){return new fn(t)}function hn(t){return t[0]}function pn(t){return t[1]}function dn(){function t(t){var a,c,s,f=t.length,l=!1;for(null==i&&(u=o(s=Tt())),a=0;a<=f;++a)!(a<f&&r(c=t[a],a,t))===l&&((l=!l)?u.lineStart():u.lineEnd()),l&&u.point(+n(c,a,t),+e(c,a,t));if(s)return u=null,s+""||null}var n=hn,e=pn,r=Kt(!0),i=null,o=ln,u=null;return t.x=function(e){return arguments.length?(n="function"==typeof e?e:Kt(+e),t):n},t.y=function(n){return arguments.length?(e="function"==typeof n?n:Kt(+n),t):e},t.defined=function(n){return arguments.length?(r="function"==typeof n?n:Kt(!!n),t):r},t.curve=function(n){return arguments.length?(o=n,null!=i&&(u=o(i)),t):o},t.context=function(n){return arguments.length?(null==n?i=u=null:u=o(i=n),t):i},t}function vn(){function t(t){var n,f,l,h,p,d=t.length,v=!1,_=new Array(d),y=new Array(d);for(null==a&&(s=c(p=Tt())),n=0;n<=d;++n){if(!(n<d&&u(h=t[n],n,t))===v)if(v=!v)f=n,s.areaStart(),s.lineStart();else{for(s.lineEnd(),s.lineStart(),l=n-1;l>=f;--l)s.point(_[l],y[l]);s.lineEnd(),s.areaEnd()}v&&(_[n]=+e(h,n,t),y[n]=+i(h,n,t),s.point(r?+r(h,n,t):_[n],o?+o(h,n,t):y[n]))}if(p)return s=null,p+""||null}function n(){return dn().defined(u).curve(c).context(a)}var e=hn,r=null,i=Kt(0),o=pn,u=Kt(!0),a=null,c=ln,s=null;return t.x=function(n){return arguments.length?(e="function"==typeof n?n:Kt(+n),r=null,t):e},t.x0=function(n){return arguments.length?(e="function"==typeof n?n:Kt(+n),t):e},t.x1=function(n){return arguments.length?(r=null==n?null:"function"==typeof n?n:Kt(+n),t):r},t.y=function(n){return arguments.length?(i="function"==typeof n?n:Kt(+n),o=null,t):i},t.y0=function(n){return arguments.length?(i="function"==typeof n?n:Kt(+n),t):i},t.y1=function(n){return arguments.length?(o=null==n?null:"function"==typeof n?n:Kt(+n),t):o},t.lineX0=t.lineY0=function(){return n().x(e).y(i)},t.lineY1=function(){return n().x(e).y(o)},t.lineX1=function(){return n().x(r).y(i)},t.defined=function(n){return arguments.length?(u="function"==typeof n?n:Kt(!!n),t):u},t.curve=function(n){return arguments.length?(c=n,null!=a&&(s=c(a)),t):c},t.context=function(n){return arguments.length?(null==n?a=s=null:s=c(a=n),t):a},t}function _n(t,n){return n<t?-1:n>t?1:n>=t?0:NaN}function yn(t){return t}function gn(){function t(t){var a,c,s,f,l,h=t.length,p=0,d=new Array(h),v=new Array(h),_=+i.apply(this,arguments),y=Math.min(mv,Math.max(-mv,o.apply(this,arguments)-_)),g=Math.min(Math.abs(y)/h,u.apply(this,arguments)),m=g*(y<0?-1:1);for(a=0;a<h;++a)(l=v[d[a]=a]=+n(t[a],a,t))>0&&(p+=l);for(null!=e?d.sort(function(t,n){return e(v[t],v[n])}):null!=r&&d.sort(function(n,e){return r(t[n],t[e])}),a=0,s=p?(y-h*m)/p:0;a<h;++a,_=f)c=d[a],l=v[c],f=_+(l>0?l*s:0)+m,v[c]={data:t[c],index:a,value:l,startAngle:_,endAngle:f,padAngle:g};return v}var n=yn,e=_n,r=null,i=Kt(0),o=Kt(mv),u=Kt(0);return t.value=function(e){return arguments.length?(n="function"==typeof e?e:Kt(+e),t):n},t.sortValues=function(n){return arguments.length?(e=n,r=null,t):e},t.sort=function(n){return arguments.length?(r=n,e=null,t):r},t.startAngle=function(n){return arguments.length?(i="function"==typeof n?n:Kt(+n),t):i},t.endAngle=function(n){return arguments.length?(o="function"==typeof n?n:Kt(+n),t):o},t.padAngle=function(n){return arguments.length?(u="function"==typeof n?n:Kt(+n),t):u},t}function mn(t){this._curve=t}function xn(t){function n(n){return new mn(t(n))}return n._curve=t,n}function bn(t){var n=t.curve;return t.angle=t.x,delete t.x,t.radius=t.y,delete t.y,t.curve=function(t){return arguments.length?n(xn(t)):n()._curve},t}function wn(){return bn(dn().curve(xv))}function Mn(){var t=vn().curve(xv),n=t.curve,e=t.lineX0,r=t.lineX1,i=t.lineY0,o=t.lineY1;return t.angle=t.x,delete t.x,t.startAngle=t.x0,delete t.x0,t.endAngle=t.x1,delete t.x1,t.radius=t.y,delete t.y,t.innerRadius=t.y0,delete t.y0,t.outerRadius=t.y1,delete t.y1,t.lineStartAngle=function(){return bn(e())},delete t.lineX0,t.lineEndAngle=function(){return bn(r())},delete t.lineX1,t.lineInnerRadius=function(){return bn(i())},delete t.lineY0,t.lineOuterRadius=function(){return bn(o())},delete t.lineY1,t.curve=function(t){return arguments.length?n(xn(t)):n()._curve},t}function Tn(){function t(){var t;if(r||(r=t=Tt()),n.apply(this,arguments).draw(r,+e.apply(this,arguments)),t)return r=null,t+""||null}var n=Kt(bv),e=Kt(64),r=null;return t.type=function(e){return arguments.length?(n="function"==typeof e?e:Kt(e),t):n},t.size=function(n){return arguments.length?(e="function"==typeof n?n:Kt(+n),t):e},t.context=function(n){return arguments.length?(r=null==n?null:n,t):r},t}function kn(){}function Nn(t,n,e){t._context.bezierCurveTo((2*t._x0+t._x1)/3,(2*t._y0+t._y1)/3,(t._x0+2*t._x1)/3,(t._y0+2*t._y1)/3,(t._x0+4*t._x1+n)/6,(t._y0+4*t._y1+e)/6)}function Sn(t){this._context=t}function An(t){return new Sn(t)}function En(t){this._context=t}function Cn(t){return new En(t)}function zn(t){this._context=t}function Pn(t){return new zn(t)}function qn(t,n){this._basis=new Sn(t),this._beta=n}function Ln(t,n,e){t._context.bezierCurveTo(t._x1+t._k*(t._x2-t._x0),t._y1+t._k*(t._y2-t._y0),t._x2+t._k*(t._x1-n),t._y2+t._k*(t._y1-e),t._x2,t._y2)}function Rn(t,n){this._context=t,this._k=(1-n)/6}function Un(t,n){this._context=t,this._k=(1-n)/6}function Dn(t,n){this._context=t,this._k=(1-n)/6}function On(t,n,e){var r=t._x1,i=t._y1,o=t._x2,u=t._y2;if(t._l01_a>_v){var a=2*t._l01_2a+3*t._l01_a*t._l12_a+t._l12_2a,c=3*t._l01_a*(t._l01_a+t._l12_a);r=(r*a-t._x0*t._l12_2a+t._x2*t._l01_2a)/c,i=(i*a-t._y0*t._l12_2a+t._y2*t._l01_2a)/c}if(t._l23_a>_v){var s=2*t._l23_2a+3*t._l23_a*t._l12_a+t._l12_2a,f=3*t._l23_a*(t._l23_a+t._l12_a);o=(o*s+t._x1*t._l23_2a-n*t._l12_2a)/f,u=(u*s+t._y1*t._l23_2a-e*t._l12_2a)/f}t._context.bezierCurveTo(r,i,o,u,t._x2,t._y2)}function Fn(t,n){this._context=t,this._alpha=n}function In(t,n){this._context=t,this._alpha=n}function Yn(t,n){this._context=t,this._alpha=n}function Bn(t){this._context=t}function jn(t){return new Bn(t)}function Hn(t){return t<0?-1:1}function Xn(t,n,e){var r=t._x1-t._x0,i=n-t._x1,o=(t._y1-t._y0)/(r||i<0&&-0),u=(e-t._y1)/(i||r<0&&-0),a=(o*i+u*r)/(r+i);return(Hn(o)+Hn(u))*Math.min(Math.abs(o),Math.abs(u),.5*Math.abs(a))||0}function Vn(t,n){var e=t._x1-t._x0;return e?(3*(t._y1-t._y0)/e-n)/2:n}function Wn(t,n,e){var r=t._x0,i=t._y0,o=t._x1,u=t._y1,a=(o-r)/3;t._context.bezierCurveTo(r+a,i+a*n,o-a,u-a*e,o,u)}function $n(t){this._context=t}function Zn(t){this._context=new Gn(t)}function Gn(t){this._context=t}function Jn(t){return new $n(t)}function Qn(t){return new Zn(t)}function Kn(t){this._context=t}function te(t){var n,e,r=t.length-1,i=new Array(r),o=new Array(r),u=new Array(r);for(i[0]=0,o[0]=2,u[0]=t[0]+2*t[1],n=1;n<r-1;++n)i[n]=1,o[n]=4,u[n]=4*t[n]+2*t[n+1];for(i[r-1]=2,o[r-1]=7,u[r-1]=8*t[r-1]+t[r],n=1;n<r;++n)e=i[n]/o[n-1],o[n]-=e,u[n]-=e*u[n-1];for(i[r-1]=u[r-1]/o[r-1],n=r-2;n>=0;--n)i[n]=(u[n]-i[n+1])/o[n];for(o[r-1]=(t[r]+i[r-1])/2,n=0;n<r-1;++n)o[n]=2*t[n+1]-i[n+1];return[i,o]}function ne(t){return new Kn(t)}function ee(t,n){this._context=t,this._t=n}function re(t){return new ee(t,.5)}function ie(t){return new ee(t,0)}function oe(t){return new ee(t,1)}function ue(t,n){if((r=t.length)>1)for(var e,r,i=1,o=t[n[0]],u=o.length;i<r;++i){e=o,o=t[n[i]];for(var a=0;a<u;++a)o[a][1]+=o[a][0]=isNaN(e[a][1])?e[a][0]:e[a][1]}}function ae(t){for(var n=t.length,e=new Array(n);--n>=0;)e[n]=n;return e}function ce(t,n){return t[n]}function se(){function t(t){var o,u,a=n.apply(this,arguments),c=t.length,s=a.length,f=new Array(s);for(o=0;o<s;++o){for(var l,h=a[o],p=f[o]=new Array(c),d=0;d<c;++d)p[d]=l=[0,+i(t[d],h,d,t)],l.data=t[d];p.key=h}for(o=0,u=e(f);o<s;++o)f[u[o]].index=o;return r(f,u),f}var n=Kt([]),e=ae,r=ue,i=ce;return t.keys=function(e){return arguments.length?(n="function"==typeof e?e:Kt(Wv.call(e)),t):n},t.value=function(n){return arguments.length?(i="function"==typeof n?n:Kt(+n),t):i},t.order=function(n){return arguments.length?(e=null==n?ae:"function"==typeof n?n:Kt(Wv.call(n)),t):e},t.offset=function(n){return arguments.length?(r=null==n?ue:n,t):r},t}function fe(t,n){if((r=t.length)>0){for(var e,r,i,o=0,u=t[0].length;o<u;++o){for(i=e=0;e<r;++e)i+=t[e][o][1]||0;if(i)for(e=0;e<r;++e)t[e][o][1]/=i}ue(t,n)}}function le(t,n){if((e=t.length)>0){for(var e,r=0,i=t[n[0]],o=i.length;r<o;++r){for(var u=0,a=0;u<e;++u)a+=t[u][r][1]||0;i[r][1]+=i[r][0]=-a/2}ue(t,n)}}function he(t,n){if((i=t.length)>0&&(r=(e=t[n[0]]).length)>0){for(var e,r,i,o=0,u=1;u<r;++u){for(var a=0,c=0,s=0;a<i;++a){for(var f=t[n[a]],l=f[u][1]||0,h=f[u-1][1]||0,p=(l-h)/2,d=0;d<a;++d){var v=t[n[d]],_=v[u][1]||0,y=v[u-1][1]||0;p+=_-y}c+=l,s+=p*l}e[u-1][1]+=e[u-1][0]=o,c&&(o-=s/c)}e[u-1][1]+=e[u-1][0]=o,ue(t,n)}}function pe(t){var n=t.map(de);return ae(t).sort(function(t,e){return n[t]-n[e]})}function de(t){for(var n,e=0,r=-1,i=t.length;++r<i;)(n=+t[r][1])&&(e+=n);return e}function ve(t){return pe(t).reverse()}function _e(t){var n,e,r=t.length,i=t.map(de),o=ae(t).sort(function(t,n){return i[n]-i[t]}),u=0,a=0,c=[],s=[];for(n=0;n<r;++n)e=o[n],u<a?(u+=i[e],c.push(e)):(a+=i[e],s.push(e));return s.reverse().concat(c)}function ye(t){return ae(t).reverse()}function ge(t,n,e){t.prototype=n.prototype=e,e.constructor=t}function me(t,n){var e=Object.create(t.prototype);for(var r in n)e[r]=n[r];return e}function xe(){}function be(t){var n;return t=(t+"").trim().toLowerCase(),(n=Gv.exec(t))?(n=parseInt(n[1],16),new Ne(n>>8&15|n>>4&240,n>>4&15|240&n,(15&n)<<4|15&n,1)):(n=Jv.exec(t))?we(parseInt(n[1],16)):(n=Qv.exec(t))?new Ne(n[1],n[2],n[3],1):(n=Kv.exec(t))?new Ne(255*n[1]/100,255*n[2]/100,255*n[3]/100,1):(n=t_.exec(t))?Me(n[1],n[2],n[3],n[4]):(n=n_.exec(t))?Me(255*n[1]/100,255*n[2]/100,255*n[3]/100,n[4]):(n=e_.exec(t))?Se(n[1],n[2]/100,n[3]/100,1):(n=r_.exec(t))?Se(n[1],n[2]/100,n[3]/100,n[4]):i_.hasOwnProperty(t)?we(i_[t]):"transparent"===t?new Ne(NaN,NaN,NaN,0):null}function we(t){return new Ne(t>>16&255,t>>8&255,255&t,1)}function Me(t,n,e,r){return r<=0&&(t=n=e=NaN),new Ne(t,n,e,r)}function Te(t){return t instanceof xe||(t=be(t)),t?(t=t.rgb(),new Ne(t.r,t.g,t.b,t.opacity)):new Ne}function ke(t,n,e,r){return 1===arguments.length?Te(t):new Ne(t,n,e,null==r?1:r)}function Ne(t,n,e,r){this.r=+t,this.g=+n,this.b=+e,this.opacity=+r}function Se(t,n,e,r){return r<=0?t=n=e=NaN:e<=0||e>=1?t=n=NaN:n<=0&&(t=NaN),new Ce(t,n,e,r)}function Ae(t){if(t instanceof Ce)return new Ce(t.h,t.s,t.l,t.opacity);if(t instanceof xe||(t=be(t)),!t)return new Ce;if(t instanceof Ce)return t;t=t.rgb();var n=t.r/255,e=t.g/255,r=t.b/255,i=Math.min(n,e,r),o=Math.max(n,e,r),u=NaN,a=o-i,c=(o+i)/2;return a?(u=n===o?(e-r)/a+6*(e<r):e===o?(r-n)/a+2:(n-e)/a+4,a/=c<.5?o+i:2-o-i,u*=60):a=c>0&&c<1?0:u,new Ce(u,a,c,t.opacity)}function Ee(t,n,e,r){return 1===arguments.length?Ae(t):new Ce(t,n,e,null==r?1:r)}function Ce(t,n,e,r){this.h=+t,this.s=+n,this.l=+e,this.opacity=+r}function ze(t,n,e){return 255*(t<60?n+(e-n)*t/60:t<180?e:t<240?n+(e-n)*(240-t)/60:n)}function Pe(t){if(t instanceof Le)return new Le(t.l,t.a,t.b,t.opacity);if(t instanceof Ye){var n=t.h*o_;return new Le(t.l,Math.cos(n)*t.c,Math.sin(n)*t.c,t.opacity)}t instanceof Ne||(t=Te(t));var e=Oe(t.r),r=Oe(t.g),i=Oe(t.b),o=Re((.4124564*e+.3575761*r+.1804375*i)/c_),u=Re((.2126729*e+.7151522*r+.072175*i)/s_),a=Re((.0193339*e+.119192*r+.9503041*i)/f_);return new Le(116*u-16,500*(o-u),200*(u-a),t.opacity)}function qe(t,n,e,r){return 1===arguments.length?Pe(t):new Le(t,n,e,null==r?1:r)}function Le(t,n,e,r){this.l=+t,this.a=+n,this.b=+e,this.opacity=+r}function Re(t){return t>d_?Math.pow(t,1/3):t/p_+l_}function Ue(t){return t>h_?t*t*t:p_*(t-l_)}function De(t){return 255*(t<=.0031308?12.92*t:1.055*Math.pow(t,1/2.4)-.055)}function Oe(t){return(t/=255)<=.04045?t/12.92:Math.pow((t+.055)/1.055,2.4)}function Fe(t){if(t instanceof Ye)return new Ye(t.h,t.c,t.l,t.opacity);t instanceof Le||(t=Pe(t));var n=Math.atan2(t.b,t.a)*u_;return new Ye(n<0?n+360:n,Math.sqrt(t.a*t.a+t.b*t.b),t.l,t.opacity)}function Ie(t,n,e,r){return 1===arguments.length?Fe(t):new Ye(t,n,e,null==r?1:r)}function Ye(t,n,e,r){this.h=+t,this.c=+n,this.l=+e,this.opacity=+r}function Be(t){if(t instanceof He)return new He(t.h,t.s,t.l,t.opacity);t instanceof Ne||(t=Te(t));var n=t.r/255,e=t.g/255,r=t.b/255,i=(w_*r+x_*n-b_*e)/(w_+x_-b_),o=r-i,u=(m_*(e-i)-y_*o)/g_,a=Math.sqrt(u*u+o*o)/(m_*i*(1-i)),c=a?Math.atan2(u,o)*u_-120:NaN;return new He(c<0?c+360:c,a,i,t.opacity)}function je(t,n,e,r){return 1===arguments.length?Be(t):new He(t,n,e,null==r?1:r)}function He(t,n,e,r){this.h=+t,this.s=+n,this.l=+e,this.opacity=+r}function Xe(t,n,e,r,i){var o=t*t,u=o*t;return((1-3*t+3*o-u)*n+(4-6*o+3*u)*e+(1+3*t+3*o-3*u)*r+u*i)/6}function Ve(t){var n=t.length-1;return function(e){var r=e<=0?e=0:e>=1?(e=1,n-1):Math.floor(e*n),i=t[r],o=t[r+1],u=r>0?t[r-1]:2*i-o,a=r<n-1?t[r+2]:2*o-i;return Xe((e-r/n)*n,u,i,o,a)}}function We(t){var n=t.length;return function(e){var r=Math.floor(((e%=1)<0?++e:e)*n),i=t[(r+n-1)%n],o=t[r%n],u=t[(r+1)%n],a=t[(r+2)%n];return Xe((e-r/n)*n,i,o,u,a)}}function $e(t){return function(){return t}}function Ze(t,n){return function(e){return t+e*n}}function Ge(t,n,e){return t=Math.pow(t,e),n=Math.pow(n,e)-t,e=1/e,function(r){return Math.pow(t+r*n,e)}}function Je(t,n){var e=n-t;return e?Ze(t,e>180||e<-180?e-360*Math.round(e/360):e):$e(isNaN(t)?n:t)}function Qe(t){return 1===(t=+t)?Ke:function(n,e){return e-n?Ge(n,e,t):$e(isNaN(n)?e:n)}}function Ke(t,n){var e=n-t;return e?Ze(t,e):$e(isNaN(t)?n:t)}function tr(t){return function(n){var e,r,i=n.length,o=new Array(i),u=new Array(i),a=new Array(i);for(e=0;e<i;++e)r=ke(n[e]),o[e]=r.r||0,u[e]=r.g||0,a[e]=r.b||0;return o=t(o),u=t(u),a=t(a),r.opacity=1,function(t){return r.r=o(t),r.g=u(t),r.b=a(t),r+""}}}function nr(t,n){var e,r=n?n.length:0,i=t?Math.min(r,t.length):0,o=new Array(r),u=new Array(r);for(e=0;e<i;++e)o[e]=cr(t[e],n[e]);
-for(;e<r;++e)u[e]=n[e];return function(t){for(e=0;e<i;++e)u[e]=o[e](t);return u}}function er(t,n){var e=new Date;return t=+t,n-=t,function(r){return e.setTime(t+n*r),e}}function rr(t,n){return t=+t,n-=t,function(e){return t+n*e}}function ir(t,n){var e,r={},i={};null!==t&&"object"==typeof t||(t={}),null!==n&&"object"==typeof n||(n={});for(e in n)e in t?r[e]=cr(t[e],n[e]):i[e]=n[e];return function(t){for(e in r)i[e]=r[e](t);return i}}function or(t){return function(){return t}}function ur(t){return function(n){return t(n)+""}}function ar(t,n){var e,r,i,o=C_.lastIndex=z_.lastIndex=0,u=-1,a=[],c=[];for(t+="",n+="";(e=C_.exec(t))&&(r=z_.exec(n));)(i=r.index)>o&&(i=n.slice(o,i),a[u]?a[u]+=i:a[++u]=i),(e=e[0])===(r=r[0])?a[u]?a[u]+=r:a[++u]=r:(a[++u]=null,c.push({i:u,x:rr(e,r)})),o=z_.lastIndex;return o<n.length&&(i=n.slice(o),a[u]?a[u]+=i:a[++u]=i),a.length<2?c[0]?ur(c[0].x):or(n):(n=c.length,function(t){for(var e,r=0;r<n;++r)a[(e=c[r]).i]=e.x(t);return a.join("")})}function cr(t,n){var e,r=typeof n;return null==n||"boolean"===r?$e(n):("number"===r?rr:"string"===r?(e=be(n))?(n=e,S_):ar:n instanceof be?S_:n instanceof Date?er:Array.isArray(n)?nr:isNaN(n)?ir:rr)(t,n)}function sr(t,n){return t=+t,n-=t,function(e){return Math.round(t+n*e)}}function fr(t,n,e,r,i,o){var u,a,c;return(u=Math.sqrt(t*t+n*n))&&(t/=u,n/=u),(c=t*e+n*r)&&(e-=t*c,r-=n*c),(a=Math.sqrt(e*e+r*r))&&(e/=a,r/=a,c/=a),t*r<n*e&&(t=-t,n=-n,c=-c,u=-u),{translateX:i,translateY:o,rotate:Math.atan2(n,t)*P_,skewX:Math.atan(c)*P_,scaleX:u,scaleY:a}}function lr(t){return"none"===t?q_:(M_||(M_=document.createElement("DIV"),T_=document.documentElement,k_=document.defaultView),M_.style.transform=t,t=k_.getComputedStyle(T_.appendChild(M_),null).getPropertyValue("transform"),T_.removeChild(M_),t=t.slice(7,-1).split(","),fr(+t[0],+t[1],+t[2],+t[3],+t[4],+t[5]))}function hr(t){return null==t?q_:(N_||(N_=document.createElementNS("http://www.w3.org/2000/svg","g")),N_.setAttribute("transform",t),(t=N_.transform.baseVal.consolidate())?(t=t.matrix,fr(t.a,t.b,t.c,t.d,t.e,t.f)):q_)}function pr(t,n,e,r){function i(t){return t.length?t.pop()+" ":""}function o(t,r,i,o,u,a){if(t!==i||r!==o){var c=u.push("translate(",null,n,null,e);a.push({i:c-4,x:rr(t,i)},{i:c-2,x:rr(r,o)})}else(i||o)&&u.push("translate("+i+n+o+e)}function u(t,n,e,o){t!==n?(t-n>180?n+=360:n-t>180&&(t+=360),o.push({i:e.push(i(e)+"rotate(",null,r)-2,x:rr(t,n)})):n&&e.push(i(e)+"rotate("+n+r)}function a(t,n,e,o){t!==n?o.push({i:e.push(i(e)+"skewX(",null,r)-2,x:rr(t,n)}):n&&e.push(i(e)+"skewX("+n+r)}function c(t,n,e,r,o,u){if(t!==e||n!==r){var a=o.push(i(o)+"scale(",null,",",null,")");u.push({i:a-4,x:rr(t,e)},{i:a-2,x:rr(n,r)})}else 1===e&&1===r||o.push(i(o)+"scale("+e+","+r+")")}return function(n,e){var r=[],i=[];return n=t(n),e=t(e),o(n.translateX,n.translateY,e.translateX,e.translateY,r,i),u(n.rotate,e.rotate,r,i),a(n.skewX,e.skewX,r,i),c(n.scaleX,n.scaleY,e.scaleX,e.scaleY,r,i),n=e=null,function(t){for(var n,e=-1,o=i.length;++e<o;)r[(n=i[e]).i]=n.x(t);return r.join("")}}}function dr(t){return((t=Math.exp(t))+1/t)/2}function vr(t){return((t=Math.exp(t))-1/t)/2}function _r(t){return((t=Math.exp(2*t))-1)/(t+1)}function yr(t,n){var e,r,i=t[0],o=t[1],u=t[2],a=n[0],c=n[1],s=n[2],f=a-i,l=c-o,h=f*f+l*l;if(h<F_)r=Math.log(s/u)/U_,e=function(t){return[i+t*f,o+t*l,u*Math.exp(U_*t*r)]};else{var p=Math.sqrt(h),d=(s*s-u*u+O_*h)/(2*u*D_*p),v=(s*s-u*u-O_*h)/(2*s*D_*p),_=Math.log(Math.sqrt(d*d+1)-d),y=Math.log(Math.sqrt(v*v+1)-v);r=(y-_)/U_,e=function(t){var n=t*r,e=dr(_),a=u/(D_*p)*(e*_r(U_*n+_)-vr(_));return[i+a*f,o+a*l,u*e/dr(U_*n+_)]}}return e.duration=1e3*r,e}function gr(t){return function(n,e){var r=t((n=Ee(n)).h,(e=Ee(e)).h),i=Ke(n.s,e.s),o=Ke(n.l,e.l),u=Ke(n.opacity,e.opacity);return function(t){return n.h=r(t),n.s=i(t),n.l=o(t),n.opacity=u(t),n+""}}}function mr(t,n){var e=Ke((t=qe(t)).l,(n=qe(n)).l),r=Ke(t.a,n.a),i=Ke(t.b,n.b),o=Ke(t.opacity,n.opacity);return function(n){return t.l=e(n),t.a=r(n),t.b=i(n),t.opacity=o(n),t+""}}function xr(t){return function(n,e){var r=t((n=Ie(n)).h,(e=Ie(e)).h),i=Ke(n.c,e.c),o=Ke(n.l,e.l),u=Ke(n.opacity,e.opacity);return function(t){return n.h=r(t),n.c=i(t),n.l=o(t),n.opacity=u(t),n+""}}}function br(t){return function n(e){function r(n,r){var i=t((n=je(n)).h,(r=je(r)).h),o=Ke(n.s,r.s),u=Ke(n.l,r.l),a=Ke(n.opacity,r.opacity);return function(t){return n.h=i(t),n.s=o(t),n.l=u(Math.pow(t,e)),n.opacity=a(t),n+""}}return e=+e,r.gamma=n,r}(1)}function wr(t,n){for(var e=new Array(n),r=0;r<n;++r)e[r]=t(r/(n-1));return e}function Mr(){for(var t,n=0,e=arguments.length,r={};n<e;++n){if(!(t=arguments[n]+"")||t in r)throw new Error("illegal type: "+t);r[t]=[]}return new Tr(r)}function Tr(t){this._=t}function kr(t,n){return t.trim().split(/^|\s+/).map(function(t){var e="",r=t.indexOf(".");if(r>=0&&(e=t.slice(r+1),t=t.slice(0,r)),t&&!n.hasOwnProperty(t))throw new Error("unknown type: "+t);return{type:t,name:e}})}function Nr(t,n){for(var e,r=0,i=t.length;r<i;++r)if((e=t[r]).name===n)return e.value}function Sr(t,n,e){for(var r=0,i=t.length;r<i;++r)if(t[r].name===n){t[r]=V_,t=t.slice(0,r).concat(t.slice(r+1));break}return null!=e&&t.push({name:n,value:e}),t}function Ar(t){return new Function("d","return {"+t.map(function(t,n){return JSON.stringify(t)+": d["+n+"]"}).join(",")+"}")}function Er(t,n){var e=Ar(t);return function(r,i){return n(e(r),i,t)}}function Cr(t){var n=Object.create(null),e=[];return t.forEach(function(t){for(var r in t)r in n||e.push(n[r]=r)}),e}function zr(t){function n(t,n){var r,i,o=e(t,function(t,e){return r?r(t,e-1):(i=t,void(r=n?Er(t,n):Ar(t)))});return o.columns=i,o}function e(t,n){function e(){if(f>=s)return u;if(i)return i=!1,o;var n,e=f;if(34===t.charCodeAt(e)){for(var r=e;r++<s;)if(34===t.charCodeAt(r)){if(34!==t.charCodeAt(r+1))break;++r}return f=r+2,n=t.charCodeAt(r+1),13===n?(i=!0,10===t.charCodeAt(r+2)&&++f):10===n&&(i=!0),t.slice(e+1,r).replace(/""/g,'"')}for(;f<s;){var a=1;if(n=t.charCodeAt(f++),10===n)i=!0;else if(13===n)i=!0,10===t.charCodeAt(f)&&(++f,++a);else if(n!==c)continue;return t.slice(e,f-a)}return t.slice(e)}for(var r,i,o={},u={},a=[],s=t.length,f=0,l=0;(r=e())!==u;){for(var h=[];r!==o&&r!==u;)h.push(r),r=e();n&&null==(h=n(h,l++))||a.push(h)}return a}function r(n,e){return null==e&&(e=Cr(n)),[e.map(u).join(t)].concat(n.map(function(n){return e.map(function(t){return u(n[t])}).join(t)})).join("\n")}function i(t){return t.map(o).join("\n")}function o(n){return n.map(u).join(t)}function u(t){return null==t?"":a.test(t+="")?'"'+t.replace(/\"/g,'""')+'"':t}var a=new RegExp('["'+t+"\n]"),c=t.charCodeAt(0);return{parse:n,parseRows:e,format:r,formatRows:i}}function Pr(t,n){function e(t){var n,e=s.status;if(!e&&Lr(s)||e>=200&&e<300||304===e){if(o)try{n=o.call(r,s)}catch(i){return void a.call("error",r,i)}else n=s;a.call("load",r,n)}else a.call("error",r,t)}var r,i,o,u,a=Mr("beforesend","progress","load","error"),c=q(),s=new XMLHttpRequest,f=null,l=null,h=0;return"undefined"==typeof XDomainRequest||"withCredentials"in s||!/^(http(s)?:)?\/\//.test(t)||(s=new XDomainRequest),"onload"in s?s.onload=s.onerror=s.ontimeout=e:s.onreadystatechange=function(t){s.readyState>3&&e(t)},s.onprogress=function(t){a.call("progress",r,t)},r={header:function(t,n){return t=(t+"").toLowerCase(),arguments.length<2?c.get(t):(null==n?c.remove(t):c.set(t,n+""),r)},mimeType:function(t){return arguments.length?(i=null==t?null:t+"",r):i},responseType:function(t){return arguments.length?(u=t,r):u},timeout:function(t){return arguments.length?(h=+t,r):h},user:function(t){return arguments.length<1?f:(f=null==t?null:t+"",r)},password:function(t){return arguments.length<1?l:(l=null==t?null:t+"",r)},response:function(t){return o=t,r},get:function(t,n){return r.send("GET",t,n)},post:function(t,n){return r.send("POST",t,n)},send:function(n,e,o){return o||"function"!=typeof e||(o=e,e=null),o&&1===o.length&&(o=qr(o)),s.open(n,t,!0,f,l),null==i||c.has("accept")||c.set("accept",i+",*/*"),s.setRequestHeader&&c.each(function(t,n){s.setRequestHeader(n,t)}),null!=i&&s.overrideMimeType&&s.overrideMimeType(i),null!=u&&(s.responseType=u),h>0&&(s.timeout=h),o&&r.on("error",o).on("load",function(t){o(null,t)}),a.call("beforesend",r,s),s.send(null==e?null:e),r},abort:function(){return s.abort(),r},on:function(){var t=a.on.apply(a,arguments);return t===a?r:t}},n?r.get(n):r}function qr(t){return function(n,e){t(null==n?e:null)}}function Lr(t){var n=t.responseType;return n&&"text"!==n?t.response:t.responseText}function Rr(t,n){return function(e,r){var i=Pr(e).mimeType(t).response(n);return r?i.get(r):i}}function Ur(t,n){return function(e,r,i){arguments.length<3&&(i=r,r=null);var o=Pr(e).mimeType(t);return o.row=function(t){return arguments.length?o.response(Dr(n,r=t)):r},o.row(r),i?o.get(i):o}}function Dr(t,n){return function(e){return t(e.responseText,n)}}function Or(){return _y||(my(Fr),_y=gy.now()+yy)}function Fr(){_y=0}function Ir(){this._call=this._time=this._next=null}function Yr(t,n,e){var r=new Ir;return r.restart(t,n,e),r}function Br(){Or(),++ly;for(var t,n=W_;n;)(t=_y-n._time)>=0&&n._call.call(null,t),n=n._next;--ly}function jr(t){_y=(vy=t||gy.now())+yy,ly=hy=0;try{Br()}finally{ly=0,Xr(),_y=0}}function Hr(){var t=gy.now(),n=t-vy;n>dy&&(yy-=n,vy=t)}function Xr(){for(var t,n,e=W_,r=1/0;e;)e._call?(r>e._time&&(r=e._time),t=e,e=e._next):(n=e._next,e._next=null,e=t?t._next=n:W_=n);$_=t,Vr(r)}function Vr(t){if(!ly){hy&&(hy=clearTimeout(hy));var n=t-_y;n>24?(t<1/0&&(hy=setTimeout(jr,n)),py&&(py=clearInterval(py))):(py||(py=setInterval(Hr,dy)),ly=1,my(jr))}}function Wr(t,n,e){var r=new Ir;return n=null==n?0:+n,r.restart(function(e){r.stop(),t(e+n)},n,e),r}function $r(t,n,e){var r=new Ir,i=n;return null==n?(r.restart(t,n,e),r):(n=+n,e=null==e?Or():+e,r.restart(function o(u){u+=i,r.restart(o,i+=n,e),t(u)},n,e),r)}function Zr(t,n,e,r){function i(n){return t(n=new Date((+n))),n}return i.floor=i,i.ceil=function(e){return t(e=new Date(e-1)),n(e,1),t(e),e},i.round=function(t){var n=i(t),e=i.ceil(t);return t-n<e-t?n:e},i.offset=function(t,e){return n(t=new Date((+t)),null==e?1:Math.floor(e)),t},i.range=function(e,r,o){var u=[];if(e=i.ceil(e),o=null==o?1:Math.floor(o),!(e<r&&o>0))return u;do u.push(new Date((+e)));while(n(e,o),t(e),e<r);return u},i.filter=function(e){return Zr(function(n){for(;t(n),!e(n);)n.setTime(n-1)},function(t,r){for(;--r>=0;)for(;n(t,1),!e(t););})},e&&(i.count=function(n,r){return xy.setTime(+n),by.setTime(+r),t(xy),t(by),Math.floor(e(xy,by))},i.every=function(t){return t=Math.floor(t),isFinite(t)&&t>0?t>1?i.filter(r?function(n){return r(n)%t===0}:function(n){return i.count(0,n)%t===0}):i:null}),i}function Gr(t){return Zr(function(n){n.setDate(n.getDate()-(n.getDay()+7-t)%7),n.setHours(0,0,0,0)},function(t,n){t.setDate(t.getDate()+7*n)},function(t,n){return(n-t-(n.getTimezoneOffset()-t.getTimezoneOffset())*ky)/Ay})}function Jr(t){return Zr(function(n){n.setUTCDate(n.getUTCDate()-(n.getUTCDay()+7-t)%7),n.setUTCHours(0,0,0,0)},function(t,n){t.setUTCDate(t.getUTCDate()+7*n)},function(t,n){return(n-t)/Ay})}function Qr(t,n){if((e=(t=n?t.toExponential(n-1):t.toExponential()).indexOf("e"))<0)return null;var e,r=t.slice(0,e);return[r.length>1?r[0]+r.slice(2):r,+t.slice(e+1)]}function Kr(t){return t=Qr(Math.abs(t)),t?t[1]:NaN}function ti(t,n){return function(e,r){for(var i=e.length,o=[],u=0,a=t[0],c=0;i>0&&a>0&&(c+a+1>r&&(a=Math.max(1,r-c)),o.push(e.substring(i-=a,i+a)),!((c+=a+1)>r));)a=t[u=(u+1)%t.length];return o.reverse().join(n)}}function ni(t,n){t=t.toPrecision(n);t:for(var e,r=t.length,i=1,o=-1;i<r;++i)switch(t[i]){case".":o=e=i;break;case"0":0===o&&(o=i),e=i;break;case"e":break t;default:o>0&&(o=0)}return o>0?t.slice(0,o)+t.slice(e+1):t}function ei(t,n){var e=Qr(t,n);if(!e)return t+"";var r=e[0],i=e[1],o=i-(Tg=3*Math.max(-8,Math.min(8,Math.floor(i/3))))+1,u=r.length;return o===u?r:o>u?r+new Array(o-u+1).join("0"):o>0?r.slice(0,o)+"."+r.slice(o):"0."+new Array(1-o).join("0")+Qr(t,Math.max(0,n+o-1))[0]}function ri(t,n){var e=Qr(t,n);if(!e)return t+"";var r=e[0],i=e[1];return i<0?"0."+new Array((-i)).join("0")+r:r.length>i+1?r.slice(0,i+1)+"."+r.slice(i+1):r+new Array(i-r.length+2).join("0")}function ii(t){return new oi(t)}function oi(t){if(!(n=Sg.exec(t)))throw new Error("invalid format: "+t);var n,e=n[1]||" ",r=n[2]||">",i=n[3]||"-",o=n[4]||"",u=!!n[5],a=n[6]&&+n[6],c=!!n[7],s=n[8]&&+n[8].slice(1),f=n[9]||"";"n"===f?(c=!0,f="g"):Ng[f]||(f=""),(u||"0"===e&&"="===r)&&(u=!0,e="0",r="="),this.fill=e,this.align=r,this.sign=i,this.symbol=o,this.zero=u,this.width=a,this.comma=c,this.precision=s,this.type=f}function ui(t){return t}function ai(t){function n(t){function n(t){var n,i,c,g=d,m=v;if("c"===p)m=_(t)+m,t="";else{t=+t;var x=(t<0||1/t<0)&&(t*=-1,!0);if(t=_(t,h),x)for(n=-1,i=t.length,x=!1;++n<i;)if(c=t.charCodeAt(n),48<c&&c<58||"x"===p&&96<c&&c<103||"X"===p&&64<c&&c<71){x=!0;break}if(g=(x?"("===a?a:"-":"-"===a||"("===a?"":a)+g,m=m+("s"===p?Eg[8+Tg/3]:"")+(x&&"("===a?")":""),y)for(n=-1,i=t.length;++n<i;)if(c=t.charCodeAt(n),48>c||c>57){m=(46===c?o+t.slice(n+1):t.slice(n))+m,t=t.slice(0,n);break}}l&&!s&&(t=r(t,1/0));var b=g.length+t.length+m.length,w=b<f?new Array(f-b+1).join(e):"";switch(l&&s&&(t=r(w+t,w.length?f-m.length:1/0),w=""),u){case"<":return g+t+m+w;case"=":return g+w+t+m;case"^":return w.slice(0,b=w.length>>1)+g+t+m+w.slice(b)}return w+g+t+m}t=ii(t);var e=t.fill,u=t.align,a=t.sign,c=t.symbol,s=t.zero,f=t.width,l=t.comma,h=t.precision,p=t.type,d="$"===c?i[0]:"#"===c&&/[boxX]/.test(p)?"0"+p.toLowerCase():"",v="$"===c?i[1]:/[%p]/.test(p)?"%":"",_=Ng[p],y=!p||/[defgprs%]/.test(p);return h=null==h?p?6:12:/[gprs]/.test(p)?Math.max(1,Math.min(21,h)):Math.max(0,Math.min(20,h)),n.toString=function(){return t+""},n}function e(t,e){var r=n((t=ii(t),t.type="f",t)),i=3*Math.max(-8,Math.min(8,Math.floor(Kr(e)/3))),o=Math.pow(10,-i),u=Eg[8+i/3];return function(t){return r(o*t)+u}}var r=t.grouping&&t.thousands?ti(t.grouping,t.thousands):ui,i=t.currency,o=t.decimal;return{format:n,formatPrefix:e}}function ci(n){return Ag=ai(n),t.format=Ag.format,t.formatPrefix=Ag.formatPrefix,Ag}function si(t){return Math.max(0,-Kr(Math.abs(t)))}function fi(t,n){return Math.max(0,3*Math.max(-8,Math.min(8,Math.floor(Kr(n)/3)))-Kr(Math.abs(t)))}function li(t,n){return t=Math.abs(t),n=Math.abs(n)-t,Math.max(0,Kr(n)-Kr(t))+1}function hi(t){if(0<=t.y&&t.y<100){var n=new Date((-1),t.m,t.d,t.H,t.M,t.S,t.L);return n.setFullYear(t.y),n}return new Date(t.y,t.m,t.d,t.H,t.M,t.S,t.L)}function pi(t){if(0<=t.y&&t.y<100){var n=new Date(Date.UTC(-1,t.m,t.d,t.H,t.M,t.S,t.L));return n.setUTCFullYear(t.y),n}return new Date(Date.UTC(t.y,t.m,t.d,t.H,t.M,t.S,t.L))}function di(t){return{y:t,m:0,d:1,H:0,M:0,S:0,L:0}}function vi(t){function n(t,n){return function(e){var r,i,o,u=[],a=-1,c=0,s=t.length;for(e instanceof Date||(e=new Date((+e)));++a<s;)37===t.charCodeAt(a)&&(u.push(t.slice(c,a)),null!=(i=zg[r=t.charAt(++a)])?r=t.charAt(++a):i="e"===r?" ":"0",(o=n[r])&&(r=o(e,i)),u.push(r),c=a+1);return u.push(t.slice(c,a)),u.join("")}}function e(t,n){return function(e){var i=di(1900),o=r(i,t,e+="",0);if(o!=e.length)return null;if("p"in i&&(i.H=i.H%12+12*i.p),"W"in i||"U"in i){"w"in i||(i.w="W"in i?1:0);var u="Z"in i?pi(di(i.y)).getUTCDay():n(di(i.y)).getDay();i.m=0,i.d="W"in i?(i.w+6)%7+7*i.W-(u+5)%7:i.w+7*i.U-(u+6)%7}return"Z"in i?(i.H+=i.Z/100|0,i.M+=i.Z%100,pi(i)):n(i)}}function r(t,n,e,r){for(var i,o,u=0,a=n.length,c=e.length;u<a;){if(r>=c)return-1;if(i=n.charCodeAt(u++),37===i){if(i=n.charAt(u++),o=B[i in zg?n.charAt(u++):i],!o||(r=o(t,e,r))<0)return-1}else if(i!=e.charCodeAt(r++))return-1}return r}function i(t,n,e){var r=C.exec(n.slice(e));return r?(t.p=z[r[0].toLowerCase()],e+r[0].length):-1}function o(t,n,e){var r=L.exec(n.slice(e));return r?(t.w=R[r[0].toLowerCase()],e+r[0].length):-1}function u(t,n,e){var r=P.exec(n.slice(e));return r?(t.w=q[r[0].toLowerCase()],e+r[0].length):-1}function a(t,n,e){var r=O.exec(n.slice(e));return r?(t.m=F[r[0].toLowerCase()],e+r[0].length):-1}function c(t,n,e){var r=U.exec(n.slice(e));return r?(t.m=D[r[0].toLowerCase()],e+r[0].length):-1}function s(t,n,e){return r(t,w,n,e)}function f(t,n,e){return r(t,M,n,e)}function l(t,n,e){return r(t,T,n,e)}function h(t){return S[t.getDay()]}function p(t){return N[t.getDay()]}function d(t){return E[t.getMonth()]}function v(t){return A[t.getMonth()]}function _(t){return k[+(t.getHours()>=12)]}function y(t){return S[t.getUTCDay()]}function g(t){return N[t.getUTCDay()]}function m(t){return E[t.getUTCMonth()]}function x(t){return A[t.getUTCMonth()]}function b(t){return k[+(t.getUTCHours()>=12)]}var w=t.dateTime,M=t.date,T=t.time,k=t.periods,N=t.days,S=t.shortDays,A=t.months,E=t.shortMonths,C=gi(k),z=mi(k),P=gi(N),q=mi(N),L=gi(S),R=mi(S),U=gi(A),D=mi(A),O=gi(E),F=mi(E),I={a:h,A:p,b:d,B:v,c:null,d:Li,e:Li,H:Ri,I:Ui,j:Di,L:Oi,m:Fi,M:Ii,p:_,S:Yi,U:Bi,w:ji,W:Hi,x:null,X:null,y:Xi,Y:Vi,Z:Wi,"%":co},Y={a:y,A:g,b:m,B:x,c:null,d:$i,e:$i,H:Zi,I:Gi,j:Ji,L:Qi,m:Ki,M:to,p:b,S:no,U:eo,w:ro,W:io,x:null,X:null,y:oo,Y:uo,Z:ao,"%":co},B={a:o,A:u,b:a,B:c,c:s,d:Si,e:Si,H:Ei,I:Ei,j:Ai,L:Pi,m:Ni,M:Ci,p:i,S:zi,U:bi,w:xi,W:wi,x:f,X:l,y:Ti,Y:Mi,Z:ki,"%":qi};return I.x=n(M,I),I.X=n(T,I),I.c=n(w,I),Y.x=n(M,Y),Y.X=n(T,Y),Y.c=n(w,Y),{format:function(t){var e=n(t+="",I);return e.toString=function(){return t},e},parse:function(t){var n=e(t+="",hi);return n.toString=function(){return t},n},utcFormat:function(t){var e=n(t+="",Y);return e.toString=function(){return t},e},utcParse:function(t){var n=e(t,pi);return n.toString=function(){return t},n}}}function _i(t,n,e){var r=t<0?"-":"",i=(r?-t:t)+"",o=i.length;return r+(o<e?new Array(e-o+1).join(n)+i:i)}function yi(t){return t.replace(Lg,"\\$&")}function gi(t){return new RegExp("^(?:"+t.map(yi).join("|")+")","i")}function mi(t){for(var n={},e=-1,r=t.length;++e<r;)n[t[e].toLowerCase()]=e;return n}function xi(t,n,e){var r=Pg.exec(n.slice(e,e+1));return r?(t.w=+r[0],e+r[0].length):-1}function bi(t,n,e){var r=Pg.exec(n.slice(e));return r?(t.U=+r[0],e+r[0].length):-1}function wi(t,n,e){var r=Pg.exec(n.slice(e));return r?(t.W=+r[0],e+r[0].length):-1}function Mi(t,n,e){var r=Pg.exec(n.slice(e,e+4));return r?(t.y=+r[0],e+r[0].length):-1}function Ti(t,n,e){var r=Pg.exec(n.slice(e,e+2));return r?(t.y=+r[0]+(+r[0]>68?1900:2e3),e+r[0].length):-1}function ki(t,n,e){var r=/^(Z)|([+-]\d\d)(?:\:?(\d\d))?/.exec(n.slice(e,e+6));return r?(t.Z=r[1]?0:-(r[2]+(r[3]||"00")),e+r[0].length):-1}function Ni(t,n,e){var r=Pg.exec(n.slice(e,e+2));return r?(t.m=r[0]-1,e+r[0].length):-1}function Si(t,n,e){var r=Pg.exec(n.slice(e,e+2));return r?(t.d=+r[0],e+r[0].length):-1}function Ai(t,n,e){var r=Pg.exec(n.slice(e,e+3));return r?(t.m=0,t.d=+r[0],e+r[0].length):-1}function Ei(t,n,e){var r=Pg.exec(n.slice(e,e+2));return r?(t.H=+r[0],e+r[0].length):-1}function Ci(t,n,e){var r=Pg.exec(n.slice(e,e+2));return r?(t.M=+r[0],e+r[0].length):-1}function zi(t,n,e){var r=Pg.exec(n.slice(e,e+2));return r?(t.S=+r[0],e+r[0].length):-1}function Pi(t,n,e){var r=Pg.exec(n.slice(e,e+3));return r?(t.L=+r[0],e+r[0].length):-1}function qi(t,n,e){var r=qg.exec(n.slice(e,e+1));return r?e+r[0].length:-1}function Li(t,n){return _i(t.getDate(),n,2)}function Ri(t,n){return _i(t.getHours(),n,2)}function Ui(t,n){return _i(t.getHours()%12||12,n,2)}function Di(t,n){return _i(1+Ry.count(Ky(t),t),n,3)}function Oi(t,n){return _i(t.getMilliseconds(),n,3)}function Fi(t,n){return _i(t.getMonth()+1,n,2)}function Ii(t,n){return _i(t.getMinutes(),n,2)}function Yi(t,n){return _i(t.getSeconds(),n,2)}function Bi(t,n){return _i(Dy.count(Ky(t),t),n,2)}function ji(t){return t.getDay()}function Hi(t,n){return _i(Oy.count(Ky(t),t),n,2)}function Xi(t,n){return _i(t.getFullYear()%100,n,2)}function Vi(t,n){return _i(t.getFullYear()%1e4,n,4)}function Wi(t){var n=t.getTimezoneOffset();return(n>0?"-":(n*=-1,"+"))+_i(n/60|0,"0",2)+_i(n%60,"0",2)}function $i(t,n){return _i(t.getUTCDate(),n,2)}function Zi(t,n){return _i(t.getUTCHours(),n,2)}function Gi(t,n){return _i(t.getUTCHours()%12||12,n,2)}function Ji(t,n){return _i(1+og.count(Mg(t),t),n,3)}function Qi(t,n){return _i(t.getUTCMilliseconds(),n,3)}function Ki(t,n){return _i(t.getUTCMonth()+1,n,2)}function to(t,n){return _i(t.getUTCMinutes(),n,2)}function no(t,n){return _i(t.getUTCSeconds(),n,2)}function eo(t,n){return _i(ag.count(Mg(t),t),n,2)}function ro(t){return t.getUTCDay()}function io(t,n){return _i(cg.count(Mg(t),t),n,2)}function oo(t,n){return _i(t.getUTCFullYear()%100,n,2)}function uo(t,n){return _i(t.getUTCFullYear()%1e4,n,4)}function ao(){return"+0000"}function co(){return"%"}function so(n){return Cg=vi(n),t.timeFormat=Cg.format,t.timeParse=Cg.parse,t.utcFormat=Cg.utcFormat,t.utcParse=Cg.utcParse,Cg}function fo(t){return t.toISOString()}function lo(t){var n=new Date(t);return isNaN(n)?null:n}function ho(t){function n(n){var o=n+"",u=e.get(o);if(!u){if(i!==Yg)return i;e.set(o,u=r.push(n))}return t[(u-1)%t.length]}var e=q(),r=[],i=Yg;return t=null==t?[]:Ig.call(t),n.domain=function(t){if(!arguments.length)return r.slice();r=[],e=q();for(var i,o,u=-1,a=t.length;++u<a;)e.has(o=(i=t[u])+"")||e.set(o,r.push(i));return n},n.range=function(e){return arguments.length?(t=Ig.call(e),n):t.slice()},n.unknown=function(t){return arguments.length?(i=t,n):i},n.copy=function(){return ho().domain(r).range(t).unknown(i)},n}function po(){function t(){var t=i().length,r=u[1]<u[0],h=u[r-0],p=u[1-r];n=(p-h)/Math.max(1,t-c+2*s),a&&(n=Math.floor(n)),h+=(p-h-n*(t-c))*f,e=n*(1-c),a&&(h=Math.round(h),e=Math.round(e));var d=l(t).map(function(t){return h+n*t});return o(r?d.reverse():d)}var n,e,r=ho().unknown(void 0),i=r.domain,o=r.range,u=[0,1],a=!1,c=0,s=0,f=.5;return delete r.unknown,r.domain=function(n){return arguments.length?(i(n),t()):i()},r.range=function(n){return arguments.length?(u=[+n[0],+n[1]],t()):u.slice()},r.rangeRound=function(n){return u=[+n[0],+n[1]],a=!0,t()},r.bandwidth=function(){return e},r.step=function(){return n},r.round=function(n){return arguments.length?(a=!!n,t()):a},r.padding=function(n){return arguments.length?(c=s=Math.max(0,Math.min(1,n)),t()):c},r.paddingInner=function(n){return arguments.length?(c=Math.max(0,Math.min(1,n)),t()):c},r.paddingOuter=function(n){return arguments.length?(s=Math.max(0,Math.min(1,n)),t()):s},r.align=function(n){return arguments.length?(f=Math.max(0,Math.min(1,n)),t()):f},r.copy=function(){return po().domain(i()).range(u).round(a).paddingInner(c).paddingOuter(s).align(f)},t()}function vo(t){var n=t.copy;return t.padding=t.paddingOuter,delete t.paddingInner,delete t.paddingOuter,t.copy=function(){return vo(n())},t}function _o(){return vo(po().paddingInner(1))}function yo(t){return function(){return t}}function go(t){return+t}function mo(t,n){return(n-=t=+t)?function(e){return(e-t)/n}:yo(n)}function xo(t){return function(n,e){var r=t(n=+n,e=+e);return function(t){return t<=n?0:t>=e?1:r(t)}}}function bo(t){return function(n,e){var r=t(n=+n,e=+e);return function(t){return t<=0?n:t>=1?e:r(t)}}}function wo(t,n,e,r){var i=t[0],o=t[1],u=n[0],a=n[1];return o<i?(i=e(o,i),u=r(a,u)):(i=e(i,o),u=r(u,a)),function(t){return u(i(t))}}function Mo(t,n,e,r){var i=Math.min(t.length,n.length)-1,o=new Array(i),u=new Array(i),a=-1;for(t[i]<t[0]&&(t=t.slice().reverse(),n=n.slice().reverse());++a<i;)o[a]=e(t[a],t[a+1]),u[a]=r(n[a],n[a+1]);return function(n){var e=Sd(t,n,1,i)-1;return u[e](o[e](n))}}function To(t,n){return n.domain(t.domain()).range(t.range()).interpolate(t.interpolate()).clamp(t.clamp())}function ko(t,n){function e(){return i=Math.min(a.length,c.length)>2?Mo:wo,o=u=null,r}function r(n){return(o||(o=i(a,c,f?xo(t):t,s)))(+n)}var i,o,u,a=Bg,c=Bg,s=cr,f=!1;return r.invert=function(t){return(u||(u=i(c,a,mo,f?bo(n):n)))(+t)},r.domain=function(t){return arguments.length?(a=Fg.call(t,go),e()):a.slice()},r.range=function(t){return arguments.length?(c=Ig.call(t),e()):c.slice()},r.rangeRound=function(t){return c=Ig.call(t),s=sr,e()},r.clamp=function(t){return arguments.length?(f=!!t,e()):f},r.interpolate=function(t){return arguments.length?(s=t,e()):s},e()}function No(n,e,r){var i,o=n[0],u=n[n.length-1],a=p(o,u,null==e?10:e);switch(r=ii(null==r?",f":r),r.type){case"s":var c=Math.max(Math.abs(o),Math.abs(u));return null!=r.precision||isNaN(i=fi(a,c))||(r.precision=i),t.formatPrefix(r,c);case"":case"e":case"g":case"p":case"r":null!=r.precision||isNaN(i=li(a,Math.max(Math.abs(o),Math.abs(u))))||(r.precision=i-("e"===r.type));break;case"f":case"%":null!=r.precision||isNaN(i=si(a))||(r.precision=i-2*("%"===r.type))}return t.format(r)}function So(t){var n=t.domain;return t.ticks=function(t){var e=n();return h(e[0],e[e.length-1],null==t?10:t)},t.tickFormat=function(t,e){return No(n(),t,e)},t.nice=function(e){var r=n(),i=r.length-1,o=null==e?10:e,u=r[0],a=r[i],c=p(u,a,o);return c&&(c=p(Math.floor(u/c)*c,Math.ceil(a/c)*c,o),r[0]=Math.floor(u/c)*c,r[i]=Math.ceil(a/c)*c,n(r)),t},t}function Ao(){var t=ko(mo,rr);return t.copy=function(){return To(t,Ao())},So(t)}function Eo(){function t(t){return+t}var n=[0,1];return t.invert=t,t.domain=t.range=function(e){return arguments.length?(n=Fg.call(e,go),t):n.slice()},t.copy=function(){return Eo().domain(n)},So(t)}function Co(t,n){t=t.slice();var e,r=0,i=t.length-1,o=t[r],u=t[i];return u<o&&(e=r,r=i,i=e,e=o,o=u,u=e),t[r]=n.floor(o),t[i]=n.ceil(u),t}function zo(t,n){return(n=Math.log(n/t))?function(e){return Math.log(e/t)/n}:yo(n)}function Po(t,n){return t<0?function(e){return-Math.pow(-n,e)*Math.pow(-t,1-e)}:function(e){return Math.pow(n,e)*Math.pow(t,1-e)}}function qo(t){return isFinite(t)?+("1e"+t):t<0?0:t}function Lo(t){return 10===t?qo:t===Math.E?Math.exp:function(n){return Math.pow(t,n)}}function Ro(t){return t===Math.E?Math.log:10===t&&Math.log10||2===t&&Math.log2||(t=Math.log(t),function(n){return Math.log(n)/t})}function Uo(t){return function(n){return-t(-n)}}function Do(){function n(){return o=Ro(i),u=Lo(i),r()[0]<0&&(o=Uo(o),u=Uo(u)),e}var e=ko(zo,Po).domain([1,10]),r=e.domain,i=10,o=Ro(10),u=Lo(10);return e.base=function(t){return arguments.length?(i=+t,n()):i},e.domain=function(t){return arguments.length?(r(t),n()):r()},e.ticks=function(t){var n,e=r(),a=e[0],c=e[e.length-1];(n=c<a)&&(p=a,a=c,c=p);var s,f,l,p=o(a),d=o(c),v=null==t?10:+t,_=[];if(!(i%1)&&d-p<v){if(p=Math.round(p)-1,d=Math.round(d)+1,a>0){for(;p<d;++p)for(f=1,s=u(p);f<i;++f)if(l=s*f,!(l<a)){if(l>c)break;_.push(l)}}else for(;p<d;++p)for(f=i-1,s=u(p);f>=1;--f)if(l=s*f,!(l<a)){if(l>c)break;_.push(l)}}else _=h(p,d,Math.min(d-p,v)).map(u);return n?_.reverse():_},e.tickFormat=function(n,r){if(null==r&&(r=10===i?".0e":","),"function"!=typeof r&&(r=t.format(r)),n===1/0)return r;null==n&&(n=10);var a=Math.max(1,i*n/e.ticks().length);return function(t){var n=t/u(Math.round(o(t)));return n*i<i-.5&&(n*=i),n<=a?r(t):""}},e.nice=function(){return r(Co(r(),{floor:function(t){return u(Math.floor(o(t)))},ceil:function(t){return u(Math.ceil(o(t)))}}))},e.copy=function(){return To(e,Do().base(i))},e}function Oo(t,n){return t<0?-Math.pow(-t,n):Math.pow(t,n)}function Fo(){function t(t,n){return(n=Oo(n,e)-(t=Oo(t,e)))?function(r){return(Oo(r,e)-t)/n}:yo(n)}function n(t,n){return n=Oo(n,e)-(t=Oo(t,e)),function(r){return Oo(t+n*r,1/e)}}var e=1,r=ko(t,n),i=r.domain;return r.exponent=function(t){return arguments.length?(e=+t,i(i())):e},r.copy=function(){return To(r,Fo().exponent(e))},So(r)}function Io(){return Fo().exponent(.5)}function Yo(){function t(){var t=0,n=Math.max(1,i.length);for(o=new Array(n-1);++t<n;)o[t-1]=_(r,t/n);return e}function e(t){if(!isNaN(t=+t))return i[Sd(o,t)]}var r=[],i=[],o=[];return e.invertExtent=function(t){var n=i.indexOf(t);return n<0?[NaN,NaN]:[n>0?o[n-1]:r[0],n<o.length?o[n]:r[r.length-1]]},e.domain=function(e){if(!arguments.length)return r.slice();r=[];for(var i,o=0,u=e.length;o<u;++o)i=e[o],null==i||isNaN(i=+i)||r.push(i);return r.sort(n),t()},e.range=function(n){return arguments.length?(i=Ig.call(n),t()):i.slice()},e.quantiles=function(){return o.slice()},e.copy=function(){return Yo().domain(r).range(i)},e}function Bo(){function t(t){if(t<=t)return u[Sd(o,t,0,i)]}function n(){var n=-1;for(o=new Array(i);++n<i;)o[n]=((n+1)*r-(n-i)*e)/(i+1);return t}var e=0,r=1,i=1,o=[.5],u=[0,1];return t.domain=function(t){return arguments.length?(e=+t[0],r=+t[1],n()):[e,r]},t.range=function(t){return arguments.length?(i=(u=Ig.call(t)).length-1,n()):u.slice()},t.invertExtent=function(t){var n=u.indexOf(t);return n<0?[NaN,NaN]:n<1?[e,o[0]]:n>=i?[o[i-1],r]:[o[n-1],o[n]]},t.copy=function(){return Bo().domain([e,r]).range(u)},So(t)}function jo(){function t(t){if(t<=t)return e[Sd(n,t,0,r)]}var n=[.5],e=[0,1],r=1;return t.domain=function(i){return arguments.length?(n=Ig.call(i),r=Math.min(n.length,e.length-1),t):n.slice()},t.range=function(i){return arguments.length?(e=Ig.call(i),r=Math.min(n.length,e.length-1),t):e.slice()},t.invertExtent=function(t){var r=e.indexOf(t);return[n[r-1],n[r]]},t.copy=function(){return jo().domain(n).range(e)},t}function Ho(t){return new Date(t)}function Xo(t){return t instanceof Date?+t:+new Date((+t))}function Vo(t,n,r,i,o,u,a,c,s){function f(e){return(a(e)<e?_:u(e)<e?y:o(e)<e?g:i(e)<e?m:n(e)<e?r(e)<e?x:b:t(e)<e?w:M)(e)}function l(n,r,i,o){if(null==n&&(n=10),"number"==typeof n){var u=Math.abs(i-r)/n,a=e(function(t){return t[2]}).right(T,u);a===T.length?(o=p(r/Zg,i/Zg,n),n=t):a?(a=T[u/T[a-1][2]<T[a][2]/u?a-1:a],o=a[1],n=a[0]):(o=p(r,i,n),n=c)}return null==o?n:n.every(o)}var h=ko(mo,rr),d=h.invert,v=h.domain,_=s(".%L"),y=s(":%S"),g=s("%I:%M"),m=s("%I %p"),x=s("%a %d"),b=s("%b %d"),w=s("%B"),M=s("%Y"),T=[[a,1,jg],[a,5,5*jg],[a,15,15*jg],[a,30,30*jg],[u,1,Hg],[u,5,5*Hg],[u,15,15*Hg],[u,30,30*Hg],[o,1,Xg],[o,3,3*Xg],[o,6,6*Xg],[o,12,12*Xg],[i,1,Vg],[i,2,2*Vg],[r,1,Wg],[n,1,$g],[n,3,3*$g],[t,1,Zg]];return h.invert=function(t){return new Date(d(t))},h.domain=function(t){return arguments.length?v(Fg.call(t,Xo)):v().map(Ho)},h.ticks=function(t,n){var e,r=v(),i=r[0],o=r[r.length-1],u=o<i;return u&&(e=i,i=o,o=e),e=l(t,i,o,n),e=e?e.range(i,o+1):[],u?e.reverse():e},h.tickFormat=function(t,n){return null==n?f:s(n)},h.nice=function(t,n){var e=v();return(t=l(t,e[0],e[e.length-1],n))?v(Co(e,t)):h},h.copy=function(){return To(h,Vo(t,n,r,i,o,u,a,c,s))},h}function Wo(){return Vo(Ky,Jy,Dy,Ry,qy,zy,Ey,wy,t.timeFormat).domain([new Date(2e3,0,1),new Date(2e3,0,2)])}function $o(){return Vo(Mg,bg,ag,og,rg,ng,Ey,wy,t.utcFormat).domain([Date.UTC(2e3,0,1),Date.UTC(2e3,0,2)])}function Zo(t){return t.match(/.{6}/g).map(function(t){return"#"+t})}function Go(t){(t<0||t>1)&&(t-=Math.floor(t));var n=Math.abs(t-.5);return rm.h=360*t-100,rm.s=1.5-1.5*n,rm.l=.8-.9*n,rm+""}function Jo(t){var n=t.length;return function(e){return t[Math.max(0,Math.min(n-1,Math.floor(e*n)))]}}function Qo(t){function n(n){var o=(n-e)/(r-e);return t(i?Math.max(0,Math.min(1,o)):o)}var e=0,r=1,i=!1;return n.domain=function(t){return arguments.length?(e=+t[0],r=+t[1],n):[e,r]},n.clamp=function(t){return arguments.length?(i=!!t,n):i},n.interpolator=function(e){return arguments.length?(t=e,n):t},n.copy=function(){return Qo(t).domain([e,r]).clamp(i)},So(n)}function Ko(t){var n=t+="",e=n.indexOf(":");return e>=0&&"xmlns"!==(n=t.slice(0,e))&&(t=t.slice(e+1)),sm.hasOwnProperty(n)?{space:sm[n],local:t}:t}function tu(t){return function(){var n=this.ownerDocument,e=this.namespaceURI;return e===cm&&n.documentElement.namespaceURI===cm?n.createElement(t):n.createElementNS(e,t)}}function nu(t){return function(){return this.ownerDocument.createElementNS(t.space,t.local)}}function eu(t){var n=Ko(t);return(n.local?nu:tu)(n)}function ru(){return new iu}function iu(){this._="@"+(++fm).toString(36)}function ou(t,n,e){return t=uu(t,n,e),function(n){var e=n.relatedTarget;e&&(e===this||8&e.compareDocumentPosition(this))||t.call(this,n)}}function uu(n,e,r){return function(i){var o=t.event;t.event=i;try{n.call(this,this.__data__,e,r)}finally{t.event=o}}}function au(t){return t.trim().split(/^|\s+/).map(function(t){var n="",e=t.indexOf(".");return e>=0&&(n=t.slice(e+1),t=t.slice(0,e)),{type:t,name:n}})}function cu(t){return function(){var n=this.__on;if(n){for(var e,r=0,i=-1,o=n.length;r<o;++r)e=n[r],t.type&&e.type!==t.type||e.name!==t.name?n[++i]=e:this.removeEventListener(e.type,e.listener,e.capture);
-++i?n.length=i:delete this.__on}}}function su(t,n,e){var r=vm.hasOwnProperty(t.type)?ou:uu;return function(i,o,u){var a,c=this.__on,s=r(n,o,u);if(c)for(var f=0,l=c.length;f<l;++f)if((a=c[f]).type===t.type&&a.name===t.name)return this.removeEventListener(a.type,a.listener,a.capture),this.addEventListener(a.type,a.listener=s,a.capture=e),void(a.value=n);this.addEventListener(t.type,s,e),a={type:t.type,name:t.name,value:n,listener:s,capture:e},c?c.push(a):this.__on=[a]}}function fu(t,n,e){var r,i,o=au(t+""),u=o.length;{if(!(arguments.length<2)){for(a=n?su:cu,null==e&&(e=!1),r=0;r<u;++r)this.each(a(o[r],n,e));return this}var a=this.node().__on;if(a)for(var c,s=0,f=a.length;s<f;++s)for(r=0,c=a[s];r<u;++r)if((i=o[r]).type===c.type&&i.name===c.name)return c.value}}function lu(n,e,r,i){var o=t.event;n.sourceEvent=t.event,t.event=n;try{return e.apply(r,i)}finally{t.event=o}}function hu(){for(var n,e=t.event;n=e.sourceEvent;)e=n;return e}function pu(t,n){var e=t.ownerSVGElement||t;if(e.createSVGPoint){var r=e.createSVGPoint();return r.x=n.clientX,r.y=n.clientY,r=r.matrixTransform(t.getScreenCTM().inverse()),[r.x,r.y]}var i=t.getBoundingClientRect();return[n.clientX-i.left-t.clientLeft,n.clientY-i.top-t.clientTop]}function du(t){var n=hu();return n.changedTouches&&(n=n.changedTouches[0]),pu(t,n)}function vu(){}function _u(t){return null==t?vu:function(){return this.querySelector(t)}}function yu(t){"function"!=typeof t&&(t=_u(t));for(var n=this._groups,e=n.length,r=new Array(e),i=0;i<e;++i)for(var o,u,a=n[i],c=a.length,s=r[i]=new Array(c),f=0;f<c;++f)(o=a[f])&&(u=t.call(o,o.__data__,f,a))&&("__data__"in o&&(u.__data__=o.__data__),s[f]=u);return new qa(r,this._parents)}function gu(){return[]}function mu(t){return null==t?gu:function(){return this.querySelectorAll(t)}}function xu(t){"function"!=typeof t&&(t=mu(t));for(var n=this._groups,e=n.length,r=[],i=[],o=0;o<e;++o)for(var u,a=n[o],c=a.length,s=0;s<c;++s)(u=a[s])&&(r.push(t.call(u,u.__data__,s,a)),i.push(u));return new qa(r,i)}function bu(t){"function"!=typeof t&&(t=dm(t));for(var n=this._groups,e=n.length,r=new Array(e),i=0;i<e;++i)for(var o,u=n[i],a=u.length,c=r[i]=[],s=0;s<a;++s)(o=u[s])&&t.call(o,o.__data__,s,u)&&c.push(o);return new qa(r,this._parents)}function wu(t){return new Array(t.length)}function Mu(){return new qa(this._enter||this._groups.map(wu),this._parents)}function Tu(t,n){this.ownerDocument=t.ownerDocument,this.namespaceURI=t.namespaceURI,this._next=null,this._parent=t,this.__data__=n}function ku(t){return function(){return t}}function Nu(t,n,e,r,i,o){for(var u,a=0,c=n.length,s=o.length;a<s;++a)(u=n[a])?(u.__data__=o[a],r[a]=u):e[a]=new Tu(t,o[a]);for(;a<c;++a)(u=n[a])&&(i[a]=u)}function Su(t,n,e,r,i,o,u){var a,c,s,f={},l=n.length,h=o.length,p=new Array(l);for(a=0;a<l;++a)(c=n[a])&&(p[a]=s=ym+u.call(c,c.__data__,a,n),s in f?i[a]=c:f[s]=c);for(a=0;a<h;++a)s=ym+u.call(t,o[a],a,o),(c=f[s])?(r[a]=c,c.__data__=o[a],f[s]=null):e[a]=new Tu(t,o[a]);for(a=0;a<l;++a)(c=n[a])&&f[p[a]]===c&&(i[a]=c)}function Au(t,n){if(!t)return p=new Array(this.size()),s=-1,this.each(function(t){p[++s]=t}),p;var e=n?Su:Nu,r=this._parents,i=this._groups;"function"!=typeof t&&(t=ku(t));for(var o=i.length,u=new Array(o),a=new Array(o),c=new Array(o),s=0;s<o;++s){var f=r[s],l=i[s],h=l.length,p=t.call(f,f&&f.__data__,s,r),d=p.length,v=a[s]=new Array(d),_=u[s]=new Array(d),y=c[s]=new Array(h);e(f,l,v,_,y,p,n);for(var g,m,x=0,b=0;x<d;++x)if(g=v[x]){for(x>=b&&(b=x+1);!(m=_[b])&&++b<d;);g._next=m||null}}return u=new qa(u,r),u._enter=a,u._exit=c,u}function Eu(){return new qa(this._exit||this._groups.map(wu),this._parents)}function Cu(t){for(var n=this._groups,e=t._groups,r=n.length,i=e.length,o=Math.min(r,i),u=new Array(r),a=0;a<o;++a)for(var c,s=n[a],f=e[a],l=s.length,h=u[a]=new Array(l),p=0;p<l;++p)(c=s[p]||f[p])&&(h[p]=c);for(;a<r;++a)u[a]=n[a];return new qa(u,this._parents)}function zu(){for(var t=this._groups,n=-1,e=t.length;++n<e;)for(var r,i=t[n],o=i.length-1,u=i[o];--o>=0;)(r=i[o])&&(u&&u!==r.nextSibling&&u.parentNode.insertBefore(r,u),u=r);return this}function Pu(t){function n(n,e){return n&&e?t(n.__data__,e.__data__):!n-!e}t||(t=qu);for(var e=this._groups,r=e.length,i=new Array(r),o=0;o<r;++o){for(var u,a=e[o],c=a.length,s=i[o]=new Array(c),f=0;f<c;++f)(u=a[f])&&(s[f]=u);s.sort(n)}return new qa(i,this._parents).order()}function qu(t,n){return t<n?-1:t>n?1:t>=n?0:NaN}function Lu(){var t=arguments[0];return arguments[0]=this,t.apply(null,arguments),this}function Ru(){var t=new Array(this.size()),n=-1;return this.each(function(){t[++n]=this}),t}function Uu(){for(var t=this._groups,n=0,e=t.length;n<e;++n)for(var r=t[n],i=0,o=r.length;i<o;++i){var u=r[i];if(u)return u}return null}function Du(){var t=0;return this.each(function(){++t}),t}function Ou(){return!this.node()}function Fu(t){for(var n=this._groups,e=0,r=n.length;e<r;++e)for(var i,o=n[e],u=0,a=o.length;u<a;++u)(i=o[u])&&t.call(i,i.__data__,u,o);return this}function Iu(t){return function(){this.removeAttribute(t)}}function Yu(t){return function(){this.removeAttributeNS(t.space,t.local)}}function Bu(t,n){return function(){this.setAttribute(t,n)}}function ju(t,n){return function(){this.setAttributeNS(t.space,t.local,n)}}function Hu(t,n){return function(){var e=n.apply(this,arguments);null==e?this.removeAttribute(t):this.setAttribute(t,e)}}function Xu(t,n){return function(){var e=n.apply(this,arguments);null==e?this.removeAttributeNS(t.space,t.local):this.setAttributeNS(t.space,t.local,e)}}function Vu(t,n){var e=Ko(t);if(arguments.length<2){var r=this.node();return e.local?r.getAttributeNS(e.space,e.local):r.getAttribute(e)}return this.each((null==n?e.local?Yu:Iu:"function"==typeof n?e.local?Xu:Hu:e.local?ju:Bu)(e,n))}function Wu(t){return t.ownerDocument&&t.ownerDocument.defaultView||t.document&&t||t.defaultView}function $u(t){return function(){this.style.removeProperty(t)}}function Zu(t,n,e){return function(){this.style.setProperty(t,n,e)}}function Gu(t,n,e){return function(){var r=n.apply(this,arguments);null==r?this.style.removeProperty(t):this.style.setProperty(t,r,e)}}function Ju(t,n,e){var r;return arguments.length>1?this.each((null==n?$u:"function"==typeof n?Gu:Zu)(t,n,null==e?"":e)):Wu(r=this.node()).getComputedStyle(r,null).getPropertyValue(t)}function Qu(t){return function(){delete this[t]}}function Ku(t,n){return function(){this[t]=n}}function ta(t,n){return function(){var e=n.apply(this,arguments);null==e?delete this[t]:this[t]=e}}function na(t,n){return arguments.length>1?this.each((null==n?Qu:"function"==typeof n?ta:Ku)(t,n)):this.node()[t]}function ea(t){return t.trim().split(/^|\s+/)}function ra(t){return t.classList||new ia(t)}function ia(t){this._node=t,this._names=ea(t.getAttribute("class")||"")}function oa(t,n){for(var e=ra(t),r=-1,i=n.length;++r<i;)e.add(n[r])}function ua(t,n){for(var e=ra(t),r=-1,i=n.length;++r<i;)e.remove(n[r])}function aa(t){return function(){oa(this,t)}}function ca(t){return function(){ua(this,t)}}function sa(t,n){return function(){(n.apply(this,arguments)?oa:ua)(this,t)}}function fa(t,n){var e=ea(t+"");if(arguments.length<2){for(var r=ra(this.node()),i=-1,o=e.length;++i<o;)if(!r.contains(e[i]))return!1;return!0}return this.each(("function"==typeof n?sa:n?aa:ca)(e,n))}function la(){this.textContent=""}function ha(t){return function(){this.textContent=t}}function pa(t){return function(){var n=t.apply(this,arguments);this.textContent=null==n?"":n}}function da(t){return arguments.length?this.each(null==t?la:("function"==typeof t?pa:ha)(t)):this.node().textContent}function va(){this.innerHTML=""}function _a(t){return function(){this.innerHTML=t}}function ya(t){return function(){var n=t.apply(this,arguments);this.innerHTML=null==n?"":n}}function ga(t){return arguments.length?this.each(null==t?va:("function"==typeof t?ya:_a)(t)):this.node().innerHTML}function ma(){this.nextSibling&&this.parentNode.appendChild(this)}function xa(){return this.each(ma)}function ba(){this.previousSibling&&this.parentNode.insertBefore(this,this.parentNode.firstChild)}function wa(){return this.each(ba)}function Ma(t){var n="function"==typeof t?t:eu(t);return this.select(function(){return this.appendChild(n.apply(this,arguments))})}function Ta(){return null}function ka(t,n){var e="function"==typeof t?t:eu(t),r=null==n?Ta:"function"==typeof n?n:_u(n);return this.select(function(){return this.insertBefore(e.apply(this,arguments),r.apply(this,arguments)||null)})}function Na(){var t=this.parentNode;t&&t.removeChild(this)}function Sa(){return this.each(Na)}function Aa(t){return arguments.length?this.property("__data__",t):this.node().__data__}function Ea(t,n,e){var r=Wu(t),i=r.CustomEvent;i?i=new i(n,e):(i=r.document.createEvent("Event"),e?(i.initEvent(n,e.bubbles,e.cancelable),i.detail=e.detail):i.initEvent(n,!1,!1)),t.dispatchEvent(i)}function Ca(t,n){return function(){return Ea(this,t,n)}}function za(t,n){return function(){return Ea(this,t,n.apply(this,arguments))}}function Pa(t,n){return this.each(("function"==typeof n?za:Ca)(t,n))}function qa(t,n){this._groups=t,this._parents=n}function La(){return new qa([[document.documentElement]],gm)}function Ra(t){return"string"==typeof t?new qa([[document.querySelector(t)]],[document.documentElement]):new qa([[t]],gm)}function Ua(t){return"string"==typeof t?new qa([document.querySelectorAll(t)],[document.documentElement]):new qa([null==t?[]:t],gm)}function Da(t,n,e){arguments.length<3&&(e=n,n=hu().changedTouches);for(var r,i=0,o=n?n.length:0;i<o;++i)if((r=n[i]).identifier===e)return pu(t,r);return null}function Oa(t,n){null==n&&(n=hu().touches);for(var e=0,r=n?n.length:0,i=new Array(r);e<r;++e)i[e]=pu(t,n[e]);return i}function Fa(t,n,e,r,i,o){var u=t.__transition;if(u){if(e in u)return}else t.__transition={};ja(t,e,{name:n,index:r,group:i,on:mm,tween:xm,time:o.time,delay:o.delay,duration:o.duration,ease:o.ease,timer:null,state:bm})}function Ia(t,n){var e=t.__transition;if(!e||!(e=e[n])||e.state>bm)throw new Error("too late");return e}function Ya(t,n){var e=t.__transition;if(!e||!(e=e[n])||e.state>Mm)throw new Error("too late");return e}function Ba(t,n){var e=t.__transition;if(!e||!(e=e[n]))throw new Error("too late");return e}function ja(t,n,e){function r(t){e.state=wm,e.delay<=t?i(t-e.delay):e.timer.restart(i,e.delay,e.time)}function i(r){var i,c,s,f;for(i in a)f=a[i],f.name===e.name&&(f.state===Tm?(f.state=Nm,f.timer.stop(),f.on.call("interrupt",t,t.__data__,f.index,f.group),delete a[i]):+i<n&&(f.state=Nm,f.timer.stop(),delete a[i]));if(Wr(function(){e.state===Tm&&(e.timer.restart(o,e.delay,e.time),o(r))}),e.state=Mm,e.on.call("start",t,t.__data__,e.index,e.group),e.state===Mm){for(e.state=Tm,u=new Array(s=e.tween.length),i=0,c=-1;i<s;++i)(f=e.tween[i].value.call(t,t.__data__,e.index,e.group))&&(u[++c]=f);u.length=c+1}}function o(r){for(var i=r<e.duration?e.ease.call(null,r/e.duration):(e.state=km,1),o=-1,c=u.length;++o<c;)u[o].call(null,i);if(e.state===km){e.state=Nm,e.timer.stop(),e.on.call("end",t,t.__data__,e.index,e.group);for(o in a)if(+o!==n)return void delete a[n];delete t.__transition}}var u,a=t.__transition;a[n]=e,e.timer=Yr(r,0,e.time)}function Ha(t,n){var e,r,i,o=t.__transition,u=!0;if(o){n=null==n?null:n+"";for(i in o)(e=o[i]).name===n?(r=e.state===Tm,e.state=Nm,e.timer.stop(),r&&e.on.call("interrupt",t,t.__data__,e.index,e.group),delete o[i]):u=!1;u&&delete t.__transition}}function Xa(t){return this.each(function(){Ha(this,t)})}function Va(t,n){var e,r;return function(){var i=Ya(this,t),o=i.tween;if(o!==e){r=e=o;for(var u=0,a=r.length;u<a;++u)if(r[u].name===n){r=r.slice(),r.splice(u,1);break}}i.tween=r}}function Wa(t,n,e){var r,i;if("function"!=typeof e)throw new Error;return function(){var o=Ya(this,t),u=o.tween;if(u!==r){i=(r=u).slice();for(var a={name:n,value:e},c=0,s=i.length;c<s;++c)if(i[c].name===n){i[c]=a;break}c===s&&i.push(a)}o.tween=i}}function $a(t,n){var e=this._id;if(t+="",arguments.length<2){for(var r,i=Ba(this.node(),e).tween,o=0,u=i.length;o<u;++o)if((r=i[o]).name===t)return r.value;return null}return this.each((null==n?Va:Wa)(e,t,n))}function Za(t,n,e){var r=t._id;return t.each(function(){var t=Ya(this,r);(t.value||(t.value={}))[n]=e.apply(this,arguments)}),function(t){return Ba(t,r).value[n]}}function Ga(t,n){var e;return("number"==typeof n?rr:n instanceof be?S_:(e=be(n))?(n=e,S_):ar)(t,n)}function Ja(t){return function(){this.removeAttribute(t)}}function Qa(t){return function(){this.removeAttributeNS(t.space,t.local)}}function Ka(t,n,e){var r,i;return function(){var o=this.getAttribute(t);return o===e?null:o===r?i:i=n(r=o,e)}}function tc(t,n,e){var r,i;return function(){var o=this.getAttributeNS(t.space,t.local);return o===e?null:o===r?i:i=n(r=o,e)}}function nc(t,n,e){var r,i,o;return function(){var u,a=e(this);return null==a?void this.removeAttribute(t):(u=this.getAttribute(t),u===a?null:u===r&&a===i?o:o=n(r=u,i=a))}}function ec(t,n,e){var r,i,o;return function(){var u,a=e(this);return null==a?void this.removeAttributeNS(t.space,t.local):(u=this.getAttributeNS(t.space,t.local),u===a?null:u===r&&a===i?o:o=n(r=u,i=a))}}function rc(t,n){var e=Ko(t),r="transform"===e?R_:Ga;return this.attrTween(t,"function"==typeof n?(e.local?ec:nc)(e,r,Za(this,"attr."+t,n)):null==n?(e.local?Qa:Ja)(e):(e.local?tc:Ka)(e,r,n))}function ic(t,n){function e(){var e=this,r=n.apply(e,arguments);return r&&function(n){e.setAttributeNS(t.space,t.local,r(n))}}return e._value=n,e}function oc(t,n){function e(){var e=this,r=n.apply(e,arguments);return r&&function(n){e.setAttribute(t,r(n))}}return e._value=n,e}function uc(t,n){var e="attr."+t;if(arguments.length<2)return(e=this.tween(e))&&e._value;if(null==n)return this.tween(e,null);if("function"!=typeof n)throw new Error;var r=Ko(t);return this.tween(e,(r.local?ic:oc)(r,n))}function ac(t,n){return function(){Ia(this,t).delay=+n.apply(this,arguments)}}function cc(t,n){return n=+n,function(){Ia(this,t).delay=n}}function sc(t){var n=this._id;return arguments.length?this.each(("function"==typeof t?ac:cc)(n,t)):Ba(this.node(),n).delay}function fc(t,n){return function(){Ya(this,t).duration=+n.apply(this,arguments)}}function lc(t,n){return n=+n,function(){Ya(this,t).duration=n}}function hc(t){var n=this._id;return arguments.length?this.each(("function"==typeof t?fc:lc)(n,t)):Ba(this.node(),n).duration}function pc(t,n){if("function"!=typeof n)throw new Error;return function(){Ya(this,t).ease=n}}function dc(t){var n=this._id;return arguments.length?this.each(pc(n,t)):Ba(this.node(),n).ease}function vc(t){"function"!=typeof t&&(t=dm(t));for(var n=this._groups,e=n.length,r=new Array(e),i=0;i<e;++i)for(var o,u=n[i],a=u.length,c=r[i]=[],s=0;s<a;++s)(o=u[s])&&t.call(o,o.__data__,s,u)&&c.push(o);return new Uc(r,this._parents,this._name,this._id)}function _c(t){if(t._id!==this._id)throw new Error;for(var n=this._groups,e=t._groups,r=n.length,i=e.length,o=Math.min(r,i),u=new Array(r),a=0;a<o;++a)for(var c,s=n[a],f=e[a],l=s.length,h=u[a]=new Array(l),p=0;p<l;++p)(c=s[p]||f[p])&&(h[p]=c);for(;a<r;++a)u[a]=n[a];return new Uc(u,this._parents,this._name,this._id)}function yc(t){return(t+"").trim().split(/^|\s+/).every(function(t){var n=t.indexOf(".");return n>=0&&(t=t.slice(0,n)),!t||"start"===t})}function gc(t,n,e){var r,i,o=yc(n)?Ia:Ya;return function(){var u=o(this,t),a=u.on;a!==r&&(i=(r=a).copy()).on(n,e),u.on=i}}function mc(t,n){var e=this._id;return arguments.length<2?Ba(this.node(),e).on.on(t):this.each(gc(e,t,n))}function xc(t){return function(){var n=this.parentNode;for(var e in this.__transition)if(+e!==t)return;n&&n.removeChild(this)}}function bc(){return this.on("end.remove",xc(this._id))}function wc(t){var n=this._name,e=this._id;"function"!=typeof t&&(t=_u(t));for(var r=this._groups,i=r.length,o=new Array(i),u=0;u<i;++u)for(var a,c,s=r[u],f=s.length,l=o[u]=new Array(f),h=0;h<f;++h)(a=s[h])&&(c=t.call(a,a.__data__,h,s))&&("__data__"in a&&(c.__data__=a.__data__),l[h]=c,Fa(l[h],n,e,h,l,Ba(a,e)));return new Uc(o,this._parents,n,e)}function Mc(t){var n=this._name,e=this._id;"function"!=typeof t&&(t=mu(t));for(var r=this._groups,i=r.length,o=[],u=[],a=0;a<i;++a)for(var c,s=r[a],f=s.length,l=0;l<f;++l)if(c=s[l]){for(var h,p=t.call(c,c.__data__,l,s),d=Ba(c,e),v=0,_=p.length;v<_;++v)(h=p[v])&&Fa(h,n,e,v,p,d);o.push(p),u.push(c)}return new Uc(o,u,n,e)}function Tc(){return new Sm(this._groups,this._parents)}function kc(t,n){var e,r,i;return function(){var o=Wu(this).getComputedStyle(this,null),u=o.getPropertyValue(t),a=(this.style.removeProperty(t),o.getPropertyValue(t));return u===a?null:u===e&&a===r?i:i=n(e=u,r=a)}}function Nc(t){return function(){this.style.removeProperty(t)}}function Sc(t,n,e){var r,i;return function(){var o=Wu(this).getComputedStyle(this,null).getPropertyValue(t);return o===e?null:o===r?i:i=n(r=o,e)}}function Ac(t,n,e){var r,i,o;return function(){var u=Wu(this).getComputedStyle(this,null),a=u.getPropertyValue(t),c=e(this);return null==c&&(this.style.removeProperty(t),c=u.getPropertyValue(t)),a===c?null:a===r&&c===i?o:o=n(r=a,i=c)}}function Ec(t,n,e){var r="transform"==(t+="")?L_:Ga;return null==n?this.styleTween(t,kc(t,r)).on("end.style."+t,Nc(t)):this.styleTween(t,"function"==typeof n?Ac(t,r,Za(this,"style."+t,n)):Sc(t,r,n),e)}function Cc(t,n,e){function r(){var r=this,i=n.apply(r,arguments);return i&&function(n){r.style.setProperty(t,i(n),e)}}return r._value=n,r}function zc(t,n,e){var r="style."+(t+="");if(arguments.length<2)return(r=this.tween(r))&&r._value;if(null==n)return this.tween(r,null);if("function"!=typeof n)throw new Error;return this.tween(r,Cc(t,n,null==e?"":e))}function Pc(t){return function(){this.textContent=t}}function qc(t){return function(){var n=t(this);this.textContent=null==n?"":n}}function Lc(t){return this.tween("text","function"==typeof t?qc(Za(this,"text",t)):Pc(null==t?"":t+""))}function Rc(){for(var t=this._name,n=this._id,e=Oc(),r=this._groups,i=r.length,o=0;o<i;++o)for(var u,a=r[o],c=a.length,s=0;s<c;++s)if(u=a[s]){var f=Ba(u,n);Fa(u,t,e,s,a,{time:f.time+f.delay+f.duration,delay:0,duration:f.duration,ease:f.ease})}return new Uc(r,this._parents,t,e)}function Uc(t,n,e,r){this._groups=t,this._parents=n,this._name=e,this._id=r}function Dc(t){return La().transition(t)}function Oc(){return++Am}function Fc(t,n){for(var e;!(e=t.__transition)||!(e=e[n]);)if(!(t=t.parentNode))return Cm.time=Or(),Cm;return e}function Ic(t){var n,e;t instanceof Uc?(n=t._id,t=t._name):(n=Oc(),(e=Cm).time=Or(),t=null==t?null:t+"");for(var r=this._groups,i=r.length,o=0;o<i;++o)for(var u,a=r[o],c=a.length,s=0;s<c;++s)(u=a[s])&&Fa(u,t,n,s,a,e||Fc(u,n));return new Uc(r,this._parents,t,n)}function Yc(t,n){var e,r,i=t.__transition;if(i){n=null==n?null:n+"";for(r in i)if((e=i[r]).state>wm&&e.name===n)return new Uc([[t]],zm,n,(+r))}return null}function Bc(t){return t}function jc(t,n,e){var r=t(e);return"translate("+(isFinite(r)?r:n(e))+",0)"}function Hc(t,n,e){var r=t(e);return"translate(0,"+(isFinite(r)?r:n(e))+")"}function Xc(t){var n=t.bandwidth()/2;return function(e){return t(e)+n}}function Vc(){return!this.__axis}function Wc(t,n){function e(e){var s,f=null==i?n.ticks?n.ticks.apply(n,r):n.domain():i,l=null==o?n.tickFormat?n.tickFormat.apply(n,r):Bc:o,h=Math.max(u,0)+c,p=t===qm||t===Rm?jc:Hc,d=n.range(),v=d[0]+.5,_=d[d.length-1]+.5,y=(n.bandwidth?Xc:Bc)(n.copy()),g=e.selection?e.selection():e,m=g.selectAll(".domain").data([null]),x=g.selectAll(".tick").data(f,n).order(),b=x.exit(),w=x.enter().append("g").attr("class","tick"),M=x.select("line"),T=x.select("text"),k=t===qm||t===Um?-1:1,N=t===Um||t===Lm?(s="x","y"):(s="y","x");m=m.merge(m.enter().insert("path",".tick").attr("class","domain").attr("stroke","#000")),x=x.merge(w),M=M.merge(w.append("line").attr("stroke","#000").attr(s+"2",k*u).attr(N+"1",.5).attr(N+"2",.5)),T=T.merge(w.append("text").attr("fill","#000").attr(s,k*h).attr(N,.5).attr("dy",t===qm?"0em":t===Rm?".71em":".32em")),e!==g&&(m=m.transition(e),x=x.transition(e),M=M.transition(e),T=T.transition(e),b=b.transition(e).attr("opacity",Dm).attr("transform",function(t){return p(y,this.parentNode.__axis||y,t)}),w.attr("opacity",Dm).attr("transform",function(t){return p(this.parentNode.__axis||y,y,t)})),b.remove(),m.attr("d",t===Um||t==Lm?"M"+k*a+","+v+"H0.5V"+_+"H"+k*a:"M"+v+","+k*a+"V0.5H"+_+"V"+k*a),x.attr("opacity",1).attr("transform",function(t){return p(y,y,t)}),M.attr(s+"2",k*u),T.attr(s,k*h).text(l),g.filter(Vc).attr("fill","none").attr("font-size",10).attr("font-family","sans-serif").attr("text-anchor",t===Lm?"start":t===Um?"end":"middle"),g.each(function(){this.__axis=y})}var r=[],i=null,o=null,u=6,a=6,c=3;return e.scale=function(t){return arguments.length?(n=t,e):n},e.ticks=function(){return r=Pm.call(arguments),e},e.tickArguments=function(t){return arguments.length?(r=null==t?[]:Pm.call(t),e):r.slice()},e.tickValues=function(t){return arguments.length?(i=null==t?null:Pm.call(t),e):i&&i.slice()},e.tickFormat=function(t){return arguments.length?(o=t,e):o},e.tickSize=function(t){return arguments.length?(u=a=+t,e):u},e.tickSizeInner=function(t){return arguments.length?(u=+t,e):u},e.tickSizeOuter=function(t){return arguments.length?(a=+t,e):a},e.tickPadding=function(t){return arguments.length?(c=+t,e):c},e}function $c(t){return Wc(qm,t)}function Zc(t){return Wc(Lm,t)}function Gc(t){return Wc(Rm,t)}function Jc(t){return Wc(Um,t)}function Qc(t,n){return t.parent===n.parent?1:2}function Kc(t){return t.reduce(ts,0)/t.length}function ts(t,n){return t+n.x}function ns(t){return 1+t.reduce(es,0)}function es(t,n){return Math.max(t,n.y)}function rs(t){for(var n;n=t.children;)t=n[0];return t}function is(t){for(var n;n=t.children;)t=n[n.length-1];return t}function os(){function t(t){var o,u=0;t.eachAfter(function(t){var e=t.children;e?(t.x=Kc(e),t.y=ns(e)):(t.x=o?u+=n(t,o):0,t.y=0,o=t)});var a=rs(t),c=is(t),s=a.x-n(a,c)/2,f=c.x+n(c,a)/2;return t.eachAfter(i?function(n){n.x=(n.x-t.x)*e,n.y=(t.y-n.y)*r}:function(n){n.x=(n.x-s)/(f-s)*e,n.y=(1-(t.y?n.y/t.y:1))*r})}var n=Qc,e=1,r=1,i=!1;return t.separation=function(e){return arguments.length?(n=e,t):n},t.size=function(n){return arguments.length?(i=!1,e=+n[0],r=+n[1],t):i?null:[e,r]},t.nodeSize=function(n){return arguments.length?(i=!0,e=+n[0],r=+n[1],t):i?[e,r]:null},t}function us(t){var n,e,r,i,o=this,u=[o];do for(n=u.reverse(),u=[];o=n.pop();)if(t(o),e=o.children)for(r=0,i=e.length;r<i;++r)u.push(e[r]);while(u.length);return this}function as(t){for(var n,e,r=this,i=[r];r=i.pop();)if(t(r),n=r.children)for(e=n.length-1;e>=0;--e)i.push(n[e]);return this}function cs(t){for(var n,e,r,i=this,o=[i],u=[];i=o.pop();)if(u.push(i),n=i.children)for(e=0,r=n.length;e<r;++e)o.push(n[e]);for(;i=u.pop();)t(i);return this}function ss(t){return this.eachAfter(function(n){for(var e=+t(n.data)||0,r=n.children,i=r&&r.length;--i>=0;)e+=r[i].value;n.value=e})}function fs(t){return this.eachBefore(function(n){n.children&&n.children.sort(t)})}function ls(t){for(var n=this,e=hs(n,t),r=[n];n!==e;)n=n.parent,r.push(n);for(var i=r.length;t!==e;)r.splice(i,0,t),t=t.parent;return r}function hs(t,n){if(t===n)return t;var e=t.ancestors(),r=n.ancestors(),i=null;for(t=e.pop(),n=r.pop();t===n;)i=t,t=e.pop(),n=r.pop();return i}function ps(){for(var t=this,n=[t];t=t.parent;)n.push(t);return n}function ds(){var t=[];return this.each(function(n){t.push(n)}),t}function vs(){var t=[];return this.eachBefore(function(n){n.children||t.push(n)}),t}function _s(){var t=this,n=[];return t.each(function(e){e!==t&&n.push({source:e.parent,target:e})}),n}function ys(t,n){var e,r,i,o,u,a=new ws(t),c=+t.value&&(a.value=t.value),s=[a];for(null==n&&(n=ms);e=s.pop();)if(c&&(e.value=+e.data.value),(i=n(e.data))&&(u=i.length))for(e.children=new Array(u),o=u-1;o>=0;--o)s.push(r=e.children[o]=new ws(i[o])),r.parent=e,r.depth=e.depth+1;return a.eachBefore(bs)}function gs(){return ys(this).eachBefore(xs)}function ms(t){return t.children}function xs(t){t.data=t.data.data}function bs(t){var n=0;do t.height=n;while((t=t.parent)&&t.height<++n)}function ws(t){this.data=t,this.depth=this.height=0,this.parent=null}function Ms(t){this._=t,this.next=null}function Ts(t){for(var n,e=(t=t.slice()).length,r=null,i=r;e;){var o=new Ms(t[e-1]);i=i?i.next=o:r=o,t[n]=t[--e]}return{head:r,tail:i}}function ks(t){return Ss(Ts(t),[])}function Ns(t,n){var e=n.x-t.x,r=n.y-t.y,i=t.r-n.r;return i*i+1e-6>e*e+r*r}function Ss(t,n){var e,r,i,o=null,u=t.head;switch(n.length){case 1:e=As(n[0]);break;case 2:e=Es(n[0],n[1]);break;case 3:e=Cs(n[0],n[1],n[2])}for(;u;)i=u._,r=u.next,e&&Ns(e,i)?o=u:(o?(t.tail=o,o.next=null):t.head=t.tail=null,n.push(i),e=Ss(t,n),n.pop(),t.head?(u.next=t.head,t.head=u):(u.next=null,t.head=t.tail=u),o=t.tail,o.next=r),u=r;return t.tail=o,e}function As(t){return{x:t.x,y:t.y,r:t.r}}function Es(t,n){var e=t.x,r=t.y,i=t.r,o=n.x,u=n.y,a=n.r,c=o-e,s=u-r,f=a-i,l=Math.sqrt(c*c+s*s);return{x:(e+o+c/l*f)/2,y:(r+u+s/l*f)/2,r:(l+i+a)/2}}function Cs(t,n,e){var r=t.x,i=t.y,o=t.r,u=n.x,a=n.y,c=n.r,s=e.x,f=e.y,l=e.r,h=2*(r-u),p=2*(i-a),d=2*(c-o),v=r*r+i*i-o*o-u*u-a*a+c*c,_=2*(r-s),y=2*(i-f),g=2*(l-o),m=r*r+i*i-o*o-s*s-f*f+l*l,x=_*p-h*y,b=(p*m-y*v)/x-r,w=(y*d-p*g)/x,M=(_*v-h*m)/x-i,T=(h*g-_*d)/x,k=w*w+T*T-1,N=2*(b*w+M*T+o),S=b*b+M*M-o*o,A=(-N-Math.sqrt(N*N-4*k*S))/(2*k);return{x:b+w*A+r,y:M+T*A+i,r:A}}function zs(t,n,e){var r=t.x,i=t.y,o=n.r+e.r,u=t.r+e.r,a=n.x-r,c=n.y-i,s=a*a+c*c;if(s){var f=.5+((u*=u)-(o*=o))/(2*s),l=Math.sqrt(Math.max(0,2*o*(u+s)-(u-=s)*u-o*o))/(2*s);e.x=r+f*a+l*c,e.y=i+f*c-l*a}else e.x=r+u,e.y=i}function Ps(t,n){var e=n.x-t.x,r=n.y-t.y,i=t.r+n.r;return i*i>e*e+r*r}function qs(t,n,e){var r=t.x-n,i=t.y-e;return r*r+i*i}function Ls(t){this._=t,this.next=null,this.previous=null}function Rs(t){if(!(i=t.length))return 0;var n,e,r,i;if(n=t[0],n.x=0,n.y=0,!(i>1))return n.r;if(e=t[1],n.x=-e.r,e.x=n.r,e.y=0,!(i>2))return n.r+e.r;zs(e,n,r=t[2]);var o,u,a,c,s,f,l,h=n.r*n.r,p=e.r*e.r,d=r.r*r.r,v=h+p+d,_=h*n.x+p*e.x+d*r.x,y=h*n.y+p*e.y+d*r.y;n=new Ls(n),e=new Ls(e),r=new Ls(r),n.next=r.previous=e,e.next=n.previous=r,r.next=e.previous=n;t:for(a=3;a<i;++a){if(zs(n._,e._,r=t[a]),r=new Ls(r),(s=n.previous)===(c=e.next)){if(Ps(c._,r._)){n=e,e=c,--a;continue t}}else{f=c._.r,l=s._.r;do if(f<=l){if(Ps(c._,r._)){e=c,n.next=e,e.previous=n,--a;continue t}c=c.next,f+=c._.r}else{if(Ps(s._,r._)){n=s,n.next=e,e.previous=n,--a;continue t}s=s.previous,l+=s._.r}while(c!==s.next)}for(r.previous=n,r.next=e,n.next=e.previous=e=r,v+=d=r._.r*r._.r,_+=d*r._.x,y+=d*r._.y,h=qs(n._,o=_/v,u=y/v);(r=r.next)!==e;)(d=qs(r._,o,u))<h&&(n=r,h=d);e=n.next}for(n=[e._],r=e;(r=r.next)!==e;)n.push(r._);for(r=ks(n),a=0;a<i;++a)n=t[a],n.x-=r.x,n.y-=r.y;return r.r}function Us(t){return Rs(t),t}function Ds(t){return null==t?null:Os(t)}function Os(t){if("function"!=typeof t)throw new Error;return t}function Fs(){return 0}function Is(t){return function(){return t}}function Ys(t){return Math.sqrt(t.value)}function Bs(){function t(t){return t.x=e/2,t.y=r/2,n?t.eachBefore(js(n)).eachAfter(Hs(i,.5)).eachBefore(Xs(1)):t.eachBefore(js(Ys)).eachAfter(Hs(Fs,1)).eachAfter(Hs(i,t.r/Math.min(e,r))).eachBefore(Xs(Math.min(e,r)/(2*t.r))),t}var n=null,e=1,r=1,i=Fs;return t.radius=function(e){return arguments.length?(n=Ds(e),t):n},t.size=function(n){return arguments.length?(e=+n[0],r=+n[1],t):[e,r]},t.padding=function(n){return arguments.length?(i="function"==typeof n?n:Is(+n),t):i},t}function js(t){return function(n){n.children||(n.r=Math.max(0,+t(n)||0))}}function Hs(t,n){return function(e){if(r=e.children){var r,i,o,u=r.length,a=t(e)*n||0;if(a)for(i=0;i<u;++i)r[i].r+=a;if(o=Rs(r),a)for(i=0;i<u;++i)r[i].r-=a;e.r=o+a}}}function Xs(t){return function(n){var e=n.parent;n.r*=t,e&&(n.x=e.x+t*n.x,n.y=e.y+t*n.y)}}function Vs(t){t.x0=Math.round(t.x0),t.y0=Math.round(t.y0),t.x1=Math.round(t.x1),t.y1=Math.round(t.y1)}function Ws(t,n,e,r,i){for(var o,u=t.children,a=-1,c=u.length,s=t.value&&(r-n)/t.value;++a<c;)o=u[a],o.y0=e,o.y1=i,o.x0=n,o.x1=n+=o.value*s}function $s(){function t(t){var u=t.height+1;return t.x0=t.y0=i,t.x1=e,t.y1=r/u,t.eachBefore(n(r,u)),o&&t.eachBefore(Vs),t}function n(t,n){return function(e){e.children&&Ws(e,e.x0,t*(e.depth+1)/n,e.x1,t*(e.depth+2)/n);var r=e.x0,o=e.y0,u=e.x1-i,a=e.y1-i;u<r&&(r=u=(r+u)/2),a<o&&(o=a=(o+a)/2),e.x0=r,e.y0=o,e.x1=u,e.y1=a}}var e=1,r=1,i=0,o=!1;return t.round=function(n){return arguments.length?(o=!!n,t):o},t.size=function(n){return arguments.length?(e=+n[0],r=+n[1],t):[e,r]},t.padding=function(n){return arguments.length?(i=+n,t):i},t}function Zs(t){return t.id}function Gs(t){return t.parentId}function Js(){function t(t){var r,i,o,u,a,c,s,f=t.length,l=new Array(f),h={};for(i=0;i<f;++i)r=t[i],a=l[i]=new ws(r),null!=(c=n(r,i,t))&&(c+="")&&(s=Om+(a.id=c),h[s]=s in h?Im:a);for(i=0;i<f;++i)if(a=l[i],c=e(t[i],i,t),null!=c&&(c+="")){if(u=h[Om+c],!u)throw new Error("missing: "+c);if(u===Im)throw new Error("ambiguous: "+c);u.children?u.children.push(a):u.children=[a],a.parent=u}else{if(o)throw new Error("multiple roots");o=a}if(!o)throw new Error("no root");if(o.parent=Fm,o.eachBefore(function(t){t.depth=t.parent.depth+1,--f}).eachBefore(bs),o.parent=null,f>0)throw new Error("cycle");return o}var n=Zs,e=Gs;return t.id=function(e){return arguments.length?(n=Os(e),t):n},t.parentId=function(n){return arguments.length?(e=Os(n),t):e},t}function Qs(t,n){return t.parent===n.parent?1:2}function Ks(t){var n=t.children;return n?n[0]:t.t}function tf(t){var n=t.children;return n?n[n.length-1]:t.t}function nf(t,n,e){var r=e/(n.i-t.i);n.c-=r,n.s+=e,t.c+=r,n.z+=e,n.m+=e}function ef(t){for(var n,e=0,r=0,i=t.children,o=i.length;--o>=0;)n=i[o],n.z+=e,n.m+=e,e+=n.s+(r+=n.c)}function rf(t,n,e){return t.a.parent===n.parent?t.a:e}function of(t,n){this._=t,this.parent=null,this.children=null,this.A=null,this.a=this,this.z=0,this.m=0,this.c=0,this.s=0,this.t=null,this.i=n}function uf(t){for(var n,e,r,i,o,u=new of(t,0),a=[u];n=a.pop();)if(r=n._.children)for(n.children=new Array(o=r.length),i=o-1;i>=0;--i)a.push(e=n.children[i]=new of(r[i],i)),e.parent=n;return(u.parent=new of(null,0)).children=[u],u}function af(){function t(t){var r=uf(t);if(r.eachAfter(n),r.parent.m=-r.z,r.eachBefore(e),c)t.eachBefore(i);else{var s=t,f=t,l=t;t.eachBefore(function(t){t.x<s.x&&(s=t),t.x>f.x&&(f=t),t.depth>l.depth&&(l=t)});var h=s===f?1:o(s,f)/2,p=h-s.x,d=u/(f.x+h+p),v=a/(l.depth||1);t.eachBefore(function(t){t.x=(t.x+p)*d,t.y=t.depth*v})}return t}function n(t){var n=t.children,e=t.parent.children,i=t.i?e[t.i-1]:null;if(n){ef(t);var u=(n[0].z+n[n.length-1].z)/2;i?(t.z=i.z+o(t._,i._),t.m=t.z-u):t.z=u}else i&&(t.z=i.z+o(t._,i._));t.parent.A=r(t,i,t.parent.A||e[0])}function e(t){t._.x=t.z+t.parent.m,t.m+=t.parent.m}function r(t,n,e){if(n){for(var r,i=t,u=t,a=n,c=i.parent.children[0],s=i.m,f=u.m,l=a.m,h=c.m;a=tf(a),i=Ks(i),a&&i;)c=Ks(c),u=tf(u),u.a=t,r=a.z+l-i.z-s+o(a._,i._),r>0&&(nf(rf(a,t,e),t,r),s+=r,f+=r),l+=a.m,s+=i.m,h+=c.m,f+=u.m;a&&!tf(u)&&(u.t=a,u.m+=l-f),i&&!Ks(c)&&(c.t=i,c.m+=s-h,e=t)}return e}function i(t){t.x*=u,t.y=t.depth*a}var o=Qs,u=1,a=1,c=null;return t.separation=function(n){return arguments.length?(o=n,t):o},t.size=function(n){return arguments.length?(c=!1,u=+n[0],a=+n[1],t):c?null:[u,a]},t.nodeSize=function(n){return arguments.length?(c=!0,u=+n[0],a=+n[1],t):c?[u,a]:null},t}function cf(t,n,e,r,i){for(var o,u=t.children,a=-1,c=u.length,s=t.value&&(i-e)/t.value;++a<c;)o=u[a],o.x0=n,o.x1=r,o.y0=e,o.y1=e+=o.value*s}function sf(t,n,e,r,i,o){for(var u,a,c,s,f,l,h,p,d,v,_,y,g=[],m=n.children,x=0,b=m.length,w=n.value;x<b;){for(s=i-e,f=o-r,h=p=l=m[x].value,_=Math.max(f/s,s/f)/(w*t),y=l*l*_,v=Math.max(p/y,y/h),c=x+1;c<b;++c){if(l+=a=m[c].value,a<h&&(h=a),a>p&&(p=a),y=l*l*_,d=Math.max(p/y,y/h),d>v){l-=a;break}v=d}g.push(u={value:l,dice:s<f,children:m.slice(x,c)}),u.dice?Ws(u,e,r,i,w?r+=f*l/w:o):cf(u,e,r,w?e+=s*l/w:i,o),w-=l,x=c}return g}function ff(){function t(t){return t.x0=t.y0=0,t.x1=i,t.y1=o,t.eachBefore(n),u=[0],r&&t.eachBefore(Vs),t}function n(t){var n=u[t.depth],r=t.x0+n,i=t.y0+n,o=t.x1-n,h=t.y1-n;o<r&&(r=o=(r+o)/2),h<i&&(i=h=(i+h)/2),t.x0=r,t.y0=i,t.x1=o,t.y1=h,t.children&&(n=u[t.depth+1]=a(t)/2,r+=l(t)-n,i+=c(t)-n,o-=s(t)-n,h-=f(t)-n,o<r&&(r=o=(r+o)/2),h<i&&(i=h=(i+h)/2),e(t,r,i,o,h))}
-var e=Bm,r=!1,i=1,o=1,u=[0],a=Fs,c=Fs,s=Fs,f=Fs,l=Fs;return t.round=function(n){return arguments.length?(r=!!n,t):r},t.size=function(n){return arguments.length?(i=+n[0],o=+n[1],t):[i,o]},t.tile=function(n){return arguments.length?(e=Os(n),t):e},t.padding=function(n){return arguments.length?t.paddingInner(n).paddingOuter(n):t.paddingInner()},t.paddingInner=function(n){return arguments.length?(a="function"==typeof n?n:Is(+n),t):a},t.paddingOuter=function(n){return arguments.length?t.paddingTop(n).paddingRight(n).paddingBottom(n).paddingLeft(n):t.paddingTop()},t.paddingTop=function(n){return arguments.length?(c="function"==typeof n?n:Is(+n),t):c},t.paddingRight=function(n){return arguments.length?(s="function"==typeof n?n:Is(+n),t):s},t.paddingBottom=function(n){return arguments.length?(f="function"==typeof n?n:Is(+n),t):f},t.paddingLeft=function(n){return arguments.length?(l="function"==typeof n?n:Is(+n),t):l},t}function lf(t,n,e,r,i){function o(t,n,e,r,i,u,a){if(t>=n-1){var s=c[t];return s.x0=r,s.y0=i,s.x1=u,s.y1=a,void 0}for(var l=f[t],h=e/2+l,p=t+1,d=n-1;p<d;){var v=p+d>>>1;f[v]<h?p=v+1:d=v}var _=f[p]-l,y=e-_;if(a-i>u-r){var g=(i*y+a*_)/e;o(t,p,_,r,i,u,g),o(p,n,y,r,g,u,a)}else{var m=(r*y+u*_)/e;o(t,p,_,r,i,m,a),o(p,n,y,m,i,u,a)}}var u,a,c=t.children,s=c.length,f=new Array(s+1);for(f[0]=a=u=0;u<s;++u)f[u+1]=a+=c[u].value;o(0,s,t.value,n,e,r,i)}function hf(t,n,e,r,i){(1&t.depth?cf:Ws)(t,n,e,r,i)}function pf(t,n){function e(){var e,i,o=r.length,u=0,a=0;for(e=0;e<o;++e)i=r[e],u+=i.x,a+=i.y;for(u=u/o-t,a=a/o-n,e=0;e<o;++e)i=r[e],i.x-=u,i.y-=a}var r;return null==t&&(t=0),null==n&&(n=0),e.initialize=function(t){r=t},e.x=function(n){return arguments.length?(t=+n,e):t},e.y=function(t){return arguments.length?(n=+t,e):n},e}function df(t){return function(){return t}}function vf(){return 1e-6*(Math.random()-.5)}function _f(t){return t.x+t.vx}function yf(t){return t.y+t.vy}function gf(t){function n(){function t(t,e,r,i,u){var a=t.data,p=t.r,d=l+p;{if(!a)return e>s+d||i<s-d||r>f+d||u<f-d;if(a.index>n){var v=s-a.x-a.vx,_=f-a.y-a.vy,y=v*v+_*_;y<d*d&&(0===v&&(v=vf(),y+=v*v),0===_&&(_=vf(),y+=_*_),y=(d-(y=Math.sqrt(y)))/y*o,c.vx+=(v*=y)*(d=(p*=p)/(h+p)),c.vy+=(_*=y)*d,a.vx-=v*(d=1-d),a.vy-=_*d)}}}for(var n,a,c,s,f,l,h,p=r.length,d=0;d<u;++d)for(a=jt(r,_f,yf).visitAfter(e),n=0;n<p;++n)c=r[n],l=i[n],h=l*l,s=c.x+c.vx,f=c.y+c.vy,a.visit(t)}function e(t){if(t.data)return t.r=i[t.data.index];for(var n=t.r=0;n<4;++n)t[n]&&t[n].r>t.r&&(t.r=t[n].r)}var r,i,o=1,u=1;return"function"!=typeof t&&(t=df(null==t?1:+t)),n.initialize=function(n){var e,o=(r=n).length;for(i=new Array(o),e=0;e<o;++e)i[e]=+t(r[e],e,r)},n.iterations=function(t){return arguments.length?(u=+t,n):u},n.strength=function(t){return arguments.length?(o=+t,n):o},n.radius=function(e){return arguments.length?(t="function"==typeof e?e:df(+e),n):t},n}function mf(t,n){return n}function xf(t){function n(t){return 1/Math.min(s[t.source.index],s[t.target.index])}function e(n){for(var e=0,r=t.length;e<d;++e)for(var i,o,c,s,l,h,p,v=0;v<r;++v)i=t[v],o=i.source,c=i.target,s=c.x+c.vx-o.x-o.vx||vf(),l=c.y+c.vy-o.y-o.vy||vf(),h=Math.sqrt(s*s+l*l),h=(h-a[v])/h*n*u[v],s*=h,l*=h,c.vx-=s*(p=f[v]),c.vy-=l*p,o.vx+=s*(p=1-p),o.vy+=l*p}function r(){if(c){var n,e,r=c.length,h=t.length,p=q(c,l);for(n=0,s=new Array(r);n<r;++n)s[n]=0;for(n=0;n<h;++n)e=t[n],e.index=n,"object"!=typeof e.source&&(e.source=p.get(e.source)),"object"!=typeof e.target&&(e.target=p.get(e.target)),++s[e.source.index],++s[e.target.index];for(n=0,f=new Array(h);n<h;++n)e=t[n],f[n]=s[e.source.index]/(s[e.source.index]+s[e.target.index]);u=new Array(h),i(),a=new Array(h),o()}}function i(){if(c)for(var n=0,e=t.length;n<e;++n)u[n]=+h(t[n],n,t)}function o(){if(c)for(var n=0,e=t.length;n<e;++n)a[n]=+p(t[n],n,t)}var u,a,c,s,f,l=mf,h=n,p=df(30),d=1;return null==t&&(t=[]),e.initialize=function(t){c=t,r()},e.links=function(n){return arguments.length?(t=n,r(),e):t},e.id=function(t){return arguments.length?(l=t,e):l},e.iterations=function(t){return arguments.length?(d=+t,e):d},e.strength=function(t){return arguments.length?(h="function"==typeof t?t:df(+t),i(),e):h},e.distance=function(t){return arguments.length?(p="function"==typeof t?t:df(+t),o(),e):p},e}function bf(t){return t.x}function wf(t){return t.y}function Mf(t){function n(){e(),p.call("tick",o),u<a&&(h.stop(),p.call("end",o))}function e(){var n,e,r=t.length;for(u+=(s-u)*c,l.each(function(t){t(u)}),n=0;n<r;++n)e=t[n],null==e.fx?e.x+=e.vx*=f:(e.x=e.fx,e.vx=0),null==e.fy?e.y+=e.vy*=f:(e.y=e.fy,e.vy=0)}function r(){for(var n,e=0,r=t.length;e<r;++e){if(n=t[e],n.index=e,isNaN(n.x)||isNaN(n.y)){var i=Hm*Math.sqrt(e),o=e*Xm;n.x=i*Math.cos(o),n.y=i*Math.sin(o)}(isNaN(n.vx)||isNaN(n.vy))&&(n.vx=n.vy=0)}}function i(n){return n.initialize&&n.initialize(t),n}var o,u=1,a=.001,c=1-Math.pow(a,1/300),s=0,f=.6,l=q(),h=Yr(n),p=Mr("tick","end");return null==t&&(t=[]),r(),o={tick:e,restart:function(){return h.restart(n),o},stop:function(){return h.stop(),o},nodes:function(n){return arguments.length?(t=n,r(),l.each(i),o):t},alpha:function(t){return arguments.length?(u=+t,o):u},alphaMin:function(t){return arguments.length?(a=+t,o):a},alphaDecay:function(t){return arguments.length?(c=+t,o):+c},alphaTarget:function(t){return arguments.length?(s=+t,o):s},velocityDecay:function(t){return arguments.length?(f=1-t,o):1-f},force:function(t,n){return arguments.length>1?(null==n?l.remove(t):l.set(t,i(n)),o):l.get(t)},find:function(n,e,r){var i,o,u,a,c,s=0,f=t.length;for(null==r?r=1/0:r*=r,s=0;s<f;++s)a=t[s],i=n-a.x,o=e-a.y,u=i*i+o*o,u<r&&(c=a,r=u);return c},on:function(t,n){return arguments.length>1?(p.on(t,n),o):p.on(t)}}}function Tf(){function t(t){var n,a=i.length,c=jt(i,bf,wf).visitAfter(e);for(u=t,n=0;n<a;++n)o=i[n],c.visit(r)}function n(){if(i){var t,n=i.length;for(a=new Array(n),t=0;t<n;++t)a[t]=+c(i[t],t,i)}}function e(t){var n,e,r,i,o,u=0;if(t.length){for(r=i=o=0;o<4;++o)(n=t[o])&&(e=n.value)&&(u+=e,r+=e*n.x,i+=e*n.y);t.x=r/u,t.y=i/u}else{n=t,n.x=n.data.x,n.y=n.data.y;do u+=a[n.data.index];while(n=n.next)}t.value=u}function r(t,n,e,r){if(!t.value)return!0;var i=t.x-o.x,c=t.y-o.y,h=r-n,p=i*i+c*c;if(h*h/l<p)return p<f&&(0===i&&(i=vf(),p+=i*i),0===c&&(c=vf(),p+=c*c),p<s&&(p=Math.sqrt(s*p)),o.vx+=i*t.value*u/p,o.vy+=c*t.value*u/p),!0;if(!(t.length||p>=f)){(t.data!==o||t.next)&&(0===i&&(i=vf(),p+=i*i),0===c&&(c=vf(),p+=c*c),p<s&&(p=Math.sqrt(s*p)));do t.data!==o&&(h=a[t.data.index]*u/p,o.vx+=i*h,o.vy+=c*h);while(t=t.next)}}var i,o,u,a,c=df(-30),s=1,f=1/0,l=.81;return t.initialize=function(t){i=t,n()},t.strength=function(e){return arguments.length?(c="function"==typeof e?e:df(+e),n(),t):c},t.distanceMin=function(n){return arguments.length?(s=n*n,t):Math.sqrt(s)},t.distanceMax=function(n){return arguments.length?(f=n*n,t):Math.sqrt(f)},t.theta=function(n){return arguments.length?(l=n*n,t):Math.sqrt(l)},t}function kf(t){function n(t){for(var n,e=0,u=r.length;e<u;++e)n=r[e],n.vx+=(o[e]-n.x)*i[e]*t}function e(){if(r){var n,e=r.length;for(i=new Array(e),o=new Array(e),n=0;n<e;++n)i[n]=isNaN(o[n]=+t(r[n],n,r))?0:+u(r[n],n,r)}}var r,i,o,u=df(.1);return"function"!=typeof t&&(t=df(null==t?0:+t)),n.initialize=function(t){r=t,e()},n.strength=function(t){return arguments.length?(u="function"==typeof t?t:df(+t),e(),n):u},n.x=function(r){return arguments.length?(t="function"==typeof r?r:df(+r),e(),n):t},n}function Nf(t){function n(t){for(var n,e=0,u=r.length;e<u;++e)n=r[e],n.vy+=(o[e]-n.y)*i[e]*t}function e(){if(r){var n,e=r.length;for(i=new Array(e),o=new Array(e),n=0;n<e;++n)i[n]=isNaN(o[n]=+t(r[n],n,r))?0:+u(r[n],n,r)}}var r,i,o,u=df(.1);return"function"!=typeof t&&(t=df(null==t?0:+t)),n.initialize=function(t){r=t,e()},n.strength=function(t){return arguments.length?(u="function"==typeof t?t:df(+t),e(),n):u},n.y=function(r){return arguments.length?(t="function"==typeof r?r:df(+r),e(),n):t},n}function Sf(){t.event.stopImmediatePropagation()}function Af(){t.event.preventDefault(),t.event.stopImmediatePropagation()}function Ef(t){var n=t.document.documentElement,e=Ra(t).on("dragstart.drag",Af,!0);"onselectstart"in n?e.on("selectstart.drag",Af,!0):(n.__noselect=n.style.MozUserSelect,n.style.MozUserSelect="none")}function Cf(t,n){var e=t.document.documentElement,r=Ra(t).on("dragstart.drag",null);n&&(r.on("click.drag",Af,!0),setTimeout(function(){r.on("click.drag",null)},0)),"onselectstart"in e?r.on("selectstart.drag",null):(e.style.MozUserSelect=e.__noselect,delete e.__noselect)}function zf(t){return function(){return t}}function Pf(t,n,e,r,i,o,u,a,c,s){this.target=t,this.type=n,this.subject=e,this.identifier=r,this.active=i,this.x=o,this.y=u,this.dx=a,this.dy=c,this._=s}function qf(){return!t.event.button}function Lf(){return this.parentNode}function Rf(n){return null==n?{x:t.event.x,y:t.event.y}:n}function Uf(){function n(t){t.on("mousedown.drag",e).on("touchstart.drag",o).on("touchmove.drag",u).on("touchend.drag touchcancel.drag",a).style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}function e(){if(!f&&l.apply(this,arguments)){var n=c("mouse",h.apply(this,arguments),du,this,arguments);n&&(Ra(t.event.view).on("mousemove.drag",r,!0).on("mouseup.drag",i,!0),Ef(t.event.view),Sf(),s=!1,n("start"))}}function r(){Af(),s=!0,d.mouse("drag")}function i(){Ra(t.event.view).on("mousemove.drag mouseup.drag",null),Cf(t.event.view,s),Af(),d.mouse("end")}function o(){if(l.apply(this,arguments)){var n,e,r=t.event.changedTouches,i=h.apply(this,arguments),o=r.length;for(n=0;n<o;++n)(e=c(r[n].identifier,i,Da,this,arguments))&&(Sf(),e("start"))}}function u(){var n,e,r=t.event.changedTouches,i=r.length;for(n=0;n<i;++n)(e=d[r[n].identifier])&&(Af(),e("drag"))}function a(){var n,e,r=t.event.changedTouches,i=r.length;for(f&&clearTimeout(f),f=setTimeout(function(){f=null},500),n=0;n<i;++n)(e=d[r[n].identifier])&&(Sf(),e("end"))}function c(e,r,i,o,u){var a,c,s,f=i(r,e),l=v.copy();if(lu(new Pf(n,"beforestart",a,e,_,f[0],f[1],0,0,l),function(){return null!=(t.event.subject=a=p.apply(o,u))&&(c=a.x-f[0]||0,s=a.y-f[1]||0,!0)}))return function h(t){var p,v=f;switch(t){case"start":d[e]=h,p=_++;break;case"end":delete d[e],--_;case"drag":f=i(r,e),p=_}lu(new Pf(n,t,a,e,p,f[0]+c,f[1]+s,f[0]-v[0],f[1]-v[1],l),l.apply,l,[t,o,u])}}var s,f,l=qf,h=Lf,p=Rf,d={},v=Mr("start","drag","end"),_=0;return n.filter=function(t){return arguments.length?(l="function"==typeof t?t:zf(!!t),n):l},n.container=function(t){return arguments.length?(h="function"==typeof t?t:zf(t),n):h},n.subject=function(t){return arguments.length?(p="function"==typeof t?t:zf(t),n):p},n.on=function(){var t=v.on.apply(v,arguments);return t===v?n:t},n}function Df(t){return function(){return t}}function Of(t){return t[0]}function Ff(t){return t[1]}function If(){this._=null}function Yf(t){t.U=t.C=t.L=t.R=t.P=t.N=null}function Bf(t,n){var e=n,r=n.R,i=e.U;i?i.L===e?i.L=r:i.R=r:t._=r,r.U=i,e.U=r,e.R=r.L,e.R&&(e.R.U=e),r.L=e}function jf(t,n){var e=n,r=n.L,i=e.U;i?i.L===e?i.L=r:i.R=r:t._=r,r.U=i,e.U=r,e.L=r.R,e.L&&(e.L.U=e),r.R=e}function Hf(t){for(;t.L;)t=t.L;return t}function Xf(t,n,e,r){var i=[null,null],o=Gm.push(i)-1;return i.left=t,i.right=n,e&&Wf(i,t,n,e),r&&Wf(i,n,t,r),$m[t.index].halfedges.push(o),$m[n.index].halfedges.push(o),i}function Vf(t,n,e){var r=[n,e];return r.left=t,r}function Wf(t,n,e,r){t[0]||t[1]?t.left===e?t[1]=r:t[0]=r:(t[0]=r,t.left=n,t.right=e)}function $f(t,n,e,r,i){var o,u=t[0],a=t[1],c=u[0],s=u[1],f=a[0],l=a[1],h=0,p=1,d=f-c,v=l-s;if(o=n-c,d||!(o>0)){if(o/=d,d<0){if(o<h)return;o<p&&(p=o)}else if(d>0){if(o>p)return;o>h&&(h=o)}if(o=r-c,d||!(o<0)){if(o/=d,d<0){if(o>p)return;o>h&&(h=o)}else if(d>0){if(o<h)return;o<p&&(p=o)}if(o=e-s,v||!(o>0)){if(o/=v,v<0){if(o<h)return;o<p&&(p=o)}else if(v>0){if(o>p)return;o>h&&(h=o)}if(o=i-s,v||!(o<0)){if(o/=v,v<0){if(o>p)return;o>h&&(h=o)}else if(v>0){if(o<h)return;o<p&&(p=o)}return!(h>0||p<1)||(h>0&&(t[0]=[c+h*d,s+h*v]),p<1&&(t[1]=[c+p*d,s+p*v]),!0)}}}}}function Zf(t,n,e,r,i){var o=t[1];if(o)return!0;var u,a,c=t[0],s=t.left,f=t.right,l=s[0],h=s[1],p=f[0],d=f[1],v=(l+p)/2,_=(h+d)/2;if(d===h){if(v<n||v>=r)return;if(l>p){if(c){if(c[1]>=i)return}else c=[v,e];o=[v,i]}else{if(c){if(c[1]<e)return}else c=[v,i];o=[v,e]}}else if(u=(l-p)/(d-h),a=_-u*v,u<-1||u>1)if(l>p){if(c){if(c[1]>=i)return}else c=[(e-a)/u,e];o=[(i-a)/u,i]}else{if(c){if(c[1]<e)return}else c=[(i-a)/u,i];o=[(e-a)/u,e]}else if(h<d){if(c){if(c[0]>=r)return}else c=[n,u*n+a];o=[r,u*r+a]}else{if(c){if(c[0]<n)return}else c=[r,u*r+a];o=[n,u*n+a]}return t[0]=c,t[1]=o,!0}function Gf(t,n,e,r){for(var i,o=Gm.length;o--;)Zf(i=Gm[o],t,n,e,r)&&$f(i,t,n,e,r)&&(Math.abs(i[0][0]-i[1][0])>Km||Math.abs(i[0][1]-i[1][1])>Km)||delete Gm[o]}function Jf(t){return $m[t.index]={site:t,halfedges:[]}}function Qf(t,n){var e=t.site,r=n.left,i=n.right;return e===i&&(i=r,r=e),i?Math.atan2(i[1]-r[1],i[0]-r[0]):(e===r?(r=n[1],i=n[0]):(r=n[0],i=n[1]),Math.atan2(r[0]-i[0],i[1]-r[1]))}function Kf(t,n){return n[+(n.left!==t.site)]}function tl(t,n){return n[+(n.left===t.site)]}function nl(){for(var t,n,e,r,i=0,o=$m.length;i<o;++i)if((t=$m[i])&&(r=(n=t.halfedges).length)){var u=new Array(r),a=new Array(r);for(e=0;e<r;++e)u[e]=e,a[e]=Qf(t,Gm[n[e]]);for(u.sort(function(t,n){return a[n]-a[t]}),e=0;e<r;++e)a[e]=n[u[e]];for(e=0;e<r;++e)n[e]=a[e]}}function el(t,n,e,r){var i,o,u,a,c,s,f,l,h,p,d,v,_=$m.length,y=!0;for(i=0;i<_;++i)if(o=$m[i]){for(u=o.site,c=o.halfedges,a=c.length;a--;)Gm[c[a]]||c.splice(a,1);for(a=0,s=c.length;a<s;)p=tl(o,Gm[c[a]]),d=p[0],v=p[1],f=Kf(o,Gm[c[++a%s]]),l=f[0],h=f[1],(Math.abs(d-l)>Km||Math.abs(v-h)>Km)&&(c.splice(a,0,Gm.push(Vf(u,p,Math.abs(d-t)<Km&&r-v>Km?[t,Math.abs(l-t)<Km?h:r]:Math.abs(v-r)<Km&&e-d>Km?[Math.abs(h-r)<Km?l:e,r]:Math.abs(d-e)<Km&&v-n>Km?[e,Math.abs(l-e)<Km?h:n]:Math.abs(v-n)<Km&&d-t>Km?[Math.abs(h-n)<Km?l:t,n]:null))-1),++s);s&&(y=!1)}if(y){var g,m,x,b=1/0;for(i=0,y=null;i<_;++i)(o=$m[i])&&(u=o.site,g=u[0]-t,m=u[1]-n,x=g*g+m*m,x<b&&(b=x,y=o));if(y){var w=[t,n],M=[t,r],T=[e,r],k=[e,n];y.halfedges.push(Gm.push(Vf(u=y.site,w,M))-1,Gm.push(Vf(u,M,T))-1,Gm.push(Vf(u,T,k))-1,Gm.push(Vf(u,k,w))-1)}}for(i=0;i<_;++i)(o=$m[i])&&(o.halfedges.length||delete $m[i])}function rl(){Yf(this),this.x=this.y=this.arc=this.site=this.cy=null}function il(t){var n=t.P,e=t.N;if(n&&e){var r=n.site,i=t.site,o=e.site;if(r!==o){var u=i[0],a=i[1],c=r[0]-u,s=r[1]-a,f=o[0]-u,l=o[1]-a,h=2*(c*l-s*f);if(!(h>=-tx)){var p=c*c+s*s,d=f*f+l*l,v=(l*p-s*d)/h,_=(c*d-f*p)/h,y=Jm.pop()||new rl;y.arc=t,y.site=i,y.x=v+u,y.y=(y.cy=_+a)+Math.sqrt(v*v+_*_),t.circle=y;for(var g=null,m=Zm._;m;)if(y.y<m.y||y.y===m.y&&y.x<=m.x){if(!m.L){g=m.P;break}m=m.L}else{if(!m.R){g=m;break}m=m.R}Zm.insert(g,y),g||(Vm=y)}}}}function ol(t){var n=t.circle;n&&(n.P||(Vm=n.N),Zm.remove(n),Jm.push(n),Yf(n),t.circle=null)}function ul(){Yf(this),this.edge=this.site=this.circle=null}function al(t){var n=Qm.pop()||new ul;return n.site=t,n}function cl(t){ol(t),Wm.remove(t),Qm.push(t),Yf(t)}function sl(t){var n=t.circle,e=n.x,r=n.cy,i=[e,r],o=t.P,u=t.N,a=[t];cl(t);for(var c=o;c.circle&&Math.abs(e-c.circle.x)<Km&&Math.abs(r-c.circle.cy)<Km;)o=c.P,a.unshift(c),cl(c),c=o;a.unshift(c),ol(c);for(var s=u;s.circle&&Math.abs(e-s.circle.x)<Km&&Math.abs(r-s.circle.cy)<Km;)u=s.N,a.push(s),cl(s),s=u;a.push(s),ol(s);var f,l=a.length;for(f=1;f<l;++f)s=a[f],c=a[f-1],Wf(s.edge,c.site,s.site,i);c=a[0],s=a[l-1],s.edge=Xf(c.site,s.site,null,i),il(c),il(s)}function fl(t){for(var n,e,r,i,o=t[0],u=t[1],a=Wm._;a;)if(r=ll(a,u)-o,r>Km)a=a.L;else{if(i=o-hl(a,u),!(i>Km)){r>-Km?(n=a.P,e=a):i>-Km?(n=a,e=a.N):n=e=a;break}if(!a.R){n=a;break}a=a.R}Jf(t);var c=al(t);if(Wm.insert(n,c),n||e){if(n===e)return ol(n),e=al(n.site),Wm.insert(c,e),c.edge=e.edge=Xf(n.site,c.site),il(n),void il(e);if(!e)return void(c.edge=Xf(n.site,c.site));ol(n),ol(e);var s=n.site,f=s[0],l=s[1],h=t[0]-f,p=t[1]-l,d=e.site,v=d[0]-f,_=d[1]-l,y=2*(h*_-p*v),g=h*h+p*p,m=v*v+_*_,x=[(_*g-p*m)/y+f,(h*m-v*g)/y+l];Wf(e.edge,s,d,x),c.edge=Xf(s,t,null,x),e.edge=Xf(t,d,null,x),il(n),il(e)}}function ll(t,n){var e=t.site,r=e[0],i=e[1],o=i-n;if(!o)return r;var u=t.P;if(!u)return-(1/0);e=u.site;var a=e[0],c=e[1],s=c-n;if(!s)return a;var f=a-r,l=1/o-1/s,h=f/s;return l?(-h+Math.sqrt(h*h-2*l*(f*f/(-2*s)-c+s/2+i-o/2)))/l+r:(r+a)/2}function hl(t,n){var e=t.N;if(e)return ll(e,n);var r=t.site;return r[1]===n?r[0]:1/0}function pl(t,n,e){return(t[0]-e[0])*(n[1]-t[1])-(t[0]-n[0])*(e[1]-t[1])}function dl(t,n){return n[1]-t[1]||n[0]-t[0]}function vl(t,n){var e,r,i,o=t.sort(dl).pop();for(Gm=[],$m=new Array(t.length),Wm=new If,Zm=new If;;)if(i=Vm,o&&(!i||o[1]<i.y||o[1]===i.y&&o[0]<i.x))o[0]===e&&o[1]===r||(fl(o),e=o[0],r=o[1]),o=t.pop();else{if(!i)break;sl(i.arc)}if(nl(),n){var u=+n[0][0],a=+n[0][1],c=+n[1][0],s=+n[1][1];Gf(u,a,c,s),el(u,a,c,s)}this.edges=Gm,this.cells=$m,Wm=Zm=Gm=$m=null}function _l(){function t(t){return new vl(t.map(function(r,i){var o=[Math.round(n(r,i,t)/Km)*Km,Math.round(e(r,i,t)/Km)*Km];return o.index=i,o.data=r,o}),r)}var n=Of,e=Ff,r=null;return t.polygons=function(n){return t(n).polygons()},t.links=function(n){return t(n).links()},t.triangles=function(n){return t(n).triangles()},t.x=function(e){return arguments.length?(n="function"==typeof e?e:Df(+e),t):n},t.y=function(n){return arguments.length?(e="function"==typeof n?n:Df(+n),t):e},t.extent=function(n){return arguments.length?(r=null==n?null:[[+n[0][0],+n[0][1]],[+n[1][0],+n[1][1]]],t):r&&[[r[0][0],r[0][1]],[r[1][0],r[1][1]]]},t.size=function(n){return arguments.length?(r=null==n?null:[[0,0],[+n[0],+n[1]]],t):r&&[r[1][0],r[1][1]]},t}function yl(t){return function(){return t}}function gl(t,n,e){this.target=t,this.type=n,this.transform=e}function ml(t,n,e){this.k=t,this.x=n,this.y=e}function xl(t){return t.__zoom||nx}function bl(){t.event.stopImmediatePropagation()}function wl(){t.event.preventDefault(),t.event.stopImmediatePropagation()}function Ml(){return!t.event.button}function Tl(){var t,n,e=this;return e instanceof SVGElement?(e=e.ownerSVGElement||e,t=e.width.baseVal.value,n=e.height.baseVal.value):(t=e.clientWidth,n=e.clientHeight),[[0,0],[t,n]]}function kl(){return this.__zoom||nx}function Nl(){function n(t){t.on("wheel.zoom",s).on("mousedown.zoom",f).on("dblclick.zoom",l).on("touchstart.zoom",h).on("touchmove.zoom",p).on("touchend.zoom touchcancel.zoom",d).style("-webkit-tap-highlight-color","rgba(0,0,0,0)").property("__zoom",kl)}function e(t,n){return n=Math.max(M,Math.min(T,n)),n===t.k?t:new ml(n,t.x,t.y)}function r(t,n,e){var r=n[0]-e[0]*t.k,i=n[1]-e[1]*t.k;return r===t.x&&i===t.y?t:new ml(t.k,r,i)}function i(t,n){var e=Math.min(0,t.invertX(n[0][0])-k)||Math.max(0,t.invertX(n[1][0])-N),r=Math.min(0,t.invertY(n[0][1])-S)||Math.max(0,t.invertY(n[1][1])-A);return e||r?t.translate(e,r):t}function o(t){return[(+t[0][0]+ +t[1][0])/2,(+t[0][1]+ +t[1][1])/2]}function u(t,n,e){t.on("start.zoom",function(){a(this,arguments).start()}).on("interrupt.zoom end.zoom",function(){a(this,arguments).end()}).tween("zoom",function(){var t=this,r=arguments,i=a(t,r),u=w.apply(t,r),c=e||o(u),s=Math.max(u[1][0]-u[0][0],u[1][1]-u[0][1]),f=t.__zoom,l="function"==typeof n?n.apply(t,r):n,h=yr(f.invert(c).concat(s/f.k),l.invert(c).concat(s/l.k));return function(t){if(1===t)t=l;else{var n=h(t),e=s/n[2];t=new ml(e,c[0]-n[0]*e,c[1]-n[1]*e)}i.zoom(null,t)}})}function a(t,n){for(var e,r=0,i=C.length;r<i;++r)if((e=C[r]).that===t)return e;return new c(t,n)}function c(t,n){this.that=t,this.args=n,this.index=-1,this.active=0}function s(){function n(){x=null,o.end()}if(b.apply(this,arguments)){var o=a(this,arguments),u=this.__zoom,c=Math.max(M,Math.min(T,u.k*Math.pow(2,-t.event.deltaY*(t.event.deltaMode?120:1)/500)));if(x){var s=du(this);_[0]===s[0]&&_[1]===s[1]||(y=u.invert(_=s)),clearTimeout(x)}else{if(u.k===c)return;o.extent=w.apply(this,arguments),y=u.invert(_=du(this)),Ha(this),o.start()}wl(),x=setTimeout(n,q),o.zoom("mouse",i(r(e(u,c),_,y),o.extent))}}function f(){function n(){wl(),v=!0,o.zoom("mouse",i(r(o.that.__zoom,_=du(o.that),y),o.extent))}function e(){u.on("mousemove.zoom mouseup.zoom",null),Cf(t.event.view,v),wl(),o.end()}if(!m&&b.apply(this,arguments)){var o=a(this,arguments),u=Ra(t.event.view).on("mousemove.zoom",n,!0).on("mouseup.zoom",e,!0);Ef(t.event.view),bl(),v=!1,o.extent=w.apply(this,arguments),y=this.__zoom.invert(_=du(this)),Ha(this),o.start()}}function l(){if(b.apply(this,arguments)){var o=this.__zoom,a=du(this),c=o.invert(a),s=o.k*(t.event.shiftKey?.5:2),f=i(r(e(o,s),a,c),w.apply(this,arguments));wl(),E>0?Ra(this).transition().duration(E).call(u,f,a):Ra(this).call(n.transform,f)}}function h(){if(b.apply(this,arguments)){var n,e,r,i=a(this,arguments),o=t.event.changedTouches,u=o.length;for(bl(),n=0;n<u;++n)e=o[n],r=Da(this,o,e.identifier),r=[r,this.__zoom.invert(r),e.identifier],i.touch0?i.touch1||(i.touch1=r):i.touch0=r;return g&&(g=clearTimeout(g),!i.touch1)?(i.end(),l.apply(this,arguments)):void(t.event.touches.length===u&&(g=setTimeout(function(){g=null},P),Ha(this),i.extent=w.apply(this,arguments),i.start()))}}function p(){var n,o,u,c,s=a(this,arguments),f=t.event.changedTouches,l=f.length;for(wl(),g&&(g=clearTimeout(g)),n=0;n<l;++n)o=f[n],u=Da(this,f,o.identifier),s.touch0&&s.touch0[2]===o.identifier?s.touch0[0]=u:s.touch1&&s.touch1[2]===o.identifier&&(s.touch1[0]=u);if(o=s.that.__zoom,s.touch1){var h=s.touch0[0],p=s.touch0[1],d=s.touch1[0],v=s.touch1[1],_=(_=d[0]-h[0])*_+(_=d[1]-h[1])*_,y=(y=v[0]-p[0])*y+(y=v[1]-p[1])*y;o=e(o,Math.sqrt(_/y)),u=[(h[0]+d[0])/2,(h[1]+d[1])/2],c=[(p[0]+v[0])/2,(p[1]+v[1])/2]}else{if(!s.touch0)return;u=s.touch0[0],c=s.touch0[1]}s.zoom("touch",i(r(o,u,c),s.extent))}function d(){var n,e,r=a(this,arguments),i=t.event.changedTouches,o=i.length;for(bl(),m&&clearTimeout(m),m=setTimeout(function(){m=null},P),n=0;n<o;++n)e=i[n],r.touch0&&r.touch0[2]===e.identifier?delete r.touch0:r.touch1&&r.touch1[2]===e.identifier&&delete r.touch1;r.touch1&&!r.touch0&&(r.touch0=r.touch1,delete r.touch1),r.touch0||r.end()}var v,_,y,g,m,x,b=Ml,w=Tl,M=0,T=1/0,k=-T,N=T,S=k,A=N,E=250,C=[],z=Mr("start","zoom","end"),P=500,q=150;return n.transform=function(t,n){var e=t.selection?t.selection():t;e.property("__zoom",kl),t!==e?u(t,n):e.interrupt().each(function(){a(this,arguments).start().zoom(null,"function"==typeof n?n.apply(this,arguments):n).end()})},n.scaleBy=function(t,e){n.scaleTo(t,function(){var t=this.__zoom.k,n="function"==typeof e?e.apply(this,arguments):e;return t*n})},n.scaleTo=function(t,u){n.transform(t,function(){var t=w.apply(this,arguments),n=this.__zoom,a=o(t),c=n.invert(a),s="function"==typeof u?u.apply(this,arguments):u;return i(r(e(n,s),a,c),t)})},n.translateBy=function(t,e,r){n.transform(t,function(){return i(this.__zoom.translate("function"==typeof e?e.apply(this,arguments):e,"function"==typeof r?r.apply(this,arguments):r),w.apply(this,arguments))})},c.prototype={start:function(){return 1===++this.active&&(this.index=C.push(this)-1,this.emit("start")),this},zoom:function(t,n){return _&&"mouse"!==t&&(y=n.invert(_)),this.touch0&&"touch"!==t&&(this.touch0[1]=n.invert(this.touch0[0])),this.touch1&&"touch"!==t&&(this.touch1[1]=n.invert(this.touch1[0])),this.that.__zoom=n,this.emit("zoom"),this},end:function(){return 0===--this.active&&(C.splice(this.index,1),_=y=null,this.index=-1,this.emit("end")),this},emit:function(t){lu(new gl(n,t,this.that.__zoom),z.apply,z,[t,this.that,this.args])}},n.filter=function(t){return arguments.length?(b="function"==typeof t?t:yl(!!t),n):b},n.extent=function(t){return arguments.length?(w="function"==typeof t?t:yl([[+t[0][0],+t[0][1]],[+t[1][0],+t[1][1]]]),n):w},n.scaleExtent=function(t){return arguments.length?(M=+t[0],T=+t[1],n):[M,T]},n.translateExtent=function(t){return arguments.length?(k=+t[0][0],N=+t[1][0],S=+t[0][1],A=+t[1][1],n):[[k,S],[N,A]]},n.duration=function(t){return arguments.length?(E=+t,n):E},n.on=function(){var t=z.on.apply(z,arguments);return t===z?n:t},n}function Sl(t){return function(){return t}}function Al(t,n,e){this.target=t,this.type=n,this.selection=e}function El(){t.event.stopImmediatePropagation()}function Cl(){t.event.preventDefault(),t.event.stopImmediatePropagation()}function zl(t){return{type:t}}function Pl(){return!t.event.button}function ql(){var t=this.ownerSVGElement||this;return[[0,0],[t.width.baseVal.value,t.height.baseVal.value]]}function Ll(t){for(;!t.__brush;)if(!(t=t.parentNode))return;return t.__brush}function Rl(t){return t[0][0]===t[1][0]||t[0][1]===t[1][1]}function Ul(t){var n=t.__brush;return n?n.dim.output(n.selection):null}function Dl(){return Il(ux)}function Ol(){return Il(ax)}function Fl(){return Il(cx)}function Il(n){function e(t){var e=t.property("__brush",a).selectAll(".overlay").data([zl("overlay")]);e.enter().append("rect").attr("class","overlay").attr("pointer-events","all").attr("cursor",sx.overlay).merge(e).each(function(){var t=Ll(this).extent;Ra(this).attr("x",t[0][0]).attr("y",t[0][1]).attr("width",t[1][0]-t[0][0]).attr("height",t[1][1]-t[0][1])}),t.selectAll(".selection").data([zl("selection")]).enter().append("rect").attr("class","selection").attr("cursor",sx.selection).attr("fill","#777").attr("fill-opacity",.3).attr("stroke","#fff").attr("shape-rendering","crispEdges");var i=t.selectAll(".handle").data(n.handles,function(t){return t.type});i.exit().remove(),i.enter().append("rect").attr("class",function(t){return"handle handle--"+t.type}).attr("cursor",function(t){return sx[t.type]}),t.each(r).attr("fill","none").attr("pointer-events","all").style("-webkit-tap-highlight-color","rgba(0,0,0,0)").on("mousedown.brush touchstart.brush",u)}function r(){var t=Ra(this),n=Ll(this).selection;n?(t.selectAll(".selection").style("display",null).attr("x",n[0][0]).attr("y",n[0][1]).attr("width",n[1][0]-n[0][0]).attr("height",n[1][1]-n[0][1]),t.selectAll(".handle").style("display",null).attr("x",function(t){return"e"===t.type[t.type.length-1]?n[1][0]-h/2:n[0][0]-h/2}).attr("y",function(t){return"s"===t.type[0]?n[1][1]-h/2:n[0][1]-h/2}).attr("width",function(t){return"n"===t.type||"s"===t.type?n[1][0]-n[0][0]+h:h}).attr("height",function(t){return"e"===t.type||"w"===t.type?n[1][1]-n[0][1]+h:h})):t.selectAll(".selection,.handle").style("display","none").attr("x",null).attr("y",null).attr("width",null).attr("height",null)}function i(t,n){return t.__brush.emitter||new o(t,n)}function o(t,n){this.that=t,this.args=n,this.state=t.__brush,this.active=0}function u(){function e(){var t=du(T);!U||w||M||(Math.abs(t[0]-O[0])>Math.abs(t[1]-O[1])?M=!0:w=!0),O=t,b=!0,Cl(),o()}function o(){var t;switch(m=O[0]-D[0],x=O[1]-D[1],N){case rx:case ex:S&&(m=Math.max(P-l,Math.min(L-v,m)),h=l+m,_=v+m),A&&(x=Math.max(q-p,Math.min(R-y,x)),d=p+x,g=y+x);break;case ix:S<0?(m=Math.max(P-l,Math.min(L-l,m)),h=l+m,_=v):S>0&&(m=Math.max(P-v,Math.min(L-v,m)),h=l,_=v+m),A<0?(x=Math.max(q-p,Math.min(R-p,x)),d=p+x,g=y):A>0&&(x=Math.max(q-y,Math.min(R-y,x)),d=p,g=y+x);break;case ox:S&&(h=Math.max(P,Math.min(L,l-m*S)),_=Math.max(P,Math.min(L,v+m*S))),A&&(d=Math.max(q,Math.min(R,p-x*A)),g=Math.max(q,Math.min(R,y+x*A)))}_<h&&(S*=-1,t=l,l=v,v=t,t=h,h=_,_=t,k in fx&&Y.attr("cursor",sx[k=fx[k]])),g<d&&(A*=-1,t=p,p=y,y=t,t=d,d=g,g=t,k in lx&&Y.attr("cursor",sx[k=lx[k]])),z=E.selection,w&&(h=z[0][0],_=z[1][0]),M&&(d=z[0][1],g=z[1][1]),z[0][0]===h&&z[0][1]===d&&z[1][0]===_&&z[1][1]===g||(E.selection=[[h,d],[_,g]],r.call(T),F.brush())}function u(){if(El(),t.event.touches){if(t.event.touches.length)return;c&&clearTimeout(c),c=setTimeout(function(){c=null},500),I.on("touchmove.brush touchend.brush touchcancel.brush",null)}else Cf(t.event.view,b),B.on("keydown.brush keyup.brush mousemove.brush mouseup.brush",null);I.attr("pointer-events","all"),Y.attr("cursor",sx.overlay),Rl(z)&&(E.selection=null,r.call(T)),F.end()}function a(){switch(t.event.keyCode){case 16:U=S&&A;break;case 18:N===ix&&(S&&(v=_-m*S,l=h+m*S),A&&(y=g-x*A,p=d+x*A),N=ox,o());break;case 32:N!==ix&&N!==ox||(S<0?v=_-m:S>0&&(l=h-m),A<0?y=g-x:A>0&&(p=d-x),N=rx,Y.attr("cursor",sx.selection),o());break;default:return}Cl()}function s(){switch(t.event.keyCode){case 16:U&&(w=M=U=!1,o());break;case 18:N===ox&&(S<0?v=_:S>0&&(l=h),A<0?y=g:A>0&&(p=d),N=ix,o());break;case 32:N===rx&&(t.event.altKey?(S&&(v=_-m*S,l=h+m*S),A&&(y=g-x*A,p=d+x*A),N=ox):(S<0?v=_:S>0&&(l=h),A<0?y=g:A>0&&(p=d),N=ix),Y.attr("cursor",sx[k]),o());break;default:return}Cl()}if(t.event.touches){if(t.event.changedTouches.length<t.event.touches.length)return Cl()}else if(c)return;if(f.apply(this,arguments)){var l,h,p,d,v,_,y,g,m,x,b,w,M,T=this,k=t.event.target.__data__.type,N="selection"===(t.event.metaKey?k="overlay":k)?ex:t.event.altKey?ox:ix,S=n===ax?null:hx[k],A=n===ux?null:px[k],E=Ll(T),C=E.extent,z=E.selection,P=C[0][0],q=C[0][1],L=C[1][0],R=C[1][1],U=S&&A&&t.event.shiftKey,D=du(T),O=D,F=i(T,arguments).beforestart();"overlay"===k?E.selection=z=[[l=n===ax?P:D[0],p=n===ux?q:D[1]],[v=n===ax?L:l,y=n===ux?R:p]]:(l=z[0][0],p=z[0][1],v=z[1][0],y=z[1][1]),h=l,d=p,_=v,g=y;var I=Ra(T).attr("pointer-events","none"),Y=I.selectAll(".overlay").attr("cursor",sx[k]);if(t.event.touches)I.on("touchmove.brush",e,!0).on("touchend.brush touchcancel.brush",u,!0);else{var B=Ra(t.event.view).on("keydown.brush",a,!0).on("keyup.brush",s,!0).on("mousemove.brush",e,!0).on("mouseup.brush",u,!0);Ef(t.event.view)}El(),Ha(T),r.call(T),F.start()}}function a(){var t=this.__brush||{selection:null};return t.extent=s.apply(this,arguments),t.dim=n,t}var c,s=ql,f=Pl,l=Mr(e,"start","brush","end"),h=6;return e.move=function(t,e){t.selection?t.on("start.brush",function(){i(this,arguments).beforestart().start()}).on("interrupt.brush end.brush",function(){i(this,arguments).end()}).tween("brush",function(){function t(t){u.selection=1===t&&Rl(s)?null:f(t),r.call(o),a.brush()}var o=this,u=o.__brush,a=i(o,arguments),c=u.selection,s=n.input("function"==typeof e?e.apply(this,arguments):e,u.extent),f=cr(c,s);return c&&s?t:t(1)}):t.each(function(){var t=this,o=arguments,u=t.__brush,a=n.input("function"==typeof e?e.apply(t,o):e,u.extent),c=i(t,o).beforestart();Ha(t),u.selection=null==a||Rl(a)?null:a,r.call(t),c.start().brush().end()})},o.prototype={beforestart:function(){return 1===++this.active&&(this.state.emitter=this,this.starting=!0),this},start:function(){return this.starting&&(this.starting=!1,this.emit("start")),this},brush:function(){return this.emit("brush"),this},end:function(){return 0===--this.active&&(delete this.state.emitter,this.emit("end")),this},emit:function(t){lu(new Al(e,t,n.output(this.state.selection)),l.apply,l,[t,this.that,this.args])}},e.extent=function(t){return arguments.length?(s="function"==typeof t?t:Sl([[+t[0][0],+t[0][1]],[+t[1][0],+t[1][1]]]),e):s},e.filter=function(t){return arguments.length?(f="function"==typeof t?t:Sl(!!t),e):f},e.handleSize=function(t){return arguments.length?(h=+t,e):h},e.on=function(){var t=l.on.apply(l,arguments);return t===l?e:t},e}function Yl(t){return function(n,e){return t(n.source.value+n.target.value,e.source.value+e.target.value)}}function Bl(){function t(t){var o,u,a,c,s,f,h=t.length,p=[],d=l(h),v=[],_=[],y=_.groups=new Array(h),g=new Array(h*h);for(o=0,s=-1;++s<h;){for(u=0,f=-1;++f<h;)u+=t[s][f];p.push(u),v.push(l(h)),o+=u}for(e&&d.sort(function(t,n){return e(p[t],p[n])}),r&&v.forEach(function(n,e){n.sort(function(n,i){return r(t[e][n],t[e][i])})}),o=mx(0,gx-n*h)/o,c=o?n:gx/h,u=0,s=-1;++s<h;){for(a=u,f=-1;++f<h;){var m=d[s],x=v[m][f],b=t[m][x],w=u,M=u+=b*o;g[x*h+m]={index:m,subindex:x,startAngle:w,endAngle:M,value:b}}y[m]={index:m,startAngle:a,endAngle:u,value:p[m]},u+=c}for(s=-1;++s<h;)for(f=s-1;++f<h;){var T=g[f*h+s],k=g[s*h+f];(T.value||k.value)&&_.push(T.value<k.value?{source:k,target:T}:{source:T,target:k})}return i?_.sort(i):_}var n=0,e=null,r=null,i=null;return t.padAngle=function(e){return arguments.length?(n=mx(0,e),t):n},t.sortGroups=function(n){return arguments.length?(e=n,t):e},t.sortSubgroups=function(n){return arguments.length?(r=n,t):r},t.sortChords=function(n){return arguments.length?(null==n?i=null:(i=Yl(n))._=n,t):i&&i._},t}function jl(t){return function(){return t}}function Hl(t){return t.source}function Xl(t){return t.target}function Vl(t){return t.radius}function Wl(t){return t.startAngle}function $l(t){return t.endAngle}function Zl(){function t(){var t,a=xx.call(arguments),c=n.apply(this,a),s=e.apply(this,a),f=+r.apply(this,(a[0]=c,
-a)),l=i.apply(this,a)-yx,h=o.apply(this,a)-yx,p=f*dx(l),d=f*vx(l),v=+r.apply(this,(a[0]=s,a)),_=i.apply(this,a)-yx,y=o.apply(this,a)-yx;if(u||(u=t=Tt()),u.moveTo(p,d),u.arc(0,0,f,l,h),l===_&&h===y||(u.quadraticCurveTo(0,0,v*dx(_),v*vx(_)),u.arc(0,0,v,_,y)),u.quadraticCurveTo(0,0,p,d),u.closePath(),t)return u=null,t+""||null}var n=Hl,e=Xl,r=Vl,i=Wl,o=$l,u=null;return t.radius=function(n){return arguments.length?(r="function"==typeof n?n:jl(+n),t):r},t.startAngle=function(n){return arguments.length?(i="function"==typeof n?n:jl(+n),t):i},t.endAngle=function(n){return arguments.length?(o="function"==typeof n?n:jl(+n),t):o},t.source=function(e){return arguments.length?(n=e,t):n},t.target=function(n){return arguments.length?(e=n,t):e},t.context=function(n){return arguments.length?(u=null==n?null:n,t):u},t}function Gl(){return new Jl}function Jl(){this.reset()}function Ql(t,n,e){var r=t.s=n+e,i=r-n,o=r-i;t.t=n-o+(e-i)}function Kl(t){return t>1?0:t<-1?ib:Math.acos(t)}function th(t){return t>1?ob:t<-1?-ob:Math.asin(t)}function nh(t){return(t=gb(t/2))*t}function eh(){}function rh(t,n){t&&Mb.hasOwnProperty(t.type)&&Mb[t.type](t,n)}function ih(t,n,e){var r,i=-1,o=t.length-e;for(n.lineStart();++i<o;)r=t[i],n.point(r[0],r[1],r[2]);n.lineEnd()}function oh(t,n){var e=-1,r=t.length;for(n.polygonStart();++e<r;)ih(t[e],n,1);n.polygonEnd()}function uh(t,n){t&&wb.hasOwnProperty(t.type)?wb[t.type](t,n):rh(t,n)}function ah(){Tb.point=sh}function ch(){fh(Mx,Tx)}function sh(t,n){Tb.point=fh,Mx=t,Tx=n,t*=sb,n*=sb,kx=t,Nx=pb(n=n/2+ub),Sx=gb(n)}function fh(t,n){t*=sb,n*=sb,n=n/2+ub;var e=t-kx,r=e>=0?1:-1,i=r*e,o=pb(n),u=gb(n),a=Sx*u,c=Nx*o+a*pb(i),s=a*r*gb(i);bx.add(hb(s,c)),kx=t,Nx=o,Sx=u}function lh(t){return wx?wx.reset():(wx=Gl(),bx=Gl()),uh(t,Tb),2*wx}function hh(t){return[hb(t[1],t[0]),th(t[2])]}function ph(t){var n=t[0],e=t[1],r=pb(e);return[r*pb(n),r*gb(n),gb(e)]}function dh(t,n){return t[0]*n[0]+t[1]*n[1]+t[2]*n[2]}function vh(t,n){return[t[1]*n[2]-t[2]*n[1],t[2]*n[0]-t[0]*n[2],t[0]*n[1]-t[1]*n[0]]}function _h(t,n){t[0]+=n[0],t[1]+=n[1],t[2]+=n[2]}function yh(t,n){return[t[0]*n,t[1]*n,t[2]*n]}function gh(t){var n=xb(t[0]*t[0]+t[1]*t[1]+t[2]*t[2]);t[0]/=n,t[1]/=n,t[2]/=n}function mh(t,n){Dx.push(Ox=[Ax=t,Cx=t]),n<Ex&&(Ex=n),n>zx&&(zx=n)}function xh(t,n){var e=ph([t*sb,n*sb]);if(Rx){var r=vh(Rx,e),i=[r[1],-r[0],0],o=vh(i,r);gh(o),o=hh(o);var u,a=t-Px,c=a>0?1:-1,s=o[0]*cb*c,f=fb(a)>180;f^(c*Px<s&&s<c*t)?(u=o[1]*cb,u>zx&&(zx=u)):(s=(s+360)%360-180,f^(c*Px<s&&s<c*t)?(u=-o[1]*cb,u<Ex&&(Ex=u)):(n<Ex&&(Ex=n),n>zx&&(zx=n))),f?t<Px?Nh(Ax,t)>Nh(Ax,Cx)&&(Cx=t):Nh(t,Cx)>Nh(Ax,Cx)&&(Ax=t):Cx>=Ax?(t<Ax&&(Ax=t),t>Cx&&(Cx=t)):t>Px?Nh(Ax,t)>Nh(Ax,Cx)&&(Cx=t):Nh(t,Cx)>Nh(Ax,Cx)&&(Ax=t)}else mh(t,n);Rx=e,Px=t}function bh(){kb.point=xh}function wh(){Ox[0]=Ax,Ox[1]=Cx,kb.point=mh,Rx=null}function Mh(t,n){if(Rx){var e=t-Px;Ux.add(fb(e)>180?e+(e>0?360:-360):e)}else qx=t,Lx=n;Tb.point(t,n),xh(t,n)}function Th(){Tb.lineStart()}function kh(){Mh(qx,Lx),Tb.lineEnd(),fb(Ux)>eb&&(Ax=-(Cx=180)),Ox[0]=Ax,Ox[1]=Cx,Rx=null}function Nh(t,n){return(n-=t)<0?n+360:n}function Sh(t,n){return t[0]-n[0]}function Ah(t,n){return t[0]<=t[1]?t[0]<=n&&n<=t[1]:n<t[0]||t[1]<n}function Eh(t){var n,e,r,i,o,u,a;if(Ux?Ux.reset():Ux=Gl(),zx=Cx=-(Ax=Ex=1/0),Dx=[],uh(t,kb),e=Dx.length){for(Dx.sort(Sh),n=1,r=Dx[0],o=[r];n<e;++n)i=Dx[n],Ah(r,i[0])||Ah(r,i[1])?(Nh(r[0],i[1])>Nh(r[0],r[1])&&(r[1]=i[1]),Nh(i[0],r[1])>Nh(r[0],r[1])&&(r[0]=i[0])):o.push(r=i);for(u=-(1/0),e=o.length-1,n=0,r=o[e];n<=e;r=i,++n)i=o[n],(a=Nh(r[1],i[0]))>u&&(u=a,Ax=i[0],Cx=r[1])}return Dx=Ox=null,Ax===1/0||Ex===1/0?[[NaN,NaN],[NaN,NaN]]:[[Ax,Ex],[Cx,zx]]}function Ch(t,n){t*=sb,n*=sb;var e=pb(n);zh(e*pb(t),e*gb(t),gb(n))}function zh(t,n,e){++Fx,Yx+=(t-Yx)/Fx,Bx+=(n-Bx)/Fx,jx+=(e-jx)/Fx}function Ph(){Nb.point=qh}function qh(t,n){t*=sb,n*=sb;var e=pb(n);Qx=e*pb(t),Kx=e*gb(t),tb=gb(n),Nb.point=Lh,zh(Qx,Kx,tb)}function Lh(t,n){t*=sb,n*=sb;var e=pb(n),r=e*pb(t),i=e*gb(t),o=gb(n),u=hb(xb((u=Kx*o-tb*i)*u+(u=tb*r-Qx*o)*u+(u=Qx*i-Kx*r)*u),Qx*r+Kx*i+tb*o);Ix+=u,Hx+=u*(Qx+(Qx=r)),Xx+=u*(Kx+(Kx=i)),Vx+=u*(tb+(tb=o)),zh(Qx,Kx,tb)}function Rh(){Nb.point=Ch}function Uh(){Nb.point=Oh}function Dh(){Fh(Gx,Jx),Nb.point=Ch}function Oh(t,n){Gx=t,Jx=n,t*=sb,n*=sb,Nb.point=Fh;var e=pb(n);Qx=e*pb(t),Kx=e*gb(t),tb=gb(n),zh(Qx,Kx,tb)}function Fh(t,n){t*=sb,n*=sb;var e=pb(n),r=e*pb(t),i=e*gb(t),o=gb(n),u=Kx*o-tb*i,a=tb*r-Qx*o,c=Qx*i-Kx*r,s=xb(u*u+a*a+c*c),f=Qx*r+Kx*i+tb*o,l=s&&-Kl(f)/s,h=hb(s,f);Wx+=l*u,$x+=l*a,Zx+=l*c,Ix+=h,Hx+=h*(Qx+(Qx=r)),Xx+=h*(Kx+(Kx=i)),Vx+=h*(tb+(tb=o)),zh(Qx,Kx,tb)}function Ih(t){Fx=Ix=Yx=Bx=jx=Hx=Xx=Vx=Wx=$x=Zx=0,uh(t,Nb);var n=Wx,e=$x,r=Zx,i=n*n+e*e+r*r;return i<rb&&(n=Hx,e=Xx,r=Vx,Ix<eb&&(n=Yx,e=Bx,r=jx),i=n*n+e*e+r*r,i<rb)?[NaN,NaN]:[hb(e,n)*cb,th(r/xb(i))*cb]}function Yh(t){return function(){return t}}function Bh(t,n){function e(e,r){return e=t(e,r),n(e[0],e[1])}return t.invert&&n.invert&&(e.invert=function(e,r){return e=n.invert(e,r),e&&t.invert(e[0],e[1])}),e}function jh(t,n){return[t>ib?t-ab:t<-ib?t+ab:t,n]}function Hh(t,n,e){return(t%=ab)?n||e?Bh(Vh(t),Wh(n,e)):Vh(t):n||e?Wh(n,e):jh}function Xh(t){return function(n,e){return n+=t,[n>ib?n-ab:n<-ib?n+ab:n,e]}}function Vh(t){var n=Xh(t);return n.invert=Xh(-t),n}function Wh(t,n){function e(t,n){var e=pb(n),a=pb(t)*e,c=gb(t)*e,s=gb(n),f=s*r+a*i;return[hb(c*o-f*u,a*r-s*i),th(f*o+c*u)]}var r=pb(t),i=gb(t),o=pb(n),u=gb(n);return e.invert=function(t,n){var e=pb(n),a=pb(t)*e,c=gb(t)*e,s=gb(n),f=s*o-c*u;return[hb(c*o+s*u,a*r+f*i),th(f*r-a*i)]},e}function $h(t){function n(n){return n=t(n[0]*sb,n[1]*sb),n[0]*=cb,n[1]*=cb,n}return t=Hh(t[0]*sb,t[1]*sb,t.length>2?t[2]*sb:0),n.invert=function(n){return n=t.invert(n[0]*sb,n[1]*sb),n[0]*=cb,n[1]*=cb,n},n}function Zh(t,n,e,r,i,o){if(e){var u=pb(n),a=gb(n),c=r*e;null==i?(i=n+r*ab,o=n-c/2):(i=Gh(u,i),o=Gh(u,o),(r>0?i<o:i>o)&&(i+=r*ab));for(var s,f=i;r>0?f>o:f<o;f-=c)s=hh([u,-a*pb(f),-a*gb(f)]),t.point(s[0],s[1])}}function Gh(t,n){n=ph(n),n[0]-=t,gh(n);var e=Kl(-n[1]);return((-n[2]<0?-e:e)+ab-eb)%ab}function Jh(){function t(t,n){e.push(t=r(t,n)),t[0]*=cb,t[1]*=cb}function n(){var t=i.apply(this,arguments),n=o.apply(this,arguments)*sb,c=u.apply(this,arguments)*sb;return e=[],r=Hh(-t[0]*sb,-t[1]*sb,0).invert,Zh(a,n,c,1),t={type:"Polygon",coordinates:[e]},e=r=null,t}var e,r,i=Yh([0,0]),o=Yh(90),u=Yh(6),a={point:t};return n.center=function(t){return arguments.length?(i="function"==typeof t?t:Yh([+t[0],+t[1]]),n):i},n.radius=function(t){return arguments.length?(o="function"==typeof t?t:Yh(+t),n):o},n.precision=function(t){return arguments.length?(u="function"==typeof t?t:Yh(+t),n):u},n}function Qh(){var t,n=[];return{point:function(n,e){t.push([n,e])},lineStart:function(){n.push(t=[])},lineEnd:eh,rejoin:function(){n.length>1&&n.push(n.pop().concat(n.shift()))},result:function(){var e=n;return n=[],t=null,e}}}function Kh(t,n,e,r,i,o){var u,a=t[0],c=t[1],s=n[0],f=n[1],l=0,h=1,p=s-a,d=f-c;if(u=e-a,p||!(u>0)){if(u/=p,p<0){if(u<l)return;u<h&&(h=u)}else if(p>0){if(u>h)return;u>l&&(l=u)}if(u=i-a,p||!(u<0)){if(u/=p,p<0){if(u>h)return;u>l&&(l=u)}else if(p>0){if(u<l)return;u<h&&(h=u)}if(u=r-c,d||!(u>0)){if(u/=d,d<0){if(u<l)return;u<h&&(h=u)}else if(d>0){if(u>h)return;u>l&&(l=u)}if(u=o-c,d||!(u<0)){if(u/=d,d<0){if(u>h)return;u>l&&(l=u)}else if(d>0){if(u<l)return;u<h&&(h=u)}return l>0&&(t[0]=a+l*p,t[1]=c+l*d),h<1&&(n[0]=a+h*p,n[1]=c+h*d),!0}}}}}function tp(t,n){return fb(t[0]-n[0])<eb&&fb(t[1]-n[1])<eb}function np(t,n,e,r){this.x=t,this.z=n,this.o=e,this.e=r,this.v=!1,this.n=this.p=null}function ep(t,n,e,r,i){var o,u,a=[],c=[];if(t.forEach(function(t){if(!((n=t.length-1)<=0)){var n,e,r=t[0],u=t[n];if(tp(r,u)){for(i.lineStart(),o=0;o<n;++o)i.point((r=t[o])[0],r[1]);return void i.lineEnd()}a.push(e=new np(r,t,null,(!0))),c.push(e.o=new np(r,null,e,(!1))),a.push(e=new np(u,t,null,(!1))),c.push(e.o=new np(u,null,e,(!0)))}}),a.length){for(c.sort(n),rp(a),rp(c),o=0,u=c.length;o<u;++o)c[o].e=e=!e;for(var s,f,l=a[0];;){for(var h=l,p=!0;h.v;)if((h=h.n)===l)return;s=h.z,i.lineStart();do{if(h.v=h.o.v=!0,h.e){if(p)for(o=0,u=s.length;o<u;++o)i.point((f=s[o])[0],f[1]);else r(h.x,h.n.x,1,i);h=h.n}else{if(p)for(s=h.p.z,o=s.length-1;o>=0;--o)i.point((f=s[o])[0],f[1]);else r(h.x,h.p.x,-1,i);h=h.p}h=h.o,s=h.z,p=!p}while(!h.v);i.lineEnd()}}}function rp(t){if(n=t.length){for(var n,e,r=0,i=t[0];++r<n;)i.n=e=t[r],e.p=i,i=e;i.n=e=t[0],e.p=i}}function ip(t,n,e,r){function i(i,o){return t<=i&&i<=e&&n<=o&&o<=r}function o(i,o,a,s){var f=0,l=0;if(null==i||(f=u(i,a))!==(l=u(o,a))||c(i,o)<0^a>0){do s.point(0===f||3===f?t:e,f>1?r:n);while((f=(f+a+4)%4)!==l)}else s.point(o[0],o[1])}function u(r,i){return fb(r[0]-t)<eb?i>0?0:3:fb(r[0]-e)<eb?i>0?2:1:fb(r[1]-n)<eb?i>0?1:0:i>0?3:2}function a(t,n){return c(t.x,n.x)}function c(t,n){var e=u(t,1),r=u(n,1);return e!==r?e-r:0===e?n[1]-t[1]:1===e?t[0]-n[0]:2===e?t[1]-n[1]:n[0]-t[0]}return function(u){function c(t,n){i(t,n)&&S.point(t,n)}function s(){for(var n=0,e=0,i=_.length;e<i;++e)for(var o,u,a=_[e],c=1,s=a.length,f=a[0],l=f[0],h=f[1];c<s;++c)o=l,u=h,f=a[c],l=f[0],h=f[1],u<=r?h>r&&(l-o)*(r-u)>(h-u)*(t-o)&&++n:h<=r&&(l-o)*(r-u)<(h-u)*(t-o)&&--n;return n}function f(){S=A,v=[],_=[],N=!0}function l(){var t=s(),n=N&&t,e=(v=w(v)).length;(n||e)&&(u.polygonStart(),n&&(u.lineStart(),o(null,null,1,u),u.lineEnd()),e&&ep(v,a,t,o,u),u.polygonEnd()),S=u,v=_=y=null}function h(){E.point=d,_&&_.push(y=[]),k=!0,T=!1,b=M=NaN}function p(){v&&(d(g,m),x&&T&&A.rejoin(),v.push(A.result())),E.point=c,T&&S.lineEnd()}function d(o,u){var a=i(o,u);if(_&&y.push([o,u]),k)g=o,m=u,x=a,k=!1,a&&(S.lineStart(),S.point(o,u));else if(a&&T)S.point(o,u);else{var c=[b=Math.max(Ib,Math.min(Fb,b)),M=Math.max(Ib,Math.min(Fb,M))],s=[o=Math.max(Ib,Math.min(Fb,o)),u=Math.max(Ib,Math.min(Fb,u))];Kh(c,s,t,n,e,r)?(T||(S.lineStart(),S.point(c[0],c[1])),S.point(s[0],s[1]),a||S.lineEnd(),N=!1):a&&(S.lineStart(),S.point(o,u),N=!1)}b=o,M=u,T=a}var v,_,y,g,m,x,b,M,T,k,N,S=u,A=Qh(),E={point:c,lineStart:h,lineEnd:p,polygonStart:f,polygonEnd:l};return E}}function op(){var t,n,e,r=0,i=0,o=960,u=500;return e={stream:function(e){return t&&n===e?t:t=ip(r,i,o,u)(n=e)},extent:function(a){return arguments.length?(r=+a[0][0],i=+a[0][1],o=+a[1][0],u=+a[1][1],t=n=null,e):[[r,i],[o,u]]}}}function up(){Yb.point=cp,Yb.lineEnd=ap}function ap(){Yb.point=Yb.lineEnd=eh}function cp(t,n){t*=sb,n*=sb,Ab=t,Eb=gb(n),Cb=pb(n),Yb.point=sp}function sp(t,n){t*=sb,n*=sb;var e=gb(n),r=pb(n),i=fb(t-Ab),o=pb(i),u=gb(i),a=r*u,c=Cb*e-Eb*r*o,s=Eb*e+Cb*r*o;Sb.add(hb(xb(a*a+c*c),s)),Ab=t,Eb=e,Cb=r}function fp(t){return Sb?Sb.reset():Sb=Gl(),uh(t,Yb),+Sb}function lp(t,n){return Bb[0]=t,Bb[1]=n,fp(jb)}function hp(t,n,e){var r=l(t,n-eb,e).concat(n);return function(t){return r.map(function(n){return[t,n]})}}function pp(t,n,e){var r=l(t,n-eb,e).concat(n);return function(t){return r.map(function(n){return[n,t]})}}function dp(){function t(){return{type:"MultiLineString",coordinates:n()}}function n(){return l(db(o/y)*y,i,y).map(p).concat(l(db(s/g)*g,c,g).map(d)).concat(l(db(r/v)*v,e,v).filter(function(t){return fb(t%y)>eb}).map(f)).concat(l(db(a/_)*_,u,_).filter(function(t){return fb(t%g)>eb}).map(h))}var e,r,i,o,u,a,c,s,f,h,p,d,v=10,_=v,y=90,g=360,m=2.5;return t.lines=function(){return n().map(function(t){return{type:"LineString",coordinates:t}})},t.outline=function(){return{type:"Polygon",coordinates:[p(o).concat(d(c).slice(1),p(i).reverse().slice(1),d(s).reverse().slice(1))]}},t.extent=function(n){return arguments.length?t.extentMajor(n).extentMinor(n):t.extentMinor()},t.extentMajor=function(n){return arguments.length?(o=+n[0][0],i=+n[1][0],s=+n[0][1],c=+n[1][1],o>i&&(n=o,o=i,i=n),s>c&&(n=s,s=c,c=n),t.precision(m)):[[o,s],[i,c]]},t.extentMinor=function(n){return arguments.length?(r=+n[0][0],e=+n[1][0],a=+n[0][1],u=+n[1][1],r>e&&(n=r,r=e,e=n),a>u&&(n=a,a=u,u=n),t.precision(m)):[[r,a],[e,u]]},t.step=function(n){return arguments.length?t.stepMajor(n).stepMinor(n):t.stepMinor()},t.stepMajor=function(n){return arguments.length?(y=+n[0],g=+n[1],t):[y,g]},t.stepMinor=function(n){return arguments.length?(v=+n[0],_=+n[1],t):[v,_]},t.precision=function(n){return arguments.length?(m=+n,f=hp(a,u,90),h=pp(r,e,m),p=hp(s,c,90),d=pp(o,i,m),t):m},t.extentMajor([[-180,-90+eb],[180,90-eb]]).extentMinor([[-180,-80-eb],[180,80+eb]])}function vp(t,n){var e=t[0]*sb,r=t[1]*sb,i=n[0]*sb,o=n[1]*sb,u=pb(r),a=gb(r),c=pb(o),s=gb(o),f=u*pb(e),l=u*gb(e),h=c*pb(i),p=c*gb(i),d=2*th(xb(nh(o-r)+u*c*nh(i-e))),v=gb(d),_=d?function(t){var n=gb(t*=d)/v,e=gb(d-t)/v,r=e*f+n*h,i=e*l+n*p,o=e*a+n*s;return[hb(i,r)*cb,hb(o,xb(r*r+i*i))*cb]}:function(){return[e*cb,r*cb]};return _.distance=d,_}function _p(t){return t}function yp(){Vb.point=gp}function gp(t,n){Vb.point=mp,zb=qb=t,Pb=Lb=n}function mp(t,n){Xb.add(Lb*t-qb*n),qb=t,Lb=n}function xp(){mp(zb,Pb)}function bp(t,n){t<Wb&&(Wb=t),t>Zb&&(Zb=t),n<$b&&($b=n),n>Gb&&(Gb=n)}function wp(t,n){Qb+=t,Kb+=n,++tw}function Mp(){aw.point=Tp}function Tp(t,n){aw.point=kp,wp(Db=t,Ob=n)}function kp(t,n){var e=t-Db,r=n-Ob,i=xb(e*e+r*r);nw+=i*(Db+t)/2,ew+=i*(Ob+n)/2,rw+=i,wp(Db=t,Ob=n)}function Np(){aw.point=wp}function Sp(){aw.point=Ep}function Ap(){Cp(Rb,Ub)}function Ep(t,n){aw.point=Cp,wp(Rb=Db=t,Ub=Ob=n)}function Cp(t,n){var e=t-Db,r=n-Ob,i=xb(e*e+r*r);nw+=i*(Db+t)/2,ew+=i*(Ob+n)/2,rw+=i,i=Ob*t-Db*n,iw+=i*(Db+t),ow+=i*(Ob+n),uw+=3*i,wp(Db=t,Ob=n)}function zp(t){function n(n,e){t.moveTo(n+u,e),t.arc(n,e,u,0,ab)}function e(n,e){t.moveTo(n,e),a.point=r}function r(n,e){t.lineTo(n,e)}function i(){a.point=n}function o(){t.closePath()}var u=4.5,a={point:n,lineStart:function(){a.point=e},lineEnd:i,polygonStart:function(){a.lineEnd=o},polygonEnd:function(){a.lineEnd=i,a.point=n},pointRadius:function(t){return u=t,a},result:eh};return a}function Pp(){function t(t,n){a.push("M",t,",",n,u)}function n(t,n){a.push("M",t,",",n),c.point=e}function e(t,n){a.push("L",t,",",n)}function r(){c.point=n}function i(){c.point=t}function o(){a.push("Z")}var u=qp(4.5),a=[],c={point:t,lineStart:r,lineEnd:i,polygonStart:function(){c.lineEnd=o},polygonEnd:function(){c.lineEnd=i,c.point=t},pointRadius:function(t){return u=qp(t),c},result:function(){if(a.length){var t=a.join("");return a=[],t}}};return c}function qp(t){return"m0,"+t+"a"+t+","+t+" 0 1,1 0,"+-2*t+"a"+t+","+t+" 0 1,1 0,"+2*t+"z"}function Lp(){function t(t){return t&&("function"==typeof o&&i.pointRadius(+o.apply(this,arguments)),uh(t,e(i))),i.result()}var n,e,r,i,o=4.5;return t.area=function(t){return uh(t,e(Vb)),Vb.result()},t.bounds=function(t){return uh(t,e(Jb)),Jb.result()},t.centroid=function(t){return uh(t,e(aw)),aw.result()},t.projection=function(r){return arguments.length?(e=null==(n=r)?_p:r.stream,t):n},t.context=function(n){return arguments.length?(i=null==(r=n)?new Pp:new zp(n),"function"!=typeof o&&i.pointRadius(o),t):r},t.pointRadius=function(n){return arguments.length?(o="function"==typeof n?n:(i.pointRadius(+n),+n),t):o},t.projection(null).context(null)}function Rp(t,n){for(var e=n[0],r=n[1],i=[gb(e),-pb(e),0],o=0,u=0,a=0,c=t.length;a<c;++a)if(f=(s=t[a]).length)for(var s,f,l=s[f-1],h=l[0],p=l[1]/2+ub,d=gb(p),v=pb(p),_=0;_<f;++_,h=g,d=x,v=b,l=y){var y=s[_],g=y[0],m=y[1]/2+ub,x=gb(m),b=pb(m),w=g-h,M=w>=0?1:-1,T=M*w,k=T>ib,N=d*x;if(cw.add(hb(N*M*gb(T),v*b+N*pb(T))),o+=k?w+M*ab:w,k^h>=e^g>=e){var S=vh(ph(l),ph(y));gh(S);var A=vh(i,S);gh(A);var E=(k^w>=0?-1:1)*th(A[2]);(r>E||r===E&&(S[0]||S[1]))&&(u+=k^w>=0?1:-1)}}var C=(o<-eb||o<eb&&cw<-eb)^1&u;return cw.reset(),C}function Up(t,n,e,r){return function(i,o){function u(n,e){var r=i(n,e);t(n=r[0],e=r[1])&&o.point(n,e)}function a(t,n){var e=i(t,n);_.point(e[0],e[1])}function c(){b.point=a,_.lineStart()}function s(){b.point=u,_.lineEnd()}function f(t,n){v.push([t,n]);var e=i(t,n);m.point(e[0],e[1])}function l(){m.lineStart(),v=[]}function h(){f(v[0][0],v[0][1]),m.lineEnd();var t,n,e,r,i=m.clean(),u=g.result(),a=u.length;if(v.pop(),p.push(v),v=null,a)if(1&i){if(e=u[0],(n=e.length-1)>0){for(x||(o.polygonStart(),x=!0),o.lineStart(),t=0;t<n;++t)o.point((r=e[t])[0],r[1]);o.lineEnd()}}else a>1&&2&i&&u.push(u.pop().concat(u.shift())),d.push(u.filter(Dp))}var p,d,v,_=n(o),y=i.invert(r[0],r[1]),g=Qh(),m=n(g),x=!1,b={point:u,lineStart:c,lineEnd:s,polygonStart:function(){b.point=f,b.lineStart=l,b.lineEnd=h,d=[],p=[]},polygonEnd:function(){b.point=u,b.lineStart=c,b.lineEnd=s,d=w(d);var t=Rp(p,y);d.length?(x||(o.polygonStart(),x=!0),ep(d,Op,t,e,o)):t&&(x||(o.polygonStart(),x=!0),o.lineStart(),e(null,null,1,o),o.lineEnd()),x&&(o.polygonEnd(),x=!1),d=p=null},sphere:function(){o.polygonStart(),o.lineStart(),e(null,null,1,o),o.lineEnd(),o.polygonEnd()}};return b}}function Dp(t){return t.length>1}function Op(t,n){return((t=t.x)[0]<0?t[1]-ob-eb:ob-t[1])-((n=n.x)[0]<0?n[1]-ob-eb:ob-n[1])}function Fp(t){var n,e=NaN,r=NaN,i=NaN;return{lineStart:function(){t.lineStart(),n=1},point:function(o,u){var a=o>0?ib:-ib,c=fb(o-e);fb(c-ib)<eb?(t.point(e,r=(r+u)/2>0?ob:-ob),t.point(i,r),t.lineEnd(),t.lineStart(),t.point(a,r),t.point(o,r),n=0):i!==a&&c>=ib&&(fb(e-i)<eb&&(e-=i*eb),fb(o-a)<eb&&(o-=a*eb),r=Ip(e,r,o,u),t.point(i,r),t.lineEnd(),t.lineStart(),t.point(a,r),n=0),t.point(e=o,r=u),i=a},lineEnd:function(){t.lineEnd(),e=r=NaN},clean:function(){return 2-n}}}function Ip(t,n,e,r){var i,o,u=gb(t-e);return fb(u)>eb?lb((gb(n)*(o=pb(r))*gb(e)-gb(r)*(i=pb(n))*gb(t))/(i*o*u)):(n+r)/2}function Yp(t,n,e,r){var i;if(null==t)i=e*ob,r.point(-ib,i),r.point(0,i),r.point(ib,i),r.point(ib,0),r.point(ib,-i),r.point(0,-i),r.point(-ib,-i),r.point(-ib,0),r.point(-ib,i);else if(fb(t[0]-n[0])>eb){var o=t[0]<n[0]?ib:-ib;i=e*o/2,r.point(-o,i),r.point(0,i),r.point(o,i)}else r.point(n[0],n[1])}function Bp(t,n){function e(e,r,i,o){Zh(o,t,n,i,e,r)}function r(t,n){return pb(t)*pb(n)>a}function i(t){var n,e,i,a,f;return{lineStart:function(){a=i=!1,f=1},point:function(l,h){var p,d=[l,h],v=r(l,h),_=c?v?0:u(l,h):v?u(l+(l<0?ib:-ib),h):0;if(!n&&(a=i=v)&&t.lineStart(),v!==i&&(p=o(n,d),(tp(n,p)||tp(d,p))&&(d[0]+=eb,d[1]+=eb,v=r(d[0],d[1]))),v!==i)f=0,v?(t.lineStart(),p=o(d,n),t.point(p[0],p[1])):(p=o(n,d),t.point(p[0],p[1]),t.lineEnd()),n=p;else if(s&&n&&c^v){var y;_&e||!(y=o(d,n,!0))||(f=0,c?(t.lineStart(),t.point(y[0][0],y[0][1]),t.point(y[1][0],y[1][1]),t.lineEnd()):(t.point(y[1][0],y[1][1]),t.lineEnd(),t.lineStart(),t.point(y[0][0],y[0][1])))}!v||n&&tp(n,d)||t.point(d[0],d[1]),n=d,i=v,e=_},lineEnd:function(){i&&t.lineEnd(),n=null},clean:function(){return f|(a&&i)<<1}}}function o(t,n,e){var r=ph(t),i=ph(n),o=[1,0,0],u=vh(r,i),c=dh(u,u),s=u[0],f=c-s*s;if(!f)return!e&&t;var l=a*c/f,h=-a*s/f,p=vh(o,u),d=yh(o,l),v=yh(u,h);_h(d,v);var _=p,y=dh(d,_),g=dh(_,_),m=y*y-g*(dh(d,d)-1);if(!(m<0)){var x=xb(m),b=yh(_,(-y-x)/g);if(_h(b,d),b=hh(b),!e)return b;var w,M=t[0],T=n[0],k=t[1],N=n[1];T<M&&(w=M,M=T,T=w);var S=T-M,A=fb(S-ib)<eb,E=A||S<eb;if(!A&&N<k&&(w=k,k=N,N=w),E?A?k+N>0^b[1]<(fb(b[0]-M)<eb?k:N):k<=b[1]&&b[1]<=N:S>ib^(M<=b[0]&&b[0]<=T)){var C=yh(_,(-y+x)/g);return _h(C,d),[b,hh(C)]}}}function u(n,e){var r=c?t:ib-t,i=0;return n<-r?i|=1:n>r&&(i|=2),e<-r?i|=4:e>r&&(i|=8),i}var a=pb(t),c=a>0,s=fb(a)>eb;return Up(r,i,e,c?[0,-t]:[-ib,t-ib])}function jp(t){return{stream:Hp(t)}}function Hp(t){function n(){}var e=n.prototype=Object.create(Xp.prototype);for(var r in t)e[r]=t[r];return function(t){var e=new n;return e.stream=t,e}}function Xp(){}function Vp(t,n){return+n?$p(t,n):Wp(t)}function Wp(t){return Hp({point:function(n,e){n=t(n,e),this.stream.point(n[0],n[1])}})}function $p(t,n){function e(r,i,o,u,a,c,s,f,l,h,p,d,v,_){var y=s-r,g=f-i,m=y*y+g*g;if(m>4*n&&v--){var x=u+h,b=a+p,w=c+d,M=xb(x*x+b*b+w*w),T=th(w/=M),k=fb(fb(w)-1)<eb||fb(o-l)<eb?(o+l)/2:hb(b,x),N=t(k,T),S=N[0],A=N[1],E=S-r,C=A-i,z=g*E-y*C;(z*z/m>n||fb((y*E+g*C)/m-.5)>.3||u*h+a*p+c*d<lw)&&(e(r,i,o,u,a,c,S,A,k,x/=M,b/=M,w,v,_),_.point(S,A),e(S,A,k,x,b,w,s,f,l,h,p,d,v,_))}}return function(n){function r(e,r){e=t(e,r),n.point(e[0],e[1])}function i(){y=NaN,w.point=o,n.lineStart()}function o(r,i){var o=ph([r,i]),u=t(r,i);e(y,g,_,m,x,b,y=u[0],g=u[1],_=r,m=o[0],x=o[1],b=o[2],fw,n),n.point(y,g)}function u(){w.point=r,n.lineEnd()}function a(){i(),w.point=c,w.lineEnd=s}function c(t,n){o(f=t,n),l=y,h=g,p=m,d=x,v=b,w.point=o}function s(){e(y,g,_,m,x,b,l,h,f,p,d,v,fw,n),w.lineEnd=u,u()}var f,l,h,p,d,v,_,y,g,m,x,b,w={point:r,lineStart:i,lineEnd:u,polygonStart:function(){n.polygonStart(),w.lineStart=a},polygonEnd:function(){n.polygonEnd(),w.lineStart=i}};return w}}function Zp(t){return Gp(function(){return t})()}function Gp(t){function n(t){return t=f(t[0]*sb,t[1]*sb),[t[0]*_+a,c-t[1]*_]}function e(t){return t=f.invert((t[0]-a)/_,(c-t[1])/_),t&&[t[0]*cb,t[1]*cb]}function r(t,n){return t=u(t,n),[t[0]*_+a,c-t[1]*_]}function i(){f=Bh(s=Hh(b,w,M),u);var t=u(m,x);return a=y-t[0]*_,c=g+t[1]*_,o()}function o(){return d=v=null,n}var u,a,c,s,f,l,h,p,d,v,_=150,y=480,g=250,m=0,x=0,b=0,w=0,M=0,T=null,k=sw,N=null,S=_p,A=.5,E=Vp(r,A);return n.stream=function(t){return d&&v===t?d:d=hw(k(s,E(S(v=t))))},n.clipAngle=function(t){return arguments.length?(k=+t?Bp(T=t*sb,6*sb):(T=null,sw),o()):T*cb},n.clipExtent=function(t){return arguments.length?(S=null==t?(N=l=h=p=null,_p):ip(N=+t[0][0],l=+t[0][1],h=+t[1][0],p=+t[1][1]),o()):null==N?null:[[N,l],[h,p]]},n.scale=function(t){return arguments.length?(_=+t,i()):_},n.translate=function(t){return arguments.length?(y=+t[0],g=+t[1],i()):[y,g]},n.center=function(t){return arguments.length?(m=t[0]%360*sb,x=t[1]%360*sb,i()):[m*cb,x*cb]},n.rotate=function(t){return arguments.length?(b=t[0]%360*sb,w=t[1]%360*sb,M=t.length>2?t[2]%360*sb:0,i()):[b*cb,w*cb,M*cb]},n.precision=function(t){return arguments.length?(E=Vp(r,A=t*t),o()):xb(A)},function(){return u=t.apply(this,arguments),n.invert=u.invert&&e,i()}}function Jp(t){var n=0,e=ib/3,r=Gp(t),i=r(n,e);return i.parallels=function(t){return arguments.length?r(n=t[0]*sb,e=t[1]*sb):[n*cb,e*cb]},i}function Qp(t,n){function e(t,n){var e=xb(o-2*i*gb(n))/i;return[e*gb(t*=i),u-e*pb(t)]}var r=gb(t),i=(r+gb(n))/2,o=1+r*(2*i-r),u=xb(o)/i;return e.invert=function(t,n){var e=u-n;return[hb(t,e)/i,th((o-(t*t+e*e)*i*i)/(2*i))]},e}function Kp(){return Jp(Qp).scale(151).translate([480,347])}function td(){return Kp().parallels([29.5,45.5]).scale(1070).translate([480,250]).rotate([96,0]).center([-.6,38.7])}function nd(t){var n=t.length;return{point:function(e,r){for(var i=-1;++i<n;)t[i].point(e,r)},sphere:function(){for(var e=-1;++e<n;)t[e].sphere()},lineStart:function(){for(var e=-1;++e<n;)t[e].lineStart()},lineEnd:function(){for(var e=-1;++e<n;)t[e].lineEnd()},polygonStart:function(){for(var e=-1;++e<n;)t[e].polygonStart()},polygonEnd:function(){for(var e=-1;++e<n;)t[e].polygonEnd()}}}function ed(){function t(t){var n=t[0],e=t[1];return u=null,r.point(n,e),u||(i.point(n,e),u)||(o.point(n,e),u)}var n,e,r,i,o,u,a=td(),c=Kp().rotate([154,0]).center([-2,58.5]).parallels([55,65]),s=Kp().rotate([157,0]).center([-3,19.9]).parallels([8,18]),f={point:function(t,n){u=[t,n]}};return t.invert=function(t){var n=a.scale(),e=a.translate(),r=(t[0]-e[0])/n,i=(t[1]-e[1])/n;return(i>=.12&&i<.234&&r>=-.425&&r<-.214?c:i>=.166&&i<.234&&r>=-.214&&r<-.115?s:a).invert(t)},t.stream=function(t){return n&&e===t?n:n=nd([a.stream(e=t),c.stream(t),s.stream(t)])},t.precision=function(n){return arguments.length?(a.precision(n),c.precision(n),s.precision(n),t):a.precision()},t.scale=function(n){return arguments.length?(a.scale(n),c.scale(.35*n),s.scale(n),t.translate(a.translate())):a.scale()},t.translate=function(n){if(!arguments.length)return a.translate();var e=a.scale(),u=+n[0],l=+n[1];return r=a.translate(n).clipExtent([[u-.455*e,l-.238*e],[u+.455*e,l+.238*e]]).stream(f),i=c.translate([u-.307*e,l+.201*e]).clipExtent([[u-.425*e+eb,l+.12*e+eb],[u-.214*e-eb,l+.234*e-eb]]).stream(f),o=s.translate([u-.205*e,l+.212*e]).clipExtent([[u-.214*e+eb,l+.166*e+eb],[u-.115*e-eb,l+.234*e-eb]]).stream(f),t},t.scale(1070)}function rd(t){return function(n,e){var r=pb(n),i=pb(e),o=t(r*i);return[o*i*gb(n),o*gb(e)]}}function id(t){return function(n,e){var r=xb(n*n+e*e),i=t(r),o=gb(i),u=pb(i);return[hb(n*o,r*u),th(r&&e*o/r)]}}function od(){return Zp(pw).scale(120).clipAngle(179.999)}function ud(){return Zp(dw).scale(480/ab).clipAngle(179.999)}function ad(t,n){return[t,_b(bb((ob+n)/2))]}function cd(){return sd(ad)}function sd(t){var n,e=Zp(t),r=e.scale,i=e.translate,o=e.clipExtent;return e.scale=function(t){return arguments.length?(r(t),n&&e.clipExtent(null),e):r()},e.translate=function(t){return arguments.length?(i(t),n&&e.clipExtent(null),e):i()},e.clipExtent=function(t){if(!arguments.length)return n?null:o();if(n=null==t){var u=ib*r(),a=i();t=[[a[0]-u,a[1]-u],[a[0]+u,a[1]+u]]}return o(t),e},e.clipExtent(null).scale(961/ab)}function fd(t){return bb((ob+t)/2)}function ld(t,n){function e(t,n){o>0?n<-ob+eb&&(n=-ob+eb):n>ob-eb&&(n=ob-eb);var e=o/yb(fd(n),i);return[e*gb(i*t),o-e*pb(i*t)]}var r=pb(t),i=t===n?gb(t):_b(r/pb(n))/_b(fd(n)/fd(t)),o=r*yb(fd(t),i)/i;return i?(e.invert=function(t,n){var e=o-n,r=mb(i)*xb(t*t+e*e);return[hb(t,e)/i,2*lb(yb(o/r,1/i))-ob]},e):ad}function hd(){return Jp(ld)}function pd(t,n){return[t,n]}function dd(){return Zp(pd).scale(480/ib)}function vd(t,n){function e(t,n){var e=o-n,r=i*t;return[e*gb(r),o-e*pb(r)]}var r=pb(t),i=t===n?gb(t):(r-pb(n))/(n-t),o=r/i+t;return fb(i)<eb?pd:(e.invert=function(t,n){var e=o-n;return[hb(t,e)/i,o-mb(i)*xb(t*t+e*e)]},e)}function _d(){return Jp(vd).scale(128).translate([480,280])}function yd(t,n){var e=pb(n),r=pb(t)*e;return[e*gb(t)/r,gb(n)/r]}function gd(){return Zp(yd).scale(139).clipAngle(60)}function md(t,n){return[pb(n)*gb(t),gb(n)]}function xd(){return Zp(md).scale(240).clipAngle(90+eb)}function bd(t,n){var e=pb(n),r=1+pb(t)*e;return[e*gb(t)/r,gb(n)/r]}function wd(){return Zp(bd).scale(240).clipAngle(142)}function Md(t,n){return[_b(bb((ob+n)/2)),-t]}function Td(){var t=sd(Md),n=t.center,e=t.rotate;return t.center=function(t){return arguments.length?n([-t[1],t[0]]):(t=n(),[t[1],-t[0]])},t.rotate=function(t){return arguments.length?e([t[0],t[1],t.length>2?t[2]+90:90]):(t=e(),[t[0],t[1],t[2]-90])},e([0,0,90])}var kd="4.1.0",Nd=e(n),Sd=Nd.right,Ad=Nd.left,Ed=Array.prototype,Cd=Ed.slice,zd=Ed.map,Pd=Math.sqrt(50),qd=Math.sqrt(10),Ld=Math.sqrt(2),Rd="$";P.prototype=q.prototype={constructor:P,has:function(t){return Rd+t in this},get:function(t){return this[Rd+t]},set:function(t,n){return this[Rd+t]=n,this},remove:function(t){var n=Rd+t;return n in this&&delete this[n]},clear:function(){for(var t in this)t[0]===Rd&&delete this[t]},keys:function(){var t=[];for(var n in this)n[0]===Rd&&t.push(n.slice(1));return t},values:function(){var t=[];for(var n in this)n[0]===Rd&&t.push(this[n]);return t},entries:function(){var t=[];for(var n in this)n[0]===Rd&&t.push({key:n.slice(1),value:this[n]});return t},size:function(){var t=0;for(var n in this)n[0]===Rd&&++t;return t},empty:function(){for(var t in this)if(t[0]===Rd)return!1;return!0},each:function(t){for(var n in this)n[0]===Rd&&t(this[n],n.slice(1),this)}};var Ud=q.prototype;F.prototype=I.prototype={constructor:F,has:Ud.has,add:function(t){return t+="",this[Rd+t]=t,this},remove:Ud.remove,clear:Ud.clear,values:Ud.keys,size:Ud.size,empty:Ud.empty,each:Ud.each};var Dd=3,Od=function vw(t){function n(n){return Math.pow(n,t)}return t=+t,n.exponent=vw,n}(Dd),Fd=function _w(t){function n(n){return 1-Math.pow(1-n,t)}return t=+t,n.exponent=_w,n}(Dd),Id=function yw(t){function n(n){return((n*=2)<=1?Math.pow(n,t):2-Math.pow(2-n,t))/2}return t=+t,n.exponent=yw,n}(Dd),Yd=Math.PI,Bd=Yd/2,jd=4/11,Hd=6/11,Xd=8/11,Vd=.75,Wd=9/11,$d=10/11,Zd=.9375,Gd=21/22,Jd=63/64,Qd=1/jd/jd,Kd=1.70158,tv=function gw(t){function n(n){return n*n*((t+1)*n-t)}return t=+t,n.overshoot=gw,n}(Kd),nv=function mw(t){function n(n){return--n*n*((t+1)*n+t)+1}return t=+t,n.overshoot=mw,n}(Kd),ev=function xw(t){function n(n){return((n*=2)<1?n*n*((t+1)*n-t):(n-=2)*n*((t+1)*n+t)+2)/2}return t=+t,n.overshoot=xw,n}(Kd),rv=2*Math.PI,iv=1,ov=.3,uv=function bw(t,n){function e(e){return t*Math.pow(2,10*--e)*Math.sin((r-e)/n)}var r=Math.asin(1/(t=Math.max(1,t)))*(n/=rv);return e.amplitude=function(t){return bw(t,n*rv)},e.period=function(n){return bw(t,n)},e}(iv,ov),av=function ww(t,n){function e(e){return 1-t*Math.pow(2,-10*(e=+e))*Math.sin((e+r)/n)}var r=Math.asin(1/(t=Math.max(1,t)))*(n/=rv);return e.amplitude=function(t){return ww(t,n*rv)},e.period=function(n){return ww(t,n)},e}(iv,ov),cv=function Mw(t,n){function e(e){return((e=2*e-1)<0?t*Math.pow(2,10*e)*Math.sin((r-e)/n):2-t*Math.pow(2,-10*e)*Math.sin((r+e)/n))/2}var r=Math.asin(1/(t=Math.max(1,t)))*(n/=rv);return e.amplitude=function(t){return Mw(t,n*rv)},e.period=function(n){return Mw(t,n)},e}(iv,ov),sv=Math.PI,fv=2*sv,lv=1e-6,hv=fv-lv;Mt.prototype=Tt.prototype={constructor:Mt,moveTo:function(t,n){this._.push("M",this._x0=this._x1=+t,",",this._y0=this._y1=+n)},closePath:function(){null!==this._x1&&(this._x1=this._x0,this._y1=this._y0,this._.push("Z"))},lineTo:function(t,n){this._.push("L",this._x1=+t,",",this._y1=+n)},quadraticCurveTo:function(t,n,e,r){this._.push("Q",+t,",",+n,",",this._x1=+e,",",this._y1=+r)},bezierCurveTo:function(t,n,e,r,i,o){this._.push("C",+t,",",+n,",",+e,",",+r,",",this._x1=+i,",",this._y1=+o)},arcTo:function(t,n,e,r,i){t=+t,n=+n,e=+e,r=+r,i=+i;var o=this._x1,u=this._y1,a=e-t,c=r-n,s=o-t,f=u-n,l=s*s+f*f;if(i<0)throw new Error("negative radius: "+i);if(null===this._x1)this._.push("M",this._x1=t,",",this._y1=n);else if(l>lv)if(Math.abs(f*a-c*s)>lv&&i){var h=e-o,p=r-u,d=a*a+c*c,v=h*h+p*p,_=Math.sqrt(d),y=Math.sqrt(l),g=i*Math.tan((sv-Math.acos((d+l-v)/(2*_*y)))/2),m=g/y,x=g/_;Math.abs(m-1)>lv&&this._.push("L",t+m*s,",",n+m*f),this._.push("A",i,",",i,",0,0,",+(f*h>s*p),",",this._x1=t+x*a,",",this._y1=n+x*c)}else this._.push("L",this._x1=t,",",this._y1=n);else;},arc:function(t,n,e,r,i,o){t=+t,n=+n,e=+e;var u=e*Math.cos(r),a=e*Math.sin(r),c=t+u,s=n+a,f=1^o,l=o?r-i:i-r;if(e<0)throw new Error("negative radius: "+e);null===this._x1?this._.push("M",c,",",s):(Math.abs(this._x1-c)>lv||Math.abs(this._y1-s)>lv)&&this._.push("L",c,",",s),e&&(l>hv?this._.push("A",e,",",e,",0,1,",f,",",t-u,",",n-a,"A",e,",",e,",0,1,",f,",",this._x1=c,",",this._y1=s):(l<0&&(l=l%fv+fv),this._.push("A",e,",",e,",0,",+(l>=sv),",",f,",",this._x1=t+e*Math.cos(i),",",this._y1=n+e*Math.sin(i))))},rect:function(t,n,e,r){this._.push("M",this._x0=this._x1=+t,",",this._y0=this._y1=+n,"h",+e,"v",+r,"h",-e,"Z")},toString:function(){return this._.join("")}};var pv=jt.prototype=Ht.prototype;pv.copy=function(){var t,n,e=new Ht(this._x,this._y,this._x0,this._y0,this._x1,this._y1),r=this._root;if(!r)return e;if(!r.length)return e._root=Xt(r),e;for(t=[{source:r,target:e._root=new Array(4)}];r=t.pop();)for(var i=0;i<4;++i)(n=r.source[i])&&(n.length?t.push({source:n,target:r.target[i]=new Array(4)}):r.target[i]=Xt(n));return e},pv.add=kt,pv.addAll=St,pv.cover=At,pv.data=Et,pv.extent=Ct,pv.find=Pt,pv.remove=qt,pv.removeAll=Lt,pv.root=Rt,pv.size=Ut,pv.visit=Dt,pv.visitAfter=Ot,pv.x=It,pv.y=Bt;var dv=[].slice,vv={};Vt.prototype=Qt.prototype={constructor:Vt,defer:function(t){if("function"!=typeof t||this._call)throw new Error;if(null!=this._error)return this;var n=dv.call(arguments,1);return n.push(t),++this._waiting,this._tasks.push(n),Wt(this),this},abort:function(){return null==this._error&&Gt(this,new Error("abort")),this},await:function(t){if("function"!=typeof t||this._call)throw new Error;return this._call=function(n,e){t.apply(null,[n].concat(e))},Jt(this),this},awaitAll:function(t){if("function"!=typeof t||this._call)throw new Error;return this._call=t,Jt(this),this}};var _v=1e-12,yv=Math.PI,gv=yv/2,mv=2*yv;fn.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._point=0},lineEnd:function(){(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,n):this._context.moveTo(t,n);break;case 1:this._point=2;default:this._context.lineTo(t,n)}}};var xv=xn(ln);mn.prototype={areaStart:function(){this._curve.areaStart()},areaEnd:function(){this._curve.areaEnd()},lineStart:function(){this._curve.lineStart()},
-lineEnd:function(){this._curve.lineEnd()},point:function(t,n){this._curve.point(n*Math.sin(t),n*-Math.cos(t))}};var bv={draw:function(t,n){var e=Math.sqrt(n/yv);t.moveTo(e,0),t.arc(0,0,e,0,mv)}},wv={draw:function(t,n){var e=Math.sqrt(n/5)/2;t.moveTo(-3*e,-e),t.lineTo(-e,-e),t.lineTo(-e,-3*e),t.lineTo(e,-3*e),t.lineTo(e,-e),t.lineTo(3*e,-e),t.lineTo(3*e,e),t.lineTo(e,e),t.lineTo(e,3*e),t.lineTo(-e,3*e),t.lineTo(-e,e),t.lineTo(-3*e,e),t.closePath()}},Mv=Math.sqrt(1/3),Tv=2*Mv,kv={draw:function(t,n){var e=Math.sqrt(n/Tv),r=e*Mv;t.moveTo(0,-e),t.lineTo(r,0),t.lineTo(0,e),t.lineTo(-r,0),t.closePath()}},Nv=.8908130915292852,Sv=Math.sin(yv/10)/Math.sin(7*yv/10),Av=Math.sin(mv/10)*Sv,Ev=-Math.cos(mv/10)*Sv,Cv={draw:function(t,n){var e=Math.sqrt(n*Nv),r=Av*e,i=Ev*e;t.moveTo(0,-e),t.lineTo(r,i);for(var o=1;o<5;++o){var u=mv*o/5,a=Math.cos(u),c=Math.sin(u);t.lineTo(c*e,-a*e),t.lineTo(a*r-c*i,c*r+a*i)}t.closePath()}},zv={draw:function(t,n){var e=Math.sqrt(n),r=-e/2;t.rect(r,r,e,e)}},Pv=Math.sqrt(3),qv={draw:function(t,n){var e=-Math.sqrt(n/(3*Pv));t.moveTo(0,2*e),t.lineTo(-Pv*e,-e),t.lineTo(Pv*e,-e),t.closePath()}},Lv=-.5,Rv=Math.sqrt(3)/2,Uv=1/Math.sqrt(12),Dv=3*(Uv/2+1),Ov={draw:function(t,n){var e=Math.sqrt(n/Dv),r=e/2,i=e*Uv,o=r,u=e*Uv+e,a=-o,c=u;t.moveTo(r,i),t.lineTo(o,u),t.lineTo(a,c),t.lineTo(Lv*r-Rv*i,Rv*r+Lv*i),t.lineTo(Lv*o-Rv*u,Rv*o+Lv*u),t.lineTo(Lv*a-Rv*c,Rv*a+Lv*c),t.lineTo(Lv*r+Rv*i,Lv*i-Rv*r),t.lineTo(Lv*o+Rv*u,Lv*u-Rv*o),t.lineTo(Lv*a+Rv*c,Lv*c-Rv*a),t.closePath()}},Fv=[bv,wv,kv,zv,Cv,qv,Ov];Sn.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=NaN,this._point=0},lineEnd:function(){switch(this._point){case 3:Nn(this,this._x1,this._y1);case 2:this._context.lineTo(this._x1,this._y1)}(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,n):this._context.moveTo(t,n);break;case 1:this._point=2;break;case 2:this._point=3,this._context.lineTo((5*this._x0+this._x1)/6,(5*this._y0+this._y1)/6);default:Nn(this,t,n)}this._x0=this._x1,this._x1=t,this._y0=this._y1,this._y1=n}},En.prototype={areaStart:kn,areaEnd:kn,lineStart:function(){this._x0=this._x1=this._x2=this._x3=this._x4=this._y0=this._y1=this._y2=this._y3=this._y4=NaN,this._point=0},lineEnd:function(){switch(this._point){case 1:this._context.moveTo(this._x2,this._y2),this._context.closePath();break;case 2:this._context.moveTo((this._x2+2*this._x3)/3,(this._y2+2*this._y3)/3),this._context.lineTo((this._x3+2*this._x2)/3,(this._y3+2*this._y2)/3),this._context.closePath();break;case 3:this.point(this._x2,this._y2),this.point(this._x3,this._y3),this.point(this._x4,this._y4)}},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1,this._x2=t,this._y2=n;break;case 1:this._point=2,this._x3=t,this._y3=n;break;case 2:this._point=3,this._x4=t,this._y4=n,this._context.moveTo((this._x0+4*this._x1+t)/6,(this._y0+4*this._y1+n)/6);break;default:Nn(this,t,n)}this._x0=this._x1,this._x1=t,this._y0=this._y1,this._y1=n}},zn.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=NaN,this._point=0},lineEnd:function(){(this._line||0!==this._line&&3===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1;break;case 1:this._point=2;break;case 2:this._point=3;var e=(this._x0+4*this._x1+t)/6,r=(this._y0+4*this._y1+n)/6;this._line?this._context.lineTo(e,r):this._context.moveTo(e,r);break;case 3:this._point=4;default:Nn(this,t,n)}this._x0=this._x1,this._x1=t,this._y0=this._y1,this._y1=n}},qn.prototype={lineStart:function(){this._x=[],this._y=[],this._basis.lineStart()},lineEnd:function(){var t=this._x,n=this._y,e=t.length-1;if(e>0)for(var r,i=t[0],o=n[0],u=t[e]-i,a=n[e]-o,c=-1;++c<=e;)r=c/e,this._basis.point(this._beta*t[c]+(1-this._beta)*(i+r*u),this._beta*n[c]+(1-this._beta)*(o+r*a));this._x=this._y=null,this._basis.lineEnd()},point:function(t,n){this._x.push(+t),this._y.push(+n)}};var Iv=function Tw(t){function n(n){return 1===t?new Sn(n):new qn(n,t)}return n.beta=function(t){return Tw(+t)},n}(.85);Rn.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._point=0},lineEnd:function(){switch(this._point){case 2:this._context.lineTo(this._x2,this._y2);break;case 3:Ln(this,this._x1,this._y1)}(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,n):this._context.moveTo(t,n);break;case 1:this._point=2,this._x1=t,this._y1=n;break;case 2:this._point=3;default:Ln(this,t,n)}this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=n}};var Yv=function kw(t){function n(n){return new Rn(n,t)}return n.tension=function(t){return kw(+t)},n}(0);Un.prototype={areaStart:kn,areaEnd:kn,lineStart:function(){this._x0=this._x1=this._x2=this._x3=this._x4=this._x5=this._y0=this._y1=this._y2=this._y3=this._y4=this._y5=NaN,this._point=0},lineEnd:function(){switch(this._point){case 1:this._context.moveTo(this._x3,this._y3),this._context.closePath();break;case 2:this._context.lineTo(this._x3,this._y3),this._context.closePath();break;case 3:this.point(this._x3,this._y3),this.point(this._x4,this._y4),this.point(this._x5,this._y5)}},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1,this._x3=t,this._y3=n;break;case 1:this._point=2,this._context.moveTo(this._x4=t,this._y4=n);break;case 2:this._point=3,this._x5=t,this._y5=n;break;default:Ln(this,t,n)}this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=n}};var Bv=function Nw(t){function n(n){return new Un(n,t)}return n.tension=function(t){return Nw(+t)},n}(0);Dn.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._point=0},lineEnd:function(){(this._line||0!==this._line&&3===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1;break;case 1:this._point=2;break;case 2:this._point=3,this._line?this._context.lineTo(this._x2,this._y2):this._context.moveTo(this._x2,this._y2);break;case 3:this._point=4;default:Ln(this,t,n)}this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=n}};var jv=function Sw(t){function n(n){return new Dn(n,t)}return n.tension=function(t){return Sw(+t)},n}(0);Fn.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._l01_a=this._l12_a=this._l23_a=this._l01_2a=this._l12_2a=this._l23_2a=this._point=0},lineEnd:function(){switch(this._point){case 2:this._context.lineTo(this._x2,this._y2);break;case 3:this.point(this,this._x2,this._y2)}(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){if(t=+t,n=+n,this._point){var e=this._x2-t,r=this._y2-n;this._l23_a=Math.sqrt(this._l23_2a=Math.pow(e*e+r*r,this._alpha))}switch(this._point){case 0:this._point=1,this._line?this._context.lineTo(t,n):this._context.moveTo(t,n);break;case 1:this._point=2;break;case 2:this._point=3;default:On(this,t,n)}this._l01_a=this._l12_a,this._l12_a=this._l23_a,this._l01_2a=this._l12_2a,this._l12_2a=this._l23_2a,this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=n}};var Hv=function Aw(t){function n(n){return t?new Fn(n,t):new Rn(n,0)}return n.alpha=function(t){return Aw(+t)},n}(.5);In.prototype={areaStart:kn,areaEnd:kn,lineStart:function(){this._x0=this._x1=this._x2=this._x3=this._x4=this._x5=this._y0=this._y1=this._y2=this._y3=this._y4=this._y5=NaN,this._l01_a=this._l12_a=this._l23_a=this._l01_2a=this._l12_2a=this._l23_2a=this._point=0},lineEnd:function(){switch(this._point){case 1:this._context.moveTo(this._x3,this._y3),this._context.closePath();break;case 2:this._context.lineTo(this._x3,this._y3),this._context.closePath();break;case 3:this.point(this._x3,this._y3),this.point(this._x4,this._y4),this.point(this._x5,this._y5)}},point:function(t,n){if(t=+t,n=+n,this._point){var e=this._x2-t,r=this._y2-n;this._l23_a=Math.sqrt(this._l23_2a=Math.pow(e*e+r*r,this._alpha))}switch(this._point){case 0:this._point=1,this._x3=t,this._y3=n;break;case 1:this._point=2,this._context.moveTo(this._x4=t,this._y4=n);break;case 2:this._point=3,this._x5=t,this._y5=n;break;default:On(this,t,n)}this._l01_a=this._l12_a,this._l12_a=this._l23_a,this._l01_2a=this._l12_2a,this._l12_2a=this._l23_2a,this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=n}};var Xv=function Ew(t){function n(n){return t?new In(n,t):new Un(n,0)}return n.alpha=function(t){return Ew(+t)},n}(.5);Yn.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._l01_a=this._l12_a=this._l23_a=this._l01_2a=this._l12_2a=this._l23_2a=this._point=0},lineEnd:function(){(this._line||0!==this._line&&3===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){if(t=+t,n=+n,this._point){var e=this._x2-t,r=this._y2-n;this._l23_a=Math.sqrt(this._l23_2a=Math.pow(e*e+r*r,this._alpha))}switch(this._point){case 0:this._point=1;break;case 1:this._point=2;break;case 2:this._point=3,this._line?this._context.lineTo(this._x2,this._y2):this._context.moveTo(this._x2,this._y2);break;case 3:this._point=4;default:On(this,t,n)}this._l01_a=this._l12_a,this._l12_a=this._l23_a,this._l01_2a=this._l12_2a,this._l12_2a=this._l23_2a,this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=n}};var Vv=function Cw(t){function n(n){return t?new Yn(n,t):new Dn(n,0)}return n.alpha=function(t){return Cw(+t)},n}(.5);Bn.prototype={areaStart:kn,areaEnd:kn,lineStart:function(){this._point=0},lineEnd:function(){this._point&&this._context.closePath()},point:function(t,n){t=+t,n=+n,this._point?this._context.lineTo(t,n):(this._point=1,this._context.moveTo(t,n))}},$n.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=this._t0=NaN,this._point=0},lineEnd:function(){switch(this._point){case 2:this._context.lineTo(this._x1,this._y1);break;case 3:Wn(this,this._t0,Vn(this,this._t0))}(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){var e=NaN;if(t=+t,n=+n,t!==this._x1||n!==this._y1){switch(this._point){case 0:this._point=1,this._line?this._context.lineTo(t,n):this._context.moveTo(t,n);break;case 1:this._point=2;break;case 2:this._point=3,Wn(this,Vn(this,e=Xn(this,t,n)),e);break;default:Wn(this,this._t0,e=Xn(this,t,n))}this._x0=this._x1,this._x1=t,this._y0=this._y1,this._y1=n,this._t0=e}}},(Zn.prototype=Object.create($n.prototype)).point=function(t,n){$n.prototype.point.call(this,n,t)},Gn.prototype={moveTo:function(t,n){this._context.moveTo(n,t)},closePath:function(){this._context.closePath()},lineTo:function(t,n){this._context.lineTo(n,t)},bezierCurveTo:function(t,n,e,r,i,o){this._context.bezierCurveTo(n,t,r,e,o,i)}},Kn.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x=[],this._y=[]},lineEnd:function(){var t=this._x,n=this._y,e=t.length;if(e)if(this._line?this._context.lineTo(t[0],n[0]):this._context.moveTo(t[0],n[0]),2===e)this._context.lineTo(t[1],n[1]);else for(var r=te(t),i=te(n),o=0,u=1;u<e;++o,++u)this._context.bezierCurveTo(r[0][o],i[0][o],r[1][o],i[1][o],t[u],n[u]);(this._line||0!==this._line&&1===e)&&this._context.closePath(),this._line=1-this._line,this._x=this._y=null},point:function(t,n){this._x.push(+t),this._y.push(+n)}},ee.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x=this._y=NaN,this._point=0},lineEnd:function(){0<this._t&&this._t<1&&2===this._point&&this._context.lineTo(this._x,this._y),(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line>=0&&(this._t=1-this._t,this._line=1-this._line)},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,n):this._context.moveTo(t,n);break;case 1:this._point=2;default:if(this._t<=0)this._context.lineTo(this._x,n),this._context.lineTo(t,n);else{var e=this._x*(1-this._t)+t*this._t;this._context.lineTo(e,this._y),this._context.lineTo(e,n)}}this._x=t,this._y=n}};var Wv=Array.prototype.slice,$v=.7,Zv=1/$v,Gv=/^#([0-9a-f]{3})$/,Jv=/^#([0-9a-f]{6})$/,Qv=/^rgb\(\s*([-+]?\d+)\s*,\s*([-+]?\d+)\s*,\s*([-+]?\d+)\s*\)$/,Kv=/^rgb\(\s*([-+]?\d+(?:\.\d+)?)%\s*,\s*([-+]?\d+(?:\.\d+)?)%\s*,\s*([-+]?\d+(?:\.\d+)?)%\s*\)$/,t_=/^rgba\(\s*([-+]?\d+)\s*,\s*([-+]?\d+)\s*,\s*([-+]?\d+)\s*,\s*([-+]?\d+(?:\.\d+)?)\s*\)$/,n_=/^rgba\(\s*([-+]?\d+(?:\.\d+)?)%\s*,\s*([-+]?\d+(?:\.\d+)?)%\s*,\s*([-+]?\d+(?:\.\d+)?)%\s*,\s*([-+]?\d+(?:\.\d+)?)\s*\)$/,e_=/^hsl\(\s*([-+]?\d+(?:\.\d+)?)\s*,\s*([-+]?\d+(?:\.\d+)?)%\s*,\s*([-+]?\d+(?:\.\d+)?)%\s*\)$/,r_=/^hsla\(\s*([-+]?\d+(?:\.\d+)?)\s*,\s*([-+]?\d+(?:\.\d+)?)%\s*,\s*([-+]?\d+(?:\.\d+)?)%\s*,\s*([-+]?\d+(?:\.\d+)?)\s*\)$/,i_={aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074};ge(xe,be,{displayable:function(){return this.rgb().displayable()},toString:function(){return this.rgb()+""}}),ge(Ne,ke,me(xe,{brighter:function(t){return t=null==t?Zv:Math.pow(Zv,t),new Ne(this.r*t,this.g*t,this.b*t,this.opacity)},darker:function(t){return t=null==t?$v:Math.pow($v,t),new Ne(this.r*t,this.g*t,this.b*t,this.opacity)},rgb:function(){return this},displayable:function(){return 0<=this.r&&this.r<=255&&0<=this.g&&this.g<=255&&0<=this.b&&this.b<=255&&0<=this.opacity&&this.opacity<=1},toString:function(){var t=this.opacity;return t=isNaN(t)?1:Math.max(0,Math.min(1,t)),(1===t?"rgb(":"rgba(")+Math.max(0,Math.min(255,Math.round(this.r)||0))+", "+Math.max(0,Math.min(255,Math.round(this.g)||0))+", "+Math.max(0,Math.min(255,Math.round(this.b)||0))+(1===t?")":", "+t+")")}})),ge(Ce,Ee,me(xe,{brighter:function(t){return t=null==t?Zv:Math.pow(Zv,t),new Ce(this.h,this.s,this.l*t,this.opacity)},darker:function(t){return t=null==t?$v:Math.pow($v,t),new Ce(this.h,this.s,this.l*t,this.opacity)},rgb:function(){var t=this.h%360+360*(this.h<0),n=isNaN(t)||isNaN(this.s)?0:this.s,e=this.l,r=e+(e<.5?e:1-e)*n,i=2*e-r;return new Ne(ze(t>=240?t-240:t+120,i,r),ze(t,i,r),ze(t<120?t+240:t-120,i,r),this.opacity)},displayable:function(){return(0<=this.s&&this.s<=1||isNaN(this.s))&&0<=this.l&&this.l<=1&&0<=this.opacity&&this.opacity<=1}}));var o_=Math.PI/180,u_=180/Math.PI,a_=18,c_=.95047,s_=1,f_=1.08883,l_=4/29,h_=6/29,p_=3*h_*h_,d_=h_*h_*h_;ge(Le,qe,me(xe,{brighter:function(t){return new Le(this.l+a_*(null==t?1:t),this.a,this.b,this.opacity)},darker:function(t){return new Le(this.l-a_*(null==t?1:t),this.a,this.b,this.opacity)},rgb:function(){var t=(this.l+16)/116,n=isNaN(this.a)?t:t+this.a/500,e=isNaN(this.b)?t:t-this.b/200;return t=s_*Ue(t),n=c_*Ue(n),e=f_*Ue(e),new Ne(De(3.2404542*n-1.5371385*t-.4985314*e),De(-.969266*n+1.8760108*t+.041556*e),De(.0556434*n-.2040259*t+1.0572252*e),this.opacity)}})),ge(Ye,Ie,me(xe,{brighter:function(t){return new Ye(this.h,this.c,this.l+a_*(null==t?1:t),this.opacity)},darker:function(t){return new Ye(this.h,this.c,this.l-a_*(null==t?1:t),this.opacity)},rgb:function(){return Pe(this).rgb()}}));var v_=-.14861,__=1.78277,y_=-.29227,g_=-.90649,m_=1.97294,x_=m_*g_,b_=m_*__,w_=__*y_-g_*v_;ge(He,je,me(xe,{brighter:function(t){return t=null==t?Zv:Math.pow(Zv,t),new He(this.h,this.s,this.l*t,this.opacity)},darker:function(t){return t=null==t?$v:Math.pow($v,t),new He(this.h,this.s,this.l*t,this.opacity)},rgb:function(){var t=isNaN(this.h)?0:(this.h+120)*o_,n=+this.l,e=isNaN(this.s)?0:this.s*n*(1-n),r=Math.cos(t),i=Math.sin(t);return new Ne(255*(n+e*(v_*r+__*i)),255*(n+e*(y_*r+g_*i)),255*(n+e*(m_*r)),this.opacity)}}));var M_,T_,k_,N_,S_=function zw(t){function n(t,n){var r=e((t=ke(t)).r,(n=ke(n)).r),i=e(t.g,n.g),o=e(t.b,n.b),u=e(t.opacity,n.opacity);return function(n){return t.r=r(n),t.g=i(n),t.b=o(n),t.opacity=u(n),t+""}}var e=Qe(t);return n.gamma=zw,n}(1),A_=tr(Ve),E_=tr(We),C_=/[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g,z_=new RegExp(C_.source,"g"),P_=180/Math.PI,q_={translateX:0,translateY:0,rotate:0,skewX:0,scaleX:1,scaleY:1},L_=pr(lr,"px, ","px)","deg)"),R_=pr(hr,", ",")",")"),U_=Math.SQRT2,D_=2,O_=4,F_=1e-12,I_=gr(Je),Y_=gr(Ke),B_=xr(Je),j_=xr(Ke),H_=br(Je),X_=br(Ke),V_={value:function(){}};Tr.prototype=Mr.prototype={constructor:Tr,on:function(t,n){var e,r=this._,i=kr(t+"",r),o=-1,u=i.length;{if(!(arguments.length<2)){if(null!=n&&"function"!=typeof n)throw new Error("invalid callback: "+n);for(;++o<u;)if(e=(t=i[o]).type)r[e]=Sr(r[e],t.name,n);else if(null==n)for(e in r)r[e]=Sr(r[e],t.name,null);return this}for(;++o<u;)if((e=(t=i[o]).type)&&(e=Nr(r[e],t.name)))return e}},copy:function(){var t={},n=this._;for(var e in n)t[e]=n[e].slice();return new Tr(t)},call:function(t,n){if((e=arguments.length-2)>0)for(var e,r,i=new Array(e),o=0;o<e;++o)i[o]=arguments[o+2];if(!this._.hasOwnProperty(t))throw new Error("unknown type: "+t);for(r=this._[t],o=0,e=r.length;o<e;++o)r[o].value.apply(n,i)},apply:function(t,n,e){if(!this._.hasOwnProperty(t))throw new Error("unknown type: "+t);for(var r=this._[t],i=0,o=r.length;i<o;++i)r[i].value.apply(n,e)}};var W_,$_,Z_=zr(","),G_=Z_.parse,J_=Z_.parseRows,Q_=Z_.format,K_=Z_.formatRows,ty=zr("\t"),ny=ty.parse,ey=ty.parseRows,ry=ty.format,iy=ty.formatRows,oy=Rr("text/html",function(t){return document.createRange().createContextualFragment(t.responseText)}),uy=Rr("application/json",function(t){return JSON.parse(t.responseText)}),ay=Rr("text/plain",function(t){return t.responseText}),cy=Rr("application/xml",function(t){var n=t.responseXML;if(!n)throw new Error("parse error");return n}),sy=Ur("text/csv",G_),fy=Ur("text/tab-separated-values",ny),ly=0,hy=0,py=0,dy=1e3,vy=0,_y=0,yy=0,gy="object"==typeof performance&&performance.now?performance:Date,my="function"==typeof requestAnimationFrame?gy===Date?function(t){requestAnimationFrame(function(){t(gy.now())})}:requestAnimationFrame:function(t){setTimeout(t,17)};Ir.prototype=Yr.prototype={constructor:Ir,restart:function(t,n,e){if("function"!=typeof t)throw new TypeError("callback is not a function");e=(null==e?Or():+e)+(null==n?0:+n),this._next||$_===this||($_?$_._next=this:W_=this,$_=this),this._call=t,this._time=e,Vr()},stop:function(){this._call&&(this._call=null,this._time=1/0,Vr())}};var xy=new Date,by=new Date,wy=Zr(function(){},function(t,n){t.setTime(+t+n)},function(t,n){return n-t});wy.every=function(t){return t=Math.floor(t),isFinite(t)&&t>0?t>1?Zr(function(n){n.setTime(Math.floor(n/t)*t)},function(n,e){n.setTime(+n+e*t)},function(n,e){return(e-n)/t}):wy:null};var My=wy.range,Ty=1e3,ky=6e4,Ny=36e5,Sy=864e5,Ay=6048e5,Ey=Zr(function(t){t.setTime(Math.floor(t/Ty)*Ty)},function(t,n){t.setTime(+t+n*Ty)},function(t,n){return(n-t)/Ty},function(t){return t.getUTCSeconds()}),Cy=Ey.range,zy=Zr(function(t){t.setTime(Math.floor(t/ky)*ky)},function(t,n){t.setTime(+t+n*ky)},function(t,n){return(n-t)/ky},function(t){return t.getMinutes()}),Py=zy.range,qy=Zr(function(t){var n=t.getTimezoneOffset()*ky%Ny;n<0&&(n+=Ny),t.setTime(Math.floor((+t-n)/Ny)*Ny+n)},function(t,n){t.setTime(+t+n*Ny)},function(t,n){return(n-t)/Ny},function(t){return t.getHours()}),Ly=qy.range,Ry=Zr(function(t){t.setHours(0,0,0,0)},function(t,n){t.setDate(t.getDate()+n)},function(t,n){return(n-t-(n.getTimezoneOffset()-t.getTimezoneOffset())*ky)/Sy},function(t){return t.getDate()-1}),Uy=Ry.range,Dy=Gr(0),Oy=Gr(1),Fy=Gr(2),Iy=Gr(3),Yy=Gr(4),By=Gr(5),jy=Gr(6),Hy=Dy.range,Xy=Oy.range,Vy=Fy.range,Wy=Iy.range,$y=Yy.range,Zy=By.range,Gy=jy.range,Jy=Zr(function(t){t.setDate(1),t.setHours(0,0,0,0)},function(t,n){t.setMonth(t.getMonth()+n)},function(t,n){return n.getMonth()-t.getMonth()+12*(n.getFullYear()-t.getFullYear())},function(t){return t.getMonth()}),Qy=Jy.range,Ky=Zr(function(t){t.setMonth(0,1),t.setHours(0,0,0,0)},function(t,n){t.setFullYear(t.getFullYear()+n)},function(t,n){return n.getFullYear()-t.getFullYear()},function(t){return t.getFullYear()});Ky.every=function(t){return isFinite(t=Math.floor(t))&&t>0?Zr(function(n){n.setFullYear(Math.floor(n.getFullYear()/t)*t),n.setMonth(0,1),n.setHours(0,0,0,0)},function(n,e){n.setFullYear(n.getFullYear()+e*t)}):null};var tg=Ky.range,ng=Zr(function(t){t.setUTCSeconds(0,0)},function(t,n){t.setTime(+t+n*ky)},function(t,n){return(n-t)/ky},function(t){return t.getUTCMinutes()}),eg=ng.range,rg=Zr(function(t){t.setUTCMinutes(0,0,0)},function(t,n){t.setTime(+t+n*Ny)},function(t,n){return(n-t)/Ny},function(t){return t.getUTCHours()}),ig=rg.range,og=Zr(function(t){t.setUTCHours(0,0,0,0)},function(t,n){t.setUTCDate(t.getUTCDate()+n)},function(t,n){return(n-t)/Sy},function(t){return t.getUTCDate()-1}),ug=og.range,ag=Jr(0),cg=Jr(1),sg=Jr(2),fg=Jr(3),lg=Jr(4),hg=Jr(5),pg=Jr(6),dg=ag.range,vg=cg.range,_g=sg.range,yg=fg.range,gg=lg.range,mg=hg.range,xg=pg.range,bg=Zr(function(t){t.setUTCDate(1),t.setUTCHours(0,0,0,0)},function(t,n){t.setUTCMonth(t.getUTCMonth()+n)},function(t,n){return n.getUTCMonth()-t.getUTCMonth()+12*(n.getUTCFullYear()-t.getUTCFullYear())},function(t){return t.getUTCMonth()}),wg=bg.range,Mg=Zr(function(t){t.setUTCMonth(0,1),t.setUTCHours(0,0,0,0)},function(t,n){t.setUTCFullYear(t.getUTCFullYear()+n)},function(t,n){return n.getUTCFullYear()-t.getUTCFullYear()},function(t){return t.getUTCFullYear()});Mg.every=function(t){return isFinite(t=Math.floor(t))&&t>0?Zr(function(n){n.setUTCFullYear(Math.floor(n.getUTCFullYear()/t)*t),n.setUTCMonth(0,1),n.setUTCHours(0,0,0,0)},function(n,e){n.setUTCFullYear(n.getUTCFullYear()+e*t)}):null};var Tg,kg=Mg.range,Ng={"":ni,"%":function(t,n){return(100*t).toFixed(n)},b:function(t){return Math.round(t).toString(2)},c:function(t){return t+""},d:function(t){return Math.round(t).toString(10)},e:function(t,n){return t.toExponential(n)},f:function(t,n){return t.toFixed(n)},g:function(t,n){return t.toPrecision(n)},o:function(t){return Math.round(t).toString(8)},p:function(t,n){return ri(100*t,n)},r:ri,s:ei,X:function(t){return Math.round(t).toString(16).toUpperCase()},x:function(t){return Math.round(t).toString(16)}},Sg=/^(?:(.)?([<>=^]))?([+\-\( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?([a-z%])?$/i;oi.prototype.toString=function(){return this.fill+this.align+this.sign+this.symbol+(this.zero?"0":"")+(null==this.width?"":Math.max(1,0|this.width))+(this.comma?",":"")+(null==this.precision?"":"."+Math.max(0,0|this.precision))+this.type};var Ag,Eg=["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"];t.format,t.formatPrefix,ci({decimal:".",thousands:",",grouping:[3],currency:["$",""]});var Cg,zg={"-":"",_:" ",0:"0"},Pg=/^\s*\d+/,qg=/^%/,Lg=/[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g;t.timeFormat,t.timeParse,t.utcFormat,t.utcParse,so({dateTime:"%x, %X",date:"%-m/%-d/%Y",time:"%-I:%M:%S %p",periods:["AM","PM"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]});var Rg="%Y-%m-%dT%H:%M:%S.%LZ",Ug=Date.prototype.toISOString?fo:t.utcFormat(Rg),Dg=+new Date("2000-01-01T00:00:00.000Z")?lo:t.utcParse(Rg),Og=Array.prototype,Fg=Og.map,Ig=Og.slice,Yg={name:"implicit"},Bg=[0,1],jg=1e3,Hg=60*jg,Xg=60*Hg,Vg=24*Xg,Wg=7*Vg,$g=30*Vg,Zg=365*Vg,Gg=Zo("1f77b4ff7f0e2ca02cd627289467bd8c564be377c27f7f7fbcbd2217becf"),Jg=Zo("393b795254a36b6ecf9c9ede6379398ca252b5cf6bcedb9c8c6d31bd9e39e7ba52e7cb94843c39ad494ad6616be7969c7b4173a55194ce6dbdde9ed6"),Qg=Zo("3182bd6baed69ecae1c6dbefe6550dfd8d3cfdae6bfdd0a231a35474c476a1d99bc7e9c0756bb19e9ac8bcbddcdadaeb636363969696bdbdbdd9d9d9"),Kg=Zo("1f77b4aec7e8ff7f0effbb782ca02c98df8ad62728ff98969467bdc5b0d58c564bc49c94e377c2f7b6d27f7f7fc7c7c7bcbd22dbdb8d17becf9edae5"),tm=X_(je(300,.5,0),je(-240,.5,1)),nm=X_(je(-100,.75,.35),je(80,1.5,.8)),em=X_(je(260,.75,.35),je(80,1.5,.8)),rm=je(),im=Jo(Zo("44015444025645045745055946075a46085c460a5d460b5e470d60470e6147106347116447136548146748166848176948186a481a6c481b6d481c6e481d6f481f70482071482173482374482475482576482677482878482979472a7a472c7a472d7b472e7c472f7d46307e46327e46337f463480453581453781453882443983443a83443b84433d84433e85423f854240864241864142874144874045884046883f47883f48893e49893e4a893e4c8a3d4d8a3d4e8a3c4f8a3c508b3b518b3b528b3a538b3a548c39558c39568c38588c38598c375a8c375b8d365c8d365d8d355e8d355f8d34608d34618d33628d33638d32648e32658e31668e31678e31688e30698e306a8e2f6b8e2f6c8e2e6d8e2e6e8e2e6f8e2d708e2d718e2c718e2c728e2c738e2b748e2b758e2a768e2a778e2a788e29798e297a8e297b8e287c8e287d8e277e8e277f8e27808e26818e26828e26828e25838e25848e25858e24868e24878e23888e23898e238a8d228b8d228c8d228d8d218e8d218f8d21908d21918c20928c20928c20938c1f948c1f958b1f968b1f978b1f988b1f998a1f9a8a1e9b8a1e9c891e9d891f9e891f9f881fa0881fa1881fa1871fa28720a38620a48621a58521a68522a78522a88423a98324aa8325ab8225ac8226ad8127ad8128ae8029af7f2ab07f2cb17e2db27d2eb37c2fb47c31b57b32b67a34b67935b77937b87838b9773aba763bbb753dbc743fbc7340bd7242be7144bf7046c06f48c16e4ac16d4cc26c4ec36b50c46a52c56954c56856c66758c7655ac8645cc8635ec96260ca6063cb5f65cb5e67cc5c69cd5b6ccd5a6ece5870cf5773d05675d05477d1537ad1517cd2507fd34e81d34d84d44b86d54989d5488bd6468ed64590d74393d74195d84098d83e9bd93c9dd93ba0da39a2da37a5db36a8db34aadc32addc30b0dd2fb2dd2db5de2bb8de29bade28bddf26c0df25c2df23c5e021c8e020cae11fcde11dd0e11cd2e21bd5e21ad8e219dae319dde318dfe318e2e418e5e419e7e419eae51aece51befe51cf1e51df4e61ef6e620f8e621fbe723fde725")),om=Jo(Zo("00000401000501010601010802010902020b02020d03030f03031204041405041606051806051a07061c08071e0907200a08220b09240c09260d0a290e0b2b100b2d110c2f120d31130d34140e36150e38160f3b180f3d19103f1a10421c10441d11471e114920114b21114e22115024125325125527125829115a2a115c2c115f2d11612f116331116533106734106936106b38106c390f6e3b0f703d0f713f0f72400f74420f75440f764510774710784910784a10794c117a4e117b4f127b51127c52137c54137d56147d57157e59157e5a167e5c167f5d177f5f187f601880621980641a80651a80671b80681c816a1c816b1d816d1d816e1e81701f81721f817320817521817621817822817922827b23827c23827e24828025828125818326818426818627818827818928818b29818c29818e2a81902a81912b81932b80942c80962c80982d80992d809b2e7f9c2e7f9e2f7fa02f7fa1307ea3307ea5317ea6317da8327daa337dab337cad347cae347bb0357bb2357bb3367ab5367ab73779b83779ba3878bc3978bd3977bf3a77c03a76c23b75c43c75c53c74c73d73c83e73ca3e72cc3f71cd4071cf4070d0416fd2426fd3436ed5446dd6456cd8456cd9466bdb476adc4869de4968df4a68e04c67e24d66e34e65e44f64e55064e75263e85362e95462ea5661eb5760ec5860ed5a5fee5b5eef5d5ef05f5ef1605df2625df2645cf3655cf4675cf4695cf56b5cf66c5cf66e5cf7705cf7725cf8745cf8765cf9785df9795df97b5dfa7d5efa7f5efa815ffb835ffb8560fb8761fc8961fc8a62fc8c63fc8e64fc9065fd9266fd9467fd9668fd9869fd9a6afd9b6bfe9d6cfe9f6dfea16efea36ffea571fea772fea973feaa74feac76feae77feb078feb27afeb47bfeb67cfeb77efeb97ffebb81febd82febf84fec185fec287fec488fec68afec88cfeca8dfecc8ffecd90fecf92fed194fed395fed597fed799fed89afdda9cfddc9efddea0fde0a1fde2a3fde3a5fde5a7fde7a9fde9aafdebacfcecaefceeb0fcf0b2fcf2b4fcf4b6fcf6b8fcf7b9fcf9bbfcfbbdfcfdbf")),um=Jo(Zo("00000401000501010601010802010a02020c02020e03021004031204031405041706041907051b08051d09061f0a07220b07240c08260d08290e092b10092d110a30120a32140b34150b37160b39180c3c190c3e1b0c411c0c431e0c451f0c48210c4a230c4c240c4f260c51280b53290b552b0b572d0b592f0a5b310a5c320a5e340a5f3609613809623909633b09643d09653e0966400a67420a68440a68450a69470b6a490b6a4a0c6b4c0c6b4d0d6c4f0d6c510e6c520e6d540f6d550f6d57106e59106e5a116e5c126e5d126e5f136e61136e62146e64156e65156e67166e69166e6a176e6c186e6d186e6f196e71196e721a6e741a6e751b6e771c6d781c6d7a1d6d7c1d6d7d1e6d7f1e6c801f6c82206c84206b85216b87216b88226a8a226a8c23698d23698f24699025689225689326679526679727669827669a28659b29649d29649f2a63a02a63a22b62a32c61a52c60a62d60a82e5fa92e5eab2f5ead305dae305cb0315bb1325ab3325ab43359b63458b73557b93556ba3655bc3754bd3853bf3952c03a51c13a50c33b4fc43c4ec63d4dc73e4cc83f4bca404acb4149cc4248ce4347cf4446d04545d24644d34743d44842d54a41d74b3fd84c3ed94d3dda4e3cdb503bdd513ade5238df5337e05536e15635e25734e35933e45a31e55c30e65d2fe75e2ee8602de9612bea632aeb6429eb6628ec6726ed6925ee6a24ef6c23ef6e21f06f20f1711ff1731df2741cf3761bf37819f47918f57b17f57d15f67e14f68013f78212f78410f8850ff8870ef8890cf98b0bf98c0af98e09fa9008fa9207fa9407fb9606fb9706fb9906fb9b06fb9d07fc9f07fca108fca309fca50afca60cfca80dfcaa0ffcac11fcae12fcb014fcb216fcb418fbb61afbb81dfbba1ffbbc21fbbe23fac026fac228fac42afac62df9c72ff9c932f9cb35f8cd37f8cf3af7d13df7d340f6d543f6d746f5d949f5db4cf4dd4ff4df53f4e156f3e35af3e55df2e661f2e865f2ea69f1ec6df1ed71f1ef75f1f179f2f27df2f482f3f586f3f68af4f88ef5f992f6fa96f8fb9af9fc9dfafda1fcffa4")),am=Jo(Zo("0d088710078813078916078a19068c1b068d1d068e20068f2206902406912605912805922a05932c05942e05952f059631059733059735049837049938049a3a049a3c049b3e049c3f049c41049d43039e44039e46039f48039f4903a04b03a14c02a14e02a25002a25102a35302a35502a45601a45801a45901a55b01a55c01a65e01a66001a66100a76300a76400a76600a76700a86900a86a00a86c00a86e00a86f00a87100a87201a87401a87501a87701a87801a87a02a87b02a87d03a87e03a88004a88104a78305a78405a78606a68707a68808a68a09a58b0aa58d0ba58e0ca48f0da4910ea3920fa39410a29511a19613a19814a099159f9a169f9c179e9d189d9e199da01a9ca11b9ba21d9aa31e9aa51f99a62098a72197a82296aa2395ab2494ac2694ad2793ae2892b02991b12a90b22b8fb32c8eb42e8db52f8cb6308bb7318ab83289ba3388bb3488bc3587bd3786be3885bf3984c03a83c13b82c23c81c33d80c43e7fc5407ec6417dc7427cc8437bc9447aca457acb4679cc4778cc4977cd4a76ce4b75cf4c74d04d73d14e72d24f71d35171d45270d5536fd5546ed6556dd7566cd8576bd9586ada5a6ada5b69db5c68dc5d67dd5e66de5f65de6164df6263e06363e16462e26561e26660e3685fe4695ee56a5de56b5de66c5ce76e5be76f5ae87059e97158e97257ea7457eb7556eb7655ec7754ed7953ed7a52ee7b51ef7c51ef7e50f07f4ff0804ef1814df1834cf2844bf3854bf3874af48849f48948f58b47f58c46f68d45f68f44f79044f79143f79342f89441f89540f9973ff9983ef99a3efa9b3dfa9c3cfa9e3bfb9f3afba139fba238fca338fca537fca636fca835fca934fdab33fdac33fdae32fdaf31fdb130fdb22ffdb42ffdb52efeb72dfeb82cfeba2cfebb2bfebd2afebe2afec029fdc229fdc328fdc527fdc627fdc827fdca26fdcb26fccd25fcce25fcd025fcd225fbd324fbd524fbd724fad824fada24f9dc24f9dd25f8df25f8e125f7e225f7e425f6e626f6e826f5e926f5eb27f4ed27f3ee27f3f027f2f227f1f426f1f525f0f724f0f921")),cm="http://www.w3.org/1999/xhtml",sm={
-svg:"http://www.w3.org/2000/svg",xhtml:cm,xlink:"http://www.w3.org/1999/xlink",xml:"http://www.w3.org/XML/1998/namespace",xmlns:"http://www.w3.org/2000/xmlns/"},fm=0;iu.prototype=ru.prototype={constructor:iu,get:function(t){for(var n=this._;!(n in t);)if(!(t=t.parentNode))return;return t[n]},set:function(t,n){return t[this._]=n},remove:function(t){return this._ in t&&delete t[this._]},toString:function(){return this._}};var lm=function(t){return function(){return this.matches(t)}};if("undefined"!=typeof document){var hm=document.documentElement;if(!hm.matches){var pm=hm.webkitMatchesSelector||hm.msMatchesSelector||hm.mozMatchesSelector||hm.oMatchesSelector;lm=function(t){return function(){return pm.call(this,t)}}}}var dm=lm,vm={};if(t.event=null,"undefined"!=typeof document){var _m=document.documentElement;"onmouseenter"in _m||(vm={mouseenter:"mouseover",mouseleave:"mouseout"})}Tu.prototype={constructor:Tu,appendChild:function(t){return this._parent.insertBefore(t,this._next)},insertBefore:function(t,n){return this._parent.insertBefore(t,n)},querySelector:function(t){return this._parent.querySelector(t)},querySelectorAll:function(t){return this._parent.querySelectorAll(t)}};var ym="$";ia.prototype={add:function(t){var n=this._names.indexOf(t);n<0&&(this._names.push(t),this._node.setAttribute("class",this._names.join(" ")))},remove:function(t){var n=this._names.indexOf(t);n>=0&&(this._names.splice(n,1),this._node.setAttribute("class",this._names.join(" ")))},contains:function(t){return this._names.indexOf(t)>=0}};var gm=[null];qa.prototype=La.prototype={constructor:qa,select:yu,selectAll:xu,filter:bu,data:Au,enter:Mu,exit:Eu,merge:Cu,order:zu,sort:Pu,call:Lu,nodes:Ru,node:Uu,size:Du,empty:Ou,each:Fu,attr:Vu,style:Ju,property:na,classed:fa,text:da,html:ga,raise:xa,lower:wa,append:Ma,insert:ka,remove:Sa,datum:Aa,on:fu,dispatch:Pa};var mm=Mr("start","end","interrupt"),xm=[],bm=0,wm=1,Mm=2,Tm=3,km=4,Nm=5,Sm=La.prototype.constructor,Am=0,Em=La.prototype;Uc.prototype=Dc.prototype={constructor:Uc,select:wc,selectAll:Mc,filter:vc,merge:_c,selection:Tc,transition:Rc,call:Em.call,nodes:Em.nodes,node:Em.node,size:Em.size,empty:Em.empty,each:Em.each,on:mc,attr:rc,attrTween:uc,style:Ec,styleTween:zc,text:Lc,remove:bc,tween:$a,delay:sc,duration:hc,ease:dc};var Cm={time:null,delay:0,duration:250,ease:et};La.prototype.interrupt=Xa,La.prototype.transition=Ic;var zm=[null],Pm=Array.prototype.slice,qm=1,Lm=2,Rm=3,Um=4,Dm=1e-6;ws.prototype=ys.prototype={constructor:ws,each:us,eachAfter:cs,eachBefore:as,sum:ss,sort:fs,path:ls,ancestors:ps,descendants:ds,leaves:vs,links:_s,copy:gs};var Om="$",Fm={depth:-1},Im={};of.prototype=Object.create(ws.prototype);var Ym=(1+Math.sqrt(5))/2,Bm=function Pw(t){function n(n,e,r,i,o){sf(t,n,e,r,i,o)}return n.ratio=function(t){return Pw((t=+t)>1?t:1)},n}(Ym),jm=function qw(t){function n(n,e,r,i,o){if((u=n._squarify)&&u.ratio===t)for(var u,a,c,s,f,l=-1,h=u.length,p=n.value;++l<h;){for(a=u[l],c=a.children,s=a.value=0,f=c.length;s<f;++s)a.value+=c[s].value;a.dice?Ws(a,e,r,i,r+=(o-r)*a.value/p):cf(a,e,r,e+=(i-e)*a.value/p,o),p-=a.value}else n._squarify=u=sf(t,n,e,r,i,o),u.ratio=t}return n.ratio=function(t){return qw((t=+t)>1?t:1)},n}(Ym),Hm=10,Xm=Math.PI*(3-Math.sqrt(5));Pf.prototype.on=function(){var t=this._.on.apply(this._,arguments);return t===this._?this:t},If.prototype={constructor:If,insert:function(t,n){var e,r,i;if(t){if(n.P=t,n.N=t.N,t.N&&(t.N.P=n),t.N=n,t.R){for(t=t.R;t.L;)t=t.L;t.L=n}else t.R=n;e=t}else this._?(t=Hf(this._),n.P=null,n.N=t,t.P=t.L=n,e=t):(n.P=n.N=null,this._=n,e=null);for(n.L=n.R=null,n.U=e,n.C=!0,t=n;e&&e.C;)r=e.U,e===r.L?(i=r.R,i&&i.C?(e.C=i.C=!1,r.C=!0,t=r):(t===e.R&&(Bf(this,e),t=e,e=t.U),e.C=!1,r.C=!0,jf(this,r))):(i=r.L,i&&i.C?(e.C=i.C=!1,r.C=!0,t=r):(t===e.L&&(jf(this,e),t=e,e=t.U),e.C=!1,r.C=!0,Bf(this,r))),e=t.U;this._.C=!1},remove:function(t){t.N&&(t.N.P=t.P),t.P&&(t.P.N=t.N),t.N=t.P=null;var n,e,r,i=t.U,o=t.L,u=t.R;if(e=o?u?Hf(u):o:u,i?i.L===t?i.L=e:i.R=e:this._=e,o&&u?(r=e.C,e.C=t.C,e.L=o,o.U=e,e!==u?(i=e.U,e.U=t.U,t=e.R,i.L=t,e.R=u,u.U=e):(e.U=i,i=e,t=e.R)):(r=t.C,t=e),t&&(t.U=i),!r){if(t&&t.C)return void(t.C=!1);do{if(t===this._)break;if(t===i.L){if(n=i.R,n.C&&(n.C=!1,i.C=!0,Bf(this,i),n=i.R),n.L&&n.L.C||n.R&&n.R.C){n.R&&n.R.C||(n.L.C=!1,n.C=!0,jf(this,n),n=i.R),n.C=i.C,i.C=n.R.C=!1,Bf(this,i),t=this._;break}}else if(n=i.L,n.C&&(n.C=!1,i.C=!0,jf(this,i),n=i.L),n.L&&n.L.C||n.R&&n.R.C){n.L&&n.L.C||(n.R.C=!1,n.C=!0,Bf(this,n),n=i.L),n.C=i.C,i.C=n.L.C=!1,jf(this,i),t=this._;break}n.C=!0,t=i,i=i.U}while(!t.C);t&&(t.C=!1)}}};var Vm,Wm,$m,Zm,Gm,Jm=[],Qm=[],Km=1e-6,tx=1e-12;vl.prototype={constructor:vl,polygons:function(){var t=this.edges;return this.cells.map(function(n){var e=n.halfedges.map(function(e){return Kf(n,t[e])});return e.data=n.site.data,e})},triangles:function(){var t=[],n=this.edges;return this.cells.forEach(function(e,r){for(var i,o=e.site,u=e.halfedges,a=-1,c=u.length,s=n[u[c-1]],f=s.left===o?s.right:s.left;++a<c;)i=f,s=n[u[a]],f=s.left===o?s.right:s.left,r<i.index&&r<f.index&&pl(o,i,f)<0&&t.push([o.data,i.data,f.data])}),t},links:function(){return this.edges.filter(function(t){return t.right}).map(function(t){return{source:t.left.data,target:t.right.data}})}},ml.prototype={constructor:ml,scale:function(t){return 1===t?this:new ml(this.k*t,this.x,this.y)},translate:function(t,n){return 0===t&0===n?this:new ml(this.k,this.x+this.k*t,this.y+this.k*n)},apply:function(t){return[t[0]*this.k+this.x,t[1]*this.k+this.y]},applyX:function(t){return t*this.k+this.x},applyY:function(t){return t*this.k+this.y},invert:function(t){return[(t[0]-this.x)/this.k,(t[1]-this.y)/this.k]},invertX:function(t){return(t-this.x)/this.k},invertY:function(t){return(t-this.y)/this.k},rescaleX:function(t){return t.copy().domain(t.range().map(this.invertX,this).map(t.invert,t))},rescaleY:function(t){return t.copy().domain(t.range().map(this.invertY,this).map(t.invert,t))},toString:function(){return"translate("+this.x+","+this.y+") scale("+this.k+")"}};var nx=new ml(1,0,0);xl.prototype=ml.prototype;var ex={name:"drag"},rx={name:"space"},ix={name:"handle"},ox={name:"center"},ux={name:"x",handles:["e","w"].map(zl),input:function(t,n){return t&&[[t[0],n[0][1]],[t[1],n[1][1]]]},output:function(t){return t&&[t[0][0],t[1][0]]}},ax={name:"y",handles:["n","s"].map(zl),input:function(t,n){return t&&[[n[0][0],t[0]],[n[1][0],t[1]]]},output:function(t){return t&&[t[0][1],t[1][1]]}},cx={name:"xy",handles:["n","e","s","w","nw","ne","se","sw"].map(zl),input:function(t){return t},output:function(t){return t}},sx={overlay:"crosshair",selection:"move",n:"ns-resize",e:"ew-resize",s:"ns-resize",w:"ew-resize",nw:"nwse-resize",ne:"nesw-resize",se:"nwse-resize",sw:"nesw-resize"},fx={e:"w",w:"e",nw:"ne",ne:"nw",se:"sw",sw:"se"},lx={n:"s",s:"n",nw:"sw",ne:"se",se:"ne",sw:"nw"},hx={overlay:1,selection:1,n:null,e:1,s:null,w:-1,nw:-1,ne:1,se:1,sw:-1},px={overlay:1,selection:1,n:-1,e:null,s:1,w:null,nw:-1,ne:-1,se:1,sw:1},dx=Math.cos,vx=Math.sin,_x=Math.PI,yx=_x/2,gx=2*_x,mx=Math.max,xx=Array.prototype.slice;Jl.prototype={constructor:Jl,reset:function(){this.s=this.t=0},add:function(t){Ql(nb,t,this.t),Ql(this,nb.s,this.s),this.s?this.t+=nb.t:this.s=nb.t},valueOf:function(){return this.s}};var bx,wx,Mx,Tx,kx,Nx,Sx,Ax,Ex,Cx,zx,Px,qx,Lx,Rx,Ux,Dx,Ox,Fx,Ix,Yx,Bx,jx,Hx,Xx,Vx,Wx,$x,Zx,Gx,Jx,Qx,Kx,tb,nb=new Jl,eb=1e-6,rb=1e-12,ib=Math.PI,ob=ib/2,ub=ib/4,ab=2*ib,cb=180/ib,sb=ib/180,fb=Math.abs,lb=Math.atan,hb=Math.atan2,pb=Math.cos,db=Math.ceil,vb=Math.exp,_b=Math.log,yb=Math.pow,gb=Math.sin,mb=Math.sign||function(t){return t>0?1:t<0?-1:0},xb=Math.sqrt,bb=Math.tan,wb={Feature:function(t,n){rh(t.geometry,n)},FeatureCollection:function(t,n){for(var e=t.features,r=-1,i=e.length;++r<i;)rh(e[r].geometry,n)}},Mb={Sphere:function(t,n){n.sphere()},Point:function(t,n){t=t.coordinates,n.point(t[0],t[1],t[2])},MultiPoint:function(t,n){for(var e=t.coordinates,r=-1,i=e.length;++r<i;)t=e[r],n.point(t[0],t[1],t[2])},LineString:function(t,n){ih(t.coordinates,n,0)},MultiLineString:function(t,n){for(var e=t.coordinates,r=-1,i=e.length;++r<i;)ih(e[r],n,0)},Polygon:function(t,n){oh(t.coordinates,n)},MultiPolygon:function(t,n){for(var e=t.coordinates,r=-1,i=e.length;++r<i;)oh(e[r],n)},GeometryCollection:function(t,n){for(var e=t.geometries,r=-1,i=e.length;++r<i;)rh(e[r],n)}},Tb={point:eh,lineStart:eh,lineEnd:eh,polygonStart:function(){bx.reset(),Tb.lineStart=ah,Tb.lineEnd=ch},polygonEnd:function(){var t=+bx;wx.add(t<0?ab+t:t),this.lineStart=this.lineEnd=this.point=eh},sphere:function(){wx.add(ab)}},kb={point:mh,lineStart:bh,lineEnd:wh,polygonStart:function(){kb.point=Mh,kb.lineStart=Th,kb.lineEnd=kh,Ux.reset(),Tb.polygonStart()},polygonEnd:function(){Tb.polygonEnd(),kb.point=mh,kb.lineStart=bh,kb.lineEnd=wh,bx<0?(Ax=-(Cx=180),Ex=-(zx=90)):Ux>eb?zx=90:Ux<-eb&&(Ex=-90),Ox[0]=Ax,Ox[1]=Cx}},Nb={sphere:eh,point:Ch,lineStart:Ph,lineEnd:Rh,polygonStart:function(){Nb.lineStart=Uh,Nb.lineEnd=Dh},polygonEnd:function(){Nb.lineStart=Ph,Nb.lineEnd=Rh}};jh.invert=jh;var Sb,Ab,Eb,Cb,zb,Pb,qb,Lb,Rb,Ub,Db,Ob,Fb=1e9,Ib=-Fb,Yb={sphere:eh,point:eh,lineStart:up,lineEnd:eh,polygonStart:eh,polygonEnd:eh},Bb=[null,null],jb={type:"LineString",coordinates:Bb},Hb=Gl(),Xb=Gl(),Vb={point:eh,lineStart:eh,lineEnd:eh,polygonStart:function(){Vb.lineStart=yp,Vb.lineEnd=xp},polygonEnd:function(){Vb.lineStart=Vb.lineEnd=Vb.point=eh,Hb.add(fb(Xb)),Xb.reset()},result:function(){var t=Hb/2;return Hb.reset(),t}},Wb=1/0,$b=Wb,Zb=-Wb,Gb=Zb,Jb={point:bp,lineStart:eh,lineEnd:eh,polygonStart:eh,polygonEnd:eh,result:function(){var t=[[Wb,$b],[Zb,Gb]];return Zb=Gb=-($b=Wb=1/0),t}},Qb=0,Kb=0,tw=0,nw=0,ew=0,rw=0,iw=0,ow=0,uw=0,aw={point:wp,lineStart:Mp,lineEnd:Np,polygonStart:function(){aw.lineStart=Sp,aw.lineEnd=Ap},polygonEnd:function(){aw.point=wp,aw.lineStart=Mp,aw.lineEnd=Np},result:function(){var t=uw?[iw/uw,ow/uw]:rw?[nw/rw,ew/rw]:tw?[Qb/tw,Kb/tw]:[NaN,NaN];return Qb=Kb=tw=nw=ew=rw=iw=ow=uw=0,t}},cw=Gl(),sw=Up(function(){return!0},Fp,Yp,[-ib,-ob]);Xp.prototype={point:function(t,n){this.stream.point(t,n)},sphere:function(){this.stream.sphere()},lineStart:function(){this.stream.lineStart()},lineEnd:function(){this.stream.lineEnd()},polygonStart:function(){this.stream.polygonStart()},polygonEnd:function(){this.stream.polygonEnd()}};var fw=16,lw=pb(30*sb),hw=Hp({point:function(t,n){this.stream.point(t*sb,n*sb)}}),pw=rd(function(t){return xb(2/(1+t))});pw.invert=id(function(t){return 2*th(t/2)});var dw=rd(function(t){return(t=Kl(t))&&t/gb(t)});dw.invert=id(function(t){return t}),ad.invert=function(t,n){return[t,2*lb(vb(n))-ob]},pd.invert=pd,yd.invert=id(lb),md.invert=id(th),bd.invert=id(function(t){return 2+lb(t)}),Md.invert=function(t,n){return[-n,2*lb(vb(t))-ob]},t.version=kd,t.bisect=Sd,t.bisectRight=Sd,t.bisectLeft=Ad,t.ascending=n,t.bisector=e,t.descending=i,t.deviation=a,t.extent=c,t.histogram=v,t.thresholdFreedmanDiaconis=y,t.thresholdScott=g,t.thresholdSturges=d,t.max=m,t.mean=x,t.median=b,t.merge=w,t.min=M,t.pairs=T,t.permute=k,t.quantile=_,t.range=l,t.scan=N,t.shuffle=S,t.sum=A,t.ticks=h,t.tickStep=p,t.transpose=E,t.variance=u,t.zip=z,t.entries=j,t.keys=Y,t.values=B,t.map=q,t.set=I,t.nest=L,t.randomUniform=H,t.randomNormal=X,t.randomLogNormal=V,t.randomBates=$,t.randomIrwinHall=W,t.randomExponential=Z,t.easeLinear=G,t.easeQuad=K,t.easeQuadIn=J,t.easeQuadOut=Q,t.easeQuadInOut=K,t.easeCubic=et,t.easeCubicIn=tt,t.easeCubicOut=nt,t.easeCubicInOut=et,t.easePoly=Id,t.easePolyIn=Od,t.easePolyOut=Fd,t.easePolyInOut=Id,t.easeSin=ot,t.easeSinIn=rt,t.easeSinOut=it,t.easeSinInOut=ot,t.easeExp=ct,t.easeExpIn=ut,t.easeExpOut=at,t.easeExpInOut=ct,t.easeCircle=lt,t.easeCircleIn=st,t.easeCircleOut=ft,t.easeCircleInOut=lt,t.easeBounce=pt,t.easeBounceIn=ht,t.easeBounceOut=pt,t.easeBounceInOut=dt,t.easeBack=ev,t.easeBackIn=tv,t.easeBackOut=nv,t.easeBackInOut=ev,t.easeElastic=av,t.easeElasticIn=uv,t.easeElasticOut=av,t.easeElasticInOut=cv,t.polygonArea=vt,t.polygonCentroid=_t,t.polygonHull=xt,t.polygonContains=bt,t.polygonLength=wt,t.path=Tt,t.quadtree=jt,t.queue=Qt,t.arc=sn,t.area=vn,t.line=dn,t.pie=gn,t.radialArea=Mn,t.radialLine=wn,t.symbol=Tn,t.symbols=Fv,t.symbolCircle=bv,t.symbolCross=wv,t.symbolDiamond=kv,t.symbolSquare=zv,t.symbolStar=Cv,t.symbolTriangle=qv,t.symbolWye=Ov,t.curveBasisClosed=Cn,t.curveBasisOpen=Pn,t.curveBasis=An,t.curveBundle=Iv,t.curveCardinalClosed=Bv,t.curveCardinalOpen=jv,t.curveCardinal=Yv,t.curveCatmullRomClosed=Xv,t.curveCatmullRomOpen=Vv,t.curveCatmullRom=Hv,t.curveLinearClosed=jn,t.curveLinear=ln,t.curveMonotoneX=Jn,t.curveMonotoneY=Qn,t.curveNatural=ne,t.curveStep=re,t.curveStepAfter=oe,t.curveStepBefore=ie,t.stack=se,t.stackOffsetExpand=fe,t.stackOffsetNone=ue,t.stackOffsetSilhouette=le,t.stackOffsetWiggle=he,t.stackOrderAscending=pe,t.stackOrderDescending=ve,t.stackOrderInsideOut=_e,t.stackOrderNone=ae,t.stackOrderReverse=ye,t.color=be,t.rgb=ke,t.hsl=Ee,t.lab=qe,t.hcl=Ie,t.cubehelix=je,t.interpolate=cr,t.interpolateArray=nr,t.interpolateDate=er,t.interpolateNumber=rr,t.interpolateObject=ir,t.interpolateRound=sr,t.interpolateString=ar,t.interpolateTransformCss=L_,t.interpolateTransformSvg=R_,t.interpolateZoom=yr,t.interpolateRgb=S_,t.interpolateRgbBasis=A_,t.interpolateRgbBasisClosed=E_,t.interpolateHsl=I_,t.interpolateHslLong=Y_,t.interpolateLab=mr,t.interpolateHcl=B_,t.interpolateHclLong=j_,t.interpolateCubehelix=H_,t.interpolateCubehelixLong=X_,t.interpolateBasis=Ve,t.interpolateBasisClosed=We,t.quantize=wr,t.dispatch=Mr,t.dsvFormat=zr,t.csvParse=G_,t.csvParseRows=J_,t.csvFormat=Q_,t.csvFormatRows=K_,t.tsvParse=ny,t.tsvParseRows=ey,t.tsvFormat=ry,t.tsvFormatRows=iy,t.request=Pr,t.html=oy,t.json=uy,t.text=ay,t.xml=cy,t.csv=sy,t.tsv=fy,t.now=Or,t.timer=Yr,t.timerFlush=Br,t.timeout=Wr,t.interval=$r,t.timeInterval=Zr,t.timeMillisecond=wy,t.timeMilliseconds=My,t.timeSecond=Ey,t.timeSeconds=Cy,t.timeMinute=zy,t.timeMinutes=Py,t.timeHour=qy,t.timeHours=Ly,t.timeDay=Ry,t.timeDays=Uy,t.timeWeek=Dy,t.timeWeeks=Hy,t.timeSunday=Dy,t.timeSundays=Hy,t.timeMonday=Oy,t.timeMondays=Xy,t.timeTuesday=Fy,t.timeTuesdays=Vy,t.timeWednesday=Iy,t.timeWednesdays=Wy,t.timeThursday=Yy,t.timeThursdays=$y,t.timeFriday=By,t.timeFridays=Zy,t.timeSaturday=jy,t.timeSaturdays=Gy,t.timeMonth=Jy,t.timeMonths=Qy,t.timeYear=Ky,t.timeYears=tg,t.utcMillisecond=wy,t.utcMilliseconds=My,t.utcSecond=Ey,t.utcSeconds=Cy,t.utcMinute=ng,t.utcMinutes=eg,t.utcHour=rg,t.utcHours=ig,t.utcDay=og,t.utcDays=ug,t.utcWeek=ag,t.utcWeeks=dg,t.utcSunday=ag,t.utcSundays=dg,t.utcMonday=cg,t.utcMondays=vg,t.utcTuesday=sg,t.utcTuesdays=_g,t.utcWednesday=fg,t.utcWednesdays=yg,t.utcThursday=lg,t.utcThursdays=gg,t.utcFriday=hg,t.utcFridays=mg,t.utcSaturday=pg,t.utcSaturdays=xg,t.utcMonth=bg,t.utcMonths=wg,t.utcYear=Mg,t.utcYears=kg,t.formatLocale=ai,t.formatDefaultLocale=ci,t.formatSpecifier=ii,t.precisionFixed=si,t.precisionPrefix=fi,t.precisionRound=li,t.isoFormat=Ug,t.isoParse=Dg,t.timeFormatLocale=vi,t.timeFormatDefaultLocale=so,t.scaleBand=po,t.scalePoint=_o,t.scaleIdentity=Eo,t.scaleLinear=Ao,t.scaleLog=Do,t.scaleOrdinal=ho,t.scaleImplicit=Yg,t.scalePow=Fo,t.scaleSqrt=Io,t.scaleQuantile=Yo,t.scaleQuantize=Bo,t.scaleThreshold=jo,t.scaleTime=Wo,t.scaleUtc=$o,t.schemeCategory10=Gg,t.schemeCategory20b=Jg,t.schemeCategory20c=Qg,t.schemeCategory20=Kg,t.scaleSequential=Qo,t.interpolateCubehelixDefault=tm,t.interpolateRainbow=Go,t.interpolateWarm=nm,t.interpolateCool=em,t.interpolateViridis=im,t.interpolateMagma=om,t.interpolateInferno=um,t.interpolatePlasma=am,t.creator=eu,t.customEvent=lu,t.local=ru,t.matcher=dm,t.mouse=du,t.namespace=Ko,t.namespaces=sm,t.select=Ra,t.selectAll=Ua,t.selection=La,t.selector=_u,t.selectorAll=mu,t.touch=Da,t.touches=Oa,t.window=Wu,t.active=Yc,t.interrupt=Ha,t.transition=Dc,t.axisTop=$c,t.axisRight=Zc,t.axisBottom=Gc,t.axisLeft=Jc,t.cluster=os,t.hierarchy=ys,t.pack=Bs,t.packSiblings=Us,t.packEnclose=ks,t.partition=$s,t.stratify=Js,t.tree=af,t.treemap=ff,t.treemapBinary=lf,t.treemapDice=Ws,t.treemapSlice=cf,t.treemapSliceDice=hf,t.treemapSquarify=Bm,t.treemapResquarify=jm,t.forceCenter=pf,t.forceCollide=gf,t.forceLink=xf,t.forceManyBody=Tf,t.forceSimulation=Mf,t.forceX=kf,t.forceY=Nf,t.drag=Uf,t.dragDisable=Ef,t.dragEnable=Cf,t.voronoi=_l,t.zoom=Nl,t.zoomIdentity=nx,t.zoomTransform=xl,t.brush=Fl,t.brushX=Dl,t.brushY=Ol,t.brushSelection=Ul,t.chord=Bl,t.ribbon=Zl,t.geoAlbers=td,t.geoAlbersUsa=ed,t.geoArea=lh,t.geoAzimuthalEqualArea=od,t.geoAzimuthalEqualAreaRaw=pw,t.geoAzimuthalEquidistant=ud,t.geoAzimuthalEquidistantRaw=dw,t.geoBounds=Eh,t.geoCentroid=Ih,t.geoCircle=Jh,t.geoClipExtent=op,t.geoConicConformal=hd,t.geoConicConformalRaw=ld,t.geoConicEqualArea=Kp,t.geoConicEqualAreaRaw=Qp,t.geoConicEquidistant=_d,t.geoConicEquidistantRaw=vd,t.geoDistance=lp,t.geoEquirectangular=dd,t.geoEquirectangularRaw=pd,t.geoGnomonic=gd,t.geoGnomonicRaw=yd,t.geoGraticule=dp,t.geoInterpolate=vp,t.geoLength=fp,t.geoMercator=cd,t.geoMercatorRaw=ad,t.geoOrthographic=xd,t.geoOrthographicRaw=md,t.geoPath=Lp,t.geoProjection=Zp,t.geoProjectionMutator=Gp,t.geoRotation=$h,t.geoStereographic=wd,t.geoStereographicRaw=bd,t.geoStream=uh,t.geoTransform=jp,t.geoTransverseMercator=Td,t.geoTransverseMercatorRaw=Md,Object.defineProperty(t,"__esModule",{value:!0})});
+!function(){function n(n){return null!=n&&!isNaN(n)}function t(n){return n.length}function e(n){for(var t=1;n*t%1;)t*=10;return t}function r(n,t){try{for(var e in t)Object.defineProperty(n.prototype,e,{value:t[e],enumerable:!1})}catch(r){n.prototype=t}}function u(){}function i(n){return aa+n in this}function o(n){return n=aa+n,n in this&&delete this[n]}function a(){var n=[];return this.forEach(function(t){n.push(t)}),n}function c(){var n=0;for(var t in this)t.charCodeAt(0)===ca&&++n;return n}function s(){for(var n in this)if(n.charCodeAt(0)===ca)return!1;return!0}function l(){}function f(n,t,e){return function(){var r=e.apply(t,arguments);return r===t?n:r}}function h(n,t){if(t in n)return t;t=t.charAt(0).toUpperCase()+t.substring(1);for(var e=0,r=sa.length;r>e;++e){var u=sa[e]+t;if(u in n)return u}}function g(){}function p(){}function v(n){function t(){for(var t,r=e,u=-1,i=r.length;++u<i;)(t=r[u].on)&&t.apply(this,arguments);return n}var e=[],r=new u;return t.on=function(t,u){var i,o=r.get(t);return arguments.length<2?o&&o.on:(o&&(o.on=null,e=e.slice(0,i=e.indexOf(o)).concat(e.slice(i+1)),r.remove(t)),u&&e.push(r.set(t,{on:u})),n)},t}function d(){Xo.event.preventDefault()}function m(){for(var n,t=Xo.event;n=t.sourceEvent;)t=n;return t}function y(n){for(var t=new p,e=0,r=arguments.length;++e<r;)t[arguments[e]]=v(t);return t.of=function(e,r){return function(u){try{var i=u.sourceEvent=Xo.event;u.target=n,Xo.event=u,t[u.type].apply(e,r)}finally{Xo.event=i}}},t}function x(n){return fa(n,da),n}function M(n){return"function"==typeof n?n:function(){return ha(n,this)}}function _(n){return"function"==typeof n?n:function(){return ga(n,this)}}function b(n,t){function e(){this.removeAttribute(n)}function r(){this.removeAttributeNS(n.space,n.local)}function u(){this.setAttribute(n,t)}function i(){this.setAttributeNS(n.space,n.local,t)}function o(){var e=t.apply(this,arguments);null==e?this.removeAttribute(n):this.setAttribute(n,e)}function a(){var e=t.apply(this,arguments);null==e?this.removeAttributeNS(n.space,n.local):this.setAttributeNS(n.space,n.local,e)}return n=Xo.ns.qualify(n),null==t?n.local?r:e:"function"==typeof t?n.local?a:o:n.local?i:u}function w(n){return n.trim().replace(/\s+/g," ")}function S(n){return new RegExp("(?:^|\\s+)"+Xo.requote(n)+"(?:\\s+|$)","g")}function k(n){return n.trim().split(/^|\s+/)}function E(n,t){function e(){for(var e=-1;++e<u;)n[e](this,t)}function r(){for(var e=-1,r=t.apply(this,arguments);++e<u;)n[e](this,r)}n=k(n).map(A);var u=n.length;return"function"==typeof t?r:e}function A(n){var t=S(n);return function(e,r){if(u=e.classList)return r?u.add(n):u.remove(n);var u=e.getAttribute("class")||"";r?(t.lastIndex=0,t.test(u)||e.setAttribute("class",w(u+" "+n))):e.setAttribute("class",w(u.replace(t," ")))}}function C(n,t,e){function r(){this.style.removeProperty(n)}function u(){this.style.setProperty(n,t,e)}function i(){var r=t.apply(this,arguments);null==r?this.style.removeProperty(n):this.style.setProperty(n,r,e)}return null==t?r:"function"==typeof t?i:u}function N(n,t){function e(){delete this[n]}function r(){this[n]=t}function u(){var e=t.apply(this,arguments);null==e?delete this[n]:this[n]=e}return null==t?e:"function"==typeof t?u:r}function L(n){return"function"==typeof n?n:(n=Xo.ns.qualify(n)).local?function(){return this.ownerDocument.createElementNS(n.space,n.local)}:function(){return this.ownerDocument.createElementNS(this.namespaceURI,n)}}function z(n){return{__data__:n}}function q(n){return function(){return va(this,n)}}function T(n){return arguments.length||(n=Xo.ascending),function(t,e){return t&&e?n(t.__data__,e.__data__):!t-!e}}function R(n,t){for(var e=0,r=n.length;r>e;e++)for(var u,i=n[e],o=0,a=i.length;a>o;o++)(u=i[o])&&t(u,o,e);return n}function D(n){return fa(n,ya),n}function P(n){var t,e;return function(r,u,i){var o,a=n[i].update,c=a.length;for(i!=e&&(e=i,t=0),u>=t&&(t=u+1);!(o=a[t])&&++t<c;);return o}}function U(){var n=this.__transition__;n&&++n.active}function j(n,t,e){function r(){var t=this[o];t&&(this.removeEventListener(n,t,t.$),delete this[o])}function u(){var u=c(t,Bo(arguments));r.call(this),this.addEventListener(n,this[o]=u,u.$=e),u._=t}function i(){var t,e=new RegExp("^__on([^.]+)"+Xo.requote(n)+"$");for(var r in this)if(t=r.match(e)){var u=this[r];this.removeEventListener(t[1],u,u.$),delete this[r]}}var o="__on"+n,a=n.indexOf("."),c=H;a>0&&(n=n.substring(0,a));var s=Ma.get(n);return s&&(n=s,c=F),a?t?u:r:t?g:i}function H(n,t){return function(e){var r=Xo.event;Xo.event=e,t[0]=this.__data__;try{n.apply(this,t)}finally{Xo.event=r}}}function F(n,t){var e=H(n,t);return function(n){var t=this,r=n.relatedTarget;r&&(r===t||8&r.compareDocumentPosition(t))||e.call(t,n)}}function O(){var n=".dragsuppress-"+ ++ba,t="click"+n,e=Xo.select(Go).on("touchmove"+n,d).on("dragstart"+n,d).on("selectstart"+n,d);if(_a){var r=Jo.style,u=r[_a];r[_a]="none"}return function(i){function o(){e.on(t,null)}e.on(n,null),_a&&(r[_a]=u),i&&(e.on(t,function(){d(),o()},!0),setTimeout(o,0))}}function Y(n,t){t.changedTouches&&(t=t.changedTouches[0]);var e=n.ownerSVGElement||n;if(e.createSVGPoint){var r=e.createSVGPoint();if(0>wa&&(Go.scrollX||Go.scrollY)){e=Xo.select("body").append("svg").style({position:"absolute",top:0,left:0,margin:0,padding:0,border:"none"},"important");var u=e[0][0].getScreenCTM();wa=!(u.f||u.e),e.remove()}return wa?(r.x=t.pageX,r.y=t.pageY):(r.x=t.clientX,r.y=t.clientY),r=r.matrixTransform(n.getScreenCTM().inverse()),[r.x,r.y]}var i=n.getBoundingClientRect();return[t.clientX-i.left-n.clientLeft,t.clientY-i.top-n.clientTop]}function I(n){return n>0?1:0>n?-1:0}function Z(n,t,e){return(t[0]-n[0])*(e[1]-n[1])-(t[1]-n[1])*(e[0]-n[0])}function V(n){return n>1?0:-1>n?Sa:Math.acos(n)}function X(n){return n>1?Ea:-1>n?-Ea:Math.asin(n)}function $(n){return((n=Math.exp(n))-1/n)/2}function B(n){return((n=Math.exp(n))+1/n)/2}function W(n){return((n=Math.exp(2*n))-1)/(n+1)}function J(n){return(n=Math.sin(n/2))*n}function G(){}function K(n,t,e){return new Q(n,t,e)}function Q(n,t,e){this.h=n,this.s=t,this.l=e}function nt(n,t,e){function r(n){return n>360?n-=360:0>n&&(n+=360),60>n?i+(o-i)*n/60:180>n?o:240>n?i+(o-i)*(240-n)/60:i}function u(n){return Math.round(255*r(n))}var i,o;return n=isNaN(n)?0:(n%=360)<0?n+360:n,t=isNaN(t)?0:0>t?0:t>1?1:t,e=0>e?0:e>1?1:e,o=.5>=e?e*(1+t):e+t-e*t,i=2*e-o,gt(u(n+120),u(n),u(n-120))}function tt(n,t,e){return new et(n,t,e)}function et(n,t,e){this.h=n,this.c=t,this.l=e}function rt(n,t,e){return isNaN(n)&&(n=0),isNaN(t)&&(t=0),ut(e,Math.cos(n*=Na)*t,Math.sin(n)*t)}function ut(n,t,e){return new it(n,t,e)}function it(n,t,e){this.l=n,this.a=t,this.b=e}function ot(n,t,e){var r=(n+16)/116,u=r+t/500,i=r-e/200;return u=ct(u)*Fa,r=ct(r)*Oa,i=ct(i)*Ya,gt(lt(3.2404542*u-1.5371385*r-.4985314*i),lt(-.969266*u+1.8760108*r+.041556*i),lt(.0556434*u-.2040259*r+1.0572252*i))}function at(n,t,e){return n>0?tt(Math.atan2(e,t)*La,Math.sqrt(t*t+e*e),n):tt(0/0,0/0,n)}function ct(n){return n>.206893034?n*n*n:(n-4/29)/7.787037}function st(n){return n>.008856?Math.pow(n,1/3):7.787037*n+4/29}function lt(n){return Math.round(255*(.00304>=n?12.92*n:1.055*Math.pow(n,1/2.4)-.055))}function ft(n){return gt(n>>16,255&n>>8,255&n)}function ht(n){return ft(n)+""}function gt(n,t,e){return new pt(n,t,e)}function pt(n,t,e){this.r=n,this.g=t,this.b=e}function vt(n){return 16>n?"0"+Math.max(0,n).toString(16):Math.min(255,n).toString(16)}function dt(n,t,e){var r,u,i,o=0,a=0,c=0;if(r=/([a-z]+)\((.*)\)/i.exec(n))switch(u=r[2].split(","),r[1]){case"hsl":return e(parseFloat(u[0]),parseFloat(u[1])/100,parseFloat(u[2])/100);case"rgb":return t(Mt(u[0]),Mt(u[1]),Mt(u[2]))}return(i=Va.get(n))?t(i.r,i.g,i.b):(null!=n&&"#"===n.charAt(0)&&(4===n.length?(o=n.charAt(1),o+=o,a=n.charAt(2),a+=a,c=n.charAt(3),c+=c):7===n.length&&(o=n.substring(1,3),a=n.substring(3,5),c=n.substring(5,7)),o=parseInt(o,16),a=parseInt(a,16),c=parseInt(c,16)),t(o,a,c))}function mt(n,t,e){var r,u,i=Math.min(n/=255,t/=255,e/=255),o=Math.max(n,t,e),a=o-i,c=(o+i)/2;return a?(u=.5>c?a/(o+i):a/(2-o-i),r=n==o?(t-e)/a+(e>t?6:0):t==o?(e-n)/a+2:(n-t)/a+4,r*=60):(r=0/0,u=c>0&&1>c?0:r),K(r,u,c)}function yt(n,t,e){n=xt(n),t=xt(t),e=xt(e);var r=st((.4124564*n+.3575761*t+.1804375*e)/Fa),u=st((.2126729*n+.7151522*t+.072175*e)/Oa),i=st((.0193339*n+.119192*t+.9503041*e)/Ya);return ut(116*u-16,500*(r-u),200*(u-i))}function xt(n){return(n/=255)<=.04045?n/12.92:Math.pow((n+.055)/1.055,2.4)}function Mt(n){var t=parseFloat(n);return"%"===n.charAt(n.length-1)?Math.round(2.55*t):t}function _t(n){return"function"==typeof n?n:function(){return n}}function bt(n){return n}function wt(n){return function(t,e,r){return 2===arguments.length&&"function"==typeof e&&(r=e,e=null),St(t,e,n,r)}}function St(n,t,e,r){function u(){var n,t=c.status;if(!t&&c.responseText||t>=200&&300>t||304===t){try{n=e.call(i,c)}catch(r){return o.error.call(i,r),void 0}o.load.call(i,n)}else o.error.call(i,c)}var i={},o=Xo.dispatch("beforesend","progress","load","error"),a={},c=new XMLHttpRequest,s=null;return!Go.XDomainRequest||"withCredentials"in c||!/^(http(s)?:)?\/\//.test(n)||(c=new XDomainRequest),"onload"in c?c.onload=c.onerror=u:c.onreadystatechange=function(){c.readyState>3&&u()},c.onprogress=function(n){var t=Xo.event;Xo.event=n;try{o.progress.call(i,c)}finally{Xo.event=t}},i.header=function(n,t){return n=(n+"").toLowerCase(),arguments.length<2?a[n]:(null==t?delete a[n]:a[n]=t+"",i)},i.mimeType=function(n){return arguments.length?(t=null==n?null:n+"",i):t},i.responseType=function(n){return arguments.length?(s=n,i):s},i.response=function(n){return e=n,i},["get","post"].forEach(function(n){i[n]=function(){return i.send.apply(i,[n].concat(Bo(arguments)))}}),i.send=function(e,r,u){if(2===arguments.length&&"function"==typeof r&&(u=r,r=null),c.open(e,n,!0),null==t||"accept"in a||(a.accept=t+",*/*"),c.setRequestHeader)for(var l in a)c.setRequestHeader(l,a[l]);return null!=t&&c.overrideMimeType&&c.overrideMimeType(t),null!=s&&(c.responseType=s),null!=u&&i.on("error",u).on("load",function(n){u(null,n)}),o.beforesend.call(i,c),c.send(null==r?null:r),i},i.abort=function(){return c.abort(),i},Xo.rebind(i,o,"on"),null==r?i:i.get(kt(r))}function kt(n){return 1===n.length?function(t,e){n(null==t?e:null)}:n}function Et(){var n=At(),t=Ct()-n;t>24?(isFinite(t)&&(clearTimeout(Wa),Wa=setTimeout(Et,t)),Ba=0):(Ba=1,Ga(Et))}function At(){var n=Date.now();for(Ja=Xa;Ja;)n>=Ja.t&&(Ja.f=Ja.c(n-Ja.t)),Ja=Ja.n;return n}function Ct(){for(var n,t=Xa,e=1/0;t;)t.f?t=n?n.n=t.n:Xa=t.n:(t.t<e&&(e=t.t),t=(n=t).n);return $a=n,e}function Nt(n,t){return t-(n?Math.ceil(Math.log(n)/Math.LN10):1)}function Lt(n,t){var e=Math.pow(10,3*oa(8-t));return{scale:t>8?function(n){return n/e}:function(n){return n*e},symbol:n}}function zt(n){var t=n.decimal,e=n.thousands,r=n.grouping,u=n.currency,i=r?function(n){for(var t=n.length,u=[],i=0,o=r[0];t>0&&o>0;)u.push(n.substring(t-=o,t+o)),o=r[i=(i+1)%r.length];return u.reverse().join(e)}:bt;return function(n){var e=Qa.exec(n),r=e[1]||" ",o=e[2]||">",a=e[3]||"",c=e[4]||"",s=e[5],l=+e[6],f=e[7],h=e[8],g=e[9],p=1,v="",d="",m=!1;switch(h&&(h=+h.substring(1)),(s||"0"===r&&"="===o)&&(s=r="0",o="=",f&&(l-=Math.floor((l-1)/4))),g){case"n":f=!0,g="g";break;case"%":p=100,d="%",g="f";break;case"p":p=100,d="%",g="r";break;case"b":case"o":case"x":case"X":"#"===c&&(v="0"+g.toLowerCase());case"c":case"d":m=!0,h=0;break;case"s":p=-1,g="r"}"$"===c&&(v=u[0],d=u[1]),"r"!=g||h||(g="g"),null!=h&&("g"==g?h=Math.max(1,Math.min(21,h)):("e"==g||"f"==g)&&(h=Math.max(0,Math.min(20,h)))),g=nc.get(g)||qt;var y=s&&f;return function(n){if(m&&n%1)return"";var e=0>n||0===n&&0>1/n?(n=-n,"-"):a;if(0>p){var u=Xo.formatPrefix(n,h);n=u.scale(n),d=u.symbol}else n*=p;n=g(n,h);var c=n.lastIndexOf("."),x=0>c?n:n.substring(0,c),M=0>c?"":t+n.substring(c+1);!s&&f&&(x=i(x));var _=v.length+x.length+M.length+(y?0:e.length),b=l>_?new Array(_=l-_+1).join(r):"";return y&&(x=i(b+x)),e+=v,n=x+M,("<"===o?e+n+b:">"===o?b+e+n:"^"===o?b.substring(0,_>>=1)+e+n+b.substring(_):e+(y?n:b+n))+d}}}function qt(n){return n+""}function Tt(){this._=new Date(arguments.length>1?Date.UTC.apply(this,arguments):arguments[0])}function Rt(n,t,e){function r(t){var e=n(t),r=i(e,1);return r-t>t-e?e:r}function u(e){return t(e=n(new ec(e-1)),1),e}function i(n,e){return t(n=new ec(+n),e),n}function o(n,r,i){var o=u(n),a=[];if(i>1)for(;r>o;)e(o)%i||a.push(new Date(+o)),t(o,1);else for(;r>o;)a.push(new Date(+o)),t(o,1);return a}function a(n,t,e){try{ec=Tt;var r=new Tt;return r._=n,o(r,t,e)}finally{ec=Date}}n.floor=n,n.round=r,n.ceil=u,n.offset=i,n.range=o;var c=n.utc=Dt(n);return c.floor=c,c.round=Dt(r),c.ceil=Dt(u),c.offset=Dt(i),c.range=a,n}function Dt(n){return function(t,e){try{ec=Tt;var r=new Tt;return r._=t,n(r,e)._}finally{ec=Date}}}function Pt(n){function t(n){function t(t){for(var e,u,i,o=[],a=-1,c=0;++a<r;)37===n.charCodeAt(a)&&(o.push(n.substring(c,a)),null!=(u=uc[e=n.charAt(++a)])&&(e=n.charAt(++a)),(i=C[e])&&(e=i(t,null==u?"e"===e?" ":"0":u)),o.push(e),c=a+1);return o.push(n.substring(c,a)),o.join("")}var r=n.length;return t.parse=function(t){var r={y:1900,m:0,d:1,H:0,M:0,S:0,L:0,Z:null},u=e(r,n,t,0);if(u!=t.length)return null;"p"in r&&(r.H=r.H%12+12*r.p);var i=null!=r.Z&&ec!==Tt,o=new(i?Tt:ec);return"j"in r?o.setFullYear(r.y,0,r.j):"w"in r&&("W"in r||"U"in r)?(o.setFullYear(r.y,0,1),o.setFullYear(r.y,0,"W"in r?(r.w+6)%7+7*r.W-(o.getDay()+5)%7:r.w+7*r.U-(o.getDay()+6)%7)):o.setFullYear(r.y,r.m,r.d),o.setHours(r.H+Math.floor(r.Z/100),r.M+r.Z%100,r.S,r.L),i?o._:o},t.toString=function(){return n},t}function e(n,t,e,r){for(var u,i,o,a=0,c=t.length,s=e.length;c>a;){if(r>=s)return-1;if(u=t.charCodeAt(a++),37===u){if(o=t.charAt(a++),i=N[o in uc?t.charAt(a++):o],!i||(r=i(n,e,r))<0)return-1}else if(u!=e.charCodeAt(r++))return-1}return r}function r(n,t,e){b.lastIndex=0;var r=b.exec(t.substring(e));return r?(n.w=w.get(r[0].toLowerCase()),e+r[0].length):-1}function u(n,t,e){M.lastIndex=0;var r=M.exec(t.substring(e));return r?(n.w=_.get(r[0].toLowerCase()),e+r[0].length):-1}function i(n,t,e){E.lastIndex=0;var r=E.exec(t.substring(e));return r?(n.m=A.get(r[0].toLowerCase()),e+r[0].length):-1}function o(n,t,e){S.lastIndex=0;var r=S.exec(t.substring(e));return r?(n.m=k.get(r[0].toLowerCase()),e+r[0].length):-1}function a(n,t,r){return e(n,C.c.toString(),t,r)}function c(n,t,r){return e(n,C.x.toString(),t,r)}function s(n,t,r){return e(n,C.X.toString(),t,r)}function l(n,t,e){var r=x.get(t.substring(e,e+=2).toLowerCase());return null==r?-1:(n.p=r,e)}var f=n.dateTime,h=n.date,g=n.time,p=n.periods,v=n.days,d=n.shortDays,m=n.months,y=n.shortMonths;t.utc=function(n){function e(n){try{ec=Tt;var t=new ec;return t._=n,r(t)}finally{ec=Date}}var r=t(n);return e.parse=function(n){try{ec=Tt;var t=r.parse(n);return t&&t._}finally{ec=Date}},e.toString=r.toString,e},t.multi=t.utc.multi=ee;var x=Xo.map(),M=jt(v),_=Ht(v),b=jt(d),w=Ht(d),S=jt(m),k=Ht(m),E=jt(y),A=Ht(y);p.forEach(function(n,t){x.set(n.toLowerCase(),t)});var C={a:function(n){return d[n.getDay()]},A:function(n){return v[n.getDay()]},b:function(n){return y[n.getMonth()]},B:function(n){return m[n.getMonth()]},c:t(f),d:function(n,t){return Ut(n.getDate(),t,2)},e:function(n,t){return Ut(n.getDate(),t,2)},H:function(n,t){return Ut(n.getHours(),t,2)},I:function(n,t){return Ut(n.getHours()%12||12,t,2)},j:function(n,t){return Ut(1+tc.dayOfYear(n),t,3)},L:function(n,t){return Ut(n.getMilliseconds(),t,3)},m:function(n,t){return Ut(n.getMonth()+1,t,2)},M:function(n,t){return Ut(n.getMinutes(),t,2)},p:function(n){return p[+(n.getHours()>=12)]},S:function(n,t){return Ut(n.getSeconds(),t,2)},U:function(n,t){return Ut(tc.sundayOfYear(n),t,2)},w:function(n){return n.getDay()},W:function(n,t){return Ut(tc.mondayOfYear(n),t,2)},x:t(h),X:t(g),y:function(n,t){return Ut(n.getFullYear()%100,t,2)},Y:function(n,t){return Ut(n.getFullYear()%1e4,t,4)},Z:ne,"%":function(){return"%"}},N={a:r,A:u,b:i,B:o,c:a,d:Bt,e:Bt,H:Jt,I:Jt,j:Wt,L:Qt,m:$t,M:Gt,p:l,S:Kt,U:Ot,w:Ft,W:Yt,x:c,X:s,y:Zt,Y:It,Z:Vt,"%":te};return t}function Ut(n,t,e){var r=0>n?"-":"",u=(r?-n:n)+"",i=u.length;return r+(e>i?new Array(e-i+1).join(t)+u:u)}function jt(n){return new RegExp("^(?:"+n.map(Xo.requote).join("|")+")","i")}function Ht(n){for(var t=new u,e=-1,r=n.length;++e<r;)t.set(n[e].toLowerCase(),e);return t}function Ft(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+1));return r?(n.w=+r[0],e+r[0].length):-1}function Ot(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e));return r?(n.U=+r[0],e+r[0].length):-1}function Yt(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e));return r?(n.W=+r[0],e+r[0].length):-1}function It(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+4));return r?(n.y=+r[0],e+r[0].length):-1}function Zt(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+2));return r?(n.y=Xt(+r[0]),e+r[0].length):-1}function Vt(n,t,e){return/^[+-]\d{4}$/.test(t=t.substring(e,e+5))?(n.Z=+t,e+5):-1}function Xt(n){return n+(n>68?1900:2e3)}function $t(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+2));return r?(n.m=r[0]-1,e+r[0].length):-1}function Bt(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+2));return r?(n.d=+r[0],e+r[0].length):-1}function Wt(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+3));return r?(n.j=+r[0],e+r[0].length):-1}function Jt(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+2));return r?(n.H=+r[0],e+r[0].length):-1}function Gt(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+2));return r?(n.M=+r[0],e+r[0].length):-1}function Kt(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+2));return r?(n.S=+r[0],e+r[0].length):-1}function Qt(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+3));return r?(n.L=+r[0],e+r[0].length):-1}function ne(n){var t=n.getTimezoneOffset(),e=t>0?"-":"+",r=~~(oa(t)/60),u=oa(t)%60;return e+Ut(r,"0",2)+Ut(u,"0",2)}function te(n,t,e){oc.lastIndex=0;var r=oc.exec(t.substring(e,e+1));return r?e+r[0].length:-1}function ee(n){for(var t=n.length,e=-1;++e<t;)n[e][0]=this(n[e][0]);return function(t){for(var e=0,r=n[e];!r[1](t);)r=n[++e];return r[0](t)}}function re(){}function ue(n,t,e){var r=e.s=n+t,u=r-n,i=r-u;e.t=n-i+(t-u)}function ie(n,t){n&&lc.hasOwnProperty(n.type)&&lc[n.type](n,t)}function oe(n,t,e){var r,u=-1,i=n.length-e;for(t.lineStart();++u<i;)r=n[u],t.point(r[0],r[1],r[2]);t.lineEnd()}function ae(n,t){var e=-1,r=n.length;for(t.polygonStart();++e<r;)oe(n[e],t,1);t.polygonEnd()}function ce(){function n(n,t){n*=Na,t=t*Na/2+Sa/4;var e=n-r,o=Math.cos(t),a=Math.sin(t),c=i*a,s=u*o+c*Math.cos(e),l=c*Math.sin(e);hc.add(Math.atan2(l,s)),r=n,u=o,i=a}var t,e,r,u,i;gc.point=function(o,a){gc.point=n,r=(t=o)*Na,u=Math.cos(a=(e=a)*Na/2+Sa/4),i=Math.sin(a)},gc.lineEnd=function(){n(t,e)}}function se(n){var t=n[0],e=n[1],r=Math.cos(e);return[r*Math.cos(t),r*Math.sin(t),Math.sin(e)]}function le(n,t){return n[0]*t[0]+n[1]*t[1]+n[2]*t[2]}function fe(n,t){return[n[1]*t[2]-n[2]*t[1],n[2]*t[0]-n[0]*t[2],n[0]*t[1]-n[1]*t[0]]}function he(n,t){n[0]+=t[0],n[1]+=t[1],n[2]+=t[2]}function ge(n,t){return[n[0]*t,n[1]*t,n[2]*t]}function pe(n){var t=Math.sqrt(n[0]*n[0]+n[1]*n[1]+n[2]*n[2]);n[0]/=t,n[1]/=t,n[2]/=t}function ve(n){return[Math.atan2(n[1],n[0]),X(n[2])]}function de(n,t){return oa(n[0]-t[0])<Aa&&oa(n[1]-t[1])<Aa}function me(n,t){n*=Na;var e=Math.cos(t*=Na);ye(e*Math.cos(n),e*Math.sin(n),Math.sin(t))}function ye(n,t,e){++pc,dc+=(n-dc)/pc,mc+=(t-mc)/pc,yc+=(e-yc)/pc}function xe(){function n(n,u){n*=Na;var i=Math.cos(u*=Na),o=i*Math.cos(n),a=i*Math.sin(n),c=Math.sin(u),s=Math.atan2(Math.sqrt((s=e*c-r*a)*s+(s=r*o-t*c)*s+(s=t*a-e*o)*s),t*o+e*a+r*c);vc+=s,xc+=s*(t+(t=o)),Mc+=s*(e+(e=a)),_c+=s*(r+(r=c)),ye(t,e,r)}var t,e,r;kc.point=function(u,i){u*=Na;var o=Math.cos(i*=Na);t=o*Math.cos(u),e=o*Math.sin(u),r=Math.sin(i),kc.point=n,ye(t,e,r)}}function Me(){kc.point=me}function _e(){function n(n,t){n*=Na;var e=Math.cos(t*=Na),o=e*Math.cos(n),a=e*Math.sin(n),c=Math.sin(t),s=u*c-i*a,l=i*o-r*c,f=r*a-u*o,h=Math.sqrt(s*s+l*l+f*f),g=r*o+u*a+i*c,p=h&&-V(g)/h,v=Math.atan2(h,g);bc+=p*s,wc+=p*l,Sc+=p*f,vc+=v,xc+=v*(r+(r=o)),Mc+=v*(u+(u=a)),_c+=v*(i+(i=c)),ye(r,u,i)}var t,e,r,u,i;kc.point=function(o,a){t=o,e=a,kc.point=n,o*=Na;var c=Math.cos(a*=Na);r=c*Math.cos(o),u=c*Math.sin(o),i=Math.sin(a),ye(r,u,i)},kc.lineEnd=function(){n(t,e),kc.lineEnd=Me,kc.point=me}}function be(){return!0}function we(n,t,e,r,u){var i=[],o=[];if(n.forEach(function(n){if(!((t=n.length-1)<=0)){var t,e=n[0],r=n[t];if(de(e,r)){u.lineStart();for(var a=0;t>a;++a)u.point((e=n[a])[0],e[1]);return u.lineEnd(),void 0}var c=new ke(e,n,null,!0),s=new ke(e,null,c,!1);c.o=s,i.push(c),o.push(s),c=new ke(r,n,null,!1),s=new ke(r,null,c,!0),c.o=s,i.push(c),o.push(s)}}),o.sort(t),Se(i),Se(o),i.length){for(var a=0,c=e,s=o.length;s>a;++a)o[a].e=c=!c;for(var l,f,h=i[0];;){for(var g=h,p=!0;g.v;)if((g=g.n)===h)return;l=g.z,u.lineStart();do{if(g.v=g.o.v=!0,g.e){if(p)for(var a=0,s=l.length;s>a;++a)u.point((f=l[a])[0],f[1]);else r(g.x,g.n.x,1,u);g=g.n}else{if(p){l=g.p.z;for(var a=l.length-1;a>=0;--a)u.point((f=l[a])[0],f[1])}else r(g.x,g.p.x,-1,u);g=g.p}g=g.o,l=g.z,p=!p}while(!g.v);u.lineEnd()}}}function Se(n){if(t=n.length){for(var t,e,r=0,u=n[0];++r<t;)u.n=e=n[r],e.p=u,u=e;u.n=e=n[0],e.p=u}}function ke(n,t,e,r){this.x=n,this.z=t,this.o=e,this.e=r,this.v=!1,this.n=this.p=null}function Ee(n,t,e,r){return function(u,i){function o(t,e){var r=u(t,e);n(t=r[0],e=r[1])&&i.point(t,e)}function a(n,t){var e=u(n,t);d.point(e[0],e[1])}function c(){y.point=a,d.lineStart()}function s(){y.point=o,d.lineEnd()}function l(n,t){v.push([n,t]);var e=u(n,t);M.point(e[0],e[1])}function f(){M.lineStart(),v=[]}function h(){l(v[0][0],v[0][1]),M.lineEnd();var n,t=M.clean(),e=x.buffer(),r=e.length;if(v.pop(),p.push(v),v=null,r){if(1&t){n=e[0];var u,r=n.length-1,o=-1;for(i.lineStart();++o<r;)i.point((u=n[o])[0],u[1]);return i.lineEnd(),void 0}r>1&&2&t&&e.push(e.pop().concat(e.shift())),g.push(e.filter(Ae))}}var g,p,v,d=t(i),m=u.invert(r[0],r[1]),y={point:o,lineStart:c,lineEnd:s,polygonStart:function(){y.point=l,y.lineStart=f,y.lineEnd=h,g=[],p=[],i.polygonStart()},polygonEnd:function(){y.point=o,y.lineStart=c,y.lineEnd=s,g=Xo.merge(g);var n=Le(m,p);g.length?we(g,Ne,n,e,i):n&&(i.lineStart(),e(null,null,1,i),i.lineEnd()),i.polygonEnd(),g=p=null},sphere:function(){i.polygonStart(),i.lineStart(),e(null,null,1,i),i.lineEnd(),i.polygonEnd()}},x=Ce(),M=t(x);return y}}function Ae(n){return n.length>1}function Ce(){var n,t=[];return{lineStart:function(){t.push(n=[])},point:function(t,e){n.push([t,e])},lineEnd:g,buffer:function(){var e=t;return t=[],n=null,e},rejoin:function(){t.length>1&&t.push(t.pop().concat(t.shift()))}}}function Ne(n,t){return((n=n.x)[0]<0?n[1]-Ea-Aa:Ea-n[1])-((t=t.x)[0]<0?t[1]-Ea-Aa:Ea-t[1])}function Le(n,t){var e=n[0],r=n[1],u=[Math.sin(e),-Math.cos(e),0],i=0,o=0;hc.reset();for(var a=0,c=t.length;c>a;++a){var s=t[a],l=s.length;if(l)for(var f=s[0],h=f[0],g=f[1]/2+Sa/4,p=Math.sin(g),v=Math.cos(g),d=1;;){d===l&&(d=0),n=s[d];var m=n[0],y=n[1]/2+Sa/4,x=Math.sin(y),M=Math.cos(y),_=m-h,b=oa(_)>Sa,w=p*x;if(hc.add(Math.atan2(w*Math.sin(_),v*M+w*Math.cos(_))),i+=b?_+(_>=0?ka:-ka):_,b^h>=e^m>=e){var S=fe(se(f),se(n));pe(S);var k=fe(u,S);pe(k);var E=(b^_>=0?-1:1)*X(k[2]);(r>E||r===E&&(S[0]||S[1]))&&(o+=b^_>=0?1:-1)}if(!d++)break;h=m,p=x,v=M,f=n}}return(-Aa>i||Aa>i&&0>hc)^1&o}function ze(n){var t,e=0/0,r=0/0,u=0/0;return{lineStart:function(){n.lineStart(),t=1},point:function(i,o){var a=i>0?Sa:-Sa,c=oa(i-e);oa(c-Sa)<Aa?(n.point(e,r=(r+o)/2>0?Ea:-Ea),n.point(u,r),n.lineEnd(),n.lineStart(),n.point(a,r),n.point(i,r),t=0):u!==a&&c>=Sa&&(oa(e-u)<Aa&&(e-=u*Aa),oa(i-a)<Aa&&(i-=a*Aa),r=qe(e,r,i,o),n.point(u,r),n.lineEnd(),n.lineStart(),n.point(a,r),t=0),n.point(e=i,r=o),u=a},lineEnd:function(){n.lineEnd(),e=r=0/0},clean:function(){return 2-t}}}function qe(n,t,e,r){var u,i,o=Math.sin(n-e);return oa(o)>Aa?Math.atan((Math.sin(t)*(i=Math.cos(r))*Math.sin(e)-Math.sin(r)*(u=Math.cos(t))*Math.sin(n))/(u*i*o)):(t+r)/2}function Te(n,t,e,r){var u;if(null==n)u=e*Ea,r.point(-Sa,u),r.point(0,u),r.point(Sa,u),r.point(Sa,0),r.point(Sa,-u),r.point(0,-u),r.point(-Sa,-u),r.point(-Sa,0),r.point(-Sa,u);else if(oa(n[0]-t[0])>Aa){var i=n[0]<t[0]?Sa:-Sa;u=e*i/2,r.point(-i,u),r.point(0,u),r.point(i,u)}else r.point(t[0],t[1])}function Re(n){function t(n,t){return Math.cos(n)*Math.cos(t)>i}function e(n){var e,i,c,s,l;return{lineStart:function(){s=c=!1,l=1},point:function(f,h){var g,p=[f,h],v=t(f,h),d=o?v?0:u(f,h):v?u(f+(0>f?Sa:-Sa),h):0;if(!e&&(s=c=v)&&n.lineStart(),v!==c&&(g=r(e,p),(de(e,g)||de(p,g))&&(p[0]+=Aa,p[1]+=Aa,v=t(p[0],p[1]))),v!==c)l=0,v?(n.lineStart(),g=r(p,e),n.point(g[0],g[1])):(g=r(e,p),n.point(g[0],g[1]),n.lineEnd()),e=g;else if(a&&e&&o^v){var m;d&i||!(m=r(p,e,!0))||(l=0,o?(n.lineStart(),n.point(m[0][0],m[0][1]),n.point(m[1][0],m[1][1]),n.lineEnd()):(n.point(m[1][0],m[1][1]),n.lineEnd(),n.lineStart(),n.point(m[0][0],m[0][1])))}!v||e&&de(e,p)||n.point(p[0],p[1]),e=p,c=v,i=d},lineEnd:function(){c&&n.lineEnd(),e=null},clean:function(){return l|(s&&c)<<1}}}function r(n,t,e){var r=se(n),u=se(t),o=[1,0,0],a=fe(r,u),c=le(a,a),s=a[0],l=c-s*s;if(!l)return!e&&n;var f=i*c/l,h=-i*s/l,g=fe(o,a),p=ge(o,f),v=ge(a,h);he(p,v);var d=g,m=le(p,d),y=le(d,d),x=m*m-y*(le(p,p)-1);if(!(0>x)){var M=Math.sqrt(x),_=ge(d,(-m-M)/y);if(he(_,p),_=ve(_),!e)return _;var b,w=n[0],S=t[0],k=n[1],E=t[1];w>S&&(b=w,w=S,S=b);var A=S-w,C=oa(A-Sa)<Aa,N=C||Aa>A;if(!C&&k>E&&(b=k,k=E,E=b),N?C?k+E>0^_[1]<(oa(_[0]-w)<Aa?k:E):k<=_[1]&&_[1]<=E:A>Sa^(w<=_[0]&&_[0]<=S)){var L=ge(d,(-m+M)/y);return he(L,p),[_,ve(L)]}}}function u(t,e){var r=o?n:Sa-n,u=0;return-r>t?u|=1:t>r&&(u|=2),-r>e?u|=4:e>r&&(u|=8),u}var i=Math.cos(n),o=i>0,a=oa(i)>Aa,c=cr(n,6*Na);return Ee(t,e,c,o?[0,-n]:[-Sa,n-Sa])}function De(n,t,e,r){return function(u){var i,o=u.a,a=u.b,c=o.x,s=o.y,l=a.x,f=a.y,h=0,g=1,p=l-c,v=f-s;if(i=n-c,p||!(i>0)){if(i/=p,0>p){if(h>i)return;g>i&&(g=i)}else if(p>0){if(i>g)return;i>h&&(h=i)}if(i=e-c,p||!(0>i)){if(i/=p,0>p){if(i>g)return;i>h&&(h=i)}else if(p>0){if(h>i)return;g>i&&(g=i)}if(i=t-s,v||!(i>0)){if(i/=v,0>v){if(h>i)return;g>i&&(g=i)}else if(v>0){if(i>g)return;i>h&&(h=i)}if(i=r-s,v||!(0>i)){if(i/=v,0>v){if(i>g)return;i>h&&(h=i)}else if(v>0){if(h>i)return;g>i&&(g=i)}return h>0&&(u.a={x:c+h*p,y:s+h*v}),1>g&&(u.b={x:c+g*p,y:s+g*v}),u}}}}}}function Pe(n,t,e,r){function u(r,u){return oa(r[0]-n)<Aa?u>0?0:3:oa(r[0]-e)<Aa?u>0?2:1:oa(r[1]-t)<Aa?u>0?1:0:u>0?3:2}function i(n,t){return o(n.x,t.x)}function o(n,t){var e=u(n,1),r=u(t,1);return e!==r?e-r:0===e?t[1]-n[1]:1===e?n[0]-t[0]:2===e?n[1]-t[1]:t[0]-n[0]}return function(a){function c(n){for(var t=0,e=d.length,r=n[1],u=0;e>u;++u)for(var i,o=1,a=d[u],c=a.length,s=a[0];c>o;++o)i=a[o],s[1]<=r?i[1]>r&&Z(s,i,n)>0&&++t:i[1]<=r&&Z(s,i,n)<0&&--t,s=i;return 0!==t}function s(i,a,c,s){var l=0,f=0;if(null==i||(l=u(i,c))!==(f=u(a,c))||o(i,a)<0^c>0){do s.point(0===l||3===l?n:e,l>1?r:t);while((l=(l+c+4)%4)!==f)}else s.point(a[0],a[1])}function l(u,i){return u>=n&&e>=u&&i>=t&&r>=i}function f(n,t){l(n,t)&&a.point(n,t)}function h(){N.point=p,d&&d.push(m=[]),S=!0,w=!1,_=b=0/0}function g(){v&&(p(y,x),M&&w&&A.rejoin(),v.push(A.buffer())),N.point=f,w&&a.lineEnd()}function p(n,t){n=Math.max(-Ac,Math.min(Ac,n)),t=Math.max(-Ac,Math.min(Ac,t));var e=l(n,t);if(d&&m.push([n,t]),S)y=n,x=t,M=e,S=!1,e&&(a.lineStart(),a.point(n,t));else if(e&&w)a.point(n,t);else{var r={a:{x:_,y:b},b:{x:n,y:t}};C(r)?(w||(a.lineStart(),a.point(r.a.x,r.a.y)),a.point(r.b.x,r.b.y),e||a.lineEnd(),k=!1):e&&(a.lineStart(),a.point(n,t),k=!1)}_=n,b=t,w=e}var v,d,m,y,x,M,_,b,w,S,k,E=a,A=Ce(),C=De(n,t,e,r),N={point:f,lineStart:h,lineEnd:g,polygonStart:function(){a=A,v=[],d=[],k=!0},polygonEnd:function(){a=E,v=Xo.merge(v);var t=c([n,r]),e=k&&t,u=v.length;(e||u)&&(a.polygonStart(),e&&(a.lineStart(),s(null,null,1,a),a.lineEnd()),u&&we(v,i,t,s,a),a.polygonEnd()),v=d=m=null}};return N}}function Ue(n,t){function e(e,r){return e=n(e,r),t(e[0],e[1])}return n.invert&&t.invert&&(e.invert=function(e,r){return e=t.invert(e,r),e&&n.invert(e[0],e[1])}),e}function je(n){var t=0,e=Sa/3,r=nr(n),u=r(t,e);return u.parallels=function(n){return arguments.length?r(t=n[0]*Sa/180,e=n[1]*Sa/180):[180*(t/Sa),180*(e/Sa)]},u}function He(n,t){function e(n,t){var e=Math.sqrt(i-2*u*Math.sin(t))/u;return[e*Math.sin(n*=u),o-e*Math.cos(n)]}var r=Math.sin(n),u=(r+Math.sin(t))/2,i=1+r*(2*u-r),o=Math.sqrt(i)/u;return e.invert=function(n,t){var e=o-t;return[Math.atan2(n,e)/u,X((i-(n*n+e*e)*u*u)/(2*u))]},e}function Fe(){function n(n,t){Nc+=u*n-r*t,r=n,u=t}var t,e,r,u;Rc.point=function(i,o){Rc.point=n,t=r=i,e=u=o},Rc.lineEnd=function(){n(t,e)}}function Oe(n,t){Lc>n&&(Lc=n),n>qc&&(qc=n),zc>t&&(zc=t),t>Tc&&(Tc=t)}function Ye(){function n(n,t){o.push("M",n,",",t,i)}function t(n,t){o.push("M",n,",",t),a.point=e}function e(n,t){o.push("L",n,",",t)}function r(){a.point=n}function u(){o.push("Z")}var i=Ie(4.5),o=[],a={point:n,lineStart:function(){a.point=t},lineEnd:r,polygonStart:function(){a.lineEnd=u},polygonEnd:function(){a.lineEnd=r,a.point=n},pointRadius:function(n){return i=Ie(n),a},result:function(){if(o.length){var n=o.join("");return o=[],n}}};return a}function Ie(n){return"m0,"+n+"a"+n+","+n+" 0 1,1 0,"+-2*n+"a"+n+","+n+" 0 1,1 0,"+2*n+"z"}function Ze(n,t){dc+=n,mc+=t,++yc}function Ve(){function n(n,r){var u=n-t,i=r-e,o=Math.sqrt(u*u+i*i);xc+=o*(t+n)/2,Mc+=o*(e+r)/2,_c+=o,Ze(t=n,e=r)}var t,e;Pc.point=function(r,u){Pc.point=n,Ze(t=r,e=u)}}function Xe(){Pc.point=Ze}function $e(){function n(n,t){var e=n-r,i=t-u,o=Math.sqrt(e*e+i*i);xc+=o*(r+n)/2,Mc+=o*(u+t)/2,_c+=o,o=u*n-r*t,bc+=o*(r+n),wc+=o*(u+t),Sc+=3*o,Ze(r=n,u=t)}var t,e,r,u;Pc.point=function(i,o){Pc.point=n,Ze(t=r=i,e=u=o)},Pc.lineEnd=function(){n(t,e)}}function Be(n){function t(t,e){n.moveTo(t,e),n.arc(t,e,o,0,ka)}function e(t,e){n.moveTo(t,e),a.point=r}function r(t,e){n.lineTo(t,e)}function u(){a.point=t}function i(){n.closePath()}var o=4.5,a={point:t,lineStart:function(){a.point=e},lineEnd:u,polygonStart:function(){a.lineEnd=i},polygonEnd:function(){a.lineEnd=u,a.point=t},pointRadius:function(n){return o=n,a},result:g};return a}function We(n){function t(n){return(a?r:e)(n)}function e(t){return Ke(t,function(e,r){e=n(e,r),t.point(e[0],e[1])})}function r(t){function e(e,r){e=n(e,r),t.point(e[0],e[1])}function r(){x=0/0,S.point=i,t.lineStart()}function i(e,r){var i=se([e,r]),o=n(e,r);u(x,M,y,_,b,w,x=o[0],M=o[1],y=e,_=i[0],b=i[1],w=i[2],a,t),t.point(x,M)}function o(){S.point=e,t.lineEnd()}function c(){r(),S.point=s,S.lineEnd=l}function s(n,t){i(f=n,h=t),g=x,p=M,v=_,d=b,m=w,S.point=i}function l(){u(x,M,y,_,b,w,g,p,f,v,d,m,a,t),S.lineEnd=o,o()}var f,h,g,p,v,d,m,y,x,M,_,b,w,S={point:e,lineStart:r,lineEnd:o,polygonStart:function(){t.polygonStart(),S.lineStart=c},polygonEnd:function(){t.polygonEnd(),S.lineStart=r}};return S}function u(t,e,r,a,c,s,l,f,h,g,p,v,d,m){var y=l-t,x=f-e,M=y*y+x*x;if(M>4*i&&d--){var _=a+g,b=c+p,w=s+v,S=Math.sqrt(_*_+b*b+w*w),k=Math.asin(w/=S),E=oa(oa(w)-1)<Aa||oa(r-h)<Aa?(r+h)/2:Math.atan2(b,_),A=n(E,k),C=A[0],N=A[1],L=C-t,z=N-e,q=x*L-y*z;(q*q/M>i||oa((y*L+x*z)/M-.5)>.3||o>a*g+c*p+s*v)&&(u(t,e,r,a,c,s,C,N,E,_/=S,b/=S,w,d,m),m.point(C,N),u(C,N,E,_,b,w,l,f,h,g,p,v,d,m))}}var i=.5,o=Math.cos(30*Na),a=16;return t.precision=function(n){return arguments.length?(a=(i=n*n)>0&&16,t):Math.sqrt(i)},t}function Je(n){var t=We(function(t,e){return n([t*La,e*La])});return function(n){return tr(t(n))}}function Ge(n){this.stream=n}function Ke(n,t){return{point:t,sphere:function(){n.sphere()},lineStart:function(){n.lineStart()},lineEnd:function(){n.lineEnd()},polygonStart:function(){n.polygonStart()},polygonEnd:function(){n.polygonEnd()}}}function Qe(n){return nr(function(){return n})()}function nr(n){function t(n){return n=a(n[0]*Na,n[1]*Na),[n[0]*h+c,s-n[1]*h]}function e(n){return n=a.invert((n[0]-c)/h,(s-n[1])/h),n&&[n[0]*La,n[1]*La]}function r(){a=Ue(o=ur(m,y,x),i);var n=i(v,d);return c=g-n[0]*h,s=p+n[1]*h,u()}function u(){return l&&(l.valid=!1,l=null),t}var i,o,a,c,s,l,f=We(function(n,t){return n=i(n,t),[n[0]*h+c,s-n[1]*h]}),h=150,g=480,p=250,v=0,d=0,m=0,y=0,x=0,M=Ec,_=bt,b=null,w=null;return t.stream=function(n){return l&&(l.valid=!1),l=tr(M(o,f(_(n)))),l.valid=!0,l},t.clipAngle=function(n){return arguments.length?(M=null==n?(b=n,Ec):Re((b=+n)*Na),u()):b
+},t.clipExtent=function(n){return arguments.length?(w=n,_=n?Pe(n[0][0],n[0][1],n[1][0],n[1][1]):bt,u()):w},t.scale=function(n){return arguments.length?(h=+n,r()):h},t.translate=function(n){return arguments.length?(g=+n[0],p=+n[1],r()):[g,p]},t.center=function(n){return arguments.length?(v=n[0]%360*Na,d=n[1]%360*Na,r()):[v*La,d*La]},t.rotate=function(n){return arguments.length?(m=n[0]%360*Na,y=n[1]%360*Na,x=n.length>2?n[2]%360*Na:0,r()):[m*La,y*La,x*La]},Xo.rebind(t,f,"precision"),function(){return i=n.apply(this,arguments),t.invert=i.invert&&e,r()}}function tr(n){return Ke(n,function(t,e){n.point(t*Na,e*Na)})}function er(n,t){return[n,t]}function rr(n,t){return[n>Sa?n-ka:-Sa>n?n+ka:n,t]}function ur(n,t,e){return n?t||e?Ue(or(n),ar(t,e)):or(n):t||e?ar(t,e):rr}function ir(n){return function(t,e){return t+=n,[t>Sa?t-ka:-Sa>t?t+ka:t,e]}}function or(n){var t=ir(n);return t.invert=ir(-n),t}function ar(n,t){function e(n,t){var e=Math.cos(t),a=Math.cos(n)*e,c=Math.sin(n)*e,s=Math.sin(t),l=s*r+a*u;return[Math.atan2(c*i-l*o,a*r-s*u),X(l*i+c*o)]}var r=Math.cos(n),u=Math.sin(n),i=Math.cos(t),o=Math.sin(t);return e.invert=function(n,t){var e=Math.cos(t),a=Math.cos(n)*e,c=Math.sin(n)*e,s=Math.sin(t),l=s*i-c*o;return[Math.atan2(c*i+s*o,a*r+l*u),X(l*r-a*u)]},e}function cr(n,t){var e=Math.cos(n),r=Math.sin(n);return function(u,i,o,a){var c=o*t;null!=u?(u=sr(e,u),i=sr(e,i),(o>0?i>u:u>i)&&(u+=o*ka)):(u=n+o*ka,i=n-.5*c);for(var s,l=u;o>0?l>i:i>l;l-=c)a.point((s=ve([e,-r*Math.cos(l),-r*Math.sin(l)]))[0],s[1])}}function sr(n,t){var e=se(t);e[0]-=n,pe(e);var r=V(-e[1]);return((-e[2]<0?-r:r)+2*Math.PI-Aa)%(2*Math.PI)}function lr(n,t,e){var r=Xo.range(n,t-Aa,e).concat(t);return function(n){return r.map(function(t){return[n,t]})}}function fr(n,t,e){var r=Xo.range(n,t-Aa,e).concat(t);return function(n){return r.map(function(t){return[t,n]})}}function hr(n){return n.source}function gr(n){return n.target}function pr(n,t,e,r){var u=Math.cos(t),i=Math.sin(t),o=Math.cos(r),a=Math.sin(r),c=u*Math.cos(n),s=u*Math.sin(n),l=o*Math.cos(e),f=o*Math.sin(e),h=2*Math.asin(Math.sqrt(J(r-t)+u*o*J(e-n))),g=1/Math.sin(h),p=h?function(n){var t=Math.sin(n*=h)*g,e=Math.sin(h-n)*g,r=e*c+t*l,u=e*s+t*f,o=e*i+t*a;return[Math.atan2(u,r)*La,Math.atan2(o,Math.sqrt(r*r+u*u))*La]}:function(){return[n*La,t*La]};return p.distance=h,p}function vr(){function n(n,u){var i=Math.sin(u*=Na),o=Math.cos(u),a=oa((n*=Na)-t),c=Math.cos(a);Uc+=Math.atan2(Math.sqrt((a=o*Math.sin(a))*a+(a=r*i-e*o*c)*a),e*i+r*o*c),t=n,e=i,r=o}var t,e,r;jc.point=function(u,i){t=u*Na,e=Math.sin(i*=Na),r=Math.cos(i),jc.point=n},jc.lineEnd=function(){jc.point=jc.lineEnd=g}}function dr(n,t){function e(t,e){var r=Math.cos(t),u=Math.cos(e),i=n(r*u);return[i*u*Math.sin(t),i*Math.sin(e)]}return e.invert=function(n,e){var r=Math.sqrt(n*n+e*e),u=t(r),i=Math.sin(u),o=Math.cos(u);return[Math.atan2(n*i,r*o),Math.asin(r&&e*i/r)]},e}function mr(n,t){function e(n,t){var e=oa(oa(t)-Ea)<Aa?0:o/Math.pow(u(t),i);return[e*Math.sin(i*n),o-e*Math.cos(i*n)]}var r=Math.cos(n),u=function(n){return Math.tan(Sa/4+n/2)},i=n===t?Math.sin(n):Math.log(r/Math.cos(t))/Math.log(u(t)/u(n)),o=r*Math.pow(u(n),i)/i;return i?(e.invert=function(n,t){var e=o-t,r=I(i)*Math.sqrt(n*n+e*e);return[Math.atan2(n,e)/i,2*Math.atan(Math.pow(o/r,1/i))-Ea]},e):xr}function yr(n,t){function e(n,t){var e=i-t;return[e*Math.sin(u*n),i-e*Math.cos(u*n)]}var r=Math.cos(n),u=n===t?Math.sin(n):(r-Math.cos(t))/(t-n),i=r/u+n;return oa(u)<Aa?er:(e.invert=function(n,t){var e=i-t;return[Math.atan2(n,e)/u,i-I(u)*Math.sqrt(n*n+e*e)]},e)}function xr(n,t){return[n,Math.log(Math.tan(Sa/4+t/2))]}function Mr(n){var t,e=Qe(n),r=e.scale,u=e.translate,i=e.clipExtent;return e.scale=function(){var n=r.apply(e,arguments);return n===e?t?e.clipExtent(null):e:n},e.translate=function(){var n=u.apply(e,arguments);return n===e?t?e.clipExtent(null):e:n},e.clipExtent=function(n){var o=i.apply(e,arguments);if(o===e){if(t=null==n){var a=Sa*r(),c=u();i([[c[0]-a,c[1]-a],[c[0]+a,c[1]+a]])}}else t&&(o=null);return o},e.clipExtent(null)}function _r(n,t){return[Math.log(Math.tan(Sa/4+t/2)),-n]}function br(n){return n[0]}function wr(n){return n[1]}function Sr(n){for(var t=n.length,e=[0,1],r=2,u=2;t>u;u++){for(;r>1&&Z(n[e[r-2]],n[e[r-1]],n[u])<=0;)--r;e[r++]=u}return e.slice(0,r)}function kr(n,t){return n[0]-t[0]||n[1]-t[1]}function Er(n,t,e){return(e[0]-t[0])*(n[1]-t[1])<(e[1]-t[1])*(n[0]-t[0])}function Ar(n,t,e,r){var u=n[0],i=e[0],o=t[0]-u,a=r[0]-i,c=n[1],s=e[1],l=t[1]-c,f=r[1]-s,h=(a*(c-s)-f*(u-i))/(f*o-a*l);return[u+h*o,c+h*l]}function Cr(n){var t=n[0],e=n[n.length-1];return!(t[0]-e[0]||t[1]-e[1])}function Nr(){Jr(this),this.edge=this.site=this.circle=null}function Lr(n){var t=Jc.pop()||new Nr;return t.site=n,t}function zr(n){Or(n),$c.remove(n),Jc.push(n),Jr(n)}function qr(n){var t=n.circle,e=t.x,r=t.cy,u={x:e,y:r},i=n.P,o=n.N,a=[n];zr(n);for(var c=i;c.circle&&oa(e-c.circle.x)<Aa&&oa(r-c.circle.cy)<Aa;)i=c.P,a.unshift(c),zr(c),c=i;a.unshift(c),Or(c);for(var s=o;s.circle&&oa(e-s.circle.x)<Aa&&oa(r-s.circle.cy)<Aa;)o=s.N,a.push(s),zr(s),s=o;a.push(s),Or(s);var l,f=a.length;for(l=1;f>l;++l)s=a[l],c=a[l-1],$r(s.edge,c.site,s.site,u);c=a[0],s=a[f-1],s.edge=Vr(c.site,s.site,null,u),Fr(c),Fr(s)}function Tr(n){for(var t,e,r,u,i=n.x,o=n.y,a=$c._;a;)if(r=Rr(a,o)-i,r>Aa)a=a.L;else{if(u=i-Dr(a,o),!(u>Aa)){r>-Aa?(t=a.P,e=a):u>-Aa?(t=a,e=a.N):t=e=a;break}if(!a.R){t=a;break}a=a.R}var c=Lr(n);if($c.insert(t,c),t||e){if(t===e)return Or(t),e=Lr(t.site),$c.insert(c,e),c.edge=e.edge=Vr(t.site,c.site),Fr(t),Fr(e),void 0;if(!e)return c.edge=Vr(t.site,c.site),void 0;Or(t),Or(e);var s=t.site,l=s.x,f=s.y,h=n.x-l,g=n.y-f,p=e.site,v=p.x-l,d=p.y-f,m=2*(h*d-g*v),y=h*h+g*g,x=v*v+d*d,M={x:(d*y-g*x)/m+l,y:(h*x-v*y)/m+f};$r(e.edge,s,p,M),c.edge=Vr(s,n,null,M),e.edge=Vr(n,p,null,M),Fr(t),Fr(e)}}function Rr(n,t){var e=n.site,r=e.x,u=e.y,i=u-t;if(!i)return r;var o=n.P;if(!o)return-1/0;e=o.site;var a=e.x,c=e.y,s=c-t;if(!s)return a;var l=a-r,f=1/i-1/s,h=l/s;return f?(-h+Math.sqrt(h*h-2*f*(l*l/(-2*s)-c+s/2+u-i/2)))/f+r:(r+a)/2}function Dr(n,t){var e=n.N;if(e)return Rr(e,t);var r=n.site;return r.y===t?r.x:1/0}function Pr(n){this.site=n,this.edges=[]}function Ur(n){for(var t,e,r,u,i,o,a,c,s,l,f=n[0][0],h=n[1][0],g=n[0][1],p=n[1][1],v=Xc,d=v.length;d--;)if(i=v[d],i&&i.prepare())for(a=i.edges,c=a.length,o=0;c>o;)l=a[o].end(),r=l.x,u=l.y,s=a[++o%c].start(),t=s.x,e=s.y,(oa(r-t)>Aa||oa(u-e)>Aa)&&(a.splice(o,0,new Br(Xr(i.site,l,oa(r-f)<Aa&&p-u>Aa?{x:f,y:oa(t-f)<Aa?e:p}:oa(u-p)<Aa&&h-r>Aa?{x:oa(e-p)<Aa?t:h,y:p}:oa(r-h)<Aa&&u-g>Aa?{x:h,y:oa(t-h)<Aa?e:g}:oa(u-g)<Aa&&r-f>Aa?{x:oa(e-g)<Aa?t:f,y:g}:null),i.site,null)),++c)}function jr(n,t){return t.angle-n.angle}function Hr(){Jr(this),this.x=this.y=this.arc=this.site=this.cy=null}function Fr(n){var t=n.P,e=n.N;if(t&&e){var r=t.site,u=n.site,i=e.site;if(r!==i){var o=u.x,a=u.y,c=r.x-o,s=r.y-a,l=i.x-o,f=i.y-a,h=2*(c*f-s*l);if(!(h>=-Ca)){var g=c*c+s*s,p=l*l+f*f,v=(f*g-s*p)/h,d=(c*p-l*g)/h,f=d+a,m=Gc.pop()||new Hr;m.arc=n,m.site=u,m.x=v+o,m.y=f+Math.sqrt(v*v+d*d),m.cy=f,n.circle=m;for(var y=null,x=Wc._;x;)if(m.y<x.y||m.y===x.y&&m.x<=x.x){if(!x.L){y=x.P;break}x=x.L}else{if(!x.R){y=x;break}x=x.R}Wc.insert(y,m),y||(Bc=m)}}}}function Or(n){var t=n.circle;t&&(t.P||(Bc=t.N),Wc.remove(t),Gc.push(t),Jr(t),n.circle=null)}function Yr(n){for(var t,e=Vc,r=De(n[0][0],n[0][1],n[1][0],n[1][1]),u=e.length;u--;)t=e[u],(!Ir(t,n)||!r(t)||oa(t.a.x-t.b.x)<Aa&&oa(t.a.y-t.b.y)<Aa)&&(t.a=t.b=null,e.splice(u,1))}function Ir(n,t){var e=n.b;if(e)return!0;var r,u,i=n.a,o=t[0][0],a=t[1][0],c=t[0][1],s=t[1][1],l=n.l,f=n.r,h=l.x,g=l.y,p=f.x,v=f.y,d=(h+p)/2,m=(g+v)/2;if(v===g){if(o>d||d>=a)return;if(h>p){if(i){if(i.y>=s)return}else i={x:d,y:c};e={x:d,y:s}}else{if(i){if(i.y<c)return}else i={x:d,y:s};e={x:d,y:c}}}else if(r=(h-p)/(v-g),u=m-r*d,-1>r||r>1)if(h>p){if(i){if(i.y>=s)return}else i={x:(c-u)/r,y:c};e={x:(s-u)/r,y:s}}else{if(i){if(i.y<c)return}else i={x:(s-u)/r,y:s};e={x:(c-u)/r,y:c}}else if(v>g){if(i){if(i.x>=a)return}else i={x:o,y:r*o+u};e={x:a,y:r*a+u}}else{if(i){if(i.x<o)return}else i={x:a,y:r*a+u};e={x:o,y:r*o+u}}return n.a=i,n.b=e,!0}function Zr(n,t){this.l=n,this.r=t,this.a=this.b=null}function Vr(n,t,e,r){var u=new Zr(n,t);return Vc.push(u),e&&$r(u,n,t,e),r&&$r(u,t,n,r),Xc[n.i].edges.push(new Br(u,n,t)),Xc[t.i].edges.push(new Br(u,t,n)),u}function Xr(n,t,e){var r=new Zr(n,null);return r.a=t,r.b=e,Vc.push(r),r}function $r(n,t,e,r){n.a||n.b?n.l===e?n.b=r:n.a=r:(n.a=r,n.l=t,n.r=e)}function Br(n,t,e){var r=n.a,u=n.b;this.edge=n,this.site=t,this.angle=e?Math.atan2(e.y-t.y,e.x-t.x):n.l===t?Math.atan2(u.x-r.x,r.y-u.y):Math.atan2(r.x-u.x,u.y-r.y)}function Wr(){this._=null}function Jr(n){n.U=n.C=n.L=n.R=n.P=n.N=null}function Gr(n,t){var e=t,r=t.R,u=e.U;u?u.L===e?u.L=r:u.R=r:n._=r,r.U=u,e.U=r,e.R=r.L,e.R&&(e.R.U=e),r.L=e}function Kr(n,t){var e=t,r=t.L,u=e.U;u?u.L===e?u.L=r:u.R=r:n._=r,r.U=u,e.U=r,e.L=r.R,e.L&&(e.L.U=e),r.R=e}function Qr(n){for(;n.L;)n=n.L;return n}function nu(n,t){var e,r,u,i=n.sort(tu).pop();for(Vc=[],Xc=new Array(n.length),$c=new Wr,Wc=new Wr;;)if(u=Bc,i&&(!u||i.y<u.y||i.y===u.y&&i.x<u.x))(i.x!==e||i.y!==r)&&(Xc[i.i]=new Pr(i),Tr(i),e=i.x,r=i.y),i=n.pop();else{if(!u)break;qr(u.arc)}t&&(Yr(t),Ur(t));var o={cells:Xc,edges:Vc};return $c=Wc=Vc=Xc=null,o}function tu(n,t){return t.y-n.y||t.x-n.x}function eu(n,t,e){return(n.x-e.x)*(t.y-n.y)-(n.x-t.x)*(e.y-n.y)}function ru(n){return n.x}function uu(n){return n.y}function iu(){return{leaf:!0,nodes:[],point:null,x:null,y:null}}function ou(n,t,e,r,u,i){if(!n(t,e,r,u,i)){var o=.5*(e+u),a=.5*(r+i),c=t.nodes;c[0]&&ou(n,c[0],e,r,o,a),c[1]&&ou(n,c[1],o,r,u,a),c[2]&&ou(n,c[2],e,a,o,i),c[3]&&ou(n,c[3],o,a,u,i)}}function au(n,t){n=Xo.rgb(n),t=Xo.rgb(t);var e=n.r,r=n.g,u=n.b,i=t.r-e,o=t.g-r,a=t.b-u;return function(n){return"#"+vt(Math.round(e+i*n))+vt(Math.round(r+o*n))+vt(Math.round(u+a*n))}}function cu(n,t){var e,r={},u={};for(e in n)e in t?r[e]=fu(n[e],t[e]):u[e]=n[e];for(e in t)e in n||(u[e]=t[e]);return function(n){for(e in r)u[e]=r[e](n);return u}}function su(n,t){return t-=n=+n,function(e){return n+t*e}}function lu(n,t){var e,r,u,i,o,a=0,c=0,s=[],l=[];for(n+="",t+="",Qc.lastIndex=0,r=0;e=Qc.exec(t);++r)e.index&&s.push(t.substring(a,c=e.index)),l.push({i:s.length,x:e[0]}),s.push(null),a=Qc.lastIndex;for(a<t.length&&s.push(t.substring(a)),r=0,i=l.length;(e=Qc.exec(n))&&i>r;++r)if(o=l[r],o.x==e[0]){if(o.i)if(null==s[o.i+1])for(s[o.i-1]+=o.x,s.splice(o.i,1),u=r+1;i>u;++u)l[u].i--;else for(s[o.i-1]+=o.x+s[o.i+1],s.splice(o.i,2),u=r+1;i>u;++u)l[u].i-=2;else if(null==s[o.i+1])s[o.i]=o.x;else for(s[o.i]=o.x+s[o.i+1],s.splice(o.i+1,1),u=r+1;i>u;++u)l[u].i--;l.splice(r,1),i--,r--}else o.x=su(parseFloat(e[0]),parseFloat(o.x));for(;i>r;)o=l.pop(),null==s[o.i+1]?s[o.i]=o.x:(s[o.i]=o.x+s[o.i+1],s.splice(o.i+1,1)),i--;return 1===s.length?null==s[0]?(o=l[0].x,function(n){return o(n)+""}):function(){return t}:function(n){for(r=0;i>r;++r)s[(o=l[r]).i]=o.x(n);return s.join("")}}function fu(n,t){for(var e,r=Xo.interpolators.length;--r>=0&&!(e=Xo.interpolators[r](n,t)););return e}function hu(n,t){var e,r=[],u=[],i=n.length,o=t.length,a=Math.min(n.length,t.length);for(e=0;a>e;++e)r.push(fu(n[e],t[e]));for(;i>e;++e)u[e]=n[e];for(;o>e;++e)u[e]=t[e];return function(n){for(e=0;a>e;++e)u[e]=r[e](n);return u}}function gu(n){return function(t){return 0>=t?0:t>=1?1:n(t)}}function pu(n){return function(t){return 1-n(1-t)}}function vu(n){return function(t){return.5*(.5>t?n(2*t):2-n(2-2*t))}}function du(n){return n*n}function mu(n){return n*n*n}function yu(n){if(0>=n)return 0;if(n>=1)return 1;var t=n*n,e=t*n;return 4*(.5>n?e:3*(n-t)+e-.75)}function xu(n){return function(t){return Math.pow(t,n)}}function Mu(n){return 1-Math.cos(n*Ea)}function _u(n){return Math.pow(2,10*(n-1))}function bu(n){return 1-Math.sqrt(1-n*n)}function wu(n,t){var e;return arguments.length<2&&(t=.45),arguments.length?e=t/ka*Math.asin(1/n):(n=1,e=t/4),function(r){return 1+n*Math.pow(2,-10*r)*Math.sin((r-e)*ka/t)}}function Su(n){return n||(n=1.70158),function(t){return t*t*((n+1)*t-n)}}function ku(n){return 1/2.75>n?7.5625*n*n:2/2.75>n?7.5625*(n-=1.5/2.75)*n+.75:2.5/2.75>n?7.5625*(n-=2.25/2.75)*n+.9375:7.5625*(n-=2.625/2.75)*n+.984375}function Eu(n,t){n=Xo.hcl(n),t=Xo.hcl(t);var e=n.h,r=n.c,u=n.l,i=t.h-e,o=t.c-r,a=t.l-u;return isNaN(o)&&(o=0,r=isNaN(r)?t.c:r),isNaN(i)?(i=0,e=isNaN(e)?t.h:e):i>180?i-=360:-180>i&&(i+=360),function(n){return rt(e+i*n,r+o*n,u+a*n)+""}}function Au(n,t){n=Xo.hsl(n),t=Xo.hsl(t);var e=n.h,r=n.s,u=n.l,i=t.h-e,o=t.s-r,a=t.l-u;return isNaN(o)&&(o=0,r=isNaN(r)?t.s:r),isNaN(i)?(i=0,e=isNaN(e)?t.h:e):i>180?i-=360:-180>i&&(i+=360),function(n){return nt(e+i*n,r+o*n,u+a*n)+""}}function Cu(n,t){n=Xo.lab(n),t=Xo.lab(t);var e=n.l,r=n.a,u=n.b,i=t.l-e,o=t.a-r,a=t.b-u;return function(n){return ot(e+i*n,r+o*n,u+a*n)+""}}function Nu(n,t){return t-=n,function(e){return Math.round(n+t*e)}}function Lu(n){var t=[n.a,n.b],e=[n.c,n.d],r=qu(t),u=zu(t,e),i=qu(Tu(e,t,-u))||0;t[0]*e[1]<e[0]*t[1]&&(t[0]*=-1,t[1]*=-1,r*=-1,u*=-1),this.rotate=(r?Math.atan2(t[1],t[0]):Math.atan2(-e[0],e[1]))*La,this.translate=[n.e,n.f],this.scale=[r,i],this.skew=i?Math.atan2(u,i)*La:0}function zu(n,t){return n[0]*t[0]+n[1]*t[1]}function qu(n){var t=Math.sqrt(zu(n,n));return t&&(n[0]/=t,n[1]/=t),t}function Tu(n,t,e){return n[0]+=e*t[0],n[1]+=e*t[1],n}function Ru(n,t){var e,r=[],u=[],i=Xo.transform(n),o=Xo.transform(t),a=i.translate,c=o.translate,s=i.rotate,l=o.rotate,f=i.skew,h=o.skew,g=i.scale,p=o.scale;return a[0]!=c[0]||a[1]!=c[1]?(r.push("translate(",null,",",null,")"),u.push({i:1,x:su(a[0],c[0])},{i:3,x:su(a[1],c[1])})):c[0]||c[1]?r.push("translate("+c+")"):r.push(""),s!=l?(s-l>180?l+=360:l-s>180&&(s+=360),u.push({i:r.push(r.pop()+"rotate(",null,")")-2,x:su(s,l)})):l&&r.push(r.pop()+"rotate("+l+")"),f!=h?u.push({i:r.push(r.pop()+"skewX(",null,")")-2,x:su(f,h)}):h&&r.push(r.pop()+"skewX("+h+")"),g[0]!=p[0]||g[1]!=p[1]?(e=r.push(r.pop()+"scale(",null,",",null,")"),u.push({i:e-4,x:su(g[0],p[0])},{i:e-2,x:su(g[1],p[1])})):(1!=p[0]||1!=p[1])&&r.push(r.pop()+"scale("+p+")"),e=u.length,function(n){for(var t,i=-1;++i<e;)r[(t=u[i]).i]=t.x(n);return r.join("")}}function Du(n,t){return t=t-(n=+n)?1/(t-n):0,function(e){return(e-n)*t}}function Pu(n,t){return t=t-(n=+n)?1/(t-n):0,function(e){return Math.max(0,Math.min(1,(e-n)*t))}}function Uu(n){for(var t=n.source,e=n.target,r=Hu(t,e),u=[t];t!==r;)t=t.parent,u.push(t);for(var i=u.length;e!==r;)u.splice(i,0,e),e=e.parent;return u}function ju(n){for(var t=[],e=n.parent;null!=e;)t.push(n),n=e,e=e.parent;return t.push(n),t}function Hu(n,t){if(n===t)return n;for(var e=ju(n),r=ju(t),u=e.pop(),i=r.pop(),o=null;u===i;)o=u,u=e.pop(),i=r.pop();return o}function Fu(n){n.fixed|=2}function Ou(n){n.fixed&=-7}function Yu(n){n.fixed|=4,n.px=n.x,n.py=n.y}function Iu(n){n.fixed&=-5}function Zu(n,t,e){var r=0,u=0;if(n.charge=0,!n.leaf)for(var i,o=n.nodes,a=o.length,c=-1;++c<a;)i=o[c],null!=i&&(Zu(i,t,e),n.charge+=i.charge,r+=i.charge*i.cx,u+=i.charge*i.cy);if(n.point){n.leaf||(n.point.x+=Math.random()-.5,n.point.y+=Math.random()-.5);var s=t*e[n.point.index];n.charge+=n.pointCharge=s,r+=s*n.point.x,u+=s*n.point.y}n.cx=r/n.charge,n.cy=u/n.charge}function Vu(n,t){return Xo.rebind(n,t,"sort","children","value"),n.nodes=n,n.links=Wu,n}function Xu(n){return n.children}function $u(n){return n.value}function Bu(n,t){return t.value-n.value}function Wu(n){return Xo.merge(n.map(function(n){return(n.children||[]).map(function(t){return{source:n,target:t}})}))}function Ju(n){return n.x}function Gu(n){return n.y}function Ku(n,t,e){n.y0=t,n.y=e}function Qu(n){return Xo.range(n.length)}function ni(n){for(var t=-1,e=n[0].length,r=[];++t<e;)r[t]=0;return r}function ti(n){for(var t,e=1,r=0,u=n[0][1],i=n.length;i>e;++e)(t=n[e][1])>u&&(r=e,u=t);return r}function ei(n){return n.reduce(ri,0)}function ri(n,t){return n+t[1]}function ui(n,t){return ii(n,Math.ceil(Math.log(t.length)/Math.LN2+1))}function ii(n,t){for(var e=-1,r=+n[0],u=(n[1]-r)/t,i=[];++e<=t;)i[e]=u*e+r;return i}function oi(n){return[Xo.min(n),Xo.max(n)]}function ai(n,t){return n.parent==t.parent?1:2}function ci(n){var t=n.children;return t&&t.length?t[0]:n._tree.thread}function si(n){var t,e=n.children;return e&&(t=e.length)?e[t-1]:n._tree.thread}function li(n,t){var e=n.children;if(e&&(u=e.length))for(var r,u,i=-1;++i<u;)t(r=li(e[i],t),n)>0&&(n=r);return n}function fi(n,t){return n.x-t.x}function hi(n,t){return t.x-n.x}function gi(n,t){return n.depth-t.depth}function pi(n,t){function e(n,r){var u=n.children;if(u&&(o=u.length))for(var i,o,a=null,c=-1;++c<o;)i=u[c],e(i,a),a=i;t(n,r)}e(n,null)}function vi(n){for(var t,e=0,r=0,u=n.children,i=u.length;--i>=0;)t=u[i]._tree,t.prelim+=e,t.mod+=e,e+=t.shift+(r+=t.change)}function di(n,t,e){n=n._tree,t=t._tree;var r=e/(t.number-n.number);n.change+=r,t.change-=r,t.shift+=e,t.prelim+=e,t.mod+=e}function mi(n,t,e){return n._tree.ancestor.parent==t.parent?n._tree.ancestor:e}function yi(n,t){return n.value-t.value}function xi(n,t){var e=n._pack_next;n._pack_next=t,t._pack_prev=n,t._pack_next=e,e._pack_prev=t}function Mi(n,t){n._pack_next=t,t._pack_prev=n}function _i(n,t){var e=t.x-n.x,r=t.y-n.y,u=n.r+t.r;return.999*u*u>e*e+r*r}function bi(n){function t(n){l=Math.min(n.x-n.r,l),f=Math.max(n.x+n.r,f),h=Math.min(n.y-n.r,h),g=Math.max(n.y+n.r,g)}if((e=n.children)&&(s=e.length)){var e,r,u,i,o,a,c,s,l=1/0,f=-1/0,h=1/0,g=-1/0;if(e.forEach(wi),r=e[0],r.x=-r.r,r.y=0,t(r),s>1&&(u=e[1],u.x=u.r,u.y=0,t(u),s>2))for(i=e[2],Ei(r,u,i),t(i),xi(r,i),r._pack_prev=i,xi(i,u),u=r._pack_next,o=3;s>o;o++){Ei(r,u,i=e[o]);var p=0,v=1,d=1;for(a=u._pack_next;a!==u;a=a._pack_next,v++)if(_i(a,i)){p=1;break}if(1==p)for(c=r._pack_prev;c!==a._pack_prev&&!_i(c,i);c=c._pack_prev,d++);p?(d>v||v==d&&u.r<r.r?Mi(r,u=a):Mi(r=c,u),o--):(xi(r,i),u=i,t(i))}var m=(l+f)/2,y=(h+g)/2,x=0;for(o=0;s>o;o++)i=e[o],i.x-=m,i.y-=y,x=Math.max(x,i.r+Math.sqrt(i.x*i.x+i.y*i.y));n.r=x,e.forEach(Si)}}function wi(n){n._pack_next=n._pack_prev=n}function Si(n){delete n._pack_next,delete n._pack_prev}function ki(n,t,e,r){var u=n.children;if(n.x=t+=r*n.x,n.y=e+=r*n.y,n.r*=r,u)for(var i=-1,o=u.length;++i<o;)ki(u[i],t,e,r)}function Ei(n,t,e){var r=n.r+e.r,u=t.x-n.x,i=t.y-n.y;if(r&&(u||i)){var o=t.r+e.r,a=u*u+i*i;o*=o,r*=r;var c=.5+(r-o)/(2*a),s=Math.sqrt(Math.max(0,2*o*(r+a)-(r-=a)*r-o*o))/(2*a);e.x=n.x+c*u+s*i,e.y=n.y+c*i-s*u}else e.x=n.x+r,e.y=n.y}function Ai(n){return 1+Xo.max(n,function(n){return n.y})}function Ci(n){return n.reduce(function(n,t){return n+t.x},0)/n.length}function Ni(n){var t=n.children;return t&&t.length?Ni(t[0]):n}function Li(n){var t,e=n.children;return e&&(t=e.length)?Li(e[t-1]):n}function zi(n){return{x:n.x,y:n.y,dx:n.dx,dy:n.dy}}function qi(n,t){var e=n.x+t[3],r=n.y+t[0],u=n.dx-t[1]-t[3],i=n.dy-t[0]-t[2];return 0>u&&(e+=u/2,u=0),0>i&&(r+=i/2,i=0),{x:e,y:r,dx:u,dy:i}}function Ti(n){var t=n[0],e=n[n.length-1];return e>t?[t,e]:[e,t]}function Ri(n){return n.rangeExtent?n.rangeExtent():Ti(n.range())}function Di(n,t,e,r){var u=e(n[0],n[1]),i=r(t[0],t[1]);return function(n){return i(u(n))}}function Pi(n,t){var e,r=0,u=n.length-1,i=n[r],o=n[u];return i>o&&(e=r,r=u,u=e,e=i,i=o,o=e),n[r]=t.floor(i),n[u]=t.ceil(o),n}function Ui(n){return n?{floor:function(t){return Math.floor(t/n)*n},ceil:function(t){return Math.ceil(t/n)*n}}:ls}function ji(n,t,e,r){var u=[],i=[],o=0,a=Math.min(n.length,t.length)-1;for(n[a]<n[0]&&(n=n.slice().reverse(),t=t.slice().reverse());++o<=a;)u.push(e(n[o-1],n[o])),i.push(r(t[o-1],t[o]));return function(t){var e=Xo.bisect(n,t,1,a)-1;return i[e](u[e](t))}}function Hi(n,t,e,r){function u(){var u=Math.min(n.length,t.length)>2?ji:Di,c=r?Pu:Du;return o=u(n,t,c,e),a=u(t,n,c,fu),i}function i(n){return o(n)}var o,a;return i.invert=function(n){return a(n)},i.domain=function(t){return arguments.length?(n=t.map(Number),u()):n},i.range=function(n){return arguments.length?(t=n,u()):t},i.rangeRound=function(n){return i.range(n).interpolate(Nu)},i.clamp=function(n){return arguments.length?(r=n,u()):r},i.interpolate=function(n){return arguments.length?(e=n,u()):e},i.ticks=function(t){return Ii(n,t)},i.tickFormat=function(t,e){return Zi(n,t,e)},i.nice=function(t){return Oi(n,t),u()},i.copy=function(){return Hi(n,t,e,r)},u()}function Fi(n,t){return Xo.rebind(n,t,"range","rangeRound","interpolate","clamp")}function Oi(n,t){return Pi(n,Ui(Yi(n,t)[2]))}function Yi(n,t){null==t&&(t=10);var e=Ti(n),r=e[1]-e[0],u=Math.pow(10,Math.floor(Math.log(r/t)/Math.LN10)),i=t/r*u;return.15>=i?u*=10:.35>=i?u*=5:.75>=i&&(u*=2),e[0]=Math.ceil(e[0]/u)*u,e[1]=Math.floor(e[1]/u)*u+.5*u,e[2]=u,e}function Ii(n,t){return Xo.range.apply(Xo,Yi(n,t))}function Zi(n,t,e){var r=Yi(n,t);return Xo.format(e?e.replace(Qa,function(n,t,e,u,i,o,a,c,s,l){return[t,e,u,i,o,a,c,s||"."+Xi(l,r),l].join("")}):",."+Vi(r[2])+"f")}function Vi(n){return-Math.floor(Math.log(n)/Math.LN10+.01)}function Xi(n,t){var e=Vi(t[2]);return n in fs?Math.abs(e-Vi(Math.max(Math.abs(t[0]),Math.abs(t[1]))))+ +("e"!==n):e-2*("%"===n)}function $i(n,t,e,r){function u(n){return(e?Math.log(0>n?0:n):-Math.log(n>0?0:-n))/Math.log(t)}function i(n){return e?Math.pow(t,n):-Math.pow(t,-n)}function o(t){return n(u(t))}return o.invert=function(t){return i(n.invert(t))},o.domain=function(t){return arguments.length?(e=t[0]>=0,n.domain((r=t.map(Number)).map(u)),o):r},o.base=function(e){return arguments.length?(t=+e,n.domain(r.map(u)),o):t},o.nice=function(){var t=Pi(r.map(u),e?Math:gs);return n.domain(t),r=t.map(i),o},o.ticks=function(){var n=Ti(r),o=[],a=n[0],c=n[1],s=Math.floor(u(a)),l=Math.ceil(u(c)),f=t%1?2:t;if(isFinite(l-s)){if(e){for(;l>s;s++)for(var h=1;f>h;h++)o.push(i(s)*h);o.push(i(s))}else for(o.push(i(s));s++<l;)for(var h=f-1;h>0;h--)o.push(i(s)*h);for(s=0;o[s]<a;s++);for(l=o.length;o[l-1]>c;l--);o=o.slice(s,l)}return o},o.tickFormat=function(n,t){if(!arguments.length)return hs;arguments.length<2?t=hs:"function"!=typeof t&&(t=Xo.format(t));var r,a=Math.max(.1,n/o.ticks().length),c=e?(r=1e-12,Math.ceil):(r=-1e-12,Math.floor);return function(n){return n/i(c(u(n)+r))<=a?t(n):""}},o.copy=function(){return $i(n.copy(),t,e,r)},Fi(o,n)}function Bi(n,t,e){function r(t){return n(u(t))}var u=Wi(t),i=Wi(1/t);return r.invert=function(t){return i(n.invert(t))},r.domain=function(t){return arguments.length?(n.domain((e=t.map(Number)).map(u)),r):e},r.ticks=function(n){return Ii(e,n)},r.tickFormat=function(n,t){return Zi(e,n,t)},r.nice=function(n){return r.domain(Oi(e,n))},r.exponent=function(o){return arguments.length?(u=Wi(t=o),i=Wi(1/t),n.domain(e.map(u)),r):t},r.copy=function(){return Bi(n.copy(),t,e)},Fi(r,n)}function Wi(n){return function(t){return 0>t?-Math.pow(-t,n):Math.pow(t,n)}}function Ji(n,t){function e(e){return o[((i.get(e)||"range"===t.t&&i.set(e,n.push(e)))-1)%o.length]}function r(t,e){return Xo.range(n.length).map(function(n){return t+e*n})}var i,o,a;return e.domain=function(r){if(!arguments.length)return n;n=[],i=new u;for(var o,a=-1,c=r.length;++a<c;)i.has(o=r[a])||i.set(o,n.push(o));return e[t.t].apply(e,t.a)},e.range=function(n){return arguments.length?(o=n,a=0,t={t:"range",a:arguments},e):o},e.rangePoints=function(u,i){arguments.length<2&&(i=0);var c=u[0],s=u[1],l=(s-c)/(Math.max(1,n.length-1)+i);return o=r(n.length<2?(c+s)/2:c+l*i/2,l),a=0,t={t:"rangePoints",a:arguments},e},e.rangeBands=function(u,i,c){arguments.length<2&&(i=0),arguments.length<3&&(c=i);var s=u[1]<u[0],l=u[s-0],f=u[1-s],h=(f-l)/(n.length-i+2*c);return o=r(l+h*c,h),s&&o.reverse(),a=h*(1-i),t={t:"rangeBands",a:arguments},e},e.rangeRoundBands=function(u,i,c){arguments.length<2&&(i=0),arguments.length<3&&(c=i);var s=u[1]<u[0],l=u[s-0],f=u[1-s],h=Math.floor((f-l)/(n.length-i+2*c)),g=f-l-(n.length-i)*h;return o=r(l+Math.round(g/2),h),s&&o.reverse(),a=Math.round(h*(1-i)),t={t:"rangeRoundBands",a:arguments},e},e.rangeBand=function(){return a},e.rangeExtent=function(){return Ti(t.a[0])},e.copy=function(){return Ji(n,t)},e.domain(n)}function Gi(n,t){function e(){var e=0,i=t.length;for(u=[];++e<i;)u[e-1]=Xo.quantile(n,e/i);return r}function r(n){return isNaN(n=+n)?void 0:t[Xo.bisect(u,n)]}var u;return r.domain=function(t){return arguments.length?(n=t.filter(function(n){return!isNaN(n)}).sort(Xo.ascending),e()):n},r.range=function(n){return arguments.length?(t=n,e()):t},r.quantiles=function(){return u},r.invertExtent=function(e){return e=t.indexOf(e),0>e?[0/0,0/0]:[e>0?u[e-1]:n[0],e<u.length?u[e]:n[n.length-1]]},r.copy=function(){return Gi(n,t)},e()}function Ki(n,t,e){function r(t){return e[Math.max(0,Math.min(o,Math.floor(i*(t-n))))]}function u(){return i=e.length/(t-n),o=e.length-1,r}var i,o;return r.domain=function(e){return arguments.length?(n=+e[0],t=+e[e.length-1],u()):[n,t]},r.range=function(n){return arguments.length?(e=n,u()):e},r.invertExtent=function(t){return t=e.indexOf(t),t=0>t?0/0:t/i+n,[t,t+1/i]},r.copy=function(){return Ki(n,t,e)},u()}function Qi(n,t){function e(e){return e>=e?t[Xo.bisect(n,e)]:void 0}return e.domain=function(t){return arguments.length?(n=t,e):n},e.range=function(n){return arguments.length?(t=n,e):t},e.invertExtent=function(e){return e=t.indexOf(e),[n[e-1],n[e]]},e.copy=function(){return Qi(n,t)},e}function no(n){function t(n){return+n}return t.invert=t,t.domain=t.range=function(e){return arguments.length?(n=e.map(t),t):n},t.ticks=function(t){return Ii(n,t)},t.tickFormat=function(t,e){return Zi(n,t,e)},t.copy=function(){return no(n)},t}function to(n){return n.innerRadius}function eo(n){return n.outerRadius}function ro(n){return n.startAngle}function uo(n){return n.endAngle}function io(n){function t(t){function o(){s.push("M",i(n(l),a))}for(var c,s=[],l=[],f=-1,h=t.length,g=_t(e),p=_t(r);++f<h;)u.call(this,c=t[f],f)?l.push([+g.call(this,c,f),+p.call(this,c,f)]):l.length&&(o(),l=[]);return l.length&&o(),s.length?s.join(""):null}var e=br,r=wr,u=be,i=oo,o=i.key,a=.7;return t.x=function(n){return arguments.length?(e=n,t):e},t.y=function(n){return arguments.length?(r=n,t):r},t.defined=function(n){return arguments.length?(u=n,t):u},t.interpolate=function(n){return arguments.length?(o="function"==typeof n?i=n:(i=Ms.get(n)||oo).key,t):o},t.tension=function(n){return arguments.length?(a=n,t):a},t}function oo(n){return n.join("L")}function ao(n){return oo(n)+"Z"}function co(n){for(var t=0,e=n.length,r=n[0],u=[r[0],",",r[1]];++t<e;)u.push("H",(r[0]+(r=n[t])[0])/2,"V",r[1]);return e>1&&u.push("H",r[0]),u.join("")}function so(n){for(var t=0,e=n.length,r=n[0],u=[r[0],",",r[1]];++t<e;)u.push("V",(r=n[t])[1],"H",r[0]);return u.join("")}function lo(n){for(var t=0,e=n.length,r=n[0],u=[r[0],",",r[1]];++t<e;)u.push("H",(r=n[t])[0],"V",r[1]);return u.join("")}function fo(n,t){return n.length<4?oo(n):n[1]+po(n.slice(1,n.length-1),vo(n,t))}function ho(n,t){return n.length<3?oo(n):n[0]+po((n.push(n[0]),n),vo([n[n.length-2]].concat(n,[n[1]]),t))}function go(n,t){return n.length<3?oo(n):n[0]+po(n,vo(n,t))}function po(n,t){if(t.length<1||n.length!=t.length&&n.length!=t.length+2)return oo(n);var e=n.length!=t.length,r="",u=n[0],i=n[1],o=t[0],a=o,c=1;if(e&&(r+="Q"+(i[0]-2*o[0]/3)+","+(i[1]-2*o[1]/3)+","+i[0]+","+i[1],u=n[1],c=2),t.length>1){a=t[1],i=n[c],c++,r+="C"+(u[0]+o[0])+","+(u[1]+o[1])+","+(i[0]-a[0])+","+(i[1]-a[1])+","+i[0]+","+i[1];for(var s=2;s<t.length;s++,c++)i=n[c],a=t[s],r+="S"+(i[0]-a[0])+","+(i[1]-a[1])+","+i[0]+","+i[1]}if(e){var l=n[c];r+="Q"+(i[0]+2*a[0]/3)+","+(i[1]+2*a[1]/3)+","+l[0]+","+l[1]}return r}function vo(n,t){for(var e,r=[],u=(1-t)/2,i=n[0],o=n[1],a=1,c=n.length;++a<c;)e=i,i=o,o=n[a],r.push([u*(o[0]-e[0]),u*(o[1]-e[1])]);return r}function mo(n){if(n.length<3)return oo(n);var t=1,e=n.length,r=n[0],u=r[0],i=r[1],o=[u,u,u,(r=n[1])[0]],a=[i,i,i,r[1]],c=[u,",",i,"L",_o(ws,o),",",_o(ws,a)];for(n.push(n[e-1]);++t<=e;)r=n[t],o.shift(),o.push(r[0]),a.shift(),a.push(r[1]),bo(c,o,a);return n.pop(),c.push("L",r),c.join("")}function yo(n){if(n.length<4)return oo(n);for(var t,e=[],r=-1,u=n.length,i=[0],o=[0];++r<3;)t=n[r],i.push(t[0]),o.push(t[1]);for(e.push(_o(ws,i)+","+_o(ws,o)),--r;++r<u;)t=n[r],i.shift(),i.push(t[0]),o.shift(),o.push(t[1]),bo(e,i,o);return e.join("")}function xo(n){for(var t,e,r=-1,u=n.length,i=u+4,o=[],a=[];++r<4;)e=n[r%u],o.push(e[0]),a.push(e[1]);for(t=[_o(ws,o),",",_o(ws,a)],--r;++r<i;)e=n[r%u],o.shift(),o.push(e[0]),a.shift(),a.push(e[1]),bo(t,o,a);return t.join("")}function Mo(n,t){var e=n.length-1;if(e)for(var r,u,i=n[0][0],o=n[0][1],a=n[e][0]-i,c=n[e][1]-o,s=-1;++s<=e;)r=n[s],u=s/e,r[0]=t*r[0]+(1-t)*(i+u*a),r[1]=t*r[1]+(1-t)*(o+u*c);return mo(n)}function _o(n,t){return n[0]*t[0]+n[1]*t[1]+n[2]*t[2]+n[3]*t[3]}function bo(n,t,e){n.push("C",_o(_s,t),",",_o(_s,e),",",_o(bs,t),",",_o(bs,e),",",_o(ws,t),",",_o(ws,e))}function wo(n,t){return(t[1]-n[1])/(t[0]-n[0])}function So(n){for(var t=0,e=n.length-1,r=[],u=n[0],i=n[1],o=r[0]=wo(u,i);++t<e;)r[t]=(o+(o=wo(u=i,i=n[t+1])))/2;return r[t]=o,r}function ko(n){for(var t,e,r,u,i=[],o=So(n),a=-1,c=n.length-1;++a<c;)t=wo(n[a],n[a+1]),oa(t)<Aa?o[a]=o[a+1]=0:(e=o[a]/t,r=o[a+1]/t,u=e*e+r*r,u>9&&(u=3*t/Math.sqrt(u),o[a]=u*e,o[a+1]=u*r));for(a=-1;++a<=c;)u=(n[Math.min(c,a+1)][0]-n[Math.max(0,a-1)][0])/(6*(1+o[a]*o[a])),i.push([u||0,o[a]*u||0]);return i}function Eo(n){return n.length<3?oo(n):n[0]+po(n,ko(n))}function Ao(n){for(var t,e,r,u=-1,i=n.length;++u<i;)t=n[u],e=t[0],r=t[1]+ys,t[0]=e*Math.cos(r),t[1]=e*Math.sin(r);return n}function Co(n){function t(t){function c(){v.push("M",a(n(m),f),l,s(n(d.reverse()),f),"Z")}for(var h,g,p,v=[],d=[],m=[],y=-1,x=t.length,M=_t(e),_=_t(u),b=e===r?function(){return g}:_t(r),w=u===i?function(){return p}:_t(i);++y<x;)o.call(this,h=t[y],y)?(d.push([g=+M.call(this,h,y),p=+_.call(this,h,y)]),m.push([+b.call(this,h,y),+w.call(this,h,y)])):d.length&&(c(),d=[],m=[]);return d.length&&c(),v.length?v.join(""):null}var e=br,r=br,u=0,i=wr,o=be,a=oo,c=a.key,s=a,l="L",f=.7;return t.x=function(n){return arguments.length?(e=r=n,t):r},t.x0=function(n){return arguments.length?(e=n,t):e},t.x1=function(n){return arguments.length?(r=n,t):r},t.y=function(n){return arguments.length?(u=i=n,t):i},t.y0=function(n){return arguments.length?(u=n,t):u},t.y1=function(n){return arguments.length?(i=n,t):i},t.defined=function(n){return arguments.length?(o=n,t):o},t.interpolate=function(n){return arguments.length?(c="function"==typeof n?a=n:(a=Ms.get(n)||oo).key,s=a.reverse||a,l=a.closed?"M":"L",t):c},t.tension=function(n){return arguments.length?(f=n,t):f},t}function No(n){return n.radius}function Lo(n){return[n.x,n.y]}function zo(n){return function(){var t=n.apply(this,arguments),e=t[0],r=t[1]+ys;return[e*Math.cos(r),e*Math.sin(r)]}}function qo(){return 64}function To(){return"circle"}function Ro(n){var t=Math.sqrt(n/Sa);return"M0,"+t+"A"+t+","+t+" 0 1,1 0,"+-t+"A"+t+","+t+" 0 1,1 0,"+t+"Z"}function Do(n,t){return fa(n,Ns),n.id=t,n}function Po(n,t,e,r){var u=n.id;return R(n,"function"==typeof e?function(n,i,o){n.__transition__[u].tween.set(t,r(e.call(n,n.__data__,i,o)))}:(e=r(e),function(n){n.__transition__[u].tween.set(t,e)}))}function Uo(n){return null==n&&(n=""),function(){this.textContent=n}}function jo(n,t,e,r){var i=n.__transition__||(n.__transition__={active:0,count:0}),o=i[e];if(!o){var a=r.time;o=i[e]={tween:new u,time:a,ease:r.ease,delay:r.delay,duration:r.duration},++i.count,Xo.timer(function(r){function u(r){return i.active>e?s():(i.active=e,o.event&&o.event.start.call(n,l,t),o.tween.forEach(function(e,r){(r=r.call(n,l,t))&&v.push(r)}),Xo.timer(function(){return p.c=c(r||1)?be:c,1},0,a),void 0)}function c(r){if(i.active!==e)return s();for(var u=r/g,a=f(u),c=v.length;c>0;)v[--c].call(n,a);return u>=1?(o.event&&o.event.end.call(n,l,t),s()):void 0}function s(){return--i.count?delete i[e]:delete n.__transition__,1}var l=n.__data__,f=o.ease,h=o.delay,g=o.duration,p=Ja,v=[];return p.t=h+a,r>=h?u(r-h):(p.c=u,void 0)},0,a)}}function Ho(n,t){n.attr("transform",function(n){return"translate("+t(n)+",0)"})}function Fo(n,t){n.attr("transform",function(n){return"translate(0,"+t(n)+")"})}function Oo(n){return n.toISOString()}function Yo(n,t,e){function r(t){return n(t)}function u(n,e){var r=n[1]-n[0],u=r/e,i=Xo.bisect(js,u);return i==js.length?[t.year,Yi(n.map(function(n){return n/31536e6}),e)[2]]:i?t[u/js[i-1]<js[i]/u?i-1:i]:[Os,Yi(n,e)[2]]
+}return r.invert=function(t){return Io(n.invert(t))},r.domain=function(t){return arguments.length?(n.domain(t),r):n.domain().map(Io)},r.nice=function(n,t){function e(e){return!isNaN(e)&&!n.range(e,Io(+e+1),t).length}var i=r.domain(),o=Ti(i),a=null==n?u(o,10):"number"==typeof n&&u(o,n);return a&&(n=a[0],t=a[1]),r.domain(Pi(i,t>1?{floor:function(t){for(;e(t=n.floor(t));)t=Io(t-1);return t},ceil:function(t){for(;e(t=n.ceil(t));)t=Io(+t+1);return t}}:n))},r.ticks=function(n,t){var e=Ti(r.domain()),i=null==n?u(e,10):"number"==typeof n?u(e,n):!n.range&&[{range:n},t];return i&&(n=i[0],t=i[1]),n.range(e[0],Io(+e[1]+1),1>t?1:t)},r.tickFormat=function(){return e},r.copy=function(){return Yo(n.copy(),t,e)},Fi(r,n)}function Io(n){return new Date(n)}function Zo(n){return JSON.parse(n.responseText)}function Vo(n){var t=Wo.createRange();return t.selectNode(Wo.body),t.createContextualFragment(n.responseText)}var Xo={version:"3.4.1"};Date.now||(Date.now=function(){return+new Date});var $o=[].slice,Bo=function(n){return $o.call(n)},Wo=document,Jo=Wo.documentElement,Go=window;try{Bo(Jo.childNodes)[0].nodeType}catch(Ko){Bo=function(n){for(var t=n.length,e=new Array(t);t--;)e[t]=n[t];return e}}try{Wo.createElement("div").style.setProperty("opacity",0,"")}catch(Qo){var na=Go.Element.prototype,ta=na.setAttribute,ea=na.setAttributeNS,ra=Go.CSSStyleDeclaration.prototype,ua=ra.setProperty;na.setAttribute=function(n,t){ta.call(this,n,t+"")},na.setAttributeNS=function(n,t,e){ea.call(this,n,t,e+"")},ra.setProperty=function(n,t,e){ua.call(this,n,t+"",e)}}Xo.ascending=function(n,t){return t>n?-1:n>t?1:n>=t?0:0/0},Xo.descending=function(n,t){return n>t?-1:t>n?1:t>=n?0:0/0},Xo.min=function(n,t){var e,r,u=-1,i=n.length;if(1===arguments.length){for(;++u<i&&!(null!=(e=n[u])&&e>=e);)e=void 0;for(;++u<i;)null!=(r=n[u])&&e>r&&(e=r)}else{for(;++u<i&&!(null!=(e=t.call(n,n[u],u))&&e>=e);)e=void 0;for(;++u<i;)null!=(r=t.call(n,n[u],u))&&e>r&&(e=r)}return e},Xo.max=function(n,t){var e,r,u=-1,i=n.length;if(1===arguments.length){for(;++u<i&&!(null!=(e=n[u])&&e>=e);)e=void 0;for(;++u<i;)null!=(r=n[u])&&r>e&&(e=r)}else{for(;++u<i&&!(null!=(e=t.call(n,n[u],u))&&e>=e);)e=void 0;for(;++u<i;)null!=(r=t.call(n,n[u],u))&&r>e&&(e=r)}return e},Xo.extent=function(n,t){var e,r,u,i=-1,o=n.length;if(1===arguments.length){for(;++i<o&&!(null!=(e=u=n[i])&&e>=e);)e=u=void 0;for(;++i<o;)null!=(r=n[i])&&(e>r&&(e=r),r>u&&(u=r))}else{for(;++i<o&&!(null!=(e=u=t.call(n,n[i],i))&&e>=e);)e=void 0;for(;++i<o;)null!=(r=t.call(n,n[i],i))&&(e>r&&(e=r),r>u&&(u=r))}return[e,u]},Xo.sum=function(n,t){var e,r=0,u=n.length,i=-1;if(1===arguments.length)for(;++i<u;)isNaN(e=+n[i])||(r+=e);else for(;++i<u;)isNaN(e=+t.call(n,n[i],i))||(r+=e);return r},Xo.mean=function(t,e){var r,u=t.length,i=0,o=-1,a=0;if(1===arguments.length)for(;++o<u;)n(r=t[o])&&(i+=(r-i)/++a);else for(;++o<u;)n(r=e.call(t,t[o],o))&&(i+=(r-i)/++a);return a?i:void 0},Xo.quantile=function(n,t){var e=(n.length-1)*t+1,r=Math.floor(e),u=+n[r-1],i=e-r;return i?u+i*(n[r]-u):u},Xo.median=function(t,e){return arguments.length>1&&(t=t.map(e)),t=t.filter(n),t.length?Xo.quantile(t.sort(Xo.ascending),.5):void 0},Xo.bisector=function(n){return{left:function(t,e,r,u){for(arguments.length<3&&(r=0),arguments.length<4&&(u=t.length);u>r;){var i=r+u>>>1;n.call(t,t[i],i)<e?r=i+1:u=i}return r},right:function(t,e,r,u){for(arguments.length<3&&(r=0),arguments.length<4&&(u=t.length);u>r;){var i=r+u>>>1;e<n.call(t,t[i],i)?u=i:r=i+1}return r}}};var ia=Xo.bisector(function(n){return n});Xo.bisectLeft=ia.left,Xo.bisect=Xo.bisectRight=ia.right,Xo.shuffle=function(n){for(var t,e,r=n.length;r;)e=0|Math.random()*r--,t=n[r],n[r]=n[e],n[e]=t;return n},Xo.permute=function(n,t){for(var e=t.length,r=new Array(e);e--;)r[e]=n[t[e]];return r},Xo.pairs=function(n){for(var t,e=0,r=n.length-1,u=n[0],i=new Array(0>r?0:r);r>e;)i[e]=[t=u,u=n[++e]];return i},Xo.zip=function(){if(!(u=arguments.length))return[];for(var n=-1,e=Xo.min(arguments,t),r=new Array(e);++n<e;)for(var u,i=-1,o=r[n]=new Array(u);++i<u;)o[i]=arguments[i][n];return r},Xo.transpose=function(n){return Xo.zip.apply(Xo,n)},Xo.keys=function(n){var t=[];for(var e in n)t.push(e);return t},Xo.values=function(n){var t=[];for(var e in n)t.push(n[e]);return t},Xo.entries=function(n){var t=[];for(var e in n)t.push({key:e,value:n[e]});return t},Xo.merge=function(n){for(var t,e,r,u=n.length,i=-1,o=0;++i<u;)o+=n[i].length;for(e=new Array(o);--u>=0;)for(r=n[u],t=r.length;--t>=0;)e[--o]=r[t];return e};var oa=Math.abs;Xo.range=function(n,t,r){if(arguments.length<3&&(r=1,arguments.length<2&&(t=n,n=0)),1/0===(t-n)/r)throw new Error("infinite range");var u,i=[],o=e(oa(r)),a=-1;if(n*=o,t*=o,r*=o,0>r)for(;(u=n+r*++a)>t;)i.push(u/o);else for(;(u=n+r*++a)<t;)i.push(u/o);return i},Xo.map=function(n){var t=new u;if(n instanceof u)n.forEach(function(n,e){t.set(n,e)});else for(var e in n)t.set(e,n[e]);return t},r(u,{has:i,get:function(n){return this[aa+n]},set:function(n,t){return this[aa+n]=t},remove:o,keys:a,values:function(){var n=[];return this.forEach(function(t,e){n.push(e)}),n},entries:function(){var n=[];return this.forEach(function(t,e){n.push({key:t,value:e})}),n},size:c,empty:s,forEach:function(n){for(var t in this)t.charCodeAt(0)===ca&&n.call(this,t.substring(1),this[t])}});var aa="\x00",ca=aa.charCodeAt(0);Xo.nest=function(){function n(t,a,c){if(c>=o.length)return r?r.call(i,a):e?a.sort(e):a;for(var s,l,f,h,g=-1,p=a.length,v=o[c++],d=new u;++g<p;)(h=d.get(s=v(l=a[g])))?h.push(l):d.set(s,[l]);return t?(l=t(),f=function(e,r){l.set(e,n(t,r,c))}):(l={},f=function(e,r){l[e]=n(t,r,c)}),d.forEach(f),l}function t(n,e){if(e>=o.length)return n;var r=[],u=a[e++];return n.forEach(function(n,u){r.push({key:n,values:t(u,e)})}),u?r.sort(function(n,t){return u(n.key,t.key)}):r}var e,r,i={},o=[],a=[];return i.map=function(t,e){return n(e,t,0)},i.entries=function(e){return t(n(Xo.map,e,0),0)},i.key=function(n){return o.push(n),i},i.sortKeys=function(n){return a[o.length-1]=n,i},i.sortValues=function(n){return e=n,i},i.rollup=function(n){return r=n,i},i},Xo.set=function(n){var t=new l;if(n)for(var e=0,r=n.length;r>e;++e)t.add(n[e]);return t},r(l,{has:i,add:function(n){return this[aa+n]=!0,n},remove:function(n){return n=aa+n,n in this&&delete this[n]},values:a,size:c,empty:s,forEach:function(n){for(var t in this)t.charCodeAt(0)===ca&&n.call(this,t.substring(1))}}),Xo.behavior={},Xo.rebind=function(n,t){for(var e,r=1,u=arguments.length;++r<u;)n[e=arguments[r]]=f(n,t,t[e]);return n};var sa=["webkit","ms","moz","Moz","o","O"];Xo.dispatch=function(){for(var n=new p,t=-1,e=arguments.length;++t<e;)n[arguments[t]]=v(n);return n},p.prototype.on=function(n,t){var e=n.indexOf("."),r="";if(e>=0&&(r=n.substring(e+1),n=n.substring(0,e)),n)return arguments.length<2?this[n].on(r):this[n].on(r,t);if(2===arguments.length){if(null==t)for(n in this)this.hasOwnProperty(n)&&this[n].on(r,null);return this}},Xo.event=null,Xo.requote=function(n){return n.replace(la,"\\$&")};var la=/[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g,fa={}.__proto__?function(n,t){n.__proto__=t}:function(n,t){for(var e in t)n[e]=t[e]},ha=function(n,t){return t.querySelector(n)},ga=function(n,t){return t.querySelectorAll(n)},pa=Jo[h(Jo,"matchesSelector")],va=function(n,t){return pa.call(n,t)};"function"==typeof Sizzle&&(ha=function(n,t){return Sizzle(n,t)[0]||null},ga=function(n,t){return Sizzle.uniqueSort(Sizzle(n,t))},va=Sizzle.matchesSelector),Xo.selection=function(){return xa};var da=Xo.selection.prototype=[];da.select=function(n){var t,e,r,u,i=[];n=M(n);for(var o=-1,a=this.length;++o<a;){i.push(t=[]),t.parentNode=(r=this[o]).parentNode;for(var c=-1,s=r.length;++c<s;)(u=r[c])?(t.push(e=n.call(u,u.__data__,c,o)),e&&"__data__"in u&&(e.__data__=u.__data__)):t.push(null)}return x(i)},da.selectAll=function(n){var t,e,r=[];n=_(n);for(var u=-1,i=this.length;++u<i;)for(var o=this[u],a=-1,c=o.length;++a<c;)(e=o[a])&&(r.push(t=Bo(n.call(e,e.__data__,a,u))),t.parentNode=e);return x(r)};var ma={svg:"http://www.w3.org/2000/svg",xhtml:"http://www.w3.org/1999/xhtml",xlink:"http://www.w3.org/1999/xlink",xml:"http://www.w3.org/XML/1998/namespace",xmlns:"http://www.w3.org/2000/xmlns/"};Xo.ns={prefix:ma,qualify:function(n){var t=n.indexOf(":"),e=n;return t>=0&&(e=n.substring(0,t),n=n.substring(t+1)),ma.hasOwnProperty(e)?{space:ma[e],local:n}:n}},da.attr=function(n,t){if(arguments.length<2){if("string"==typeof n){var e=this.node();return n=Xo.ns.qualify(n),n.local?e.getAttributeNS(n.space,n.local):e.getAttribute(n)}for(t in n)this.each(b(t,n[t]));return this}return this.each(b(n,t))},da.classed=function(n,t){if(arguments.length<2){if("string"==typeof n){var e=this.node(),r=(n=k(n)).length,u=-1;if(t=e.classList){for(;++u<r;)if(!t.contains(n[u]))return!1}else for(t=e.getAttribute("class");++u<r;)if(!S(n[u]).test(t))return!1;return!0}for(t in n)this.each(E(t,n[t]));return this}return this.each(E(n,t))},da.style=function(n,t,e){var r=arguments.length;if(3>r){if("string"!=typeof n){2>r&&(t="");for(e in n)this.each(C(e,n[e],t));return this}if(2>r)return Go.getComputedStyle(this.node(),null).getPropertyValue(n);e=""}return this.each(C(n,t,e))},da.property=function(n,t){if(arguments.length<2){if("string"==typeof n)return this.node()[n];for(t in n)this.each(N(t,n[t]));return this}return this.each(N(n,t))},da.text=function(n){return arguments.length?this.each("function"==typeof n?function(){var t=n.apply(this,arguments);this.textContent=null==t?"":t}:null==n?function(){this.textContent=""}:function(){this.textContent=n}):this.node().textContent},da.html=function(n){return arguments.length?this.each("function"==typeof n?function(){var t=n.apply(this,arguments);this.innerHTML=null==t?"":t}:null==n?function(){this.innerHTML=""}:function(){this.innerHTML=n}):this.node().innerHTML},da.append=function(n){return n=L(n),this.select(function(){return this.appendChild(n.apply(this,arguments))})},da.insert=function(n,t){return n=L(n),t=M(t),this.select(function(){return this.insertBefore(n.apply(this,arguments),t.apply(this,arguments)||null)})},da.remove=function(){return this.each(function(){var n=this.parentNode;n&&n.removeChild(this)})},da.data=function(n,t){function e(n,e){var r,i,o,a=n.length,f=e.length,h=Math.min(a,f),g=new Array(f),p=new Array(f),v=new Array(a);if(t){var d,m=new u,y=new u,x=[];for(r=-1;++r<a;)d=t.call(i=n[r],i.__data__,r),m.has(d)?v[r]=i:m.set(d,i),x.push(d);for(r=-1;++r<f;)d=t.call(e,o=e[r],r),(i=m.get(d))?(g[r]=i,i.__data__=o):y.has(d)||(p[r]=z(o)),y.set(d,o),m.remove(d);for(r=-1;++r<a;)m.has(x[r])&&(v[r]=n[r])}else{for(r=-1;++r<h;)i=n[r],o=e[r],i?(i.__data__=o,g[r]=i):p[r]=z(o);for(;f>r;++r)p[r]=z(e[r]);for(;a>r;++r)v[r]=n[r]}p.update=g,p.parentNode=g.parentNode=v.parentNode=n.parentNode,c.push(p),s.push(g),l.push(v)}var r,i,o=-1,a=this.length;if(!arguments.length){for(n=new Array(a=(r=this[0]).length);++o<a;)(i=r[o])&&(n[o]=i.__data__);return n}var c=D([]),s=x([]),l=x([]);if("function"==typeof n)for(;++o<a;)e(r=this[o],n.call(r,r.parentNode.__data__,o));else for(;++o<a;)e(r=this[o],n);return s.enter=function(){return c},s.exit=function(){return l},s},da.datum=function(n){return arguments.length?this.property("__data__",n):this.property("__data__")},da.filter=function(n){var t,e,r,u=[];"function"!=typeof n&&(n=q(n));for(var i=0,o=this.length;o>i;i++){u.push(t=[]),t.parentNode=(e=this[i]).parentNode;for(var a=0,c=e.length;c>a;a++)(r=e[a])&&n.call(r,r.__data__,a,i)&&t.push(r)}return x(u)},da.order=function(){for(var n=-1,t=this.length;++n<t;)for(var e,r=this[n],u=r.length-1,i=r[u];--u>=0;)(e=r[u])&&(i&&i!==e.nextSibling&&i.parentNode.insertBefore(e,i),i=e);return this},da.sort=function(n){n=T.apply(this,arguments);for(var t=-1,e=this.length;++t<e;)this[t].sort(n);return this.order()},da.each=function(n){return R(this,function(t,e,r){n.call(t,t.__data__,e,r)})},da.call=function(n){var t=Bo(arguments);return n.apply(t[0]=this,t),this},da.empty=function(){return!this.node()},da.node=function(){for(var n=0,t=this.length;t>n;n++)for(var e=this[n],r=0,u=e.length;u>r;r++){var i=e[r];if(i)return i}return null},da.size=function(){var n=0;return this.each(function(){++n}),n};var ya=[];Xo.selection.enter=D,Xo.selection.enter.prototype=ya,ya.append=da.append,ya.empty=da.empty,ya.node=da.node,ya.call=da.call,ya.size=da.size,ya.select=function(n){for(var t,e,r,u,i,o=[],a=-1,c=this.length;++a<c;){r=(u=this[a]).update,o.push(t=[]),t.parentNode=u.parentNode;for(var s=-1,l=u.length;++s<l;)(i=u[s])?(t.push(r[s]=e=n.call(u.parentNode,i.__data__,s,a)),e.__data__=i.__data__):t.push(null)}return x(o)},ya.insert=function(n,t){return arguments.length<2&&(t=P(this)),da.insert.call(this,n,t)},da.transition=function(){for(var n,t,e=ks||++Ls,r=[],u=Es||{time:Date.now(),ease:yu,delay:0,duration:250},i=-1,o=this.length;++i<o;){r.push(n=[]);for(var a=this[i],c=-1,s=a.length;++c<s;)(t=a[c])&&jo(t,c,e,u),n.push(t)}return Do(r,e)},da.interrupt=function(){return this.each(U)},Xo.select=function(n){var t=["string"==typeof n?ha(n,Wo):n];return t.parentNode=Jo,x([t])},Xo.selectAll=function(n){var t=Bo("string"==typeof n?ga(n,Wo):n);return t.parentNode=Jo,x([t])};var xa=Xo.select(Jo);da.on=function(n,t,e){var r=arguments.length;if(3>r){if("string"!=typeof n){2>r&&(t=!1);for(e in n)this.each(j(e,n[e],t));return this}if(2>r)return(r=this.node()["__on"+n])&&r._;e=!1}return this.each(j(n,t,e))};var Ma=Xo.map({mouseenter:"mouseover",mouseleave:"mouseout"});Ma.forEach(function(n){"on"+n in Wo&&Ma.remove(n)});var _a="onselectstart"in Wo?null:h(Jo.style,"userSelect"),ba=0;Xo.mouse=function(n){return Y(n,m())};var wa=/WebKit/.test(Go.navigator.userAgent)?-1:0;Xo.touches=function(n,t){return arguments.length<2&&(t=m().touches),t?Bo(t).map(function(t){var e=Y(n,t);return e.identifier=t.identifier,e}):[]},Xo.behavior.drag=function(){function n(){this.on("mousedown.drag",o).on("touchstart.drag",a)}function t(){return Xo.event.changedTouches[0].identifier}function e(n,t){return Xo.touches(n).filter(function(n){return n.identifier===t})[0]}function r(n,t,e,r){return function(){function o(){var n=t(l,g),e=n[0]-v[0],r=n[1]-v[1];d|=e|r,v=n,f({type:"drag",x:n[0]+c[0],y:n[1]+c[1],dx:e,dy:r})}function a(){m.on(e+"."+p,null).on(r+"."+p,null),y(d&&Xo.event.target===h),f({type:"dragend"})}var c,s=this,l=s.parentNode,f=u.of(s,arguments),h=Xo.event.target,g=n(),p=null==g?"drag":"drag-"+g,v=t(l,g),d=0,m=Xo.select(Go).on(e+"."+p,o).on(r+"."+p,a),y=O();i?(c=i.apply(s,arguments),c=[c.x-v[0],c.y-v[1]]):c=[0,0],f({type:"dragstart"})}}var u=y(n,"drag","dragstart","dragend"),i=null,o=r(g,Xo.mouse,"mousemove","mouseup"),a=r(t,e,"touchmove","touchend");return n.origin=function(t){return arguments.length?(i=t,n):i},Xo.rebind(n,u,"on")};var Sa=Math.PI,ka=2*Sa,Ea=Sa/2,Aa=1e-6,Ca=Aa*Aa,Na=Sa/180,La=180/Sa,za=Math.SQRT2,qa=2,Ta=4;Xo.interpolateZoom=function(n,t){function e(n){var t=n*y;if(m){var e=B(v),o=i/(qa*h)*(e*W(za*t+v)-$(v));return[r+o*s,u+o*l,i*e/B(za*t+v)]}return[r+n*s,u+n*l,i*Math.exp(za*t)]}var r=n[0],u=n[1],i=n[2],o=t[0],a=t[1],c=t[2],s=o-r,l=a-u,f=s*s+l*l,h=Math.sqrt(f),g=(c*c-i*i+Ta*f)/(2*i*qa*h),p=(c*c-i*i-Ta*f)/(2*c*qa*h),v=Math.log(Math.sqrt(g*g+1)-g),d=Math.log(Math.sqrt(p*p+1)-p),m=d-v,y=(m||Math.log(c/i))/za;return e.duration=1e3*y,e},Xo.behavior.zoom=function(){function n(n){n.on(A,s).on(Pa+".zoom",f).on(C,h).on("dblclick.zoom",g).on(L,l)}function t(n){return[(n[0]-S.x)/S.k,(n[1]-S.y)/S.k]}function e(n){return[n[0]*S.k+S.x,n[1]*S.k+S.y]}function r(n){S.k=Math.max(E[0],Math.min(E[1],n))}function u(n,t){t=e(t),S.x+=n[0]-t[0],S.y+=n[1]-t[1]}function i(){_&&_.domain(M.range().map(function(n){return(n-S.x)/S.k}).map(M.invert)),w&&w.domain(b.range().map(function(n){return(n-S.y)/S.k}).map(b.invert))}function o(n){n({type:"zoomstart"})}function a(n){i(),n({type:"zoom",scale:S.k,translate:[S.x,S.y]})}function c(n){n({type:"zoomend"})}function s(){function n(){l=1,u(Xo.mouse(r),g),a(i)}function e(){f.on(C,Go===r?h:null).on(N,null),p(l&&Xo.event.target===s),c(i)}var r=this,i=z.of(r,arguments),s=Xo.event.target,l=0,f=Xo.select(Go).on(C,n).on(N,e),g=t(Xo.mouse(r)),p=O();U.call(r),o(i)}function l(){function n(){var n=Xo.touches(g);return h=S.k,n.forEach(function(n){n.identifier in v&&(v[n.identifier]=t(n))}),n}function e(){for(var t=Xo.event.changedTouches,e=0,i=t.length;i>e;++e)v[t[e].identifier]=null;var o=n(),c=Date.now();if(1===o.length){if(500>c-x){var s=o[0],l=v[s.identifier];r(2*S.k),u(s,l),d(),a(p)}x=c}else if(o.length>1){var s=o[0],f=o[1],h=s[0]-f[0],g=s[1]-f[1];m=h*h+g*g}}function i(){for(var n,t,e,i,o=Xo.touches(g),c=0,s=o.length;s>c;++c,i=null)if(e=o[c],i=v[e.identifier]){if(t)break;n=e,t=i}if(i){var l=(l=e[0]-n[0])*l+(l=e[1]-n[1])*l,f=m&&Math.sqrt(l/m);n=[(n[0]+e[0])/2,(n[1]+e[1])/2],t=[(t[0]+i[0])/2,(t[1]+i[1])/2],r(f*h)}x=null,u(n,t),a(p)}function f(){if(Xo.event.touches.length){for(var t=Xo.event.changedTouches,e=0,r=t.length;r>e;++e)delete v[t[e].identifier];for(var u in v)return void n()}b.on(M,null).on(_,null),w.on(A,s).on(L,l),k(),c(p)}var h,g=this,p=z.of(g,arguments),v={},m=0,y=Xo.event.changedTouches[0].identifier,M="touchmove.zoom-"+y,_="touchend.zoom-"+y,b=Xo.select(Go).on(M,i).on(_,f),w=Xo.select(g).on(A,null).on(L,e),k=O();U.call(g),e(),o(p)}function f(){var n=z.of(this,arguments);m?clearTimeout(m):(U.call(this),o(n)),m=setTimeout(function(){m=null,c(n)},50),d();var e=v||Xo.mouse(this);p||(p=t(e)),r(Math.pow(2,.002*Ra())*S.k),u(e,p),a(n)}function h(){p=null}function g(){var n=z.of(this,arguments),e=Xo.mouse(this),i=t(e),s=Math.log(S.k)/Math.LN2;o(n),r(Math.pow(2,Xo.event.shiftKey?Math.ceil(s)-1:Math.floor(s)+1)),u(e,i),a(n),c(n)}var p,v,m,x,M,_,b,w,S={x:0,y:0,k:1},k=[960,500],E=Da,A="mousedown.zoom",C="mousemove.zoom",N="mouseup.zoom",L="touchstart.zoom",z=y(n,"zoomstart","zoom","zoomend");return n.event=function(n){n.each(function(){var n=z.of(this,arguments),t=S;ks?Xo.select(this).transition().each("start.zoom",function(){S=this.__chart__||{x:0,y:0,k:1},o(n)}).tween("zoom:zoom",function(){var e=k[0],r=k[1],u=e/2,i=r/2,o=Xo.interpolateZoom([(u-S.x)/S.k,(i-S.y)/S.k,e/S.k],[(u-t.x)/t.k,(i-t.y)/t.k,e/t.k]);return function(t){var r=o(t),c=e/r[2];this.__chart__=S={x:u-r[0]*c,y:i-r[1]*c,k:c},a(n)}}).each("end.zoom",function(){c(n)}):(this.__chart__=S,o(n),a(n),c(n))})},n.translate=function(t){return arguments.length?(S={x:+t[0],y:+t[1],k:S.k},i(),n):[S.x,S.y]},n.scale=function(t){return arguments.length?(S={x:S.x,y:S.y,k:+t},i(),n):S.k},n.scaleExtent=function(t){return arguments.length?(E=null==t?Da:[+t[0],+t[1]],n):E},n.center=function(t){return arguments.length?(v=t&&[+t[0],+t[1]],n):v},n.size=function(t){return arguments.length?(k=t&&[+t[0],+t[1]],n):k},n.x=function(t){return arguments.length?(_=t,M=t.copy(),S={x:0,y:0,k:1},n):_},n.y=function(t){return arguments.length?(w=t,b=t.copy(),S={x:0,y:0,k:1},n):w},Xo.rebind(n,z,"on")};var Ra,Da=[0,1/0],Pa="onwheel"in Wo?(Ra=function(){return-Xo.event.deltaY*(Xo.event.deltaMode?120:1)},"wheel"):"onmousewheel"in Wo?(Ra=function(){return Xo.event.wheelDelta},"mousewheel"):(Ra=function(){return-Xo.event.detail},"MozMousePixelScroll");G.prototype.toString=function(){return this.rgb()+""},Xo.hsl=function(n,t,e){return 1===arguments.length?n instanceof Q?K(n.h,n.s,n.l):dt(""+n,mt,K):K(+n,+t,+e)};var Ua=Q.prototype=new G;Ua.brighter=function(n){return n=Math.pow(.7,arguments.length?n:1),K(this.h,this.s,this.l/n)},Ua.darker=function(n){return n=Math.pow(.7,arguments.length?n:1),K(this.h,this.s,n*this.l)},Ua.rgb=function(){return nt(this.h,this.s,this.l)},Xo.hcl=function(n,t,e){return 1===arguments.length?n instanceof et?tt(n.h,n.c,n.l):n instanceof it?at(n.l,n.a,n.b):at((n=yt((n=Xo.rgb(n)).r,n.g,n.b)).l,n.a,n.b):tt(+n,+t,+e)};var ja=et.prototype=new G;ja.brighter=function(n){return tt(this.h,this.c,Math.min(100,this.l+Ha*(arguments.length?n:1)))},ja.darker=function(n){return tt(this.h,this.c,Math.max(0,this.l-Ha*(arguments.length?n:1)))},ja.rgb=function(){return rt(this.h,this.c,this.l).rgb()},Xo.lab=function(n,t,e){return 1===arguments.length?n instanceof it?ut(n.l,n.a,n.b):n instanceof et?rt(n.l,n.c,n.h):yt((n=Xo.rgb(n)).r,n.g,n.b):ut(+n,+t,+e)};var Ha=18,Fa=.95047,Oa=1,Ya=1.08883,Ia=it.prototype=new G;Ia.brighter=function(n){return ut(Math.min(100,this.l+Ha*(arguments.length?n:1)),this.a,this.b)},Ia.darker=function(n){return ut(Math.max(0,this.l-Ha*(arguments.length?n:1)),this.a,this.b)},Ia.rgb=function(){return ot(this.l,this.a,this.b)},Xo.rgb=function(n,t,e){return 1===arguments.length?n instanceof pt?gt(n.r,n.g,n.b):dt(""+n,gt,nt):gt(~~n,~~t,~~e)};var Za=pt.prototype=new G;Za.brighter=function(n){n=Math.pow(.7,arguments.length?n:1);var t=this.r,e=this.g,r=this.b,u=30;return t||e||r?(t&&u>t&&(t=u),e&&u>e&&(e=u),r&&u>r&&(r=u),gt(Math.min(255,~~(t/n)),Math.min(255,~~(e/n)),Math.min(255,~~(r/n)))):gt(u,u,u)},Za.darker=function(n){return n=Math.pow(.7,arguments.length?n:1),gt(~~(n*this.r),~~(n*this.g),~~(n*this.b))},Za.hsl=function(){return mt(this.r,this.g,this.b)},Za.toString=function(){return"#"+vt(this.r)+vt(this.g)+vt(this.b)};var Va=Xo.map({aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074});Va.forEach(function(n,t){Va.set(n,ft(t))}),Xo.functor=_t,Xo.xhr=wt(bt),Xo.dsv=function(n,t){function e(n,e,i){arguments.length<3&&(i=e,e=null);var o=St(n,t,null==e?r:u(e),i);return o.row=function(n){return arguments.length?o.response(null==(e=n)?r:u(n)):e},o}function r(n){return e.parse(n.responseText)}function u(n){return function(t){return e.parse(t.responseText,n)}}function i(t){return t.map(o).join(n)}function o(n){return a.test(n)?'"'+n.replace(/\"/g,'""')+'"':n}var a=new RegExp('["'+n+"\n]"),c=n.charCodeAt(0);return e.parse=function(n,t){var r;return e.parseRows(n,function(n,e){if(r)return r(n,e-1);var u=new Function("d","return {"+n.map(function(n,t){return JSON.stringify(n)+": d["+t+"]"}).join(",")+"}");r=t?function(n,e){return t(u(n),e)}:u})},e.parseRows=function(n,t){function e(){if(l>=s)return o;if(u)return u=!1,i;var t=l;if(34===n.charCodeAt(t)){for(var e=t;e++<s;)if(34===n.charCodeAt(e)){if(34!==n.charCodeAt(e+1))break;++e}l=e+2;var r=n.charCodeAt(e+1);return 13===r?(u=!0,10===n.charCodeAt(e+2)&&++l):10===r&&(u=!0),n.substring(t+1,e).replace(/""/g,'"')}for(;s>l;){var r=n.charCodeAt(l++),a=1;if(10===r)u=!0;else if(13===r)u=!0,10===n.charCodeAt(l)&&(++l,++a);else if(r!==c)continue;return n.substring(t,l-a)}return n.substring(t)}for(var r,u,i={},o={},a=[],s=n.length,l=0,f=0;(r=e())!==o;){for(var h=[];r!==i&&r!==o;)h.push(r),r=e();(!t||(h=t(h,f++)))&&a.push(h)}return a},e.format=function(t){if(Array.isArray(t[0]))return e.formatRows(t);var r=new l,u=[];return t.forEach(function(n){for(var t in n)r.has(t)||u.push(r.add(t))}),[u.map(o).join(n)].concat(t.map(function(t){return u.map(function(n){return o(t[n])}).join(n)})).join("\n")},e.formatRows=function(n){return n.map(i).join("\n")},e},Xo.csv=Xo.dsv(",","text/csv"),Xo.tsv=Xo.dsv("	","text/tab-separated-values");var Xa,$a,Ba,Wa,Ja,Ga=Go[h(Go,"requestAnimationFrame")]||function(n){setTimeout(n,17)};Xo.timer=function(n,t,e){var r=arguments.length;2>r&&(t=0),3>r&&(e=Date.now());var u=e+t,i={c:n,t:u,f:!1,n:null};$a?$a.n=i:Xa=i,$a=i,Ba||(Wa=clearTimeout(Wa),Ba=1,Ga(Et))},Xo.timer.flush=function(){At(),Ct()},Xo.round=function(n,t){return t?Math.round(n*(t=Math.pow(10,t)))/t:Math.round(n)};var Ka=["y","z","a","f","p","n","\xb5","m","","k","M","G","T","P","E","Z","Y"].map(Lt);Xo.formatPrefix=function(n,t){var e=0;return n&&(0>n&&(n*=-1),t&&(n=Xo.round(n,Nt(n,t))),e=1+Math.floor(1e-12+Math.log(n)/Math.LN10),e=Math.max(-24,Math.min(24,3*Math.floor((0>=e?e+1:e-1)/3)))),Ka[8+e/3]};var Qa=/(?:([^{])?([<>=^]))?([+\- ])?([$#])?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i,nc=Xo.map({b:function(n){return n.toString(2)},c:function(n){return String.fromCharCode(n)},o:function(n){return n.toString(8)},x:function(n){return n.toString(16)},X:function(n){return n.toString(16).toUpperCase()},g:function(n,t){return n.toPrecision(t)},e:function(n,t){return n.toExponential(t)},f:function(n,t){return n.toFixed(t)},r:function(n,t){return(n=Xo.round(n,Nt(n,t))).toFixed(Math.max(0,Math.min(20,Nt(n*(1+1e-15),t))))}}),tc=Xo.time={},ec=Date;Tt.prototype={getDate:function(){return this._.getUTCDate()},getDay:function(){return this._.getUTCDay()},getFullYear:function(){return this._.getUTCFullYear()},getHours:function(){return this._.getUTCHours()},getMilliseconds:function(){return this._.getUTCMilliseconds()},getMinutes:function(){return this._.getUTCMinutes()},getMonth:function(){return this._.getUTCMonth()},getSeconds:function(){return this._.getUTCSeconds()},getTime:function(){return this._.getTime()},getTimezoneOffset:function(){return 0},valueOf:function(){return this._.valueOf()},setDate:function(){rc.setUTCDate.apply(this._,arguments)},setDay:function(){rc.setUTCDay.apply(this._,arguments)},setFullYear:function(){rc.setUTCFullYear.apply(this._,arguments)},setHours:function(){rc.setUTCHours.apply(this._,arguments)},setMilliseconds:function(){rc.setUTCMilliseconds.apply(this._,arguments)},setMinutes:function(){rc.setUTCMinutes.apply(this._,arguments)},setMonth:function(){rc.setUTCMonth.apply(this._,arguments)},setSeconds:function(){rc.setUTCSeconds.apply(this._,arguments)},setTime:function(){rc.setTime.apply(this._,arguments)}};var rc=Date.prototype;tc.year=Rt(function(n){return n=tc.day(n),n.setMonth(0,1),n},function(n,t){n.setFullYear(n.getFullYear()+t)},function(n){return n.getFullYear()}),tc.years=tc.year.range,tc.years.utc=tc.year.utc.range,tc.day=Rt(function(n){var t=new ec(2e3,0);return t.setFullYear(n.getFullYear(),n.getMonth(),n.getDate()),t},function(n,t){n.setDate(n.getDate()+t)},function(n){return n.getDate()-1}),tc.days=tc.day.range,tc.days.utc=tc.day.utc.range,tc.dayOfYear=function(n){var t=tc.year(n);return Math.floor((n-t-6e4*(n.getTimezoneOffset()-t.getTimezoneOffset()))/864e5)},["sunday","monday","tuesday","wednesday","thursday","friday","saturday"].forEach(function(n,t){t=7-t;var e=tc[n]=Rt(function(n){return(n=tc.day(n)).setDate(n.getDate()-(n.getDay()+t)%7),n},function(n,t){n.setDate(n.getDate()+7*Math.floor(t))},function(n){var e=tc.year(n).getDay();return Math.floor((tc.dayOfYear(n)+(e+t)%7)/7)-(e!==t)});tc[n+"s"]=e.range,tc[n+"s"].utc=e.utc.range,tc[n+"OfYear"]=function(n){var e=tc.year(n).getDay();return Math.floor((tc.dayOfYear(n)+(e+t)%7)/7)}}),tc.week=tc.sunday,tc.weeks=tc.sunday.range,tc.weeks.utc=tc.sunday.utc.range,tc.weekOfYear=tc.sundayOfYear;var uc={"-":"",_:" ",0:"0"},ic=/^\s*\d+/,oc=/^%/;Xo.locale=function(n){return{numberFormat:zt(n),timeFormat:Pt(n)}};var ac=Xo.locale({decimal:".",thousands:",",grouping:[3],currency:["$",""],dateTime:"%a %b %e %X %Y",date:"%m/%d/%Y",time:"%H:%M:%S",periods:["AM","PM"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]});Xo.format=ac.numberFormat,Xo.geo={},re.prototype={s:0,t:0,add:function(n){ue(n,this.t,cc),ue(cc.s,this.s,this),this.s?this.t+=cc.t:this.s=cc.t},reset:function(){this.s=this.t=0},valueOf:function(){return this.s}};var cc=new re;Xo.geo.stream=function(n,t){n&&sc.hasOwnProperty(n.type)?sc[n.type](n,t):ie(n,t)};var sc={Feature:function(n,t){ie(n.geometry,t)},FeatureCollection:function(n,t){for(var e=n.features,r=-1,u=e.length;++r<u;)ie(e[r].geometry,t)}},lc={Sphere:function(n,t){t.sphere()},Point:function(n,t){n=n.coordinates,t.point(n[0],n[1],n[2])},MultiPoint:function(n,t){for(var e=n.coordinates,r=-1,u=e.length;++r<u;)n=e[r],t.point(n[0],n[1],n[2])},LineString:function(n,t){oe(n.coordinates,t,0)},MultiLineString:function(n,t){for(var e=n.coordinates,r=-1,u=e.length;++r<u;)oe(e[r],t,0)},Polygon:function(n,t){ae(n.coordinates,t)},MultiPolygon:function(n,t){for(var e=n.coordinates,r=-1,u=e.length;++r<u;)ae(e[r],t)},GeometryCollection:function(n,t){for(var e=n.geometries,r=-1,u=e.length;++r<u;)ie(e[r],t)}};Xo.geo.area=function(n){return fc=0,Xo.geo.stream(n,gc),fc};var fc,hc=new re,gc={sphere:function(){fc+=4*Sa},point:g,lineStart:g,lineEnd:g,polygonStart:function(){hc.reset(),gc.lineStart=ce},polygonEnd:function(){var n=2*hc;fc+=0>n?4*Sa+n:n,gc.lineStart=gc.lineEnd=gc.point=g}};Xo.geo.bounds=function(){function n(n,t){x.push(M=[l=n,h=n]),f>t&&(f=t),t>g&&(g=t)}function t(t,e){var r=se([t*Na,e*Na]);if(m){var u=fe(m,r),i=[u[1],-u[0],0],o=fe(i,u);pe(o),o=ve(o);var c=t-p,s=c>0?1:-1,v=o[0]*La*s,d=oa(c)>180;if(d^(v>s*p&&s*t>v)){var y=o[1]*La;y>g&&(g=y)}else if(v=(v+360)%360-180,d^(v>s*p&&s*t>v)){var y=-o[1]*La;f>y&&(f=y)}else f>e&&(f=e),e>g&&(g=e);d?p>t?a(l,t)>a(l,h)&&(h=t):a(t,h)>a(l,h)&&(l=t):h>=l?(l>t&&(l=t),t>h&&(h=t)):t>p?a(l,t)>a(l,h)&&(h=t):a(t,h)>a(l,h)&&(l=t)}else n(t,e);m=r,p=t}function e(){_.point=t}function r(){M[0]=l,M[1]=h,_.point=n,m=null}function u(n,e){if(m){var r=n-p;y+=oa(r)>180?r+(r>0?360:-360):r}else v=n,d=e;gc.point(n,e),t(n,e)}function i(){gc.lineStart()}function o(){u(v,d),gc.lineEnd(),oa(y)>Aa&&(l=-(h=180)),M[0]=l,M[1]=h,m=null}function a(n,t){return(t-=n)<0?t+360:t}function c(n,t){return n[0]-t[0]}function s(n,t){return t[0]<=t[1]?t[0]<=n&&n<=t[1]:n<t[0]||t[1]<n}var l,f,h,g,p,v,d,m,y,x,M,_={point:n,lineStart:e,lineEnd:r,polygonStart:function(){_.point=u,_.lineStart=i,_.lineEnd=o,y=0,gc.polygonStart()},polygonEnd:function(){gc.polygonEnd(),_.point=n,_.lineStart=e,_.lineEnd=r,0>hc?(l=-(h=180),f=-(g=90)):y>Aa?g=90:-Aa>y&&(f=-90),M[0]=l,M[1]=h
+}};return function(n){g=h=-(l=f=1/0),x=[],Xo.geo.stream(n,_);var t=x.length;if(t){x.sort(c);for(var e,r=1,u=x[0],i=[u];t>r;++r)e=x[r],s(e[0],u)||s(e[1],u)?(a(u[0],e[1])>a(u[0],u[1])&&(u[1]=e[1]),a(e[0],u[1])>a(u[0],u[1])&&(u[0]=e[0])):i.push(u=e);for(var o,e,p=-1/0,t=i.length-1,r=0,u=i[t];t>=r;u=e,++r)e=i[r],(o=a(u[1],e[0]))>p&&(p=o,l=e[0],h=u[1])}return x=M=null,1/0===l||1/0===f?[[0/0,0/0],[0/0,0/0]]:[[l,f],[h,g]]}}(),Xo.geo.centroid=function(n){pc=vc=dc=mc=yc=xc=Mc=_c=bc=wc=Sc=0,Xo.geo.stream(n,kc);var t=bc,e=wc,r=Sc,u=t*t+e*e+r*r;return Ca>u&&(t=xc,e=Mc,r=_c,Aa>vc&&(t=dc,e=mc,r=yc),u=t*t+e*e+r*r,Ca>u)?[0/0,0/0]:[Math.atan2(e,t)*La,X(r/Math.sqrt(u))*La]};var pc,vc,dc,mc,yc,xc,Mc,_c,bc,wc,Sc,kc={sphere:g,point:me,lineStart:xe,lineEnd:Me,polygonStart:function(){kc.lineStart=_e},polygonEnd:function(){kc.lineStart=xe}},Ec=Ee(be,ze,Te,[-Sa,-Sa/2]),Ac=1e9;Xo.geo.clipExtent=function(){var n,t,e,r,u,i,o={stream:function(n){return u&&(u.valid=!1),u=i(n),u.valid=!0,u},extent:function(a){return arguments.length?(i=Pe(n=+a[0][0],t=+a[0][1],e=+a[1][0],r=+a[1][1]),u&&(u.valid=!1,u=null),o):[[n,t],[e,r]]}};return o.extent([[0,0],[960,500]])},(Xo.geo.conicEqualArea=function(){return je(He)}).raw=He,Xo.geo.albers=function(){return Xo.geo.conicEqualArea().rotate([96,0]).center([-.6,38.7]).parallels([29.5,45.5]).scale(1070)},Xo.geo.albersUsa=function(){function n(n){var i=n[0],o=n[1];return t=null,e(i,o),t||(r(i,o),t)||u(i,o),t}var t,e,r,u,i=Xo.geo.albers(),o=Xo.geo.conicEqualArea().rotate([154,0]).center([-2,58.5]).parallels([55,65]),a=Xo.geo.conicEqualArea().rotate([157,0]).center([-3,19.9]).parallels([8,18]),c={point:function(n,e){t=[n,e]}};return n.invert=function(n){var t=i.scale(),e=i.translate(),r=(n[0]-e[0])/t,u=(n[1]-e[1])/t;return(u>=.12&&.234>u&&r>=-.425&&-.214>r?o:u>=.166&&.234>u&&r>=-.214&&-.115>r?a:i).invert(n)},n.stream=function(n){var t=i.stream(n),e=o.stream(n),r=a.stream(n);return{point:function(n,u){t.point(n,u),e.point(n,u),r.point(n,u)},sphere:function(){t.sphere(),e.sphere(),r.sphere()},lineStart:function(){t.lineStart(),e.lineStart(),r.lineStart()},lineEnd:function(){t.lineEnd(),e.lineEnd(),r.lineEnd()},polygonStart:function(){t.polygonStart(),e.polygonStart(),r.polygonStart()},polygonEnd:function(){t.polygonEnd(),e.polygonEnd(),r.polygonEnd()}}},n.precision=function(t){return arguments.length?(i.precision(t),o.precision(t),a.precision(t),n):i.precision()},n.scale=function(t){return arguments.length?(i.scale(t),o.scale(.35*t),a.scale(t),n.translate(i.translate())):i.scale()},n.translate=function(t){if(!arguments.length)return i.translate();var s=i.scale(),l=+t[0],f=+t[1];return e=i.translate(t).clipExtent([[l-.455*s,f-.238*s],[l+.455*s,f+.238*s]]).stream(c).point,r=o.translate([l-.307*s,f+.201*s]).clipExtent([[l-.425*s+Aa,f+.12*s+Aa],[l-.214*s-Aa,f+.234*s-Aa]]).stream(c).point,u=a.translate([l-.205*s,f+.212*s]).clipExtent([[l-.214*s+Aa,f+.166*s+Aa],[l-.115*s-Aa,f+.234*s-Aa]]).stream(c).point,n},n.scale(1070)};var Cc,Nc,Lc,zc,qc,Tc,Rc={point:g,lineStart:g,lineEnd:g,polygonStart:function(){Nc=0,Rc.lineStart=Fe},polygonEnd:function(){Rc.lineStart=Rc.lineEnd=Rc.point=g,Cc+=oa(Nc/2)}},Dc={point:Oe,lineStart:g,lineEnd:g,polygonStart:g,polygonEnd:g},Pc={point:Ze,lineStart:Ve,lineEnd:Xe,polygonStart:function(){Pc.lineStart=$e},polygonEnd:function(){Pc.point=Ze,Pc.lineStart=Ve,Pc.lineEnd=Xe}};Xo.geo.path=function(){function n(n){return n&&("function"==typeof a&&i.pointRadius(+a.apply(this,arguments)),o&&o.valid||(o=u(i)),Xo.geo.stream(n,o)),i.result()}function t(){return o=null,n}var e,r,u,i,o,a=4.5;return n.area=function(n){return Cc=0,Xo.geo.stream(n,u(Rc)),Cc},n.centroid=function(n){return dc=mc=yc=xc=Mc=_c=bc=wc=Sc=0,Xo.geo.stream(n,u(Pc)),Sc?[bc/Sc,wc/Sc]:_c?[xc/_c,Mc/_c]:yc?[dc/yc,mc/yc]:[0/0,0/0]},n.bounds=function(n){return qc=Tc=-(Lc=zc=1/0),Xo.geo.stream(n,u(Dc)),[[Lc,zc],[qc,Tc]]},n.projection=function(n){return arguments.length?(u=(e=n)?n.stream||Je(n):bt,t()):e},n.context=function(n){return arguments.length?(i=null==(r=n)?new Ye:new Be(n),"function"!=typeof a&&i.pointRadius(a),t()):r},n.pointRadius=function(t){return arguments.length?(a="function"==typeof t?t:(i.pointRadius(+t),+t),n):a},n.projection(Xo.geo.albersUsa()).context(null)},Xo.geo.transform=function(n){return{stream:function(t){var e=new Ge(t);for(var r in n)e[r]=n[r];return e}}},Ge.prototype={point:function(n,t){this.stream.point(n,t)},sphere:function(){this.stream.sphere()},lineStart:function(){this.stream.lineStart()},lineEnd:function(){this.stream.lineEnd()},polygonStart:function(){this.stream.polygonStart()},polygonEnd:function(){this.stream.polygonEnd()}},Xo.geo.projection=Qe,Xo.geo.projectionMutator=nr,(Xo.geo.equirectangular=function(){return Qe(er)}).raw=er.invert=er,Xo.geo.rotation=function(n){function t(t){return t=n(t[0]*Na,t[1]*Na),t[0]*=La,t[1]*=La,t}return n=ur(n[0]%360*Na,n[1]*Na,n.length>2?n[2]*Na:0),t.invert=function(t){return t=n.invert(t[0]*Na,t[1]*Na),t[0]*=La,t[1]*=La,t},t},rr.invert=er,Xo.geo.circle=function(){function n(){var n="function"==typeof r?r.apply(this,arguments):r,t=ur(-n[0]*Na,-n[1]*Na,0).invert,u=[];return e(null,null,1,{point:function(n,e){u.push(n=t(n,e)),n[0]*=La,n[1]*=La}}),{type:"Polygon",coordinates:[u]}}var t,e,r=[0,0],u=6;return n.origin=function(t){return arguments.length?(r=t,n):r},n.angle=function(r){return arguments.length?(e=cr((t=+r)*Na,u*Na),n):t},n.precision=function(r){return arguments.length?(e=cr(t*Na,(u=+r)*Na),n):u},n.angle(90)},Xo.geo.distance=function(n,t){var e,r=(t[0]-n[0])*Na,u=n[1]*Na,i=t[1]*Na,o=Math.sin(r),a=Math.cos(r),c=Math.sin(u),s=Math.cos(u),l=Math.sin(i),f=Math.cos(i);return Math.atan2(Math.sqrt((e=f*o)*e+(e=s*l-c*f*a)*e),c*l+s*f*a)},Xo.geo.graticule=function(){function n(){return{type:"MultiLineString",coordinates:t()}}function t(){return Xo.range(Math.ceil(i/d)*d,u,d).map(h).concat(Xo.range(Math.ceil(s/m)*m,c,m).map(g)).concat(Xo.range(Math.ceil(r/p)*p,e,p).filter(function(n){return oa(n%d)>Aa}).map(l)).concat(Xo.range(Math.ceil(a/v)*v,o,v).filter(function(n){return oa(n%m)>Aa}).map(f))}var e,r,u,i,o,a,c,s,l,f,h,g,p=10,v=p,d=90,m=360,y=2.5;return n.lines=function(){return t().map(function(n){return{type:"LineString",coordinates:n}})},n.outline=function(){return{type:"Polygon",coordinates:[h(i).concat(g(c).slice(1),h(u).reverse().slice(1),g(s).reverse().slice(1))]}},n.extent=function(t){return arguments.length?n.majorExtent(t).minorExtent(t):n.minorExtent()},n.majorExtent=function(t){return arguments.length?(i=+t[0][0],u=+t[1][0],s=+t[0][1],c=+t[1][1],i>u&&(t=i,i=u,u=t),s>c&&(t=s,s=c,c=t),n.precision(y)):[[i,s],[u,c]]},n.minorExtent=function(t){return arguments.length?(r=+t[0][0],e=+t[1][0],a=+t[0][1],o=+t[1][1],r>e&&(t=r,r=e,e=t),a>o&&(t=a,a=o,o=t),n.precision(y)):[[r,a],[e,o]]},n.step=function(t){return arguments.length?n.majorStep(t).minorStep(t):n.minorStep()},n.majorStep=function(t){return arguments.length?(d=+t[0],m=+t[1],n):[d,m]},n.minorStep=function(t){return arguments.length?(p=+t[0],v=+t[1],n):[p,v]},n.precision=function(t){return arguments.length?(y=+t,l=lr(a,o,90),f=fr(r,e,y),h=lr(s,c,90),g=fr(i,u,y),n):y},n.majorExtent([[-180,-90+Aa],[180,90-Aa]]).minorExtent([[-180,-80-Aa],[180,80+Aa]])},Xo.geo.greatArc=function(){function n(){return{type:"LineString",coordinates:[t||r.apply(this,arguments),e||u.apply(this,arguments)]}}var t,e,r=hr,u=gr;return n.distance=function(){return Xo.geo.distance(t||r.apply(this,arguments),e||u.apply(this,arguments))},n.source=function(e){return arguments.length?(r=e,t="function"==typeof e?null:e,n):r},n.target=function(t){return arguments.length?(u=t,e="function"==typeof t?null:t,n):u},n.precision=function(){return arguments.length?n:0},n},Xo.geo.interpolate=function(n,t){return pr(n[0]*Na,n[1]*Na,t[0]*Na,t[1]*Na)},Xo.geo.length=function(n){return Uc=0,Xo.geo.stream(n,jc),Uc};var Uc,jc={sphere:g,point:g,lineStart:vr,lineEnd:g,polygonStart:g,polygonEnd:g},Hc=dr(function(n){return Math.sqrt(2/(1+n))},function(n){return 2*Math.asin(n/2)});(Xo.geo.azimuthalEqualArea=function(){return Qe(Hc)}).raw=Hc;var Fc=dr(function(n){var t=Math.acos(n);return t&&t/Math.sin(t)},bt);(Xo.geo.azimuthalEquidistant=function(){return Qe(Fc)}).raw=Fc,(Xo.geo.conicConformal=function(){return je(mr)}).raw=mr,(Xo.geo.conicEquidistant=function(){return je(yr)}).raw=yr;var Oc=dr(function(n){return 1/n},Math.atan);(Xo.geo.gnomonic=function(){return Qe(Oc)}).raw=Oc,xr.invert=function(n,t){return[n,2*Math.atan(Math.exp(t))-Ea]},(Xo.geo.mercator=function(){return Mr(xr)}).raw=xr;var Yc=dr(function(){return 1},Math.asin);(Xo.geo.orthographic=function(){return Qe(Yc)}).raw=Yc;var Ic=dr(function(n){return 1/(1+n)},function(n){return 2*Math.atan(n)});(Xo.geo.stereographic=function(){return Qe(Ic)}).raw=Ic,_r.invert=function(n,t){return[-t,2*Math.atan(Math.exp(n))-Ea]},(Xo.geo.transverseMercator=function(){var n=Mr(_r),t=n.center,e=n.rotate;return n.center=function(n){return n?t([-n[1],n[0]]):(n=t(),[-n[1],n[0]])},n.rotate=function(n){return n?e([n[0],n[1],n.length>2?n[2]+90:90]):(n=e(),[n[0],n[1],n[2]-90])},n.rotate([0,0])}).raw=_r,Xo.geom={},Xo.geom.hull=function(n){function t(n){if(n.length<3)return[];var t,u=_t(e),i=_t(r),o=n.length,a=[],c=[];for(t=0;o>t;t++)a.push([+u.call(this,n[t],t),+i.call(this,n[t],t),t]);for(a.sort(kr),t=0;o>t;t++)c.push([a[t][0],-a[t][1]]);var s=Sr(a),l=Sr(c),f=l[0]===s[0],h=l[l.length-1]===s[s.length-1],g=[];for(t=s.length-1;t>=0;--t)g.push(n[a[s[t]][2]]);for(t=+f;t<l.length-h;++t)g.push(n[a[l[t]][2]]);return g}var e=br,r=wr;return arguments.length?t(n):(t.x=function(n){return arguments.length?(e=n,t):e},t.y=function(n){return arguments.length?(r=n,t):r},t)},Xo.geom.polygon=function(n){return fa(n,Zc),n};var Zc=Xo.geom.polygon.prototype=[];Zc.area=function(){for(var n,t=-1,e=this.length,r=this[e-1],u=0;++t<e;)n=r,r=this[t],u+=n[1]*r[0]-n[0]*r[1];return.5*u},Zc.centroid=function(n){var t,e,r=-1,u=this.length,i=0,o=0,a=this[u-1];for(arguments.length||(n=-1/(6*this.area()));++r<u;)t=a,a=this[r],e=t[0]*a[1]-a[0]*t[1],i+=(t[0]+a[0])*e,o+=(t[1]+a[1])*e;return[i*n,o*n]},Zc.clip=function(n){for(var t,e,r,u,i,o,a=Cr(n),c=-1,s=this.length-Cr(this),l=this[s-1];++c<s;){for(t=n.slice(),n.length=0,u=this[c],i=t[(r=t.length-a)-1],e=-1;++e<r;)o=t[e],Er(o,l,u)?(Er(i,l,u)||n.push(Ar(i,o,l,u)),n.push(o)):Er(i,l,u)&&n.push(Ar(i,o,l,u)),i=o;a&&n.push(n[0]),l=u}return n};var Vc,Xc,$c,Bc,Wc,Jc=[],Gc=[];Pr.prototype.prepare=function(){for(var n,t=this.edges,e=t.length;e--;)n=t[e].edge,n.b&&n.a||t.splice(e,1);return t.sort(jr),t.length},Br.prototype={start:function(){return this.edge.l===this.site?this.edge.a:this.edge.b},end:function(){return this.edge.l===this.site?this.edge.b:this.edge.a}},Wr.prototype={insert:function(n,t){var e,r,u;if(n){if(t.P=n,t.N=n.N,n.N&&(n.N.P=t),n.N=t,n.R){for(n=n.R;n.L;)n=n.L;n.L=t}else n.R=t;e=n}else this._?(n=Qr(this._),t.P=null,t.N=n,n.P=n.L=t,e=n):(t.P=t.N=null,this._=t,e=null);for(t.L=t.R=null,t.U=e,t.C=!0,n=t;e&&e.C;)r=e.U,e===r.L?(u=r.R,u&&u.C?(e.C=u.C=!1,r.C=!0,n=r):(n===e.R&&(Gr(this,e),n=e,e=n.U),e.C=!1,r.C=!0,Kr(this,r))):(u=r.L,u&&u.C?(e.C=u.C=!1,r.C=!0,n=r):(n===e.L&&(Kr(this,e),n=e,e=n.U),e.C=!1,r.C=!0,Gr(this,r))),e=n.U;this._.C=!1},remove:function(n){n.N&&(n.N.P=n.P),n.P&&(n.P.N=n.N),n.N=n.P=null;var t,e,r,u=n.U,i=n.L,o=n.R;if(e=i?o?Qr(o):i:o,u?u.L===n?u.L=e:u.R=e:this._=e,i&&o?(r=e.C,e.C=n.C,e.L=i,i.U=e,e!==o?(u=e.U,e.U=n.U,n=e.R,u.L=n,e.R=o,o.U=e):(e.U=u,u=e,n=e.R)):(r=n.C,n=e),n&&(n.U=u),!r){if(n&&n.C)return n.C=!1,void 0;do{if(n===this._)break;if(n===u.L){if(t=u.R,t.C&&(t.C=!1,u.C=!0,Gr(this,u),t=u.R),t.L&&t.L.C||t.R&&t.R.C){t.R&&t.R.C||(t.L.C=!1,t.C=!0,Kr(this,t),t=u.R),t.C=u.C,u.C=t.R.C=!1,Gr(this,u),n=this._;break}}else if(t=u.L,t.C&&(t.C=!1,u.C=!0,Kr(this,u),t=u.L),t.L&&t.L.C||t.R&&t.R.C){t.L&&t.L.C||(t.R.C=!1,t.C=!0,Gr(this,t),t=u.L),t.C=u.C,u.C=t.L.C=!1,Kr(this,u),n=this._;break}t.C=!0,n=u,u=u.U}while(!n.C);n&&(n.C=!1)}}},Xo.geom.voronoi=function(n){function t(n){var t=new Array(n.length),r=a[0][0],u=a[0][1],i=a[1][0],o=a[1][1];return nu(e(n),a).cells.forEach(function(e,a){var c=e.edges,s=e.site,l=t[a]=c.length?c.map(function(n){var t=n.start();return[t.x,t.y]}):s.x>=r&&s.x<=i&&s.y>=u&&s.y<=o?[[r,o],[i,o],[i,u],[r,u]]:[];l.point=n[a]}),t}function e(n){return n.map(function(n,t){return{x:Math.round(i(n,t)/Aa)*Aa,y:Math.round(o(n,t)/Aa)*Aa,i:t}})}var r=br,u=wr,i=r,o=u,a=Kc;return n?t(n):(t.links=function(n){return nu(e(n)).edges.filter(function(n){return n.l&&n.r}).map(function(t){return{source:n[t.l.i],target:n[t.r.i]}})},t.triangles=function(n){var t=[];return nu(e(n)).cells.forEach(function(e,r){for(var u,i,o=e.site,a=e.edges.sort(jr),c=-1,s=a.length,l=a[s-1].edge,f=l.l===o?l.r:l.l;++c<s;)u=l,i=f,l=a[c].edge,f=l.l===o?l.r:l.l,r<i.i&&r<f.i&&eu(o,i,f)<0&&t.push([n[r],n[i.i],n[f.i]])}),t},t.x=function(n){return arguments.length?(i=_t(r=n),t):r},t.y=function(n){return arguments.length?(o=_t(u=n),t):u},t.clipExtent=function(n){return arguments.length?(a=null==n?Kc:n,t):a===Kc?null:a},t.size=function(n){return arguments.length?t.clipExtent(n&&[[0,0],n]):a===Kc?null:a&&a[1]},t)};var Kc=[[-1e6,-1e6],[1e6,1e6]];Xo.geom.delaunay=function(n){return Xo.geom.voronoi().triangles(n)},Xo.geom.quadtree=function(n,t,e,r,u){function i(n){function i(n,t,e,r,u,i,o,a){if(!isNaN(e)&&!isNaN(r))if(n.leaf){var c=n.x,l=n.y;if(null!=c)if(oa(c-e)+oa(l-r)<.01)s(n,t,e,r,u,i,o,a);else{var f=n.point;n.x=n.y=n.point=null,s(n,f,c,l,u,i,o,a),s(n,t,e,r,u,i,o,a)}else n.x=e,n.y=r,n.point=t}else s(n,t,e,r,u,i,o,a)}function s(n,t,e,r,u,o,a,c){var s=.5*(u+a),l=.5*(o+c),f=e>=s,h=r>=l,g=(h<<1)+f;n.leaf=!1,n=n.nodes[g]||(n.nodes[g]=iu()),f?u=s:a=s,h?o=l:c=l,i(n,t,e,r,u,o,a,c)}var l,f,h,g,p,v,d,m,y,x=_t(a),M=_t(c);if(null!=t)v=t,d=e,m=r,y=u;else if(m=y=-(v=d=1/0),f=[],h=[],p=n.length,o)for(g=0;p>g;++g)l=n[g],l.x<v&&(v=l.x),l.y<d&&(d=l.y),l.x>m&&(m=l.x),l.y>y&&(y=l.y),f.push(l.x),h.push(l.y);else for(g=0;p>g;++g){var _=+x(l=n[g],g),b=+M(l,g);v>_&&(v=_),d>b&&(d=b),_>m&&(m=_),b>y&&(y=b),f.push(_),h.push(b)}var w=m-v,S=y-d;w>S?y=d+w:m=v+S;var k=iu();if(k.add=function(n){i(k,n,+x(n,++g),+M(n,g),v,d,m,y)},k.visit=function(n){ou(n,k,v,d,m,y)},g=-1,null==t){for(;++g<p;)i(k,n[g],f[g],h[g],v,d,m,y);--g}else n.forEach(k.add);return f=h=n=l=null,k}var o,a=br,c=wr;return(o=arguments.length)?(a=ru,c=uu,3===o&&(u=e,r=t,e=t=0),i(n)):(i.x=function(n){return arguments.length?(a=n,i):a},i.y=function(n){return arguments.length?(c=n,i):c},i.extent=function(n){return arguments.length?(null==n?t=e=r=u=null:(t=+n[0][0],e=+n[0][1],r=+n[1][0],u=+n[1][1]),i):null==t?null:[[t,e],[r,u]]},i.size=function(n){return arguments.length?(null==n?t=e=r=u=null:(t=e=0,r=+n[0],u=+n[1]),i):null==t?null:[r-t,u-e]},i)},Xo.interpolateRgb=au,Xo.interpolateObject=cu,Xo.interpolateNumber=su,Xo.interpolateString=lu;var Qc=/[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g;Xo.interpolate=fu,Xo.interpolators=[function(n,t){var e=typeof t;return("string"===e?Va.has(t)||/^(#|rgb\(|hsl\()/.test(t)?au:lu:t instanceof G?au:"object"===e?Array.isArray(t)?hu:cu:su)(n,t)}],Xo.interpolateArray=hu;var ns=function(){return bt},ts=Xo.map({linear:ns,poly:xu,quad:function(){return du},cubic:function(){return mu},sin:function(){return Mu},exp:function(){return _u},circle:function(){return bu},elastic:wu,back:Su,bounce:function(){return ku}}),es=Xo.map({"in":bt,out:pu,"in-out":vu,"out-in":function(n){return vu(pu(n))}});Xo.ease=function(n){var t=n.indexOf("-"),e=t>=0?n.substring(0,t):n,r=t>=0?n.substring(t+1):"in";return e=ts.get(e)||ns,r=es.get(r)||bt,gu(r(e.apply(null,$o.call(arguments,1))))},Xo.interpolateHcl=Eu,Xo.interpolateHsl=Au,Xo.interpolateLab=Cu,Xo.interpolateRound=Nu,Xo.transform=function(n){var t=Wo.createElementNS(Xo.ns.prefix.svg,"g");return(Xo.transform=function(n){if(null!=n){t.setAttribute("transform",n);var e=t.transform.baseVal.consolidate()}return new Lu(e?e.matrix:rs)})(n)},Lu.prototype.toString=function(){return"translate("+this.translate+")rotate("+this.rotate+")skewX("+this.skew+")scale("+this.scale+")"};var rs={a:1,b:0,c:0,d:1,e:0,f:0};Xo.interpolateTransform=Ru,Xo.layout={},Xo.layout.bundle=function(){return function(n){for(var t=[],e=-1,r=n.length;++e<r;)t.push(Uu(n[e]));return t}},Xo.layout.chord=function(){function n(){var n,s,f,h,g,p={},v=[],d=Xo.range(i),m=[];for(e=[],r=[],n=0,h=-1;++h<i;){for(s=0,g=-1;++g<i;)s+=u[h][g];v.push(s),m.push(Xo.range(i)),n+=s}for(o&&d.sort(function(n,t){return o(v[n],v[t])}),a&&m.forEach(function(n,t){n.sort(function(n,e){return a(u[t][n],u[t][e])})}),n=(ka-l*i)/n,s=0,h=-1;++h<i;){for(f=s,g=-1;++g<i;){var y=d[h],x=m[y][g],M=u[y][x],_=s,b=s+=M*n;p[y+"-"+x]={index:y,subindex:x,startAngle:_,endAngle:b,value:M}}r[y]={index:y,startAngle:f,endAngle:s,value:(s-f)/n},s+=l}for(h=-1;++h<i;)for(g=h-1;++g<i;){var w=p[h+"-"+g],S=p[g+"-"+h];(w.value||S.value)&&e.push(w.value<S.value?{source:S,target:w}:{source:w,target:S})}c&&t()}function t(){e.sort(function(n,t){return c((n.source.value+n.target.value)/2,(t.source.value+t.target.value)/2)})}var e,r,u,i,o,a,c,s={},l=0;return s.matrix=function(n){return arguments.length?(i=(u=n)&&u.length,e=r=null,s):u},s.padding=function(n){return arguments.length?(l=n,e=r=null,s):l},s.sortGroups=function(n){return arguments.length?(o=n,e=r=null,s):o},s.sortSubgroups=function(n){return arguments.length?(a=n,e=null,s):a},s.sortChords=function(n){return arguments.length?(c=n,e&&t(),s):c},s.chords=function(){return e||n(),e},s.groups=function(){return r||n(),r},s},Xo.layout.force=function(){function n(n){return function(t,e,r,u){if(t.point!==n){var i=t.cx-n.x,o=t.cy-n.y,a=u-e,c=i*i+o*o;if(c>a*a/d){if(p>c){var s=t.charge/c;n.px-=i*s,n.py-=o*s}return!0}if(t.point&&c&&p>c){var s=t.pointCharge/c;n.px-=i*s,n.py-=o*s}}return!t.charge}}function t(n){n.px=Xo.event.x,n.py=Xo.event.y,a.resume()}var e,r,u,i,o,a={},c=Xo.dispatch("start","tick","end"),s=[1,1],l=.9,f=us,h=is,g=-30,p=os,v=.1,d=.64,m=[],y=[];return a.tick=function(){if((r*=.99)<.005)return c.end({type:"end",alpha:r=0}),!0;var t,e,a,f,h,p,d,x,M,_=m.length,b=y.length;for(e=0;b>e;++e)a=y[e],f=a.source,h=a.target,x=h.x-f.x,M=h.y-f.y,(p=x*x+M*M)&&(p=r*i[e]*((p=Math.sqrt(p))-u[e])/p,x*=p,M*=p,h.x-=x*(d=f.weight/(h.weight+f.weight)),h.y-=M*d,f.x+=x*(d=1-d),f.y+=M*d);if((d=r*v)&&(x=s[0]/2,M=s[1]/2,e=-1,d))for(;++e<_;)a=m[e],a.x+=(x-a.x)*d,a.y+=(M-a.y)*d;if(g)for(Zu(t=Xo.geom.quadtree(m),r,o),e=-1;++e<_;)(a=m[e]).fixed||t.visit(n(a));for(e=-1;++e<_;)a=m[e],a.fixed?(a.x=a.px,a.y=a.py):(a.x-=(a.px-(a.px=a.x))*l,a.y-=(a.py-(a.py=a.y))*l);c.tick({type:"tick",alpha:r})},a.nodes=function(n){return arguments.length?(m=n,a):m},a.links=function(n){return arguments.length?(y=n,a):y},a.size=function(n){return arguments.length?(s=n,a):s},a.linkDistance=function(n){return arguments.length?(f="function"==typeof n?n:+n,a):f},a.distance=a.linkDistance,a.linkStrength=function(n){return arguments.length?(h="function"==typeof n?n:+n,a):h},a.friction=function(n){return arguments.length?(l=+n,a):l},a.charge=function(n){return arguments.length?(g="function"==typeof n?n:+n,a):g},a.chargeDistance=function(n){return arguments.length?(p=n*n,a):Math.sqrt(p)},a.gravity=function(n){return arguments.length?(v=+n,a):v},a.theta=function(n){return arguments.length?(d=n*n,a):Math.sqrt(d)},a.alpha=function(n){return arguments.length?(n=+n,r?r=n>0?n:0:n>0&&(c.start({type:"start",alpha:r=n}),Xo.timer(a.tick)),a):r},a.start=function(){function n(n,r){if(!e){for(e=new Array(c),a=0;c>a;++a)e[a]=[];for(a=0;s>a;++a){var u=y[a];e[u.source.index].push(u.target),e[u.target.index].push(u.source)}}for(var i,o=e[t],a=-1,s=o.length;++a<s;)if(!isNaN(i=o[a][n]))return i;return Math.random()*r}var t,e,r,c=m.length,l=y.length,p=s[0],v=s[1];for(t=0;c>t;++t)(r=m[t]).index=t,r.weight=0;for(t=0;l>t;++t)r=y[t],"number"==typeof r.source&&(r.source=m[r.source]),"number"==typeof r.target&&(r.target=m[r.target]),++r.source.weight,++r.target.weight;for(t=0;c>t;++t)r=m[t],isNaN(r.x)&&(r.x=n("x",p)),isNaN(r.y)&&(r.y=n("y",v)),isNaN(r.px)&&(r.px=r.x),isNaN(r.py)&&(r.py=r.y);if(u=[],"function"==typeof f)for(t=0;l>t;++t)u[t]=+f.call(this,y[t],t);else for(t=0;l>t;++t)u[t]=f;if(i=[],"function"==typeof h)for(t=0;l>t;++t)i[t]=+h.call(this,y[t],t);else for(t=0;l>t;++t)i[t]=h;if(o=[],"function"==typeof g)for(t=0;c>t;++t)o[t]=+g.call(this,m[t],t);else for(t=0;c>t;++t)o[t]=g;return a.resume()},a.resume=function(){return a.alpha(.1)},a.stop=function(){return a.alpha(0)},a.drag=function(){return e||(e=Xo.behavior.drag().origin(bt).on("dragstart.force",Fu).on("drag.force",t).on("dragend.force",Ou)),arguments.length?(this.on("mouseover.force",Yu).on("mouseout.force",Iu).call(e),void 0):e},Xo.rebind(a,c,"on")};var us=20,is=1,os=1/0;Xo.layout.hierarchy=function(){function n(t,o,a){var c=u.call(e,t,o);if(t.depth=o,a.push(t),c&&(s=c.length)){for(var s,l,f=-1,h=t.children=new Array(s),g=0,p=o+1;++f<s;)l=h[f]=n(c[f],p,a),l.parent=t,g+=l.value;r&&h.sort(r),i&&(t.value=g)}else delete t.children,i&&(t.value=+i.call(e,t,o)||0);return t}function t(n,r){var u=n.children,o=0;if(u&&(a=u.length))for(var a,c=-1,s=r+1;++c<a;)o+=t(u[c],s);else i&&(o=+i.call(e,n,r)||0);return i&&(n.value=o),o}function e(t){var e=[];return n(t,0,e),e}var r=Bu,u=Xu,i=$u;return e.sort=function(n){return arguments.length?(r=n,e):r},e.children=function(n){return arguments.length?(u=n,e):u},e.value=function(n){return arguments.length?(i=n,e):i},e.revalue=function(n){return t(n,0),n},e},Xo.layout.partition=function(){function n(t,e,r,u){var i=t.children;if(t.x=e,t.y=t.depth*u,t.dx=r,t.dy=u,i&&(o=i.length)){var o,a,c,s=-1;for(r=t.value?r/t.value:0;++s<o;)n(a=i[s],e,c=a.value*r,u),e+=c}}function t(n){var e=n.children,r=0;if(e&&(u=e.length))for(var u,i=-1;++i<u;)r=Math.max(r,t(e[i]));return 1+r}function e(e,i){var o=r.call(this,e,i);return n(o[0],0,u[0],u[1]/t(o[0])),o}var r=Xo.layout.hierarchy(),u=[1,1];return e.size=function(n){return arguments.length?(u=n,e):u},Vu(e,r)},Xo.layout.pie=function(){function n(i){var o=i.map(function(e,r){return+t.call(n,e,r)}),a=+("function"==typeof r?r.apply(this,arguments):r),c=(("function"==typeof u?u.apply(this,arguments):u)-a)/Xo.sum(o),s=Xo.range(i.length);null!=e&&s.sort(e===as?function(n,t){return o[t]-o[n]}:function(n,t){return e(i[n],i[t])});var l=[];return s.forEach(function(n){var t;l[n]={data:i[n],value:t=o[n],startAngle:a,endAngle:a+=t*c}}),l}var t=Number,e=as,r=0,u=ka;return n.value=function(e){return arguments.length?(t=e,n):t},n.sort=function(t){return arguments.length?(e=t,n):e},n.startAngle=function(t){return arguments.length?(r=t,n):r},n.endAngle=function(t){return arguments.length?(u=t,n):u},n};var as={};Xo.layout.stack=function(){function n(a,c){var s=a.map(function(e,r){return t.call(n,e,r)}),l=s.map(function(t){return t.map(function(t,e){return[i.call(n,t,e),o.call(n,t,e)]})}),f=e.call(n,l,c);s=Xo.permute(s,f),l=Xo.permute(l,f);var h,g,p,v=r.call(n,l,c),d=s.length,m=s[0].length;for(g=0;m>g;++g)for(u.call(n,s[0][g],p=v[g],l[0][g][1]),h=1;d>h;++h)u.call(n,s[h][g],p+=l[h-1][g][1],l[h][g][1]);return a}var t=bt,e=Qu,r=ni,u=Ku,i=Ju,o=Gu;return n.values=function(e){return arguments.length?(t=e,n):t},n.order=function(t){return arguments.length?(e="function"==typeof t?t:cs.get(t)||Qu,n):e},n.offset=function(t){return arguments.length?(r="function"==typeof t?t:ss.get(t)||ni,n):r},n.x=function(t){return arguments.length?(i=t,n):i},n.y=function(t){return arguments.length?(o=t,n):o},n.out=function(t){return arguments.length?(u=t,n):u},n};var cs=Xo.map({"inside-out":function(n){var t,e,r=n.length,u=n.map(ti),i=n.map(ei),o=Xo.range(r).sort(function(n,t){return u[n]-u[t]}),a=0,c=0,s=[],l=[];for(t=0;r>t;++t)e=o[t],c>a?(a+=i[e],s.push(e)):(c+=i[e],l.push(e));return l.reverse().concat(s)},reverse:function(n){return Xo.range(n.length).reverse()},"default":Qu}),ss=Xo.map({silhouette:function(n){var t,e,r,u=n.length,i=n[0].length,o=[],a=0,c=[];for(e=0;i>e;++e){for(t=0,r=0;u>t;t++)r+=n[t][e][1];r>a&&(a=r),o.push(r)}for(e=0;i>e;++e)c[e]=(a-o[e])/2;return c},wiggle:function(n){var t,e,r,u,i,o,a,c,s,l=n.length,f=n[0],h=f.length,g=[];for(g[0]=c=s=0,e=1;h>e;++e){for(t=0,u=0;l>t;++t)u+=n[t][e][1];for(t=0,i=0,a=f[e][0]-f[e-1][0];l>t;++t){for(r=0,o=(n[t][e][1]-n[t][e-1][1])/(2*a);t>r;++r)o+=(n[r][e][1]-n[r][e-1][1])/a;i+=o*n[t][e][1]}g[e]=c-=u?i/u*a:0,s>c&&(s=c)}for(e=0;h>e;++e)g[e]-=s;return g},expand:function(n){var t,e,r,u=n.length,i=n[0].length,o=1/u,a=[];for(e=0;i>e;++e){for(t=0,r=0;u>t;t++)r+=n[t][e][1];if(r)for(t=0;u>t;t++)n[t][e][1]/=r;else for(t=0;u>t;t++)n[t][e][1]=o}for(e=0;i>e;++e)a[e]=0;return a},zero:ni});Xo.layout.histogram=function(){function n(n,i){for(var o,a,c=[],s=n.map(e,this),l=r.call(this,s,i),f=u.call(this,l,s,i),i=-1,h=s.length,g=f.length-1,p=t?1:1/h;++i<g;)o=c[i]=[],o.dx=f[i+1]-(o.x=f[i]),o.y=0;if(g>0)for(i=-1;++i<h;)a=s[i],a>=l[0]&&a<=l[1]&&(o=c[Xo.bisect(f,a,1,g)-1],o.y+=p,o.push(n[i]));return c}var t=!0,e=Number,r=oi,u=ui;return n.value=function(t){return arguments.length?(e=t,n):e},n.range=function(t){return arguments.length?(r=_t(t),n):r},n.bins=function(t){return arguments.length?(u="number"==typeof t?function(n){return ii(n,t)}:_t(t),n):u},n.frequency=function(e){return arguments.length?(t=!!e,n):t},n},Xo.layout.tree=function(){function n(n,i){function o(n,t){var r=n.children,u=n._tree;if(r&&(i=r.length)){for(var i,a,s,l=r[0],f=l,h=-1;++h<i;)s=r[h],o(s,a),f=c(s,a,f),a=s;vi(n);var g=.5*(l._tree.prelim+s._tree.prelim);t?(u.prelim=t._tree.prelim+e(n,t),u.mod=u.prelim-g):u.prelim=g}else t&&(u.prelim=t._tree.prelim+e(n,t))}function a(n,t){n.x=n._tree.prelim+t;var e=n.children;if(e&&(r=e.length)){var r,u=-1;for(t+=n._tree.mod;++u<r;)a(e[u],t)}}function c(n,t,r){if(t){for(var u,i=n,o=n,a=t,c=n.parent.children[0],s=i._tree.mod,l=o._tree.mod,f=a._tree.mod,h=c._tree.mod;a=si(a),i=ci(i),a&&i;)c=ci(c),o=si(o),o._tree.ancestor=n,u=a._tree.prelim+f-i._tree.prelim-s+e(a,i),u>0&&(di(mi(a,n,r),n,u),s+=u,l+=u),f+=a._tree.mod,s+=i._tree.mod,h+=c._tree.mod,l+=o._tree.mod;a&&!si(o)&&(o._tree.thread=a,o._tree.mod+=f-l),i&&!ci(c)&&(c._tree.thread=i,c._tree.mod+=s-h,r=n)}return r}var s=t.call(this,n,i),l=s[0];pi(l,function(n,t){n._tree={ancestor:n,prelim:0,mod:0,change:0,shift:0,number:t?t._tree.number+1:0}}),o(l),a(l,-l._tree.prelim);var f=li(l,hi),h=li(l,fi),g=li(l,gi),p=f.x-e(f,h)/2,v=h.x+e(h,f)/2,d=g.depth||1;return pi(l,u?function(n){n.x*=r[0],n.y=n.depth*r[1],delete n._tree}:function(n){n.x=(n.x-p)/(v-p)*r[0],n.y=n.depth/d*r[1],delete n._tree}),s}var t=Xo.layout.hierarchy().sort(null).value(null),e=ai,r=[1,1],u=!1;return n.separation=function(t){return arguments.length?(e=t,n):e},n.size=function(t){return arguments.length?(u=null==(r=t),n):u?null:r},n.nodeSize=function(t){return arguments.length?(u=null!=(r=t),n):u?r:null},Vu(n,t)},Xo.layout.pack=function(){function n(n,i){var o=e.call(this,n,i),a=o[0],c=u[0],s=u[1],l=null==t?Math.sqrt:"function"==typeof t?t:function(){return t};if(a.x=a.y=0,pi(a,function(n){n.r=+l(n.value)}),pi(a,bi),r){var f=r*(t?1:Math.max(2*a.r/c,2*a.r/s))/2;pi(a,function(n){n.r+=f}),pi(a,bi),pi(a,function(n){n.r-=f})}return ki(a,c/2,s/2,t?1:1/Math.max(2*a.r/c,2*a.r/s)),o}var t,e=Xo.layout.hierarchy().sort(yi),r=0,u=[1,1];return n.size=function(t){return arguments.length?(u=t,n):u},n.radius=function(e){return arguments.length?(t=null==e||"function"==typeof e?e:+e,n):t},n.padding=function(t){return arguments.length?(r=+t,n):r},Vu(n,e)},Xo.layout.cluster=function(){function n(n,i){var o,a=t.call(this,n,i),c=a[0],s=0;pi(c,function(n){var t=n.children;t&&t.length?(n.x=Ci(t),n.y=Ai(t)):(n.x=o?s+=e(n,o):0,n.y=0,o=n)});var l=Ni(c),f=Li(c),h=l.x-e(l,f)/2,g=f.x+e(f,l)/2;return pi(c,u?function(n){n.x=(n.x-c.x)*r[0],n.y=(c.y-n.y)*r[1]}:function(n){n.x=(n.x-h)/(g-h)*r[0],n.y=(1-(c.y?n.y/c.y:1))*r[1]}),a}var t=Xo.layout.hierarchy().sort(null).value(null),e=ai,r=[1,1],u=!1;return n.separation=function(t){return arguments.length?(e=t,n):e},n.size=function(t){return arguments.length?(u=null==(r=t),n):u?null:r},n.nodeSize=function(t){return arguments.length?(u=null!=(r=t),n):u?r:null},Vu(n,t)},Xo.layout.treemap=function(){function n(n,t){for(var e,r,u=-1,i=n.length;++u<i;)r=(e=n[u]).value*(0>t?0:t),e.area=isNaN(r)||0>=r?0:r}function t(e){var i=e.children;if(i&&i.length){var o,a,c,s=f(e),l=[],h=i.slice(),p=1/0,v="slice"===g?s.dx:"dice"===g?s.dy:"slice-dice"===g?1&e.depth?s.dy:s.dx:Math.min(s.dx,s.dy);for(n(h,s.dx*s.dy/e.value),l.area=0;(c=h.length)>0;)l.push(o=h[c-1]),l.area+=o.area,"squarify"!==g||(a=r(l,v))<=p?(h.pop(),p=a):(l.area-=l.pop().area,u(l,v,s,!1),v=Math.min(s.dx,s.dy),l.length=l.area=0,p=1/0);l.length&&(u(l,v,s,!0),l.length=l.area=0),i.forEach(t)}}function e(t){var r=t.children;if(r&&r.length){var i,o=f(t),a=r.slice(),c=[];for(n(a,o.dx*o.dy/t.value),c.area=0;i=a.pop();)c.push(i),c.area+=i.area,null!=i.z&&(u(c,i.z?o.dx:o.dy,o,!a.length),c.length=c.area=0);r.forEach(e)}}function r(n,t){for(var e,r=n.area,u=0,i=1/0,o=-1,a=n.length;++o<a;)(e=n[o].area)&&(i>e&&(i=e),e>u&&(u=e));return r*=r,t*=t,r?Math.max(t*u*p/r,r/(t*i*p)):1/0}function u(n,t,e,r){var u,i=-1,o=n.length,a=e.x,s=e.y,l=t?c(n.area/t):0;if(t==e.dx){for((r||l>e.dy)&&(l=e.dy);++i<o;)u=n[i],u.x=a,u.y=s,u.dy=l,a+=u.dx=Math.min(e.x+e.dx-a,l?c(u.area/l):0);u.z=!0,u.dx+=e.x+e.dx-a,e.y+=l,e.dy-=l}else{for((r||l>e.dx)&&(l=e.dx);++i<o;)u=n[i],u.x=a,u.y=s,u.dx=l,s+=u.dy=Math.min(e.y+e.dy-s,l?c(u.area/l):0);u.z=!1,u.dy+=e.y+e.dy-s,e.x+=l,e.dx-=l}}function i(r){var u=o||a(r),i=u[0];return i.x=0,i.y=0,i.dx=s[0],i.dy=s[1],o&&a.revalue(i),n([i],i.dx*i.dy/i.value),(o?e:t)(i),h&&(o=u),u}var o,a=Xo.layout.hierarchy(),c=Math.round,s=[1,1],l=null,f=zi,h=!1,g="squarify",p=.5*(1+Math.sqrt(5));return i.size=function(n){return arguments.length?(s=n,i):s},i.padding=function(n){function t(t){var e=n.call(i,t,t.depth);return null==e?zi(t):qi(t,"number"==typeof e?[e,e,e,e]:e)}function e(t){return qi(t,n)}if(!arguments.length)return l;var r;return f=null==(l=n)?zi:"function"==(r=typeof n)?t:"number"===r?(n=[n,n,n,n],e):e,i},i.round=function(n){return arguments.length?(c=n?Math.round:Number,i):c!=Number},i.sticky=function(n){return arguments.length?(h=n,o=null,i):h},i.ratio=function(n){return arguments.length?(p=n,i):p},i.mode=function(n){return arguments.length?(g=n+"",i):g},Vu(i,a)},Xo.random={normal:function(n,t){var e=arguments.length;return 2>e&&(t=1),1>e&&(n=0),function(){var e,r,u;do e=2*Math.random()-1,r=2*Math.random()-1,u=e*e+r*r;while(!u||u>1);return n+t*e*Math.sqrt(-2*Math.log(u)/u)}},logNormal:function(){var n=Xo.random.normal.apply(Xo,arguments);return function(){return Math.exp(n())}},bates:function(n){var t=Xo.random.irwinHall(n);return function(){return t()/n}},irwinHall:function(n){return function(){for(var t=0,e=0;n>e;e++)t+=Math.random();return t}}},Xo.scale={};var ls={floor:bt,ceil:bt};Xo.scale.linear=function(){return Hi([0,1],[0,1],fu,!1)};var fs={s:1,g:1,p:1,r:1,e:1};Xo.scale.log=function(){return $i(Xo.scale.linear().domain([0,1]),10,!0,[1,10])};var hs=Xo.format(".0e"),gs={floor:function(n){return-Math.ceil(-n)},ceil:function(n){return-Math.floor(-n)}};Xo.scale.pow=function(){return Bi(Xo.scale.linear(),1,[0,1])},Xo.scale.sqrt=function(){return Xo.scale.pow().exponent(.5)},Xo.scale.ordinal=function(){return Ji([],{t:"range",a:[[]]})},Xo.scale.category10=function(){return Xo.scale.ordinal().range(ps)},Xo.scale.category20=function(){return Xo.scale.ordinal().range(vs)},Xo.scale.category20b=function(){return Xo.scale.ordinal().range(ds)},Xo.scale.category20c=function(){return Xo.scale.ordinal().range(ms)};var ps=[2062260,16744206,2924588,14034728,9725885,9197131,14907330,8355711,12369186,1556175].map(ht),vs=[2062260,11454440,16744206,16759672,2924588,10018698,14034728,16750742,9725885,12955861,9197131,12885140,14907330,16234194,8355711,13092807,12369186,14408589,1556175,10410725].map(ht),ds=[3750777,5395619,7040719,10264286,6519097,9216594,11915115,13556636,9202993,12426809,15186514,15190932,8666169,11356490,14049643,15177372,8077683,10834324,13528509,14589654].map(ht),ms=[3244733,7057110,10406625,13032431,15095053,16616764,16625259,16634018,3253076,7652470,10607003,13101504,7695281,10394312,12369372,14342891,6513507,9868950,12434877,14277081].map(ht);Xo.scale.quantile=function(){return Gi([],[])
+},Xo.scale.quantize=function(){return Ki(0,1,[0,1])},Xo.scale.threshold=function(){return Qi([.5],[0,1])},Xo.scale.identity=function(){return no([0,1])},Xo.svg={},Xo.svg.arc=function(){function n(){var n=t.apply(this,arguments),i=e.apply(this,arguments),o=r.apply(this,arguments)+ys,a=u.apply(this,arguments)+ys,c=(o>a&&(c=o,o=a,a=c),a-o),s=Sa>c?"0":"1",l=Math.cos(o),f=Math.sin(o),h=Math.cos(a),g=Math.sin(a);return c>=xs?n?"M0,"+i+"A"+i+","+i+" 0 1,1 0,"+-i+"A"+i+","+i+" 0 1,1 0,"+i+"M0,"+n+"A"+n+","+n+" 0 1,0 0,"+-n+"A"+n+","+n+" 0 1,0 0,"+n+"Z":"M0,"+i+"A"+i+","+i+" 0 1,1 0,"+-i+"A"+i+","+i+" 0 1,1 0,"+i+"Z":n?"M"+i*l+","+i*f+"A"+i+","+i+" 0 "+s+",1 "+i*h+","+i*g+"L"+n*h+","+n*g+"A"+n+","+n+" 0 "+s+",0 "+n*l+","+n*f+"Z":"M"+i*l+","+i*f+"A"+i+","+i+" 0 "+s+",1 "+i*h+","+i*g+"L0,0"+"Z"}var t=to,e=eo,r=ro,u=uo;return n.innerRadius=function(e){return arguments.length?(t=_t(e),n):t},n.outerRadius=function(t){return arguments.length?(e=_t(t),n):e},n.startAngle=function(t){return arguments.length?(r=_t(t),n):r},n.endAngle=function(t){return arguments.length?(u=_t(t),n):u},n.centroid=function(){var n=(t.apply(this,arguments)+e.apply(this,arguments))/2,i=(r.apply(this,arguments)+u.apply(this,arguments))/2+ys;return[Math.cos(i)*n,Math.sin(i)*n]},n};var ys=-Ea,xs=ka-Aa;Xo.svg.line=function(){return io(bt)};var Ms=Xo.map({linear:oo,"linear-closed":ao,step:co,"step-before":so,"step-after":lo,basis:mo,"basis-open":yo,"basis-closed":xo,bundle:Mo,cardinal:go,"cardinal-open":fo,"cardinal-closed":ho,monotone:Eo});Ms.forEach(function(n,t){t.key=n,t.closed=/-closed$/.test(n)});var _s=[0,2/3,1/3,0],bs=[0,1/3,2/3,0],ws=[0,1/6,2/3,1/6];Xo.svg.line.radial=function(){var n=io(Ao);return n.radius=n.x,delete n.x,n.angle=n.y,delete n.y,n},so.reverse=lo,lo.reverse=so,Xo.svg.area=function(){return Co(bt)},Xo.svg.area.radial=function(){var n=Co(Ao);return n.radius=n.x,delete n.x,n.innerRadius=n.x0,delete n.x0,n.outerRadius=n.x1,delete n.x1,n.angle=n.y,delete n.y,n.startAngle=n.y0,delete n.y0,n.endAngle=n.y1,delete n.y1,n},Xo.svg.chord=function(){function n(n,a){var c=t(this,i,n,a),s=t(this,o,n,a);return"M"+c.p0+r(c.r,c.p1,c.a1-c.a0)+(e(c,s)?u(c.r,c.p1,c.r,c.p0):u(c.r,c.p1,s.r,s.p0)+r(s.r,s.p1,s.a1-s.a0)+u(s.r,s.p1,c.r,c.p0))+"Z"}function t(n,t,e,r){var u=t.call(n,e,r),i=a.call(n,u,r),o=c.call(n,u,r)+ys,l=s.call(n,u,r)+ys;return{r:i,a0:o,a1:l,p0:[i*Math.cos(o),i*Math.sin(o)],p1:[i*Math.cos(l),i*Math.sin(l)]}}function e(n,t){return n.a0==t.a0&&n.a1==t.a1}function r(n,t,e){return"A"+n+","+n+" 0 "+ +(e>Sa)+",1 "+t}function u(n,t,e,r){return"Q 0,0 "+r}var i=hr,o=gr,a=No,c=ro,s=uo;return n.radius=function(t){return arguments.length?(a=_t(t),n):a},n.source=function(t){return arguments.length?(i=_t(t),n):i},n.target=function(t){return arguments.length?(o=_t(t),n):o},n.startAngle=function(t){return arguments.length?(c=_t(t),n):c},n.endAngle=function(t){return arguments.length?(s=_t(t),n):s},n},Xo.svg.diagonal=function(){function n(n,u){var i=t.call(this,n,u),o=e.call(this,n,u),a=(i.y+o.y)/2,c=[i,{x:i.x,y:a},{x:o.x,y:a},o];return c=c.map(r),"M"+c[0]+"C"+c[1]+" "+c[2]+" "+c[3]}var t=hr,e=gr,r=Lo;return n.source=function(e){return arguments.length?(t=_t(e),n):t},n.target=function(t){return arguments.length?(e=_t(t),n):e},n.projection=function(t){return arguments.length?(r=t,n):r},n},Xo.svg.diagonal.radial=function(){var n=Xo.svg.diagonal(),t=Lo,e=n.projection;return n.projection=function(n){return arguments.length?e(zo(t=n)):t},n},Xo.svg.symbol=function(){function n(n,r){return(Ss.get(t.call(this,n,r))||Ro)(e.call(this,n,r))}var t=To,e=qo;return n.type=function(e){return arguments.length?(t=_t(e),n):t},n.size=function(t){return arguments.length?(e=_t(t),n):e},n};var Ss=Xo.map({circle:Ro,cross:function(n){var t=Math.sqrt(n/5)/2;return"M"+-3*t+","+-t+"H"+-t+"V"+-3*t+"H"+t+"V"+-t+"H"+3*t+"V"+t+"H"+t+"V"+3*t+"H"+-t+"V"+t+"H"+-3*t+"Z"},diamond:function(n){var t=Math.sqrt(n/(2*Cs)),e=t*Cs;return"M0,"+-t+"L"+e+",0"+" 0,"+t+" "+-e+",0"+"Z"},square:function(n){var t=Math.sqrt(n)/2;return"M"+-t+","+-t+"L"+t+","+-t+" "+t+","+t+" "+-t+","+t+"Z"},"triangle-down":function(n){var t=Math.sqrt(n/As),e=t*As/2;return"M0,"+e+"L"+t+","+-e+" "+-t+","+-e+"Z"},"triangle-up":function(n){var t=Math.sqrt(n/As),e=t*As/2;return"M0,"+-e+"L"+t+","+e+" "+-t+","+e+"Z"}});Xo.svg.symbolTypes=Ss.keys();var ks,Es,As=Math.sqrt(3),Cs=Math.tan(30*Na),Ns=[],Ls=0;Ns.call=da.call,Ns.empty=da.empty,Ns.node=da.node,Ns.size=da.size,Xo.transition=function(n){return arguments.length?ks?n.transition():n:xa.transition()},Xo.transition.prototype=Ns,Ns.select=function(n){var t,e,r,u=this.id,i=[];n=M(n);for(var o=-1,a=this.length;++o<a;){i.push(t=[]);for(var c=this[o],s=-1,l=c.length;++s<l;)(r=c[s])&&(e=n.call(r,r.__data__,s,o))?("__data__"in r&&(e.__data__=r.__data__),jo(e,s,u,r.__transition__[u]),t.push(e)):t.push(null)}return Do(i,u)},Ns.selectAll=function(n){var t,e,r,u,i,o=this.id,a=[];n=_(n);for(var c=-1,s=this.length;++c<s;)for(var l=this[c],f=-1,h=l.length;++f<h;)if(r=l[f]){i=r.__transition__[o],e=n.call(r,r.__data__,f,c),a.push(t=[]);for(var g=-1,p=e.length;++g<p;)(u=e[g])&&jo(u,g,o,i),t.push(u)}return Do(a,o)},Ns.filter=function(n){var t,e,r,u=[];"function"!=typeof n&&(n=q(n));for(var i=0,o=this.length;o>i;i++){u.push(t=[]);for(var e=this[i],a=0,c=e.length;c>a;a++)(r=e[a])&&n.call(r,r.__data__,a,i)&&t.push(r)}return Do(u,this.id)},Ns.tween=function(n,t){var e=this.id;return arguments.length<2?this.node().__transition__[e].tween.get(n):R(this,null==t?function(t){t.__transition__[e].tween.remove(n)}:function(r){r.__transition__[e].tween.set(n,t)})},Ns.attr=function(n,t){function e(){this.removeAttribute(a)}function r(){this.removeAttributeNS(a.space,a.local)}function u(n){return null==n?e:(n+="",function(){var t,e=this.getAttribute(a);return e!==n&&(t=o(e,n),function(n){this.setAttribute(a,t(n))})})}function i(n){return null==n?r:(n+="",function(){var t,e=this.getAttributeNS(a.space,a.local);return e!==n&&(t=o(e,n),function(n){this.setAttributeNS(a.space,a.local,t(n))})})}if(arguments.length<2){for(t in n)this.attr(t,n[t]);return this}var o="transform"==n?Ru:fu,a=Xo.ns.qualify(n);return Po(this,"attr."+n,t,a.local?i:u)},Ns.attrTween=function(n,t){function e(n,e){var r=t.call(this,n,e,this.getAttribute(u));return r&&function(n){this.setAttribute(u,r(n))}}function r(n,e){var r=t.call(this,n,e,this.getAttributeNS(u.space,u.local));return r&&function(n){this.setAttributeNS(u.space,u.local,r(n))}}var u=Xo.ns.qualify(n);return this.tween("attr."+n,u.local?r:e)},Ns.style=function(n,t,e){function r(){this.style.removeProperty(n)}function u(t){return null==t?r:(t+="",function(){var r,u=Go.getComputedStyle(this,null).getPropertyValue(n);return u!==t&&(r=fu(u,t),function(t){this.style.setProperty(n,r(t),e)})})}var i=arguments.length;if(3>i){if("string"!=typeof n){2>i&&(t="");for(e in n)this.style(e,n[e],t);return this}e=""}return Po(this,"style."+n,t,u)},Ns.styleTween=function(n,t,e){function r(r,u){var i=t.call(this,r,u,Go.getComputedStyle(this,null).getPropertyValue(n));return i&&function(t){this.style.setProperty(n,i(t),e)}}return arguments.length<3&&(e=""),this.tween("style."+n,r)},Ns.text=function(n){return Po(this,"text",n,Uo)},Ns.remove=function(){return this.each("end.transition",function(){var n;this.__transition__.count<2&&(n=this.parentNode)&&n.removeChild(this)})},Ns.ease=function(n){var t=this.id;return arguments.length<1?this.node().__transition__[t].ease:("function"!=typeof n&&(n=Xo.ease.apply(Xo,arguments)),R(this,function(e){e.__transition__[t].ease=n}))},Ns.delay=function(n){var t=this.id;return R(this,"function"==typeof n?function(e,r,u){e.__transition__[t].delay=+n.call(e,e.__data__,r,u)}:(n=+n,function(e){e.__transition__[t].delay=n}))},Ns.duration=function(n){var t=this.id;return R(this,"function"==typeof n?function(e,r,u){e.__transition__[t].duration=Math.max(1,n.call(e,e.__data__,r,u))}:(n=Math.max(1,n),function(e){e.__transition__[t].duration=n}))},Ns.each=function(n,t){var e=this.id;if(arguments.length<2){var r=Es,u=ks;ks=e,R(this,function(t,r,u){Es=t.__transition__[e],n.call(t,t.__data__,r,u)}),Es=r,ks=u}else R(this,function(r){var u=r.__transition__[e];(u.event||(u.event=Xo.dispatch("start","end"))).on(n,t)});return this},Ns.transition=function(){for(var n,t,e,r,u=this.id,i=++Ls,o=[],a=0,c=this.length;c>a;a++){o.push(n=[]);for(var t=this[a],s=0,l=t.length;l>s;s++)(e=t[s])&&(r=Object.create(e.__transition__[u]),r.delay+=r.duration,jo(e,s,i,r)),n.push(e)}return Do(o,i)},Xo.svg.axis=function(){function n(n){n.each(function(){var n,s=Xo.select(this),l=this.__chart__||e,f=this.__chart__=e.copy(),h=null==c?f.ticks?f.ticks.apply(f,a):f.domain():c,g=null==t?f.tickFormat?f.tickFormat.apply(f,a):bt:t,p=s.selectAll(".tick").data(h,f),v=p.enter().insert("g",".domain").attr("class","tick").style("opacity",Aa),d=Xo.transition(p.exit()).style("opacity",Aa).remove(),m=Xo.transition(p).style("opacity",1),y=Ri(f),x=s.selectAll(".domain").data([0]),M=(x.enter().append("path").attr("class","domain"),Xo.transition(x));v.append("line"),v.append("text");var _=v.select("line"),b=m.select("line"),w=p.select("text").text(g),S=v.select("text"),k=m.select("text");switch(r){case"bottom":n=Ho,_.attr("y2",u),S.attr("y",Math.max(u,0)+o),b.attr("x2",0).attr("y2",u),k.attr("x",0).attr("y",Math.max(u,0)+o),w.attr("dy",".71em").style("text-anchor","middle"),M.attr("d","M"+y[0]+","+i+"V0H"+y[1]+"V"+i);break;case"top":n=Ho,_.attr("y2",-u),S.attr("y",-(Math.max(u,0)+o)),b.attr("x2",0).attr("y2",-u),k.attr("x",0).attr("y",-(Math.max(u,0)+o)),w.attr("dy","0em").style("text-anchor","middle"),M.attr("d","M"+y[0]+","+-i+"V0H"+y[1]+"V"+-i);break;case"left":n=Fo,_.attr("x2",-u),S.attr("x",-(Math.max(u,0)+o)),b.attr("x2",-u).attr("y2",0),k.attr("x",-(Math.max(u,0)+o)).attr("y",0),w.attr("dy",".32em").style("text-anchor","end"),M.attr("d","M"+-i+","+y[0]+"H0V"+y[1]+"H"+-i);break;case"right":n=Fo,_.attr("x2",u),S.attr("x",Math.max(u,0)+o),b.attr("x2",u).attr("y2",0),k.attr("x",Math.max(u,0)+o).attr("y",0),w.attr("dy",".32em").style("text-anchor","start"),M.attr("d","M"+i+","+y[0]+"H0V"+y[1]+"H"+i)}if(f.rangeBand){var E=f,A=E.rangeBand()/2;l=f=function(n){return E(n)+A}}else l.rangeBand?l=f:d.call(n,f);v.call(n,l),m.call(n,f)})}var t,e=Xo.scale.linear(),r=zs,u=6,i=6,o=3,a=[10],c=null;return n.scale=function(t){return arguments.length?(e=t,n):e},n.orient=function(t){return arguments.length?(r=t in qs?t+"":zs,n):r},n.ticks=function(){return arguments.length?(a=arguments,n):a},n.tickValues=function(t){return arguments.length?(c=t,n):c},n.tickFormat=function(e){return arguments.length?(t=e,n):t},n.tickSize=function(t){var e=arguments.length;return e?(u=+t,i=+arguments[e-1],n):u},n.innerTickSize=function(t){return arguments.length?(u=+t,n):u},n.outerTickSize=function(t){return arguments.length?(i=+t,n):i},n.tickPadding=function(t){return arguments.length?(o=+t,n):o},n.tickSubdivide=function(){return arguments.length&&n},n};var zs="bottom",qs={top:1,right:1,bottom:1,left:1};Xo.svg.brush=function(){function n(i){i.each(function(){var i=Xo.select(this).style("pointer-events","all").style("-webkit-tap-highlight-color","rgba(0,0,0,0)").on("mousedown.brush",u).on("touchstart.brush",u),o=i.selectAll(".background").data([0]);o.enter().append("rect").attr("class","background").style("visibility","hidden").style("cursor","crosshair"),i.selectAll(".extent").data([0]).enter().append("rect").attr("class","extent").style("cursor","move");var a=i.selectAll(".resize").data(p,bt);a.exit().remove(),a.enter().append("g").attr("class",function(n){return"resize "+n}).style("cursor",function(n){return Ts[n]}).append("rect").attr("x",function(n){return/[ew]$/.test(n)?-3:null}).attr("y",function(n){return/^[ns]/.test(n)?-3:null}).attr("width",6).attr("height",6).style("visibility","hidden"),a.style("display",n.empty()?"none":null);var l,f=Xo.transition(i),h=Xo.transition(o);c&&(l=Ri(c),h.attr("x",l[0]).attr("width",l[1]-l[0]),e(f)),s&&(l=Ri(s),h.attr("y",l[0]).attr("height",l[1]-l[0]),r(f)),t(f)})}function t(n){n.selectAll(".resize").attr("transform",function(n){return"translate("+l[+/e$/.test(n)]+","+f[+/^s/.test(n)]+")"})}function e(n){n.select(".extent").attr("x",l[0]),n.selectAll(".extent,.n>rect,.s>rect").attr("width",l[1]-l[0])}function r(n){n.select(".extent").attr("y",f[0]),n.selectAll(".extent,.e>rect,.w>rect").attr("height",f[1]-f[0])}function u(){function u(){32==Xo.event.keyCode&&(C||(x=null,L[0]-=l[1],L[1]-=f[1],C=2),d())}function p(){32==Xo.event.keyCode&&2==C&&(L[0]+=l[1],L[1]+=f[1],C=0,d())}function v(){var n=Xo.mouse(_),u=!1;M&&(n[0]+=M[0],n[1]+=M[1]),C||(Xo.event.altKey?(x||(x=[(l[0]+l[1])/2,(f[0]+f[1])/2]),L[0]=l[+(n[0]<x[0])],L[1]=f[+(n[1]<x[1])]):x=null),E&&m(n,c,0)&&(e(S),u=!0),A&&m(n,s,1)&&(r(S),u=!0),u&&(t(S),w({type:"brush",mode:C?"move":"resize"}))}function m(n,t,e){var r,u,a=Ri(t),c=a[0],s=a[1],p=L[e],v=e?f:l,d=v[1]-v[0];return C&&(c-=p,s-=d+p),r=(e?g:h)?Math.max(c,Math.min(s,n[e])):n[e],C?u=(r+=p)+d:(x&&(p=Math.max(c,Math.min(s,2*x[e]-r))),r>p?(u=r,r=p):u=p),v[0]!=r||v[1]!=u?(e?o=null:i=null,v[0]=r,v[1]=u,!0):void 0}function y(){v(),S.style("pointer-events","all").selectAll(".resize").style("display",n.empty()?"none":null),Xo.select("body").style("cursor",null),z.on("mousemove.brush",null).on("mouseup.brush",null).on("touchmove.brush",null).on("touchend.brush",null).on("keydown.brush",null).on("keyup.brush",null),N(),w({type:"brushend"})}var x,M,_=this,b=Xo.select(Xo.event.target),w=a.of(_,arguments),S=Xo.select(_),k=b.datum(),E=!/^(n|s)$/.test(k)&&c,A=!/^(e|w)$/.test(k)&&s,C=b.classed("extent"),N=O(),L=Xo.mouse(_),z=Xo.select(Go).on("keydown.brush",u).on("keyup.brush",p);if(Xo.event.changedTouches?z.on("touchmove.brush",v).on("touchend.brush",y):z.on("mousemove.brush",v).on("mouseup.brush",y),S.interrupt().selectAll("*").interrupt(),C)L[0]=l[0]-L[0],L[1]=f[0]-L[1];else if(k){var q=+/w$/.test(k),T=+/^n/.test(k);M=[l[1-q]-L[0],f[1-T]-L[1]],L[0]=l[q],L[1]=f[T]}else Xo.event.altKey&&(x=L.slice());S.style("pointer-events","none").selectAll(".resize").style("display",null),Xo.select("body").style("cursor",b.style("cursor")),w({type:"brushstart"}),v()}var i,o,a=y(n,"brushstart","brush","brushend"),c=null,s=null,l=[0,0],f=[0,0],h=!0,g=!0,p=Rs[0];return n.event=function(n){n.each(function(){var n=a.of(this,arguments),t={x:l,y:f,i:i,j:o},e=this.__chart__||t;this.__chart__=t,ks?Xo.select(this).transition().each("start.brush",function(){i=e.i,o=e.j,l=e.x,f=e.y,n({type:"brushstart"})}).tween("brush:brush",function(){var e=hu(l,t.x),r=hu(f,t.y);return i=o=null,function(u){l=t.x=e(u),f=t.y=r(u),n({type:"brush",mode:"resize"})}}).each("end.brush",function(){i=t.i,o=t.j,n({type:"brush",mode:"resize"}),n({type:"brushend"})}):(n({type:"brushstart"}),n({type:"brush",mode:"resize"}),n({type:"brushend"}))})},n.x=function(t){return arguments.length?(c=t,p=Rs[!c<<1|!s],n):c},n.y=function(t){return arguments.length?(s=t,p=Rs[!c<<1|!s],n):s},n.clamp=function(t){return arguments.length?(c&&s?(h=!!t[0],g=!!t[1]):c?h=!!t:s&&(g=!!t),n):c&&s?[h,g]:c?h:s?g:null},n.extent=function(t){var e,r,u,a,h;return arguments.length?(c&&(e=t[0],r=t[1],s&&(e=e[0],r=r[0]),i=[e,r],c.invert&&(e=c(e),r=c(r)),e>r&&(h=e,e=r,r=h),(e!=l[0]||r!=l[1])&&(l=[e,r])),s&&(u=t[0],a=t[1],c&&(u=u[1],a=a[1]),o=[u,a],s.invert&&(u=s(u),a=s(a)),u>a&&(h=u,u=a,a=h),(u!=f[0]||a!=f[1])&&(f=[u,a])),n):(c&&(i?(e=i[0],r=i[1]):(e=l[0],r=l[1],c.invert&&(e=c.invert(e),r=c.invert(r)),e>r&&(h=e,e=r,r=h))),s&&(o?(u=o[0],a=o[1]):(u=f[0],a=f[1],s.invert&&(u=s.invert(u),a=s.invert(a)),u>a&&(h=u,u=a,a=h))),c&&s?[[e,u],[r,a]]:c?[e,r]:s&&[u,a])},n.clear=function(){return n.empty()||(l=[0,0],f=[0,0],i=o=null),n},n.empty=function(){return!!c&&l[0]==l[1]||!!s&&f[0]==f[1]},Xo.rebind(n,a,"on")};var Ts={n:"ns-resize",e:"ew-resize",s:"ns-resize",w:"ew-resize",nw:"nwse-resize",ne:"nesw-resize",se:"nwse-resize",sw:"nesw-resize"},Rs=[["n","e","s","w","nw","ne","se","sw"],["e","w"],["n","s"],[]],Ds=tc.format=ac.timeFormat,Ps=Ds.utc,Us=Ps("%Y-%m-%dT%H:%M:%S.%LZ");Ds.iso=Date.prototype.toISOString&&+new Date("2000-01-01T00:00:00.000Z")?Oo:Us,Oo.parse=function(n){var t=new Date(n);return isNaN(t)?null:t},Oo.toString=Us.toString,tc.second=Rt(function(n){return new ec(1e3*Math.floor(n/1e3))},function(n,t){n.setTime(n.getTime()+1e3*Math.floor(t))},function(n){return n.getSeconds()}),tc.seconds=tc.second.range,tc.seconds.utc=tc.second.utc.range,tc.minute=Rt(function(n){return new ec(6e4*Math.floor(n/6e4))},function(n,t){n.setTime(n.getTime()+6e4*Math.floor(t))},function(n){return n.getMinutes()}),tc.minutes=tc.minute.range,tc.minutes.utc=tc.minute.utc.range,tc.hour=Rt(function(n){var t=n.getTimezoneOffset()/60;return new ec(36e5*(Math.floor(n/36e5-t)+t))},function(n,t){n.setTime(n.getTime()+36e5*Math.floor(t))},function(n){return n.getHours()}),tc.hours=tc.hour.range,tc.hours.utc=tc.hour.utc.range,tc.month=Rt(function(n){return n=tc.day(n),n.setDate(1),n},function(n,t){n.setMonth(n.getMonth()+t)},function(n){return n.getMonth()}),tc.months=tc.month.range,tc.months.utc=tc.month.utc.range;var js=[1e3,5e3,15e3,3e4,6e4,3e5,9e5,18e5,36e5,108e5,216e5,432e5,864e5,1728e5,6048e5,2592e6,7776e6,31536e6],Hs=[[tc.second,1],[tc.second,5],[tc.second,15],[tc.second,30],[tc.minute,1],[tc.minute,5],[tc.minute,15],[tc.minute,30],[tc.hour,1],[tc.hour,3],[tc.hour,6],[tc.hour,12],[tc.day,1],[tc.day,2],[tc.week,1],[tc.month,1],[tc.month,3],[tc.year,1]],Fs=Ds.multi([[".%L",function(n){return n.getMilliseconds()}],[":%S",function(n){return n.getSeconds()}],["%I:%M",function(n){return n.getMinutes()}],["%I %p",function(n){return n.getHours()}],["%a %d",function(n){return n.getDay()&&1!=n.getDate()}],["%b %d",function(n){return 1!=n.getDate()}],["%B",function(n){return n.getMonth()}],["%Y",be]]),Os={range:function(n,t,e){return Xo.range(+n,+t,e).map(Io)},floor:bt,ceil:bt};Hs.year=tc.year,tc.scale=function(){return Yo(Xo.scale.linear(),Hs,Fs)};var Ys=Hs.map(function(n){return[n[0].utc,n[1]]}),Is=Ps.multi([[".%L",function(n){return n.getUTCMilliseconds()}],[":%S",function(n){return n.getUTCSeconds()}],["%I:%M",function(n){return n.getUTCMinutes()}],["%I %p",function(n){return n.getUTCHours()}],["%a %d",function(n){return n.getUTCDay()&&1!=n.getUTCDate()}],["%b %d",function(n){return 1!=n.getUTCDate()}],["%B",function(n){return n.getUTCMonth()}],["%Y",be]]);Ys.year=tc.year.utc,tc.scale.utc=function(){return Yo(Xo.scale.linear(),Ys,Is)},Xo.text=wt(function(n){return n.responseText}),Xo.json=function(n,t){return St(n,"application/json",Zo,t)},Xo.html=function(n,t){return St(n,"text/html",Vo,t)},Xo.xml=wt(function(n){return n.responseXML}),"function"==typeof define&&define.amd?define(Xo):"object"==typeof module&&module.exports?module.exports=Xo:this.d3=Xo}();
\ No newline at end of file
diff --git a/themes/bootstrap3/js/vendor/jquery.dotdotdot.min.js b/themes/bootstrap3/js/vendor/jquery.dotdotdot.min.js
new file mode 100644
index 0000000000000000000000000000000000000000..419e7c36d0f9e1483232d977701c0f6a18f1e88f
--- /dev/null
+++ b/themes/bootstrap3/js/vendor/jquery.dotdotdot.min.js
@@ -0,0 +1,13 @@
+/*
+ *	jQuery dotdotdot 1.8.1
+ *
+ *	Copyright (c) Fred Heusschen
+ *	www.frebsite.nl
+ *
+ *	Plugin website:
+ *	dotdotdot.frebsite.nl
+ *
+ *	Licensed under the MIT license.
+ *	http://en.wikipedia.org/wiki/MIT_License
+ */
+!function(t,e){function n(t,e,n){var r=t.children(),o=!1;t.empty();for(var i=0,d=r.length;d>i;i++){var l=r.eq(i);if(t.append(l),n&&t.append(n),a(t,e)){l.remove(),o=!0;break}n&&n.detach()}return o}function r(e,n,i,d,l){var s=!1,c="a, table, thead, tbody, tfoot, tr, col, colgroup, object, embed, param, ol, ul, dl, blockquote, select, optgroup, option, textarea, script, style",u="script, .dotdotdot-keep";return e.contents().detach().each(function(){var h=this,f=t(h);if("undefined"==typeof h)return!0;if(f.is(u))e.append(f);else{if(s)return!0;e.append(f),!l||f.is(d.after)||f.find(d.after).length||e[e.is(c)?"after":"append"](l),a(i,d)&&(s=3==h.nodeType?o(f,n,i,d,l):r(f,n,i,d,l)),s||l&&l.detach()}}),n.addClass("is-truncated"),s}function o(e,n,r,o,d){var c=e[0];if(!c)return!1;var h=s(c),f=-1!==h.indexOf(" ")?" ":" ",p="letter"==o.wrap?"":f,g=h.split(p),v=-1,w=-1,b=0,y=g.length-1;for(o.fallbackToLetter&&0==b&&0==y&&(p="",g=h.split(p),y=g.length-1);y>=b&&(0!=b||0!=y);){var m=Math.floor((b+y)/2);if(m==w)break;w=m,l(c,g.slice(0,w+1).join(p)+o.ellipsis),r.children().each(function(){t(this).toggle().toggle()}),a(r,o)?(y=w,o.fallbackToLetter&&0==b&&0==y&&(p="",g=g[0].split(p),v=-1,w=-1,b=0,y=g.length-1)):(v=w,b=w)}if(-1==v||1==g.length&&0==g[0].length){var x=e.parent();e.detach();var C=d&&d.closest(x).length?d.length:0;x.contents().length>C?c=u(x.contents().eq(-1-C),n):(c=u(x,n,!0),C||x.detach()),c&&(h=i(s(c),o),l(c,h),C&&d&&t(c).parent().append(d))}else h=i(g.slice(0,v+1).join(p),o),l(c,h);return!0}function a(t,e){return t.innerHeight()>e.maxHeight}function i(e,n){for(;t.inArray(e.slice(-1),n.lastCharacter.remove)>-1;)e=e.slice(0,-1);return t.inArray(e.slice(-1),n.lastCharacter.noEllipsis)<0&&(e+=n.ellipsis),e}function d(t){return{width:t.innerWidth(),height:t.innerHeight()}}function l(t,e){t.innerText?t.innerText=e:t.nodeValue?t.nodeValue=e:t.textContent&&(t.textContent=e)}function s(t){return t.innerText?t.innerText:t.nodeValue?t.nodeValue:t.textContent?t.textContent:""}function c(t){do t=t.previousSibling;while(t&&1!==t.nodeType&&3!==t.nodeType);return t}function u(e,n,r){var o,a=e&&e[0];if(a){if(!r){if(3===a.nodeType)return a;if(t.trim(e.text()))return u(e.contents().last(),n)}for(o=c(a);!o;){if(e=e.parent(),e.is(n)||!e.length)return!1;o=c(e[0])}if(o)return u(t(o),n)}return!1}function h(e,n){return e?"string"==typeof e?(e=t(e,n),e.length?e:!1):e.jquery?e:!1:!1}function f(t){for(var e=t.innerHeight(),n=["paddingTop","paddingBottom"],r=0,o=n.length;o>r;r++){var a=parseInt(t.css(n[r]),10);isNaN(a)&&(a=0),e-=a}return e}if(!t.fn.dotdotdot){t.fn.dotdotdot=function(e){if(0==this.length)return t.fn.dotdotdot.debug('No element found for "'+this.selector+'".'),this;if(this.length>1)return this.each(function(){t(this).dotdotdot(e)});var o=this,i=o.contents();o.data("dotdotdot")&&o.trigger("destroy.dot"),o.data("dotdotdot-style",o.attr("style")||""),o.css("word-wrap","break-word"),"nowrap"===o.css("white-space")&&o.css("white-space","normal"),o.bind_events=function(){return o.bind("update.dot",function(e,d){switch(o.removeClass("is-truncated"),e.preventDefault(),e.stopPropagation(),typeof l.height){case"number":l.maxHeight=l.height;break;case"function":l.maxHeight=l.height.call(o[0]);break;default:l.maxHeight=f(o)}l.maxHeight+=l.tolerance,"undefined"!=typeof d&&(("string"==typeof d||"nodeType"in d&&1===d.nodeType)&&(d=t("<div />").append(d).contents()),d instanceof t&&(i=d)),g=o.wrapInner('<div class="dotdotdot" />').children(),g.contents().detach().end().append(i.clone(!0)).find("br").replaceWith("  <br />  ").end().css({height:"auto",width:"auto",border:"none",padding:0,margin:0});var c=!1,u=!1;return s.afterElement&&(c=s.afterElement.clone(!0),c.show(),s.afterElement.detach()),a(g,l)&&(u="children"==l.wrap?n(g,l,c):r(g,o,g,l,c)),g.replaceWith(g.contents()),g=null,t.isFunction(l.callback)&&l.callback.call(o[0],u,i),s.isTruncated=u,u}).bind("isTruncated.dot",function(t,e){return t.preventDefault(),t.stopPropagation(),"function"==typeof e&&e.call(o[0],s.isTruncated),s.isTruncated}).bind("originalContent.dot",function(t,e){return t.preventDefault(),t.stopPropagation(),"function"==typeof e&&e.call(o[0],i),i}).bind("destroy.dot",function(t){t.preventDefault(),t.stopPropagation(),o.unwatch().unbind_events().contents().detach().end().append(i).attr("style",o.data("dotdotdot-style")||"").removeClass("is-truncated").data("dotdotdot",!1)}),o},o.unbind_events=function(){return o.unbind(".dot"),o},o.watch=function(){if(o.unwatch(),"window"==l.watch){var e=t(window),n=e.width(),r=e.height();e.bind("resize.dot"+s.dotId,function(){n==e.width()&&r==e.height()&&l.windowResizeFix||(n=e.width(),r=e.height(),u&&clearInterval(u),u=setTimeout(function(){o.trigger("update.dot")},100))})}else c=d(o),u=setInterval(function(){if(o.is(":visible")){var t=d(o);c.width==t.width&&c.height==t.height||(o.trigger("update.dot"),c=t)}},500);return o},o.unwatch=function(){return t(window).unbind("resize.dot"+s.dotId),u&&clearInterval(u),o};var l=t.extend(!0,{},t.fn.dotdotdot.defaults,e),s={},c={},u=null,g=null;return l.lastCharacter.remove instanceof Array||(l.lastCharacter.remove=t.fn.dotdotdot.defaultArrays.lastCharacter.remove),l.lastCharacter.noEllipsis instanceof Array||(l.lastCharacter.noEllipsis=t.fn.dotdotdot.defaultArrays.lastCharacter.noEllipsis),s.afterElement=h(l.after,o),s.isTruncated=!1,s.dotId=p++,o.data("dotdotdot",!0).bind_events().trigger("update.dot"),l.watch&&o.watch(),o},t.fn.dotdotdot.defaults={ellipsis:"... ",wrap:"word",fallbackToLetter:!0,lastCharacter:{},tolerance:0,callback:null,after:null,height:null,watch:!1,windowResizeFix:!0},t.fn.dotdotdot.defaultArrays={lastCharacter:{remove:[" "," ",",",";",".","!","?"],noEllipsis:[]}},t.fn.dotdotdot.debug=function(t){};var p=1,g=t.fn.html;t.fn.html=function(n){return n!=e&&!t.isFunction(n)&&this.data("dotdotdot")?this.trigger("update",[n]):g.apply(this,arguments)};var v=t.fn.text;t.fn.text=function(n){return n!=e&&!t.isFunction(n)&&this.data("dotdotdot")?(n=t("<div />").text(n).html(),this.trigger("update",[n])):v.apply(this,arguments)}}}(jQuery),jQuery(document).ready(function(t){t(".dot-ellipsis").each(function(){var e=t(this).hasClass("dot-resize-update"),n=t(this).hasClass("dot-timer-update"),r=0,o=t(this).attr("class").split(/\s+/);t.each(o,function(t,e){var n=e.match(/^dot-height-(\d+)$/);null!==n&&(r=Number(n[1]))});var a=new Object;n&&(a.watch=!0),e&&(a.watch="window"),r>0&&(a.height=r),t(this).dotdotdot(a)})}),jQuery(window).load(function(){jQuery(".dot-ellipsis.dot-load-update").trigger("update.dot")});
\ No newline at end of file
diff --git a/themes/bootstrap3/less/bootstrap.less b/themes/bootstrap3/less/bootstrap.less
index 96cbf57419abe79f7b1773cf0e46e1bf6f2d65ad..d077d35b4d44cf773537f6a59aa599b876dd74e9 100644
--- a/themes/bootstrap3/less/bootstrap.less
+++ b/themes/bootstrap3/less/bootstrap.less
@@ -3,11 +3,12 @@
 @import "vendor/bootstrap-accessibility/bootstrap-accessibility";
 @import "vendor/a11y";
 
-@fa-font-path: "../../../../../../themes/bootstrap3/css/fonts";
+@import "components/variables";
 
 @import "components/advanced-search";
 @import "components/alphabrowse";
 @import "components/autocomplete";
+@import "components/channels";
 @import "components/icons";
 @import "components/js-tree";
 @import "components/lightbox";
@@ -18,21 +19,47 @@
 @import "components/similar-carousel";
 @import "components/sliders";
 
-.alert.alert-info a {text-decoration: underline;}
-.btn.disabled {
-  &:active,
-  &:focus,
-  &:hover {color: #000;}
-}
-header .dropdown form { display: none; }
-.list-unstyled {margin: 0;}
-.highlight,mark {
+/**
+ * Notes
+ * = As of 4.0, code styles aren't enforced, but
+ *   preferred styles are outlined here: http://codeguide.co/#css
+ * = The preferred method for writing code is to put generic and mobile styles first
+ *   and surround desktop styling with media min-width queries.
+ * = Bootstrap 3 breakpoints: <768px, >=768px, >=992px, >=1200px
+ *                                xs,      sm,      md,       lg
+ * = Breakpoint of <=530px also used to target phones specifically
+ */
+
+html { font-size: 14px; } // Root font size from Bootstrap, allows consistent use of rem units
+a,
+label { cursor: pointer; }
+.alert.alert-info a { text-decoration: underline; }
+
+// Improve contrast
+.btn.disabled:active,
+.btn.disabled:focus,
+.btn.disabled:hover { color: #000; }
+.list-unstyled { margin: 0; }
+.icon-bar { background-color: #888; }
+
+// Normalize highlighting
+.highlight,
+mark {
   background: lighten(#FF0, 20%);
   padding: .1em .2em;
 }
-.icon-bar {background-color: #888;}
-img {max-width: 100%;}
-.popover {width: 250px;}
+
+// Normalize
+img { max-width: 100%; }
+
+// Bootstrap overrides
+.breadcrumb {
+  margin-top: .5rem;
+  margin-bottom: .5rem;
+}
+.label { display: inline-block; }
+.popover { width: 250px; }
+.resulthead { .clearfix(); }
 .sub-breadcrumb {
   padding: 5px 10px;
   white-space: nowrap;
@@ -44,12 +71,10 @@ img {max-width: 100%;}
     content: "@{breadcrumb-separator}\00a0";
   }
 }
-.tab-content {padding: 4px;}
+.tab-content { padding: 4px; }
 
-@media (max-width: 991px) {
-  header .container.navbar {margin-bottom: 0;}
-  .searchForm {margin-top: 0;}
-}
+h2 { font-size: 20px; }
+h3 { font-size: 16px; }
 @media (min-width: 768px) {
   h2 {
     font-size: 23px;
@@ -60,16 +85,39 @@ img {max-width: 100%;}
     font-weight: normal;
   }
   .form-control { max-width: 400px; }
+  #modal .form-control { max-width: none; }
+}
+
+/* ------ Layout ------ */
+footer {
+  &:extend(.container);
+  padding: 1rem;
 }
-@media (max-width: 767px) {
-  h2 { font-size: 20px; }
-  h3 { font-size: 16px; }
-  .searchForm {padding-top: 0;}
+@media (min-width: 768px) {
+  .footer-container {
+    display: flex;
+    width: 100%;
+  }
+  .footer-column { flex: 0 1 100%; }
+
+  // Main content and sidebar widths and float
+  .mainbody { width: 75%; }
+  .sidebar { width: 25%; }
+  .mainbody.left,
+  .sidebar.left {
+    float: left;
+    padding-right: 1rem;
+  }
+  .mainbody.right,
+  .sidebar.right {
+    float: right;
+    padding-left: 1rem;
+  }
 }
 
-/* --- Form Errors --- */
+/* ------ Form Errors ------ */
 .has-error {margin-bottom: 0;}
-.sms-error {.has-error;}
+.sms-error { &:extend(.has-error); }
 .help-block.with-errors {
   margin: 0;
   padding-top: @padding-base-vertical;
@@ -77,41 +125,159 @@ img {max-width: 100%;}
   &:empty {padding: 0;}
 }
 
-/* --- Badges - blend the links in --- */
-.badge a {color: #fff;}
+/* ------ Admin ------ */
+.form-admin-maintenance .form-control {
+  display: inline-block;
+  width: 100px;
+}
+
+/* ------ Badges - blend the links in ------ */
+.badge a { color: #fff; }
 
-/* --- Browse --- */
-.browse.list-group .list-group-item {
+/* ------ Browse ------ */
+// Layout
+@media (min-width: 768px) {
+  .browse-container { display: flex; }
+  .browse-list {
+    flex-basis: 25%;
+    padding-right: 1rem;
+  }
+  .browse-list:last-child { padding-right: 0; }
+}
+// List item styling
+.browse-item {
+  position: relative;
+  display: block;
+  padding: .5rem 1rem;
+  border: 1px solid @list-group-border;
+  border-bottom: 0;
   word-wrap: break-word;
-  &.view-record {
-    padding: 2px 4px;
-    font-size: 85%;
-    text-align: right;
-    border-top: 0;
+}
+.browse-item.active {
+  background-color: @brand-primary;
+  color: #fff;
+
+  .badge {
+    background-color: #fff;
+    color: @gray-darker;
+  }
+}
+.browse-item:hover { background-color: @nav-link-hover-bg; }
+.browse-item:last-child { border-bottom: 1px solid @list-group-border; }
+
+.browse-item.with-badge {
+  padding-right: 3rem; // Prevent text from overlapping badge
+  .badge {
+    position: absolute;
+    top: .5rem;
+    right: .25rem;
   }
 }
+.browse-item.view-record {
+  padding: 2px 4px;
+  font-size: 85%;
+  text-align: right;
+  border-top: 0;
+}
 
-/* --- Cart --- */
+/* ------ Cart ------ */
 .cart-controls .checkbox {
-  line-height: 2.5em;
-  padding-right: 1em;
+  line-height: 2.5rem;
+  padding-right: 1rem;
+}
+.nav .btn-bookbag-toggle { float: left; }
+.nav .btn-bookbag-toggle a {
+  display: block;
+  padding: @nav-link-padding;
+  text-decoration: none;
+  &:hover,
+  &:focus {
+    .outline(1px);
+    text-decoration: none;
+    background-color: @nav-link-hover-bg;
+  }
+}
+
+/* ------ Collections ------ */
+// Layout
+@media (min-width: 768px) {
+  .collection-hierarchytree { display: flex; }
+  .collection-hierarchytree .tree-panel,
+  #tree-preview {
+    flex-basis: 50%;
+    padding: 1rem;
+  }
+}
+
+/* ------ Devtools ------ */
+.translation-output {
+  width: 100%;
+  max-width: none;
+  font-family: @font-family-monospace;
+  font-size: 12px;
+  white-space: pre;
+}
+
+/* ------ Facets ------ */
+.date-fields {
+  display: flex;
+
+  .date-from { padding-right: .25rem; }
+  .date-to   { padding-left:  .25rem; }
 }
+.top-facets {
+  margin-left: -.5rem;
+  margin-right: -.5rem;
+}
+.top-facets .facet,
+.top-facets .narrow-toggle,
+.top-facets > strong {
+  display: inline-block;
+  padding: .25rem .5rem;
+  white-space: nowrap;
+}
+.top-facets .narrow-toggle { text-decoration: underline; }
+@media (min-width: 768px) {
+  .author-facets { display: flex; }
+  .author-list { flex: 0 1 100%; }
+}
+
+/* ------ MyResearch ------ */
+.form-login .btn-link ~ .btn-link { padding-left: 0; } // Login link spacing
+.myresearch-menu a {
+  display: block;
+  padding: 10px 15px;
+  &:hover,
+  &:focus { background-color: @nav-link-hover-bg; }
 
-/* --- PubDateVis --- */
+  .badge { float: right; }
+}
+.myresearch-menu a.active {
+  background-color: @brand-primary;
+  color: #fff;
+
+  .badge {
+    background-color: #fff;
+    color: @gray-darker;
+  }
+}
+.list-edit-container { .clearfix(); }
+
+/* ------ PubDateVis ------ */
 #dateVisColorSettings {
   background-color: #fff; // background of box
-  fill: rgb(234,234,234); // fillColor
+  fill: #eee;             // fillColor
   outline-color: #c38835; // selection color
   stroke: @brand-primary; // color
 }
 
-/* --- Table wrapping to prevent horizontal overflow --- */
+/* ------ Table wrapping to prevent horizontal overflow ------ */
 .table {
   table-layout: fixed;
   word-wrap: break-word;
 }
 
-/* --- Visualization View --- */
+/* ------ Visualization View ------ */
 .node {
   position: absolute;
   box-sizing: content-box;
@@ -119,10 +285,10 @@ img {max-width: 100%;}
   overflow: hidden;
   font: 10px sans-serif;
   line-height: 12px;
-  border: 1px solid white;
+  border: 1px solid #fff;
 }
 .node div {margin-top: 0px;}
-.toplevel {border: 2px solid black;}
+.toplevel {border: 2px solid #000;}
 .node .label {
   position: absolute;
   bottom: 0;
@@ -137,9 +303,7 @@ img {max-width: 100%;}
 .notalabel {color: #000;}
 #viz-instructions {padding-top: 600px;}
 
-span[class^="services-"], span[class*=" services-"] span::before {
-  content: ", ";
-}
-span[class^="services-"], span[class*=" services-"] span:first-of-type::before {
-  content: "";
-}
+span[class^="services-"],
+span[class*=" services-"] span::before { content: ", "; }
+span[class^="services-"],
+span[class*=" services-"] span:first-of-type::before { content: ""; }
diff --git a/themes/bootstrap3/less/components/advanced-search.less b/themes/bootstrap3/less/components/advanced-search.less
index d3eb90d9fda9d8b67657b6763858600320707c2b..40c1f1fd0d326c31e78e627bb528c15dd44695b4 100644
--- a/themes/bootstrap3/less/components/advanced-search.less
+++ b/themes/bootstrap3/less/components/advanced-search.less
@@ -1,51 +1,185 @@
-.group {
+// Group of multiple searches
+.adv-group {
+  .clearfix();
   position: relative;
-  background: @gray-lighter;
+  margin-bottom: .5rem;
+  padding: 1rem;
+  border: 1px solid @panel-default-border;
   border-radius: @border-radius-base;
-  border: 1px solid darken(@gray-lighter, 15%);
-  margin-top: 0;
-  margin-bottom: .5em !important;
+
+  & ~ & { margin-top: 1rem; } // Spacing between groups
+
   .add_search_link {
     display: inline-block;
     margin-top: 4px;
   }
-  & .group-close {
-    &:extend(.close);
+}
+.add_search_link,
+.adv-group-close {
+  display: inline-block;
+  padding-top: .25rem;
+  padding-bottom: .25rem;
+}
+.adv-group-close { color: @state-danger-text; }
+.adv-search,
+.adv-search .input-group { width: 100%; }
+.adv-search {
+  .clearfix();
+  margin-bottom: 1.5rem;
+}
+
+.adv-term-input { margin-bottom: .5rem; }
+.adv-term-type {
+  float: left;
+  max-width: 80%;
+}
+.adv-term-remove {
+  &:extend(.close); // borrow the X from bootstrap close
+  float: left;
+  width: 20%;
+  height: 30px;
+  line-height: 1.7;
+  text-align: center;
+  opacity: .4;
+}
+.adv-submit { .clearfix(); }
+.adv-submit .clear-btn { float: right; }
+
+@media (min-width: 768px) {
+  .adv-group-terms {
+    float: left;
+    width: 75%;
+    padding-right: 1rem;
+  }
+  .adv-group-match {
+    float: right;
+    width: 25%;
+  }
+  .adv-group-close {
     position: absolute;
-    top: .3em;
-    right: .5em;
-    opacity: .4;
-    z-index: 2;
-  }
-  .search {
-    margin-bottom: 2px;
-    .close {opacity: .8;}
-  }
-  @media (min-width: 768px) {
-    padding: 10px 10px 10px 25px;
-    [class^=col-] {padding-left: 0;}
-  }
-  @media (max-width: 767px) {
-    .search  .middle {
-      float: left;
-      width: 90%;
+    right: 1rem;
+    bottom: 1rem;
+    min-width: calc(25% - 1rem);
+  }
+  .adv-search {
+    margin-bottom: 0;
+
+    .adv-term-input,
+    .adv-term-type { float: left; }
+    .adv-term-input {
+      width: 60%;
+      margin-right: 2%;
     }
-    & .group-close {
-      top: .5em;
-      right: 1em;
-      opacity: .6;
+    .adv-term-type { max-width: 30%; }
+    .adv-term-remove { width: 8%; }
+  }
+}
+
+#groupPlaceHolder {
+  display: block;
+  padding: 1rem;
+}
+
+/* --- Fieldsets --- */
+@media (min-width: 768px) {
+  fieldset,
+  .fieldset {
+    float: left;
+    width: 33%;
+    padding-right: 1rem;
+    padding-bottom: 1rem;
+  }
+  .solr-facets,
+  .summon-facets {
+    float: none;
+    width: auto;
+    margin-top: 1rem;
+  }
+  .summon-facets .facet-fieldset {
+    float: left;
+    width: 50%;
+    padding-right: 1rem;
+  }
+}
+
+/* --- EDS --- */
+.adv-term-input,
+.adv-term-op { margin-bottom: .25rem; }
+.adv-search:first-of-type .adv-term-op { display: none; }
+@media (min-width: 768px) {
+  .eds-adv .adv-term-op {
+    float: left;
+    width: 16%;
+    margin-right: 1%;
+
+    body.rtl & {
+      float: right;
+      margin-left: 0;
+      margin-right: 1%;
     }
   }
-  @media (max-width: 991px) {
-    .form-control {max-width: none;}
+  .eds-adv .adv-search:first-of-type .adv-term-input { margin-left: 17%; }
+  .eds-adv .adv-term-input {
+    width: 39%;
+    margin-right: 0;
+  }
+  .eds-adv .help-block {
+    float: left;
+    width: 6%;
+    text-align: center;
   }
 }
-#groupPlaceHolder {
-  display:block;
-  padding:6px;
+
+/* --- Primo --- */
+.primo-adv-search .search { margin-bottom: .5rem; }
+.primo-adv-search .search-container { width: 100%; }
+.primo-adv-label {
+  line-height: @input-height-base;
+  padding-right: 1rem;
+}
+@media (min-width: 768px) {
+  .primo.adv-group,
+  .primo-adv-search .search {
+    display: flex;
+
+    select {
+      flex-shrink: 2;
+      margin-right: .5rem;
+    }
+    .primo-adv-input { flex-grow: 1; }
+  }
+  .primo-adv-label { flex-shrink: 0; }
 }
-.template-dir-eds.template-name-advanced {
-  legend {margin-bottom: 0;}
-  .no-js .group:nth-child(n+3) {display: none;}
-  .search .close a {margin-left: -2em;}
+
+/* --- Solr --- */
+@media (min-width: 768px) {
+  .solr-facet-container {
+    display: flex;
+    flex-wrap: wrap;
+  }
+  .solr-adv-facet { flex: 1 25%; }
 }
+
+/* -- Right to left --- */
+body.rtl {
+  fieldset,
+  .fieldset,
+  .adv-search .adv-term-input,
+  .adv-search .adv-term-type,
+  .eds-adv .help-block,
+  .summon-facets .facet-fieldset { float: right; }
+  .adv-submit .clear-btn,
+  .adv-group-match { float: left; }
+  .adv-search .adv-term-input {
+    margin-left: 2%;
+    margin-right: 0;
+  }
+  .date-from {
+    padding-left: .25rem;
+    padding-right: 0;
+  }
+  .date-to {
+    padding-left: 0;
+    padding-right: .25rem;
+  }
+}
\ No newline at end of file
diff --git a/themes/bootstrap3/less/components/alphabrowse.less b/themes/bootstrap3/less/components/alphabrowse.less
index 1a9bf7ee451e3e87bfc0eac37bca9e38b6aa9f24..4bddc4269dc903ea591b13344d2dc3a8678a5c95 100644
--- a/themes/bootstrap3/less/components/alphabrowse.less
+++ b/themes/bootstrap3/less/components/alphabrowse.less
@@ -1,15 +1,15 @@
 .alphabrowse {
   border-collapse: separate;
-  .lcc {width: 20%;}
+  .lcc { width: 20%; }
   .titles {
     width: 10%;
     text-align: center;
   }
   /* highlighting the row makes ff bugs; operate on its children */
   tr.browse-match td {
-    border-top: .2em solid @brand-primary;
-    border-bottom: .2em solid @brand-primary;
-    &:first-child {border-left: .2em solid @brand-primary;}
-    &:last-child {border-right: .2em solid @brand-primary;}
+    border-top: .2rem solid @brand-primary;
+    border-bottom: .2rem solid @brand-primary;
+    &:first-child { border-left: .2em solid @brand-primary;  }
+    &:last-child  { border-right: .2em solid @brand-primary; }
   }
 }
diff --git a/themes/bootstrap3/less/components/autocomplete.less b/themes/bootstrap3/less/components/autocomplete.less
index 9df9844b579add43290630dd1d3b97aa485413d3..9bc6433444ca0374d3a00998fc04ed18476ce226 100644
--- a/themes/bootstrap3/less/components/autocomplete.less
+++ b/themes/bootstrap3/less/components/autocomplete.less
@@ -1,25 +1,26 @@
-/* crhallberg/autocomplete.js 0.14 */
+/* https://github.com/vufind-org/autocomplete.js 1.0b */
 @autocomplete-item-bg   : #fff;
 @autocomplete-active-bg : @brand-primary;
-@autocomplete-hover-bg  : lighten(@brand-primary, 60%);
+@autocomplete-hover-bg  : lighten(@brand-primary, 40%);
 @autocomplete-border    : lightgray;
 @autocomplete-secondary : darkgray; // item description
 
 .autocomplete-results {
   position: absolute;
+  display: table;
+  max-width: 500px; /* CUSTOMIZED */
   margin: 0;
   margin-top: 2px;
   padding: 0;
   border: 1px solid @autocomplete-border;
   background-color: @autocomplete-item-bg;
-  border-radius: @border-radius-base;
   overflow: hidden;
   z-index: 50;
 
-  .item {
+  .ac-item {
     display: block;
     margin: 0;
-    padding: .75rem 1.25rem;
+    padding: .5rem;
     border-bottom: 1px solid @autocomplete-border;
     cursor: pointer;
 
@@ -36,4 +37,17 @@
       color: @autocomplete-secondary;
     }
   }
+  .ac-section-header {
+    float: right;
+    display: block;
+    margin-top: -1.75rem;
+    padding: 0 .5rem;
+    color: @autocomplete-border;
+    background-color: #fff;
+  }
+  .ac-section-divider {
+    margin: 1rem .5rem;
+    border: 0;
+    border-top: 2px solid @autocomplete-border;
+  }
 }
diff --git a/themes/bootstrap3/less/components/channels.less b/themes/bootstrap3/less/components/channels.less
new file mode 100644
index 0000000000000000000000000000000000000000..272c687b9d4a28d6fb663e0f54b474017914e5c5
--- /dev/null
+++ b/themes/bootstrap3/less/components/channels.less
@@ -0,0 +1,42 @@
+.channel {
+  position: relative;
+  width: 100%;
+  height: 300px;
+  border: 1px solid @btn-default-border;
+  border-radius: @border-radius-base;
+}
+.channel .slider-menu {
+  border-top-color: @btn-default-border;
+  border-radius: 0 0 @border-radius-base @border-radius-base;
+  .channel-links .btn { margin-left: 4px; }
+}
+.channel .channel-record.slide {
+  display: inline-block;
+  min-width: 100px;
+  max-height: 240px;
+  padding: 0 .5rem;
+  text-align: center;
+  text-overflow: ellipsis;
+  overflow: hidden;
+}
+.channel .channel-record.is-selected { &:extend(a:hover); }
+.channel .channel-record .thumb {
+  height: 200px;
+  background-position: center center;
+  background-repeat: no-repeat;
+  background-size: contain;
+}
+.channel .popover {
+  width: 500px;
+  max-width: none;
+}
+
+.channel-title a:hover { text-decoration: none; }
+.channel-title i.fa-fw {
+  width: 1.4em;
+  padding-top: 0.5em;
+  font-size: 0.6em;
+  text-align: center;
+  vertical-align: top;
+}
+.channel-title .placeholder { width: 25px; }
diff --git a/themes/bootstrap3/less/components/icons.less b/themes/bootstrap3/less/components/icons.less
index f706cd44692f4678b7f445d399403e513cf9f27e..ed654a6ed50f84aae44d12426c570c701cda0035 100644
--- a/themes/bootstrap3/less/components/icons.less
+++ b/themes/bootstrap3/less/components/icons.less
@@ -1,7 +1,12 @@
+/**
+ * Assign catalog formats to Font Awesome icons
+ */
 
+// Alias
+.fa-printer:before        {content: "\f02f";} // .fa-print
 // Search Icons
-.fa-grid:before   {content: "\f00a";} // .fa-th
-.fa-visual:before {content: "\f008";} // .fa-film
+.fa-grid:before           {content: "\f00a";} // .fa-th
+.fa-visual:before         {content: "\f008";} // .fa-film
 // Type Icons
 .fa-x:before              {content: "\f0f6";} // .fa-file-text-o
 .fa-atlas:before          {content: "\f14e";} // .fa-compass
diff --git a/themes/bootstrap3/less/components/js-tree.less b/themes/bootstrap3/less/components/js-tree.less
index 110cecb21cac4648f1cb1574df49d7d731b9d626..947dda20cce89d3f99c5ecda73207715ac2540b8 100644
--- a/themes/bootstrap3/less/components/js-tree.less
+++ b/themes/bootstrap3/less/components/js-tree.less
@@ -1,4 +1,5 @@
-.hierarchy-tree {
+.hierarchy-tree,
+.jstree-facet {
   /* jsTree arrows */
   .jstree-ocl:before {
     float: left;
@@ -12,15 +13,15 @@
     text-decoration: inherit;
     speak: none;
   }
-  .jstree-open > .jstree-ocl:before {content: "\f0d7";}
-  .jstree-closed > .jstree-ocl:before {content: "\f0da";}
-  .jstree-leaf > .jstree-ocl:before {content: " ";}
+  .jstree-open > .jstree-ocl:before   {content: "\f0d7";} // .fa-caret-down
+  .jstree-closed > .jstree-ocl:before {content: "\f0da";} // .fa-caret-right
+  .jstree-leaf > .jstree-ocl:before   {content: " ";}
   .jstree-icon {
     width: 16px;
     color: #000;
   }
   .jstree-anchor {
-    padding: 2px 5px;
+    padding-left: 5px;
     white-space: nowrap;
   }
   .jstree-container-ul,
@@ -37,10 +38,16 @@
   }
   .jstree-search a {
     font-style: italic;
-    color: #8b0000 ;
+    color: #8b0000;
     font-weight: bold;
   }
 }
+.jstree-node.list-group-item {
+  margin-bottom: 0;
+  border: 0;
+  border-bottom: 1px solid @list-group-border;
+  border-radius: 0;
+}
 
 /* --- Record --- */
 #hierarchyTreeHolder {
@@ -73,12 +80,14 @@
 }
 /* facet list styling */
 .jstree-facet li span.main {
-  display: block;
-  padding-left: 1px; /* Fix Firefox cutting the checkboxes */
   overflow: hidden;
   text-overflow: ellipsis;
   white-space: nowrap;
 }
+.jstree-facet .main.applied .fa-check {
+  margin-top: 2px;
+  margin-right: 4px;
+}
 .jstree-facet .jstree-container-ul {
   padding: 0;
   & > li.active,
@@ -88,12 +97,10 @@
   }
 }
 li.jstree-facet,
-li.jstree-node {
-  list-style: none;
-}
-li.jstree-facet .badge {cursor: text;}
-li.jstree-facet ul {padding-left: 20px;}
+li.jstree-node { list-style: none; }
+li.jstree-facet .badge { cursor: text; }
+li.jstree-facet ul { padding-left: 20px; }
 
-.list-group.facet .jstree-node.list-group-item { padding-left: 19px; }
-.list-group.facet .jstree-icon::before { margin-left: -12px; }
-.list-group.facet .jstree-facet li span.main { padding: 1px; }
+.facet .jstree-node.list-group-item { padding-left: 19px; }
+.facet .jstree-icon::before { margin-left: -12px; }
+.facet .jstree-facet li span.main { padding: 1px; }
diff --git a/themes/bootstrap3/less/components/lightbox.less b/themes/bootstrap3/less/components/lightbox.less
index e793dc0b3120e5a88790d11008ff95ab9c1c740e..9361fab53c8332b260db43ea81f248ccf5d7c0a8 100644
--- a/themes/bootstrap3/less/components/lightbox.less
+++ b/themes/bootstrap3/less/components/lightbox.less
@@ -1,8 +1,5 @@
-.lightbox-only { display: none; }
-#modal .lightbox-only { display: initial; }
-
-#modal {background-color: rgba(0,0,0,.2);}
-#modal .modal-content > .close {
+#modal { background-color: rgba(0,0,0,.2); }
+#modal .modal-content > .close { // Fancy side X button
   position: absolute;
   right: -50px;
   top: 0;
@@ -10,15 +7,27 @@
   font-size: 32pt;
   color: #fff;
   opacity: .7;
+  body.rtl & {
+    left: -50px;
+    right: auto;
+  }
 }
-#modal .modal-content > .close:hover {opacity: 1;}
+#modal .modal-content > .close:hover { opacity: 1; }
 #modal .modal-body h1,
 #modal .modal-body h2 {
   margin-top: 0.3rem;
   margin-bottom: 1.3rem;
 }
 
-#modal .cart-controls .btn {margin-bottom: 4px;}
-#modal .cart-controls .checkbox {padding-bottom: 1em;}
-#modal .cart-controls ~ hr {margin-top: 0;}
+#modal .cart-controls .btn { margin-bottom: 4px; }
+#modal .cart-controls .checkbox { padding-bottom: 1rem; }
+#modal .cart-controls ~ hr { margin-top: 0; }
 .lightbox-scroll { overflow-y: auto; }
+
+// Loading spinner
+.modal-loading { float: right; }
+body.rtl .modal-loading { float: left; }
+
+// Utility classes
+.lightbox-only { display: none; }
+#modal .lightbox-only { display: initial; }
\ No newline at end of file
diff --git a/themes/bootstrap3/less/components/offcanvas.less b/themes/bootstrap3/less/components/offcanvas.less
index 845a95f41c1694e58e720dba988967ad49206b64..d6620248847a94505f503eb70b6b8c1b8e5e08a8 100644
--- a/themes/bootstrap3/less/components/offcanvas.less
+++ b/themes/bootstrap3/less/components/offcanvas.less
@@ -1,8 +1,8 @@
-@offcanvas-offset: 75%;
-@offcanvas-padding: 30px;
+@offcanvas-offset: 75vw;  // Width of open menu
+@offcanvas-padding: 30px; // Body offset when offcanvas active, also width of toggle
 
 .offcanvas-overlay,
-.offcanvas-toggle {display: none;}
+.offcanvas-toggle { display: none; }
 
 @media screen and (max-width: 767px) {
   body.offcanvas {
@@ -15,48 +15,42 @@
       padding-left: 0;
       padding-right: 0;
       overflow-y: auto;
-      h4 {padding-left: @padding-base-horizontal;}
-      .checkbox {margin-left: 20px + @padding-base-horizontal;}
+      h4 { padding-left: @padding-base-horizontal; }
+      .checkbox { margin-left: 20px + @padding-base-horizontal; }
       .list-group, .list-group-item {
         border-left: 0;
         border-right: 0;
         border-radius: 0 !important;
       }
     }
-    &.active {overflow-y: hidden;}
+    &.active { overflow-y: hidden; }
     &.offcanvas-left {
       padding-left: @offcanvas-padding - @grid-gutter-width/2;
-      & .main {background: #FFF;}
+      & .main { background: #FFF; }
       &.active {
         margin-left: @offcanvas-offset;
         margin-right: -@offcanvas-offset;
-        .sidebar {left: 0;}
-        .offcanvas-overlay {right: -@offcanvas-offset;}
-        .offcanvas-toggle {left: @offcanvas-offset;}
-      }
-      .sidebar {left: -@offcanvas-offset;}
-      .offcanvas-overlay {right: -100%;}
-      .offcanvas-toggle {
-        border-radius: 0 @border-radius-small @border-radius-small 0; // top right and bottom right
-        left: 0;
+        .sidebar { left: 0; }
+        .offcanvas-overlay { right: -@offcanvas-offset; }
+        .offcanvas-toggle { left: @offcanvas-offset; }
       }
+      .sidebar { left: -@offcanvas-offset; }
+      .offcanvas-overlay { right: -100%; }
+      .offcanvas-toggle { left: 0; }
     }
     &.offcanvas-right {
       padding-right: @offcanvas-padding - @grid-gutter-width/2;
-      & .main > .container {background: #FFF;}
+      & .main > .container { background: #FFF; }
       &.active {
         margin-left: -@offcanvas-offset;
         margin-right: @offcanvas-offset;
-        .sidebar {right: 0;}
-        .offcanvas-overlay {left: -@offcanvas-offset;}
-        .offcanvas-toggle {right: @offcanvas-offset;}
-      }
-      .sidebar {right: -@offcanvas-offset;}
-      .offcanvas-overlay {left: -100%;}
-      .offcanvas-toggle {
-        border-radius: @border-radius-small 0 0 @border-radius-small; // top left and bottom left
-        right: 0;
+        .sidebar { right: 0; }
+        .offcanvas-overlay { left: -@offcanvas-offset; }
+        .offcanvas-toggle { right: @offcanvas-offset; }
       }
+      .sidebar { right: -@offcanvas-offset; }
+      .offcanvas-overlay { left: -100%; }
+      .offcanvas-toggle { right: 0; }
     }
     .offcanvas-overlay {
       display: block;
@@ -70,17 +64,19 @@
     .offcanvas-toggle {
       display: block;
       position: fixed;
-      top: 50%;
+      top: 0;
       width: calc(@offcanvas-padding - 5px);
-      padding: 20px 0;
-      background: @brand-primary;
-      color: #EEE;
+      height: 100%;
+      border-left: 1px solid @gray-lighter;
+      border-right: 1px solid @gray-lighter;
+      line-height: 90vh; // Center vertically
       text-align: center;
+      background-color: #fff;
       z-index: 5;
     }
     .offcanvas-overlay,
     .offcanvas-toggle,
-    .offcanvas-toggle * {cursor: pointer;}
+    .offcanvas-toggle * { cursor: pointer; }
     &,.sidebar,
     .offcanvas-overlay,
     .offcanvas-toggle {
diff --git a/themes/bootstrap3/less/components/record.less b/themes/bootstrap3/less/components/record.less
index bb5af6a238c711c1a4560349574ec4f2694d6ce1..ce93d3d346d02156a41cc7cb718746563fc55058 100644
--- a/themes/bootstrap3/less/components/record.less
+++ b/themes/bootstrap3/less/components/record.less
@@ -1,35 +1,108 @@
-.citation .pace-car {
-  th,
-  td {
-    border: 0;
-    padding: 0;
+.record .media-body h3 { margin-top: 0; } // Align title with top of image
+.recordcover { max-height: 300px; } // Keep the image from getting out of control
+@media (max-width: 767px) {
+  .record .media-left,
+  .record .media-right { display: block; }
+  .record .media-body { // Add a gap between the thumbnail and the info
+    display: block;
+    width: auto;
+    margin-top: 1rem;
   }
 }
-.citation th {text-align: right;}
-.item-notes ul { padding-left: 2rem; }
-.recordcover {max-height: 300px;}
+// Comma-separate formatting
+.result .record .format::after,
+.record .format:last-child::after { content: ""; }
+.record .format::after { content: ", "; }
+.record-previews { margin-top: .5rem; }
+
+/* ------ Nav ------ */
+.record-nav.nav { margin-bottom: 1rem; }
+.record-nav > li,
+.btn-bookbag-toggle { width: 100%; }
+.record-nav > li > a { padding: .5rem; }
+.record-nav > li > a,
+.btn-bookbag-toggle { text-align: center; }
+@media(min-width: 768px) {
+  .record-nav > li,
+  .btn-bookbag-toggle { width: auto; }
+  .record-nav > li > a { padding: @nav-link-padding; }
+  .record-nav > li > a,
+  .btn-bookbag-toggle { text-align: left; }
+}
+
+/* ------ Comments ------ */
+.comment-label,
+.comment-name { font-style: italic; }
+.comment { margin-bottom: 1rem; }
+.comment-name .delete { color: @state-danger-text; }
+@media (min-width: 768px) {
+  .comment-form,
+  .comment {
+    display: flex;
+    margin-bottom: 0;
+  }
+  .comment-label,
+  .comment-name {
+    min-width: 25%;
+    font-style: unset;
+  }
+  .comment-form .text-form { width: 100%; }
+  .comment-form > label { flex: 0 0 auto; }
+  .comment-form textarea {
+    display: block;
+    width: 100%;
+  }
+}
+
+/* ------ Tags ------ */
+.tagList button {
+  margin-top: 0;
+  padding-top: 0;
+  padding-bottom: 4px;
+  font-size: 95%;
+  vertical-align: initial;
+}
+.tagList .tag .badge {
+  margin: 0;
+  padding: 3px 7px;
+  font-weight: normal;
+}
+.tagList button .fa-close { margin-top: 3px; }
 .tagList {
   .tag {
     display: inline-block;
     margin: 0 1px 1px;
     border-radius: 4px;
+    // Use bootstrap mixin to make tags look like buttons
+    .button-size(@padding-base-vertical; @padding-base-vertical; @font-size-base; @line-height-base; @border-radius-base);
     &.selected {
       background-color: @btn-primary-bg;
-      a {color: #fff;}
+      a { color: #fff; }
       .badge {
         color: @gray-darker;
         background-color: #fff;
-        &:hover {color: #a94442;}
+        &:hover { color: #a94442; }
       }
     }
 
-    .button-size(@padding-base-vertical; @padding-base-vertical; @font-size-base; @line-height-base; @border-radius-base);
-    .badge .fa {width: 12px;}
+    .badge .fa { width: 12px; }
+  }
+  button { border: 0; }
+  .tag-form { display: inline; }
+}
+.tagList.loggedin .tag:not(.selected) .badge:hover { background-color: @brand-success; }
+
+
+.citation .pace-car {
+  th,
+  td {
+    border: 0;
+    padding: 0;
   }
-  button {border: 0;}
-  .tag-form {display: inline;}
 }
-.tagList.loggedin .tag:not(.selected) .badge:hover {background-color: @brand-success;}
+.citation th { text-align: right; }
+
+.item-notes ul { padding-left: 2rem; }
 
 .subject-line:hover { color: #999; }
 .subject-line:hover a { color: @link-hover-color; }
@@ -38,15 +111,9 @@
   text-decoration: none;
 }
 
-.record .format::after { content: ", "; }
-.result .record .format::after,
-.record .format:last-child::after { content: ""; }
-
 .marc-row-LEADER,
 .marc-row-006,
 .marc-row-007,
 .marc-row-008 {
   white-space: pre-wrap;
 }
-
-.comment-form textarea.form-control { display: block; }
diff --git a/themes/bootstrap3/less/components/search.less b/themes/bootstrap3/less/components/search.less
index 53b7ccc70c36f28bc741a747946543f3b566469d..c9e9f7b7c1ceaea385cd4243eba7e3402530e0b7 100644
--- a/themes/bootstrap3/less/components/search.less
+++ b/themes/bootstrap3/less/components/search.less
@@ -1,93 +1,217 @@
-@thumbnail-width-small: 60px;
+// Thumbnail sizes for media items: search results, list entries, record views
+@thumbnail-width-small:   60px;
 @thumbnail-width-medium: 100px;
-@thumbnail-width-large: 160px;
+@thumbnail-width-large:  160px;
 
-.bulkActionButtons label {display: inline-block;}
-.bulkActionButtons label input {margin-top: 2px;}
-.grid { @media (max-width: 767px) {min-height: 250px;} }
+// Hide these on mobile
+@media (max-width: 767px) {
+  .bulkActionButtons,
+  #datevispublishDatexWrapper,
+  .result .checkbox { display: none; }
+}
+
+.searchHomeContent { .clearfix(); }
+.home-facet-list {
+  padding-left: 0;
+  padding-right: 1rem;
+  list-style: none;
+}
+@media (min-width: 768px) {
+  .search-home-facets,
+  .home-facet-container { display: flex; }
+  .home-facet {
+    flex: 1 1 100%;
+    flex-basis: auto;
+  }
+  .home-facet-list { flex: 0 1 100%; }
+}
+
+.searchForm {
+  margin: 0;
+  padding: 0;
+}
+
+header .container.navbar { margin-bottom: 0; }
+
+.search-sort { display: flex; }
+.search-sort label {
+  line-height: @input-height-base;
+  padding-right: .5rem;
+}
+.search-stats {
+  display: block;
+  padding-top: 1rem;
+  padding-bottom: 1rem;
+}
+
+@media (min-width: 768px) {
+  .search-header { display: flex; }
+  .search-stats { flex-grow: 1; }
+  .search-controls { text-align: right; }
+}
+
+.bulk-checkbox,
+.bulkActionButtons label { display: inline-block; }
+.bulkActionButtons label input { margin-top: 2px; }
+.bulkActionButtons { .clearfix(); }
+@media (max-width: 767px) {
+  .grid { min-height: 250px; }
+}
 .result {
-  padding-top: 1.5rem;
-  .checkbox {
-    float: left;
-    padding-right: .5rem;
+  display: flex;
+  padding-top: 1rem;
+
+  .record-checkbox,
+  .record-number { display: none; }
+
+  .title { font-weight: bold; }
+  .list-tab-content.record .img-col { display: none; }
+  .list-tab-content.record .info-col { width: 100%; }
+  .format {
+    &:extend(.label);
+    &:extend(.label-info);
   }
-  .media,
-  .media-body { overflow: visible; }
-  .media-body .row {
-    margin-left: 0;
-    margin-right: 0;
+
+  .checkbox-select-item { float: left; }
+
+  @media (max-width: 767px) {
+    a {
+      max-width: 100%;
+      text-decoration: underline;
+    }
+  }
+  @media (min-width: 768px) {
+    .record-checkbox {
+      display: block;
+      flex: 0;
+      cursor: pointer;
+    }
+    .record-number {
+      display: block;
+      flex: 0 2rem;
+      text-align: center;
+    }
   }
+}
+.record,
+.result {
   .media {
-    margin-top: 0;
-    margin-bottom: 1rem;
-    .clearfix();
+    flex: 1;
+    margin: 0;
   }
   .media-left,
   .media-right {
-    padding: 0;
     text-align: center;
-    a {
-      display: inline-block;
-      text-align: center;
-    }
     img {
-      max-width: none;
+      max-width: 100%;
       max-height: 300px;
     }
-    &.small a,
-    &.small > img {
+    &.small img,
+    &.medium img,
+    &.large img {
+      display: inline-block;
       width: @thumbnail-width-small;
-      img { max-width: @thumbnail-width-small; }
-    }
-    &.medium a,
-    &.medium > img {
-      width: @thumbnail-width-medium;
-      img { max-width: @thumbnail-width-medium; }
+      max-width: none;
     }
-    &.large a,
-    &.large > img {
-      width: @thumbnail-width-large;
-      img { max-width: @thumbnail-width-large; }
+  }
+
+  @media (min-width: 768px) {
+    .media-left,
+    .media-right {
+      max-width: 25%;
+      padding-right: 10px;
+      padding-left: 10px;
+
+      a {
+        display: inline-block;
+        max-width: 100%;
+        text-align: center;
+        white-space: nowrap;
+        text-decoration: underline;
+      }
+
+      &.small img,
+      &.medium img,
+      &.large img {
+        width: auto;
+        max-width: 100%;
+      }
+      &.small  > a,
+      &.small  > img { width: @thumbnail-width-small; }
+      &.medium > a,
+      &.medium > img { width: @thumbnail-width-medium; }
+      &.large  > a,
+      &.large  > img { width: @thumbnail-width-large; }
     }
   }
-  .media-left { padding-left: 10px; }
-  .media-right { padding-right: 10px; }
-  .title {font-weight: bold;}
-  .list-tab-content.record .img-col { display: none; }
-  .list-tab-content.record .info-col { width: 100%; }
+}
+.record .media-left,
+.record .media-right {
+  &.small img,
+  &.medium img,
+  &.large img { width: auto; }
+}
+.result-body {
+  padding: 0;
+  padding-bottom: .25rem;
+}
+.result-links .alert { margin: 0; }
+.result-formats { margin-bottom: .5rem; }
 
-  @media (max-width: 767px) {
-    a { text-decoration: underline; }
+.btn-bookbag-toggle form { display: inline; }
+.cart-link-icon.fa { margin-right: .3rem; }
+.result .cart-link-icon {
+  color: @text-color;
+  /* .fa-fw */
+  width: 1.28571429em;
+  text-align: center;
+}
+.savedLists {
+  &:extend(.alert);
+  &:extend(.alert-info);
+  display: none;
+}
+
+@media (min-width: 768px) {
+  .result-body {
+    float: left;
+    width: 75%;
+  }
+  .result-links {
+    float: left;
+    width: 25%;
+    padding: 0;
   }
-  @media (max-width: 530px) {
-    .checkbox { padding: 0; }
-    .media-left { padding-right: 0; }
+  .savedLists.loaded { display: block; }
+}
+body.rtl {
+  .result .btn-bookbag-toggle .fa {
+    margin-left: .3rem;
+    margin-right: 0;
   }
-
-  .format {
-    &:extend(.label);
-    &:extend(.label-info);
+  @media (min-width: 768px) {
+    .result-body,
+    .result-links { float: right; }
   }
 }
-
+/* ------ EMBEDDED RESULTS STYLE ------ */
 .result.embedded {
   .getFull {
     display: block;
-    margin-left: 1.5rem;
-    padding-right: 30px;
+    margin-left: -.5rem;
+    padding-left: .5rem;
     border-left: 1px solid transparent;
   }
   .getFull.expanded {
     &:extend(.list-group-item);
     margin-top: -11px;
-    margin-left: .75rem;
-    padding-left: .75rem;
+    padding-left: .5rem;
     border-top-left-radius: @border-radius-base;
     border-top-right-radius: @border-radius-base;
     &::before {
       content: '\25BC';
       position: absolute;
-      right: 15px;
+      right: 1rem;
       color: @gray;
     }
   }
@@ -98,7 +222,7 @@
     background: #fff;
   }
   .long-view {
-    margin-left: .75rem;
+    margin-left: -.5rem;
     padding: .5rem;
     border: 1px solid @list-group-border;
     background-color: #fff;
@@ -111,16 +235,72 @@
   .list-tab-content { padding: 1rem; }
 }
 
-.search-controls .alert {margin-bottom: 0;}
-.searchtools a {padding: 0 .5em;}
-.title-in-heading {
-  font-size: inherit;
-  font-style: italic;
+/* ------ GRID VIEW ------ */
+.search-grid::after {
+  display: table;
+  clear: both;
+  content: '';
 }
+.grid-result {
+  display: flex;
+  float: left;
+  width: 50%;
 
-.wikipedia img { margin-right: 1rem; }
+  .grid-body { flex: 1; }
+  .grid-checkbox {
+    flex: 0 0 30px;
+    min-width: 0;
+  }
+  .title { font-weight: bold; }
+  .label,
+  .format {
+    display: inline-block;
+    white-space: normal;
+  }
+}
+.grid-large-break,
+.grid-small-break { clear: both; }
+@media (min-width: 992px) {
+  .grid-result{ width: 25%; }
+  .grid-small-break { display: none; }
+}
+
+.searchtools a {
+  padding: 0 .5rem;
+  white-space: nowrap;
+}
+
+/* ------ COMBINED ------ */
+// No sidebar in combined:
+.template-dir-combined.template-name-results.offcanvas {
+  margin: 0;
+  padding: 0;
+}
 
+@media (min-width: 768px) {
+  .combined-search-container {
+    display: flex;
+
+    .result { margin-left: 0; }
+    .result-body {
+      float: none;
+      width: auto;
+    }
+    .result-links { display: none; }
+  }
+  .combined-column {
+    flex: 0 1 100%;
+    padding-left: 1rem;
+  }
+  .combined-column:last-child { padding-right: 1rem; }
+}
+
+.wikipedia img { margin-right: 1rem; }
 .geoItem {
     font-size: .9em;
     margin: 0px 0px 10px;
 }
+.title-in-heading {
+  font-size: inherit;
+  font-style: italic;
+}
diff --git a/themes/bootstrap3/less/components/sidebar.less b/themes/bootstrap3/less/components/sidebar.less
index e3c1603ab03aea0c5419e2ac68063021594751ee..2303c2a8c7179012244061ecaf1fbc8cb5505688 100644
--- a/themes/bootstrap3/less/components/sidebar.less
+++ b/themes/bootstrap3/less/components/sidebar.less
@@ -1,41 +1,106 @@
-/* Sidebar rounded corners */
-.narrow-toggle { text-align: center; }
-.sidebar {
-  label:not(.list-group-item) {margin-left: 20px;}
-  .list-group.facet .list-group-item.title {
-    cursor: pointer;
-    &.collapsed {
-      border-radius: @border-radius-base;
-      &:after {content: '\25BC';}
+.facet-group {
+  display: block;
+  margin-bottom: 1rem;
+
+  .facet,
+  .title {
+    display: block;
+    padding: 8px 15px;
+    line-height: 1.5rem;
+
+    .badge,
+    .status {
+      float: right;
+
+      body.rtl & { float: left; }
+    }
+    .badge {
+      max-height: 19px;
+      line-height: 1.1rem;
     }
-    &:after {
+  }
+  .facet { border-bottom: 1px solid @list-group-border; }
+  .title {
+    padding-right: 8px;
+    border: 1px solid @list-group-border;
+    font-weight: bold;
+  }
+
+  [data-toggle="collapse"] {
+    cursor: pointer;
+
+    &::after {
       content: '\25B2';
       float: right;
+
+      body.rtl & { float: left; }
     }
   }
-  .collapse,.collapsing {
-    .list-group-item {
-      border-top-left-radius: 0px;
-      border-top-right-radius: 0px;
-      &[id^=more] {
-        border-bottom-left-radius: @border-radius-base;
-        border-bottom-right-radius: @border-radius-base;
-      }
-    }
+  .collapsed::after {content: '\25BC';}
+
+  .collapse,
+  .collapsing,
+  & > .facet {
+    border-left: 1px solid @list-group-border;
+    border-right: 1px solid @list-group-border;
   }
-  #side-collapse-publishDate .list-group-item {
-    border-bottom-left-radius: @border-radius-base;
-    border-bottom-right-radius: @border-radius-base;
+  & > .facet:first-child { border-top: 1px solid @list-group-border; }
+
+  .facetOR .text {
+    display: inline-block;
+    padding-left: 0.5rem;
+    text-indent: -0.5rem;
   }
+
+  .excludable {
+    display: flex;
+    flex-direction: row-reverse;
+    padding-right: 0;
+
+    .badge { flex-shrink: 0; }
+    .text { flex-grow: 1; }
+    .exclude {
+      flex-basis: 2rem;
+      flex-shrink: 0;
+      text-align: center;
+    }
+
+    body.rtl & {
+      padding-left: 0;
+      padding-right: 15px;
+    }
+  }
+}
+
+.checkbox-filter {
+  display: block;
+  padding-bottom: 1rem;
+  font-weight: bold;
+  color: @text-color;
 }
-label.list-group-item {
-  margin-top: 0;
-  padding-left: 35px;
-  font-weight: normal;
-  border-radius: 0;
+.facet-group > .checkbox,
+.sidebar .facet.checkbox {
+  margin: 0;
+  padding-left: 2rem;
 }
-.list-group-item.title {font-weight: bold;}
-.sidebar .facet a {text-decoration: none;}
+
+.active-filters .facet,
+.facet-group .active {
+  padding-right: .65rem;
+  background-color: @brand-primary;
+  color: #fff;
+
+  a { color: #fff; }
+}
+.facet.active .badge,
+.jstree-node.active .badge,
+.jstree-node.active .badge .fa {
+  background-color: #fff;
+  color: @brand-primary;
+}
+
+.narrow-toggle { text-align: center; }
+
 .sidebar .format {
   &:extend(.label);
   &:extend(.label-info);
@@ -51,3 +116,10 @@ label.list-group-item {
 }
 
 .full-facet-list { margin-top: 1rem; }
+.full-facet-list .active .fa {
+  float: right;
+  margin-top: .25rem;
+  margin-right: 0.5rem;
+  margin-left: 0.5rem;
+}
+body.rtl .full-facet-list .active .fa { float: left; }
diff --git a/themes/bootstrap3/less/components/similar-carousel.less b/themes/bootstrap3/less/components/similar-carousel.less
index ba2ad84fe5d2ea003d194db1a8e87b4df0949642..be2b2cae194ae43045d877586ee020165a70e1c6 100644
--- a/themes/bootstrap3/less/components/similar-carousel.less
+++ b/themes/bootstrap3/less/components/similar-carousel.less
@@ -5,8 +5,18 @@
       width: 8px;
       height: 8px;
       margin: 2px;
-      background-color: rgba(255,255,255,.3);
-      border-color: @gray-darker;
+      margin-bottom: 4px;
+      background-color: #fff;
+      border: 1px solid @gray-darker;
+      box-shadow: none;
+      transition-duration: .4s;
+      transition-property: width, height, margin;
+
+      &.active {
+        width: 16px;
+        height: 16px;
+        margin-bottom: 0;
+      }
     }
   }
   .hover-overlay {
@@ -33,5 +43,11 @@
     }
     &:hover .content {display: block;}
   }
+  .item {
+    padding: 0 4em;
+    &.prev,
+    &.active,
+    &.next { display: flex; }
+  }
+  .carousel-item { flex-basis: 25%; }
 }
-#similar-items-carousel .item {padding: 0 4em;}
diff --git a/themes/bootstrap3/less/components/sliders.less b/themes/bootstrap3/less/components/sliders.less
index 2f9b2104784846a122fe30fe160297e6ddcd73aa..5138e950b9b2c8b2a6f221db0fcf7879bcdb482a 100644
--- a/themes/bootstrap3/less/components/sliders.less
+++ b/themes/bootstrap3/less/components/sliders.less
@@ -5,8 +5,8 @@
     width: 100%;
   }
   .slider-track {
-  background:@gray-light;
-  box-shadow:inset 0 1px 0 rgba(0, 0, 0, 0.4);
+    background:@gray-light;
+    box-shadow:inset 0 1px 0 rgba(0, 0, 0, 0.4);
   }
   .slider-handle {
     background:@brand-primary;
diff --git a/themes/bootstrap3/less/components/variables.less b/themes/bootstrap3/less/components/variables.less
new file mode 100644
index 0000000000000000000000000000000000000000..3edcfee95bfe8cfb2c28b9a20fcb87786cfc8a87
--- /dev/null
+++ b/themes/bootstrap3/less/components/variables.less
@@ -0,0 +1,52 @@
+// Make sure Font Awesome icons are loaded properly
+@fa-font-path: "../../../../../../themes/bootstrap3/css/fonts";
+
+/**
+ * The following are useful Bootstrap variables that are used throughout the code,
+ * with comments and their defaults. See /themes/bootstrap3/less/vendor/bootstrap/variables.less for more.
+ */
+
+// @padding-base-vertical:   6px;  // Buttons, tabs, and other padding
+// @padding-base-horizontal: 12px;
+
+// @navbar-height:                    50px;
+
+// @border-radius-base: 4px;
+
+/* ------ COLORS ------ */
+
+// @gray-base:    #000;
+// @gray-darker:  lighten(@gray-base, 13.5%); // #222
+// @gray-dark:    lighten(@gray-base, 20.0%); // #333
+// @gray:         lighten(@gray-base, 33.5%); // #555
+// @gray-light:   lighten(@gray-base, 46.7%); // #777
+// @gray-lighter: lighten(@gray-base, 93.5%); // #eee
+//
+// @brand-primary: darken(#428bca, 6.5%); // #337ab7 (primary buttons, links, and active elements)
+// @brand-success: #5cb85c;
+// @brand-info:    #5bc0de;
+// @brand-warning: #f0ad4e;
+// @brand-danger:  #d9534f;
+
+// @list-group-border:  #ddd; // Borders on menus and sidebars
+
+// @text-color:            @gray-dark;
+// @link-color:            @brand-primary;
+// @link-hover-color:      darken(@link-color, 15%);
+
+// Define colors for form feedback states and, by default, alerts.
+// @state-success-text:             #3c763d;
+// @state-success-bg:               #dff0d8;
+// @state-success-border:           darken(spin(@state-success-bg, -10), 5%);
+//
+// @state-info-text:                #31708f;
+// @state-info-bg:                  #d9edf7;
+// @state-info-border:              darken(spin(@state-info-bg, -10), 7%);
+//
+// @state-warning-text:             #8a6d3b;
+// @state-warning-bg:               #fcf8e3;
+// @state-warning-border:           darken(spin(@state-warning-bg, -10), 5%);
+//
+// @state-danger-text:              #a94442;
+// @state-danger-bg:                #f2dede;
+// @state-danger-border:            darken(spin(@state-danger-bg, -10), 5%);
diff --git a/themes/bootstrap3/less/vendor/font-awesome/font-awesome.less b/themes/bootstrap3/less/vendor/font-awesome/font-awesome.less
index c44e5f466a0de31751b647118a55dd563478815f..c3677def3131af54af2a87d9cd2bb737a321e97e 100644
--- a/themes/bootstrap3/less/vendor/font-awesome/font-awesome.less
+++ b/themes/bootstrap3/less/vendor/font-awesome/font-awesome.less
@@ -1,5 +1,5 @@
 /*!
- *  Font Awesome 4.6.3 by @davegandy - http://fontawesome.io - @fontawesome
+ *  Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome
  *  License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)
  */
 
diff --git a/themes/bootstrap3/less/vendor/font-awesome/icons.less b/themes/bootstrap3/less/vendor/font-awesome/icons.less
index ba21b222d6ff0e0f604d99acf34dca0ce2bd9066..159d600425c73c282be34f94af12179f091a16d2 100644
--- a/themes/bootstrap3/less/vendor/font-awesome/icons.less
+++ b/themes/bootstrap3/less/vendor/font-awesome/icons.less
@@ -605,6 +605,7 @@
 .@{fa-css-prefix}-opencart:before { content: @fa-var-opencart; }
 .@{fa-css-prefix}-expeditedssl:before { content: @fa-var-expeditedssl; }
 .@{fa-css-prefix}-battery-4:before,
+.@{fa-css-prefix}-battery:before,
 .@{fa-css-prefix}-battery-full:before { content: @fa-var-battery-full; }
 .@{fa-css-prefix}-battery-3:before,
 .@{fa-css-prefix}-battery-three-quarters:before { content: @fa-var-battery-three-quarters; }
@@ -731,3 +732,58 @@
 .@{fa-css-prefix}-google-plus-official:before { content: @fa-var-google-plus-official; }
 .@{fa-css-prefix}-fa:before,
 .@{fa-css-prefix}-font-awesome:before { content: @fa-var-font-awesome; }
+.@{fa-css-prefix}-handshake-o:before { content: @fa-var-handshake-o; }
+.@{fa-css-prefix}-envelope-open:before { content: @fa-var-envelope-open; }
+.@{fa-css-prefix}-envelope-open-o:before { content: @fa-var-envelope-open-o; }
+.@{fa-css-prefix}-linode:before { content: @fa-var-linode; }
+.@{fa-css-prefix}-address-book:before { content: @fa-var-address-book; }
+.@{fa-css-prefix}-address-book-o:before { content: @fa-var-address-book-o; }
+.@{fa-css-prefix}-vcard:before,
+.@{fa-css-prefix}-address-card:before { content: @fa-var-address-card; }
+.@{fa-css-prefix}-vcard-o:before,
+.@{fa-css-prefix}-address-card-o:before { content: @fa-var-address-card-o; }
+.@{fa-css-prefix}-user-circle:before { content: @fa-var-user-circle; }
+.@{fa-css-prefix}-user-circle-o:before { content: @fa-var-user-circle-o; }
+.@{fa-css-prefix}-user-o:before { content: @fa-var-user-o; }
+.@{fa-css-prefix}-id-badge:before { content: @fa-var-id-badge; }
+.@{fa-css-prefix}-drivers-license:before,
+.@{fa-css-prefix}-id-card:before { content: @fa-var-id-card; }
+.@{fa-css-prefix}-drivers-license-o:before,
+.@{fa-css-prefix}-id-card-o:before { content: @fa-var-id-card-o; }
+.@{fa-css-prefix}-quora:before { content: @fa-var-quora; }
+.@{fa-css-prefix}-free-code-camp:before { content: @fa-var-free-code-camp; }
+.@{fa-css-prefix}-telegram:before { content: @fa-var-telegram; }
+.@{fa-css-prefix}-thermometer-4:before,
+.@{fa-css-prefix}-thermometer:before,
+.@{fa-css-prefix}-thermometer-full:before { content: @fa-var-thermometer-full; }
+.@{fa-css-prefix}-thermometer-3:before,
+.@{fa-css-prefix}-thermometer-three-quarters:before { content: @fa-var-thermometer-three-quarters; }
+.@{fa-css-prefix}-thermometer-2:before,
+.@{fa-css-prefix}-thermometer-half:before { content: @fa-var-thermometer-half; }
+.@{fa-css-prefix}-thermometer-1:before,
+.@{fa-css-prefix}-thermometer-quarter:before { content: @fa-var-thermometer-quarter; }
+.@{fa-css-prefix}-thermometer-0:before,
+.@{fa-css-prefix}-thermometer-empty:before { content: @fa-var-thermometer-empty; }
+.@{fa-css-prefix}-shower:before { content: @fa-var-shower; }
+.@{fa-css-prefix}-bathtub:before,
+.@{fa-css-prefix}-s15:before,
+.@{fa-css-prefix}-bath:before { content: @fa-var-bath; }
+.@{fa-css-prefix}-podcast:before { content: @fa-var-podcast; }
+.@{fa-css-prefix}-window-maximize:before { content: @fa-var-window-maximize; }
+.@{fa-css-prefix}-window-minimize:before { content: @fa-var-window-minimize; }
+.@{fa-css-prefix}-window-restore:before { content: @fa-var-window-restore; }
+.@{fa-css-prefix}-times-rectangle:before,
+.@{fa-css-prefix}-window-close:before { content: @fa-var-window-close; }
+.@{fa-css-prefix}-times-rectangle-o:before,
+.@{fa-css-prefix}-window-close-o:before { content: @fa-var-window-close-o; }
+.@{fa-css-prefix}-bandcamp:before { content: @fa-var-bandcamp; }
+.@{fa-css-prefix}-grav:before { content: @fa-var-grav; }
+.@{fa-css-prefix}-etsy:before { content: @fa-var-etsy; }
+.@{fa-css-prefix}-imdb:before { content: @fa-var-imdb; }
+.@{fa-css-prefix}-ravelry:before { content: @fa-var-ravelry; }
+.@{fa-css-prefix}-eercast:before { content: @fa-var-eercast; }
+.@{fa-css-prefix}-microchip:before { content: @fa-var-microchip; }
+.@{fa-css-prefix}-snowflake-o:before { content: @fa-var-snowflake-o; }
+.@{fa-css-prefix}-superpowers:before { content: @fa-var-superpowers; }
+.@{fa-css-prefix}-wpexplorer:before { content: @fa-var-wpexplorer; }
+.@{fa-css-prefix}-meetup:before { content: @fa-var-meetup; }
diff --git a/themes/bootstrap3/less/vendor/font-awesome/variables.less b/themes/bootstrap3/less/vendor/font-awesome/variables.less
index 2b3381975e9e6ba8b0bf98ee86abf264ad158cb7..7ddbbc0115f5b017bae9f401651f00d824a396b2 100644
--- a/themes/bootstrap3/less/vendor/font-awesome/variables.less
+++ b/themes/bootstrap3/less/vendor/font-awesome/variables.less
@@ -4,14 +4,18 @@
 @fa-font-path:        "../fonts";
 @fa-font-size-base:   14px;
 @fa-line-height-base: 1;
-//@fa-font-path:        "//netdna.bootstrapcdn.com/font-awesome/4.6.3/fonts"; // for referencing Bootstrap CDN font files directly
+//@fa-font-path:        "//netdna.bootstrapcdn.com/font-awesome/4.7.0/fonts"; // for referencing Bootstrap CDN font files directly
 @fa-css-prefix:       fa;
-@fa-version:          "4.6.3";
+@fa-version:          "4.7.0";
 @fa-border-color:     #eee;
 @fa-inverse:          #fff;
 @fa-li-width:         (30em / 14);
 
 @fa-var-500px: "\f26e";
+@fa-var-address-book: "\f2b9";
+@fa-var-address-book-o: "\f2ba";
+@fa-var-address-card: "\f2bb";
+@fa-var-address-card-o: "\f2bc";
 @fa-var-adjust: "\f042";
 @fa-var-adn: "\f170";
 @fa-var-align-center: "\f037";
@@ -60,11 +64,15 @@
 @fa-var-backward: "\f04a";
 @fa-var-balance-scale: "\f24e";
 @fa-var-ban: "\f05e";
+@fa-var-bandcamp: "\f2d5";
 @fa-var-bank: "\f19c";
 @fa-var-bar-chart: "\f080";
 @fa-var-bar-chart-o: "\f080";
 @fa-var-barcode: "\f02a";
 @fa-var-bars: "\f0c9";
+@fa-var-bath: "\f2cd";
+@fa-var-bathtub: "\f2cd";
+@fa-var-battery: "\f240";
 @fa-var-battery-0: "\f244";
 @fa-var-battery-1: "\f243";
 @fa-var-battery-2: "\f242";
@@ -214,19 +222,25 @@
 @fa-var-dot-circle-o: "\f192";
 @fa-var-download: "\f019";
 @fa-var-dribbble: "\f17d";
+@fa-var-drivers-license: "\f2c2";
+@fa-var-drivers-license-o: "\f2c3";
 @fa-var-dropbox: "\f16b";
 @fa-var-drupal: "\f1a9";
 @fa-var-edge: "\f282";
 @fa-var-edit: "\f044";
+@fa-var-eercast: "\f2da";
 @fa-var-eject: "\f052";
 @fa-var-ellipsis-h: "\f141";
 @fa-var-ellipsis-v: "\f142";
 @fa-var-empire: "\f1d1";
 @fa-var-envelope: "\f0e0";
 @fa-var-envelope-o: "\f003";
+@fa-var-envelope-open: "\f2b6";
+@fa-var-envelope-open-o: "\f2b7";
 @fa-var-envelope-square: "\f199";
 @fa-var-envira: "\f299";
 @fa-var-eraser: "\f12d";
+@fa-var-etsy: "\f2d7";
 @fa-var-eur: "\f153";
 @fa-var-euro: "\f153";
 @fa-var-exchange: "\f0ec";
@@ -294,6 +308,7 @@
 @fa-var-forumbee: "\f211";
 @fa-var-forward: "\f04e";
 @fa-var-foursquare: "\f180";
+@fa-var-free-code-camp: "\f2c5";
 @fa-var-frown-o: "\f119";
 @fa-var-futbol-o: "\f1e3";
 @fa-var-gamepad: "\f11b";
@@ -326,6 +341,7 @@
 @fa-var-google-wallet: "\f1ee";
 @fa-var-graduation-cap: "\f19d";
 @fa-var-gratipay: "\f184";
+@fa-var-grav: "\f2d6";
 @fa-var-group: "\f0c0";
 @fa-var-h-square: "\f0fd";
 @fa-var-hacker-news: "\f1d4";
@@ -342,6 +358,7 @@
 @fa-var-hand-scissors-o: "\f257";
 @fa-var-hand-spock-o: "\f259";
 @fa-var-hand-stop-o: "\f256";
+@fa-var-handshake-o: "\f2b5";
 @fa-var-hard-of-hearing: "\f2a4";
 @fa-var-hashtag: "\f292";
 @fa-var-hdd-o: "\f0a0";
@@ -365,8 +382,12 @@
 @fa-var-houzz: "\f27c";
 @fa-var-html5: "\f13b";
 @fa-var-i-cursor: "\f246";
+@fa-var-id-badge: "\f2c1";
+@fa-var-id-card: "\f2c2";
+@fa-var-id-card-o: "\f2c3";
 @fa-var-ils: "\f20b";
 @fa-var-image: "\f03e";
+@fa-var-imdb: "\f2d8";
 @fa-var-inbox: "\f01c";
 @fa-var-indent: "\f03c";
 @fa-var-industry: "\f275";
@@ -404,6 +425,7 @@
 @fa-var-link: "\f0c1";
 @fa-var-linkedin: "\f0e1";
 @fa-var-linkedin-square: "\f08c";
+@fa-var-linode: "\f2b8";
 @fa-var-linux: "\f17c";
 @fa-var-list: "\f03a";
 @fa-var-list-alt: "\f022";
@@ -436,8 +458,10 @@
 @fa-var-meanpath: "\f20c";
 @fa-var-medium: "\f23a";
 @fa-var-medkit: "\f0fa";
+@fa-var-meetup: "\f2e0";
 @fa-var-meh-o: "\f11a";
 @fa-var-mercury: "\f223";
+@fa-var-microchip: "\f2db";
 @fa-var-microphone: "\f130";
 @fa-var-microphone-slash: "\f131";
 @fa-var-minus: "\f068";
@@ -502,6 +526,7 @@
 @fa-var-plus-circle: "\f055";
 @fa-var-plus-square: "\f0fe";
 @fa-var-plus-square-o: "\f196";
+@fa-var-podcast: "\f2ce";
 @fa-var-power-off: "\f011";
 @fa-var-print: "\f02f";
 @fa-var-product-hunt: "\f288";
@@ -511,10 +536,12 @@
 @fa-var-question: "\f128";
 @fa-var-question-circle: "\f059";
 @fa-var-question-circle-o: "\f29c";
+@fa-var-quora: "\f2c4";
 @fa-var-quote-left: "\f10d";
 @fa-var-quote-right: "\f10e";
 @fa-var-ra: "\f1d0";
 @fa-var-random: "\f074";
+@fa-var-ravelry: "\f2d9";
 @fa-var-rebel: "\f1d0";
 @fa-var-recycle: "\f1b8";
 @fa-var-reddit: "\f1a1";
@@ -541,6 +568,7 @@
 @fa-var-rub: "\f158";
 @fa-var-ruble: "\f158";
 @fa-var-rupee: "\f156";
+@fa-var-s15: "\f2cd";
 @fa-var-safari: "\f267";
 @fa-var-save: "\f0c7";
 @fa-var-scissors: "\f0c4";
@@ -565,6 +593,7 @@
 @fa-var-shopping-bag: "\f290";
 @fa-var-shopping-basket: "\f291";
 @fa-var-shopping-cart: "\f07a";
+@fa-var-shower: "\f2cc";
 @fa-var-sign-in: "\f090";
 @fa-var-sign-language: "\f2a7";
 @fa-var-sign-out: "\f08b";
@@ -581,6 +610,7 @@
 @fa-var-snapchat: "\f2ab";
 @fa-var-snapchat-ghost: "\f2ac";
 @fa-var-snapchat-square: "\f2ad";
+@fa-var-snowflake-o: "\f2dc";
 @fa-var-soccer-ball-o: "\f1e3";
 @fa-var-sort: "\f0dc";
 @fa-var-sort-alpha-asc: "\f15d";
@@ -626,6 +656,7 @@
 @fa-var-subway: "\f239";
 @fa-var-suitcase: "\f0f2";
 @fa-var-sun-o: "\f185";
+@fa-var-superpowers: "\f2dd";
 @fa-var-superscript: "\f12b";
 @fa-var-support: "\f1cd";
 @fa-var-table: "\f0ce";
@@ -635,6 +666,7 @@
 @fa-var-tags: "\f02c";
 @fa-var-tasks: "\f0ae";
 @fa-var-taxi: "\f1ba";
+@fa-var-telegram: "\f2c6";
 @fa-var-television: "\f26c";
 @fa-var-tencent-weibo: "\f1d5";
 @fa-var-terminal: "\f120";
@@ -644,6 +676,17 @@
 @fa-var-th-large: "\f009";
 @fa-var-th-list: "\f00b";
 @fa-var-themeisle: "\f2b2";
+@fa-var-thermometer: "\f2c7";
+@fa-var-thermometer-0: "\f2cb";
+@fa-var-thermometer-1: "\f2ca";
+@fa-var-thermometer-2: "\f2c9";
+@fa-var-thermometer-3: "\f2c8";
+@fa-var-thermometer-4: "\f2c7";
+@fa-var-thermometer-empty: "\f2cb";
+@fa-var-thermometer-full: "\f2c7";
+@fa-var-thermometer-half: "\f2c9";
+@fa-var-thermometer-quarter: "\f2ca";
+@fa-var-thermometer-three-quarters: "\f2c8";
 @fa-var-thumb-tack: "\f08d";
 @fa-var-thumbs-down: "\f165";
 @fa-var-thumbs-o-down: "\f088";
@@ -653,6 +696,8 @@
 @fa-var-times: "\f00d";
 @fa-var-times-circle: "\f057";
 @fa-var-times-circle-o: "\f05c";
+@fa-var-times-rectangle: "\f2d3";
+@fa-var-times-rectangle-o: "\f2d4";
 @fa-var-tint: "\f043";
 @fa-var-toggle-down: "\f150";
 @fa-var-toggle-left: "\f191";
@@ -693,11 +738,16 @@
 @fa-var-usb: "\f287";
 @fa-var-usd: "\f155";
 @fa-var-user: "\f007";
+@fa-var-user-circle: "\f2bd";
+@fa-var-user-circle-o: "\f2be";
 @fa-var-user-md: "\f0f0";
+@fa-var-user-o: "\f2c0";
 @fa-var-user-plus: "\f234";
 @fa-var-user-secret: "\f21b";
 @fa-var-user-times: "\f235";
 @fa-var-users: "\f0c0";
+@fa-var-vcard: "\f2bb";
+@fa-var-vcard-o: "\f2bc";
 @fa-var-venus: "\f221";
 @fa-var-venus-double: "\f226";
 @fa-var-venus-mars: "\f228";
@@ -722,10 +772,16 @@
 @fa-var-wheelchair-alt: "\f29b";
 @fa-var-wifi: "\f1eb";
 @fa-var-wikipedia-w: "\f266";
+@fa-var-window-close: "\f2d3";
+@fa-var-window-close-o: "\f2d4";
+@fa-var-window-maximize: "\f2d0";
+@fa-var-window-minimize: "\f2d1";
+@fa-var-window-restore: "\f2d2";
 @fa-var-windows: "\f17a";
 @fa-var-won: "\f159";
 @fa-var-wordpress: "\f19a";
 @fa-var-wpbeginner: "\f297";
+@fa-var-wpexplorer: "\f2de";
 @fa-var-wpforms: "\f298";
 @fa-var-wrench: "\f0ad";
 @fa-var-xing: "\f168";
diff --git a/themes/bootstrap3/scss/bootstrap.scss b/themes/bootstrap3/scss/bootstrap.scss
index aad53f084f692285b9bc7a0c6cb7a72503eb8a6c..97ab99f01f9488292c4c3b93ea72aa70164e7c83 100644
--- a/themes/bootstrap3/scss/bootstrap.scss
+++ b/themes/bootstrap3/scss/bootstrap.scss
@@ -4,11 +4,12 @@ $fa-font-path: "../../bootstrap3/css/fonts";
 @import "vendor/bootstrap-accessibility/bootstrap-accessibility";
 @import "vendor/a11y";
 
-$fa-font-path: "../../../../../../themes/bootstrap3/css/fonts" !default;
+@import "components/variables";
 
 @import "components/advanced-search";
 @import "components/alphabrowse";
 @import "components/autocomplete";
+@import "components/channels";
 @import "components/icons";
 @import "components/js-tree";
 @import "components/lightbox";
@@ -19,21 +20,47 @@ $fa-font-path: "../../../../../../themes/bootstrap3/css/fonts" !default;
 @import "components/similar-carousel";
 @import "components/sliders";
 
-.alert.alert-info a {text-decoration: underline;}
-.btn.disabled {
-  &:active,
-  &:focus,
-  &:hover {color: #000;}
-}
-header .dropdown form { display: none; }
-.list-unstyled {margin: 0;}
-.highlight,mark {
+/**
+ * Notes
+ * = As of 4.0, code styles aren't enforced, but
+ *   preferred styles are outlined here: http://codeguide.co/#css
+ * = The preferred method for writing code is to put generic and mobile styles first
+ *   and surround desktop styling with media min-width queries.
+ * = Bootstrap 3 breakpoints: <768px, >=768px, >=992px, >=1200px
+ *                                xs,      sm,      md,       lg
+ * = Breakpoint of <=530px also used to target phones specifically
+ */
+
+html { font-size: 14px; } // Root font size from Bootstrap, allows consistent use of rem units
+a,
+label { cursor: pointer; }
+.alert.alert-info a { text-decoration: underline; }
+
+// Improve contrast
+.btn.disabled:active,
+.btn.disabled:focus,
+.btn.disabled:hover { color: #000; }
+.list-unstyled { margin: 0; }
+.icon-bar { background-color: #888; }
+
+// Normalize highlighting
+.highlight,
+mark {
   background: lighten(#FF0, 20%);
   padding: .1em .2em;
 }
-.icon-bar {background-color: #888;}
-img {max-width: 100%;}
-.popover {width: 250px;}
+
+// Normalize
+img { max-width: 100%; }
+
+// Bootstrap overrides
+.breadcrumb {
+  margin-top: .5rem;
+  margin-bottom: .5rem;
+}
+.label { display: inline-block; }
+.popover { width: 250px; }
+.resulthead { @include clearfix(); }
 .sub-breadcrumb {
   padding: 5px 10px;
   white-space: nowrap;
@@ -45,12 +72,10 @@ img {max-width: 100%;}
     content: "#{$breadcrumb-separator}\00a0";
   }
 }
-.tab-content {padding: 4px;}
+.tab-content { padding: 4px; }
 
-@media (max-width: 991px) {
-  header .container.navbar {margin-bottom: 0;}
-  .searchForm {margin-top: 0;}
-}
+h2 { font-size: 20px; }
+h3 { font-size: 16px; }
 @media (min-width: 768px) {
   h2 {
     font-size: 23px;
@@ -61,16 +86,39 @@ img {max-width: 100%;}
     font-weight: normal;
   }
   .form-control { max-width: 400px; }
+  #modal .form-control { max-width: none; }
+}
+
+/* ------ Layout ------ */
+footer {
+  @extend .container;
+  padding: 1rem;
 }
-@media (max-width: 767px) {
-  h2 { font-size: 20px; }
-  h3 { font-size: 16px; }
-  .searchForm {padding-top: 0;}
+@media (min-width: 768px) {
+  .footer-container {
+    display: flex;
+    width: 100%;
+  }
+  .footer-column { flex: 0 1 100%; }
+
+  // Main content and sidebar widths and float
+  .mainbody { width: 75%; }
+  .sidebar { width: 25%; }
+  .mainbody.left,
+  .sidebar.left {
+    float: left;
+    padding-right: 1rem;
+  }
+  .mainbody.right,
+  .sidebar.right {
+    float: right;
+    padding-left: 1rem;
+  }
 }
 
-/* --- Form Errors --- */
+/* ------ Form Errors ------ */
 .has-error {margin-bottom: 0;}
-.sms-error {@extend .has-error;}
+.sms-error { @extend .has-error; }
 .help-block.with-errors {
   margin: 0;
   padding-top: $padding-base-vertical;
@@ -78,41 +126,159 @@ img {max-width: 100%;}
   &:empty {padding: 0;}
 }
 
-/* --- Badges - blend the links in --- */
-.badge a {color: #fff;}
+/* ------ Admin ------ */
+.form-admin-maintenance .form-control {
+  display: inline-block;
+  width: 100px;
+}
+
+/* ------ Badges - blend the links in ------ */
+.badge a { color: #fff; }
 
-/* --- Browse --- */
-.browse.list-group .list-group-item {
+/* ------ Browse ------ */
+// Layout
+@media (min-width: 768px) {
+  .browse-container { display: flex; }
+  .browse-list {
+    flex-basis: 25%;
+    padding-left: .5rem;
+    padding-right: .5rem;
+  }
+}
+// List item styling
+.browse-item {
+  position: relative;
+  display: block;
+  padding: .5rem 1rem;
+  border: 1px solid $list-group-border;
+  border-bottom: 0;
   word-wrap: break-word;
-  &.view-record {
-    padding: 2px 4px;
-    font-size: 85%;
-    text-align: right;
-    border-top: 0;
+}
+.browse-item.active {
+  background-color: $brand-primary;
+  color: #fff;
+
+  .badge {
+    background-color: #fff;
+    color: $gray-darker;
+  }
+}
+.browse-item:hover { background-color: $nav-link-hover-bg; }
+.browse-item:last-child { border-bottom: 1px solid $list-group-border; }
+
+.browse-item.with-badge {
+  padding-right: 3rem; // Prevent text from overlapping badge
+  .badge {
+    position: absolute;
+    top: .5rem;
+    right: .25rem;
   }
 }
+.browse-item.view-record {
+  padding: 2px 4px;
+  font-size: 85%;
+  text-align: right;
+  border-top: 0;
+}
 
-/* --- Cart --- */
+/* ------ Cart ------ */
 .cart-controls .checkbox {
-  line-height: 2.5em;
-  padding-right: 1em;
+  line-height: 2.5rem;
+  padding-right: 1rem;
+}
+.nav .btn-bookbag-toggle { float: left; }
+.nav .btn-bookbag-toggle a {
+  display: block;
+  padding: $nav-link-padding;
+  text-decoration: none;
+  &:hover,
+  &:focus {
+    @include outline(1px);
+    text-decoration: none;
+    background-color: $nav-link-hover-bg;
+  }
+}
+
+/* ------ Collections ------ */
+// Layout
+@media (min-width: 768px) {
+  .collection-hierarchytree { display: flex; }
+  .collection-hierarchytree .tree-panel,
+  #tree-preview {
+    flex-basis: 50%;
+    padding: 1rem;
+  }
+}
+
+/* ------ Devtools ------ */
+.translation-output {
+  width: 100%;
+  max-width: none;
+  font-family: $font-family-monospace;
+  font-size: 12px;
+  white-space: pre;
+}
+
+/* ------ Facets ------ */
+.date-fields {
+  display: flex;
+
+  .date-from { padding-right: .25rem; }
+  .date-to   { padding-left:  .25rem; }
 }
+.top-facets {
+  margin-left: -.5rem;
+  margin-right: -.5rem;
+}
+.top-facets .facet,
+.top-facets .narrow-toggle,
+.top-facets > strong {
+  display: inline-block;
+  padding: .25rem .5rem;
+  white-space: nowrap;
+}
+.top-facets .narrow-toggle { text-decoration: underline; }
+@media (min-width: 768px) {
+  .author-facets { display: flex; }
+  .author-list { flex: 0 1 100%; }
+}
+
+/* ------ MyResearch ------ */
+.form-login .btn-link ~ .btn-link { padding-left: 0; } // Login link spacing
+.myresearch-menu a {
+  display: block;
+  padding: 10px 15px;
+  &:hover,
+  &:focus { background-color: $nav-link-hover-bg; }
 
-/* --- PubDateVis --- */
+  .badge { float: right; }
+}
+.myresearch-menu a.active {
+  background-color: $brand-primary;
+  color: #fff;
+
+  .badge {
+    background-color: #fff;
+    color: $gray-darker;
+  }
+}
+.list-edit-container { @include clearfix(); }
+
+/* ------ PubDateVis ------ */
 #dateVisColorSettings {
   background-color: #fff; // background of box
-  fill: rgb(234,234,234); // fillColor
+  fill: #eee;             // fillColor
   outline-color: #c38835; // selection color
   stroke: $brand-primary; // color
 }
 
-/* --- Table wrapping to prevent horizontal overflow --- */
+/* ------ Table wrapping to prevent horizontal overflow ------ */
 .table {
   table-layout: fixed;
   word-wrap: break-word;
 }
 
-/* --- Visualization View --- */
+/* ------ Visualization View ------ */
 .node {
   position: absolute;
   box-sizing: content-box;
@@ -120,10 +286,10 @@ img {max-width: 100%;}
   overflow: hidden;
   font: 10px sans-serif;
   line-height: 12px;
-  border: 1px solid white;
+  border: 1px solid #fff;
 }
 .node div {margin-top: 0px;}
-.toplevel {border: 2px solid black;}
+.toplevel {border: 2px solid #000;}
 .node .label {
   position: absolute;
   bottom: 0;
@@ -138,9 +304,7 @@ img {max-width: 100%;}
 .notalabel {color: #000;}
 #viz-instructions {padding-top: 600px;}
 
-span[class^="services-"], span[class*=" services-"] span::before {
-  content: ", ";
-}
-span[class^="services-"], span[class*=" services-"] span:first-of-type::before {
-  content: "";
-}
+span[class^="services-"],
+span[class*=" services-"] span::before { content: ", "; }
+span[class^="services-"],
+span[class*=" services-"] span:first-of-type::before { content: ""; }
diff --git a/themes/bootstrap3/scss/components/advanced-search.scss b/themes/bootstrap3/scss/components/advanced-search.scss
index 1f65e9da23ab43456797e9dc4b8dae226bea9376..3d64b0aad16e702db191ea1634f7f15739ed0e30 100644
--- a/themes/bootstrap3/scss/components/advanced-search.scss
+++ b/themes/bootstrap3/scss/components/advanced-search.scss
@@ -1,51 +1,185 @@
-.group {
+// Group of multiple searches
+.adv-group {
+  @include clearfix();
   position: relative;
-  background: $gray-lighter;
+  margin-bottom: .5rem;
+  padding: 1rem;
+  border: 1px solid $panel-default-border;
   border-radius: $border-radius-base;
-  border: 1px solid darken($gray-lighter, 15%);
-  margin-top: 0;
-  margin-bottom: .5em !important;
+
+  & ~ & { margin-top: 1rem; } // Spacing between groups
+
   .add_search_link {
     display: inline-block;
     margin-top: 4px;
   }
-  & .group-close {
-    @extend .close;
+}
+.add_search_link,
+.adv-group-close {
+  display: inline-block;
+  padding-top: .25rem;
+  padding-bottom: .25rem;
+}
+.adv-group-close { color: $state-danger-text; }
+.adv-search,
+.adv-search .input-group { width: 100%; }
+.adv-search {
+  @include clearfix();
+  margin-bottom: 1.5rem;
+}
+
+.adv-term-input { margin-bottom: .5rem; }
+.adv-term-type {
+  float: left;
+  max-width: 80%;
+}
+.adv-term-remove {
+  @extend .close; // borrow the X from bootstrap close
+  float: left;
+  width: 20%;
+  height: 30px;
+  line-height: 1.7;
+  text-align: center;
+  opacity: .4;
+}
+.adv-submit { @include clearfix(); }
+.adv-submit .clear-btn { float: right; }
+
+@media (min-width: 768px) {
+  .adv-group-terms {
+    float: left;
+    width: 75%;
+    padding-right: 1rem;
+  }
+  .adv-group-match {
+    float: right;
+    width: 25%;
+  }
+  .adv-group-close {
     position: absolute;
-    top: .3em;
-    right: .5em;
-    opacity: .4;
-    z-index: 2;
-  }
-  .search {
-    margin-bottom: 2px;
-    .close {opacity: .8;}
-  }
-  @media (min-width: 768px) {
-    padding: 10px 10px 10px 25px;
-    [class^=col-] {padding-left: 0;}
-  }
-  @media (max-width: 767px) {
-    .search  .middle {
-      float: left;
-      width: 90%;
+    right: 1rem;
+    bottom: 1rem;
+    min-width: calc(25% - 1rem);
+  }
+  .adv-search {
+    margin-bottom: 0;
+
+    .adv-term-input,
+    .adv-term-type { float: left; }
+    .adv-term-input {
+      width: 60%;
+      margin-right: 2%;
     }
-    & .group-close {
-      top: .5em;
-      right: 1em;
-      opacity: .6;
+    .adv-term-type { max-width: 30%; }
+    .adv-term-remove { width: 8%; }
+  }
+}
+
+#groupPlaceHolder {
+  display: block;
+  padding: 1rem;
+}
+
+/* --- Fieldsets --- */
+@media (min-width: 768px) {
+  fieldset,
+  .fieldset {
+    float: left;
+    width: 33%;
+    padding-right: 1rem;
+    padding-bottom: 1rem;
+  }
+  .solr-facets,
+  .summon-facets {
+    float: none;
+    width: auto;
+    margin-top: 1rem;
+  }
+  .summon-facets .facet-fieldset {
+    float: left;
+    width: 50%;
+    padding-right: 1rem;
+  }
+}
+
+/* --- EDS --- */
+.adv-term-input,
+.adv-term-op { margin-bottom: .25rem; }
+.adv-search:first-of-type .adv-term-op { display: none; }
+@media (min-width: 768px) {
+  .eds-adv .adv-term-op {
+    float: left;
+    width: 16%;
+    margin-right: 1%;
+
+    body.rtl & {
+      float: right;
+      margin-left: 0;
+      margin-right: 1%;
     }
   }
-  @media (max-width: 991px) {
-    .form-control {max-width: none;}
+  .eds-adv .adv-search:first-of-type .adv-term-input { margin-left: 17%; }
+  .eds-adv .adv-term-input {
+    width: 39%;
+    margin-right: 0;
+  }
+  .eds-adv .help-block {
+    float: left;
+    width: 6%;
+    text-align: center;
   }
 }
-#groupPlaceHolder {
-  display:block;
-  padding:6px;
+
+/* --- Primo --- */
+.primo-adv-search .search { margin-bottom: .5rem; }
+.primo-adv-search .search-container { width: 100%; }
+.primo-adv-label {
+  line-height: $input-height-base;
+  padding-right: 1rem;
+}
+@media (min-width: 768px) {
+  .primo.adv-group,
+  .primo-adv-search .search {
+    display: flex;
+
+    select {
+      flex-shrink: 2;
+      margin-right: .5rem;
+    }
+    .primo-adv-input { flex-grow: 1; }
+  }
+  .primo-adv-label { flex-shrink: 0; }
 }
-.template-dir-eds.template-name-advanced {
-  legend {margin-bottom: 0;}
-  .no-js .group:nth-child(n+3) {display: none;}
-  .search .close a {margin-left: -2em;}
+
+/* --- Solr --- */
+@media (min-width: 768px) {
+  .solr-facet-container {
+    display: flex;
+    flex-wrap: wrap;
+  }
+  .solr-adv-facet { flex: 1 25%; }
 }
+
+/* -- Right to left --- */
+body.rtl {
+  fieldset,
+  .fieldset,
+  .adv-search .adv-term-input,
+  .adv-search .adv-term-type,
+  .eds-adv .help-block,
+  .summon-facets .facet-fieldset { float: right; }
+  .adv-submit .clear-btn,
+  .adv-group-match { float: left; }
+  .adv-search .adv-term-input {
+    margin-left: 2%;
+    margin-right: 0;
+  }
+  .date-from {
+    padding-left: .25rem;
+    padding-right: 0;
+  }
+  .date-to {
+    padding-left: 0;
+    padding-right: .25rem;
+  }
+}
\ No newline at end of file
diff --git a/themes/bootstrap3/scss/components/alphabrowse.scss b/themes/bootstrap3/scss/components/alphabrowse.scss
index 672066778870d7928f5ea6468c5bd4f1a173314e..d1f28f7cd7dda1525c36621639dbc87dc88cb09f 100644
--- a/themes/bootstrap3/scss/components/alphabrowse.scss
+++ b/themes/bootstrap3/scss/components/alphabrowse.scss
@@ -1,15 +1,15 @@
 .alphabrowse {
   border-collapse: separate;
-  .lcc {width: 20%;}
+  .lcc { width: 20%; }
   .titles {
     width: 10%;
     text-align: center;
   }
   /* highlighting the row makes ff bugs; operate on its children */
   tr.browse-match td {
-    border-top: .2em solid $brand-primary;
-    border-bottom: .2em solid $brand-primary;
-    &:first-child {border-left: .2em solid $brand-primary;}
-    &:last-child {border-right: .2em solid $brand-primary;}
+    border-top: .2rem solid $brand-primary;
+    border-bottom: .2rem solid $brand-primary;
+    &:first-child { border-left: .2em solid $brand-primary;  }
+    &:last-child  { border-right: .2em solid $brand-primary; }
   }
 }
diff --git a/themes/bootstrap3/scss/components/autocomplete.scss b/themes/bootstrap3/scss/components/autocomplete.scss
index 1841dec17fc484dbd3ab1bbd0e2c1c83768ac2ca..4d72a36ed4f8ea1d37a9e7fef895ba6db69a066c 100644
--- a/themes/bootstrap3/scss/components/autocomplete.scss
+++ b/themes/bootstrap3/scss/components/autocomplete.scss
@@ -1,25 +1,26 @@
-/* crhallberg/autocomplete.js 0.14 */
+/* https://github.com/vufind-org/autocomplete.js 1.0b */
 $autocomplete-item-bg   : #fff !default;
 $autocomplete-active-bg : $brand-primary !default;
-$autocomplete-hover-bg  : lighten($brand-primary, 60%) !default;
+$autocomplete-hover-bg  : lighten($brand-primary, 40%) !default;
 $autocomplete-border    : lightgray !default;
 $autocomplete-secondary : darkgray !default; // item description
 
 .autocomplete-results {
   position: absolute;
+  display: table;
+  max-width: 500px; /* CUSTOMIZED */
   margin: 0;
   margin-top: 2px;
   padding: 0;
   border: 1px solid $autocomplete-border;
   background-color: $autocomplete-item-bg;
-  border-radius: $border-radius-base;
   overflow: hidden;
   z-index: 50;
 
-  .item {
+  .ac-item {
     display: block;
     margin: 0;
-    padding: .75rem 1.25rem;
+    padding: .5rem;
     border-bottom: 1px solid $autocomplete-border;
     cursor: pointer;
 
@@ -36,4 +37,17 @@ $autocomplete-secondary : darkgray !default; // item description
       color: $autocomplete-secondary;
     }
   }
+  .ac-section-header {
+    float: right;
+    display: block;
+    margin-top: -1.75rem;
+    padding: 0 .5rem;
+    color: $autocomplete-border;
+    background-color: #fff;
+  }
+  .ac-section-divider {
+    margin: 1rem .5rem;
+    border: 0;
+    border-top: 2px solid $autocomplete-border;
+  }
 }
diff --git a/themes/bootstrap3/scss/components/channels.scss b/themes/bootstrap3/scss/components/channels.scss
new file mode 100644
index 0000000000000000000000000000000000000000..dddb8817c9814a25656b915d0289311f09a06d58
--- /dev/null
+++ b/themes/bootstrap3/scss/components/channels.scss
@@ -0,0 +1,42 @@
+.channel {
+  position: relative;
+  width: 100%;
+  height: 300px;
+  border: 1px solid $btn-default-border;
+  border-radius: $border-radius-base;
+}
+.channel .slider-menu {
+  border-top-color: $btn-default-border;
+  border-radius: 0 0 $border-radius-base $border-radius-base;
+  .channel-links .btn { margin-left: 4px; }
+}
+.channel .channel-record.slide {
+  display: inline-block;
+  min-width: 100px;
+  max-height: 240px;
+  padding: 0 .5rem;
+  text-align: center;
+  text-overflow: ellipsis;
+  overflow: hidden;
+}
+.channel .channel-record.is-selected { @extend a:hover; }
+.channel .channel-record .thumb {
+  height: 200px;
+  background-position: center center;
+  background-repeat: no-repeat;
+  background-size: contain;
+}
+.channel .popover {
+  width: 500px;
+  max-width: none;
+}
+
+.channel-title a:hover { text-decoration: none; }
+.channel-title i.fa-fw {
+  width: 1.4em;
+  padding-top: 0.5em;
+  font-size: 0.6em;
+  text-align: center;
+  vertical-align: top;
+}
+.channel-title .placeholder { width: 25px; }
diff --git a/themes/bootstrap3/scss/components/icons.scss b/themes/bootstrap3/scss/components/icons.scss
index f706cd44692f4678b7f445d399403e513cf9f27e..ed654a6ed50f84aae44d12426c570c701cda0035 100644
--- a/themes/bootstrap3/scss/components/icons.scss
+++ b/themes/bootstrap3/scss/components/icons.scss
@@ -1,7 +1,12 @@
+/**
+ * Assign catalog formats to Font Awesome icons
+ */
 
+// Alias
+.fa-printer:before        {content: "\f02f";} // .fa-print
 // Search Icons
-.fa-grid:before   {content: "\f00a";} // .fa-th
-.fa-visual:before {content: "\f008";} // .fa-film
+.fa-grid:before           {content: "\f00a";} // .fa-th
+.fa-visual:before         {content: "\f008";} // .fa-film
 // Type Icons
 .fa-x:before              {content: "\f0f6";} // .fa-file-text-o
 .fa-atlas:before          {content: "\f14e";} // .fa-compass
diff --git a/themes/bootstrap3/scss/components/js-tree.scss b/themes/bootstrap3/scss/components/js-tree.scss
index a53839e3155fa14aefc6848824204d447a83b684..3a0c314052aa6b51be60d2ed790726e0ea876b04 100644
--- a/themes/bootstrap3/scss/components/js-tree.scss
+++ b/themes/bootstrap3/scss/components/js-tree.scss
@@ -1,4 +1,5 @@
-.hierarchy-tree {
+.hierarchy-tree,
+.jstree-facet {
   /* jsTree arrows */
   .jstree-ocl:before {
     float: left;
@@ -12,15 +13,15 @@
     text-decoration: inherit;
     speak: none;
   }
-  .jstree-open > .jstree-ocl:before {content: "\f0d7";}
-  .jstree-closed > .jstree-ocl:before {content: "\f0da";}
-  .jstree-leaf > .jstree-ocl:before {content: " ";}
+  .jstree-open > .jstree-ocl:before   {content: "\f0d7";} // .fa-caret-down
+  .jstree-closed > .jstree-ocl:before {content: "\f0da";} // .fa-caret-right
+  .jstree-leaf > .jstree-ocl:before   {content: " ";}
   .jstree-icon {
     width: 16px;
     color: #000;
   }
   .jstree-anchor {
-    padding: 2px 5px;
+    padding-left: 5px;
     white-space: nowrap;
   }
   .jstree-container-ul,
@@ -37,10 +38,16 @@
   }
   .jstree-search a {
     font-style: italic;
-    color: #8b0000 ;
+    color: #8b0000;
     font-weight: bold;
   }
 }
+.jstree-node.list-group-item {
+  margin-bottom: 0;
+  border: 0;
+  border-bottom: 1px solid $list-group-border;
+  border-radius: 0;
+}
 
 /* --- Record --- */
 #hierarchyTreeHolder {
@@ -73,12 +80,14 @@
 }
 /* facet list styling */
 .jstree-facet li span.main {
-  display: block;
-  padding-left: 1px; /* Fix Firefox cutting the checkboxes */
   overflow: hidden;
   text-overflow: ellipsis;
   white-space: nowrap;
 }
+.jstree-facet .main.applied .fa-check {
+  margin-top: 2px;
+  margin-right: 4px;
+}
 .jstree-facet .jstree-container-ul {
   padding: 0;
   & > li.active,
@@ -88,12 +97,10 @@
   }
 }
 li.jstree-facet,
-li.jstree-node {
-  list-style: none;
-}
-li.jstree-facet .badge {cursor: text;}
-li.jstree-facet ul {padding-left: 20px;}
+li.jstree-node { list-style: none; }
+li.jstree-facet .badge { cursor: text; }
+li.jstree-facet ul { padding-left: 20px; }
 
-.list-group.facet .jstree-node.list-group-item { padding-left: 19px; }
-.list-group.facet .jstree-icon::before { margin-left: -12px; }
-.list-group.facet .jstree-facet li span.main { padding: 1px; }
+.facet .jstree-node.list-group-item { padding-left: 19px; }
+.facet .jstree-icon::before { margin-left: -12px; }
+.facet .jstree-facet li span.main { padding: 1px; }
diff --git a/themes/bootstrap3/scss/components/lightbox.scss b/themes/bootstrap3/scss/components/lightbox.scss
index e793dc0b3120e5a88790d11008ff95ab9c1c740e..9361fab53c8332b260db43ea81f248ccf5d7c0a8 100644
--- a/themes/bootstrap3/scss/components/lightbox.scss
+++ b/themes/bootstrap3/scss/components/lightbox.scss
@@ -1,8 +1,5 @@
-.lightbox-only { display: none; }
-#modal .lightbox-only { display: initial; }
-
-#modal {background-color: rgba(0,0,0,.2);}
-#modal .modal-content > .close {
+#modal { background-color: rgba(0,0,0,.2); }
+#modal .modal-content > .close { // Fancy side X button
   position: absolute;
   right: -50px;
   top: 0;
@@ -10,15 +7,27 @@
   font-size: 32pt;
   color: #fff;
   opacity: .7;
+  body.rtl & {
+    left: -50px;
+    right: auto;
+  }
 }
-#modal .modal-content > .close:hover {opacity: 1;}
+#modal .modal-content > .close:hover { opacity: 1; }
 #modal .modal-body h1,
 #modal .modal-body h2 {
   margin-top: 0.3rem;
   margin-bottom: 1.3rem;
 }
 
-#modal .cart-controls .btn {margin-bottom: 4px;}
-#modal .cart-controls .checkbox {padding-bottom: 1em;}
-#modal .cart-controls ~ hr {margin-top: 0;}
+#modal .cart-controls .btn { margin-bottom: 4px; }
+#modal .cart-controls .checkbox { padding-bottom: 1rem; }
+#modal .cart-controls ~ hr { margin-top: 0; }
 .lightbox-scroll { overflow-y: auto; }
+
+// Loading spinner
+.modal-loading { float: right; }
+body.rtl .modal-loading { float: left; }
+
+// Utility classes
+.lightbox-only { display: none; }
+#modal .lightbox-only { display: initial; }
\ No newline at end of file
diff --git a/themes/bootstrap3/scss/components/offcanvas.scss b/themes/bootstrap3/scss/components/offcanvas.scss
index 8a160dd13ce5b984420b5ef45c313f5c62fc1a03..559279c66884e6b48cc80c4dc94cf98650a83abd 100644
--- a/themes/bootstrap3/scss/components/offcanvas.scss
+++ b/themes/bootstrap3/scss/components/offcanvas.scss
@@ -1,8 +1,8 @@
-$offcanvas-offset: 75% !default;
-$offcanvas-padding: 30px !default;
+$offcanvas-offset: 75vw !default;  // Width of open menu
+$offcanvas-padding: 30px !default; // Body offset when offcanvas active, also width of toggle
 
 .offcanvas-overlay,
-.offcanvas-toggle {display: none;}
+.offcanvas-toggle { display: none; }
 
 @media screen and (max-width: 767px) {
   body.offcanvas {
@@ -15,48 +15,42 @@ $offcanvas-padding: 30px !default;
       padding-left: 0;
       padding-right: 0;
       overflow-y: auto;
-      h4 {padding-left: $padding-base-horizontal;}
-      .checkbox {margin-left: 20px + $padding-base-horizontal;}
+      h4 { padding-left: $padding-base-horizontal; }
+      .checkbox { margin-left: 20px + $padding-base-horizontal; }
       .list-group, .list-group-item {
         border-left: 0;
         border-right: 0;
         border-radius: 0 !important;
       }
     }
-    &.active {overflow-y: hidden;}
+    &.active { overflow-y: hidden; }
     &.offcanvas-left {
       padding-left: $offcanvas-padding - $grid-gutter-width/2;
-      & .main {background: #FFF;}
+      & .main { background: #FFF; }
       &.active {
         margin-left: $offcanvas-offset;
         margin-right: -$offcanvas-offset;
-        .sidebar {left: 0;}
-        .offcanvas-overlay {right: -$offcanvas-offset;}
-        .offcanvas-toggle {left: $offcanvas-offset;}
-      }
-      .sidebar {left: -$offcanvas-offset;}
-      .offcanvas-overlay {right: -100%;}
-      .offcanvas-toggle {
-        border-radius: 0 $border-radius-small $border-radius-small 0; // top right and bottom right
-        left: 0;
+        .sidebar { left: 0; }
+        .offcanvas-overlay { right: -$offcanvas-offset; }
+        .offcanvas-toggle { left: $offcanvas-offset; }
       }
+      .sidebar { left: -$offcanvas-offset; }
+      .offcanvas-overlay { right: -100%; }
+      .offcanvas-toggle { left: 0; }
     }
     &.offcanvas-right {
       padding-right: $offcanvas-padding - $grid-gutter-width/2;
-      & .main > .container {background: #FFF;}
+      & .main > .container { background: #FFF; }
       &.active {
         margin-left: -$offcanvas-offset;
         margin-right: $offcanvas-offset;
-        .sidebar {right: 0;}
-        .offcanvas-overlay {left: -$offcanvas-offset;}
-        .offcanvas-toggle {right: $offcanvas-offset;}
-      }
-      .sidebar {right: -$offcanvas-offset;}
-      .offcanvas-overlay {left: -100%;}
-      .offcanvas-toggle {
-        border-radius: $border-radius-small 0 0 $border-radius-small; // top left and bottom left
-        right: 0;
+        .sidebar { right: 0; }
+        .offcanvas-overlay { left: -$offcanvas-offset; }
+        .offcanvas-toggle { right: $offcanvas-offset; }
       }
+      .sidebar { right: -$offcanvas-offset; }
+      .offcanvas-overlay { left: -100%; }
+      .offcanvas-toggle { right: 0; }
     }
     .offcanvas-overlay {
       display: block;
@@ -70,17 +64,19 @@ $offcanvas-padding: 30px !default;
     .offcanvas-toggle {
       display: block;
       position: fixed;
-      top: 50%;
+      top: 0;
       width: calc($offcanvas-padding - 5px);
-      padding: 20px 0;
-      background: $brand-primary;
-      color: #EEE;
+      height: 100%;
+      border-left: 1px solid $gray-lighter;
+      border-right: 1px solid $gray-lighter;
+      line-height: 90vh; // Center vertically
       text-align: center;
+      background-color: #fff;
       z-index: 5;
     }
     .offcanvas-overlay,
     .offcanvas-toggle,
-    .offcanvas-toggle * {cursor: pointer;}
+    .offcanvas-toggle * { cursor: pointer; }
     &,.sidebar,
     .offcanvas-overlay,
     .offcanvas-toggle {
diff --git a/themes/bootstrap3/scss/components/record.scss b/themes/bootstrap3/scss/components/record.scss
index f6952443d5b42cf3ac960b7bc67725e720b0bef4..a5cb36a546c1bc5ac5a9180d7319f10c39648c1c 100644
--- a/themes/bootstrap3/scss/components/record.scss
+++ b/themes/bootstrap3/scss/components/record.scss
@@ -1,35 +1,108 @@
-.citation .pace-car {
-  th,
-  td {
-    border: 0;
-    padding: 0;
+.record .media-body h3 { margin-top: 0; } // Align title with top of image
+.recordcover { max-height: 300px; } // Keep the image from getting out of control
+@media (max-width: 767px) {
+  .record .media-left,
+  .record .media-right { display: block; }
+  .record .media-body { // Add a gap between the thumbnail and the info
+    display: block;
+    width: auto;
+    margin-top: 1rem;
   }
 }
-.citation th {text-align: right;}
-.item-notes ul { padding-left: 2rem; }
-.recordcover {max-height: 300px;}
+// Comma-separate formatting
+.result .record .format::after,
+.record .format:last-child::after { content: ""; }
+.record .format::after { content: ", "; }
+.record-previews { margin-top: .5rem; }
+
+/* ------ Nav ------ */
+.record-nav.nav { margin-bottom: 1rem; }
+.record-nav > li,
+.btn-bookbag-toggle { width: 100%; }
+.record-nav > li > a { padding: .5rem; }
+.record-nav > li > a,
+.btn-bookbag-toggle { text-align: center; }
+@media(min-width: 768px) {
+  .record-nav > li,
+  .btn-bookbag-toggle { width: auto; }
+  .record-nav > li > a { padding: $nav-link-padding; }
+  .record-nav > li > a,
+  .btn-bookbag-toggle { text-align: left; }
+}
+
+/* ------ Comments ------ */
+.comment-label,
+.comment-name { font-style: italic; }
+.comment { margin-bottom: 1rem; }
+.comment-name .delete { color: $state-danger-text; }
+@media (min-width: 768px) {
+  .comment-form,
+  .comment {
+    display: flex;
+    margin-bottom: 0;
+  }
+  .comment-label,
+  .comment-name {
+    min-width: 25%;
+    font-style: unset;
+  }
+  .comment-form .text-form { width: 100%; }
+  .comment-form > label { flex: 0 0 auto; }
+  .comment-form textarea {
+    display: block;
+    width: 100%;
+  }
+}
+
+/* ------ Tags ------ */
+.tagList button {
+  margin-top: 0;
+  padding-top: 0;
+  padding-bottom: 4px;
+  font-size: 95%;
+  vertical-align: initial;
+}
+.tagList .tag .badge {
+  margin: 0;
+  padding: 3px 7px;
+  font-weight: normal;
+}
+.tagList button .fa-close { margin-top: 3px; }
 .tagList {
   .tag {
     display: inline-block;
     margin: 0 1px 1px;
     border-radius: 4px;
+    // Use bootstrap mixin to make tags look like buttons
+    @include button-size($padding-base-vertical, $padding-base-vertical, $font-size-base, $line-height-base, $border-radius-base);
     &.selected {
       background-color: $btn-primary-bg;
-      a {color: #fff;}
+      a { color: #fff; }
       .badge {
         color: $gray-darker;
         background-color: #fff;
-        &:hover {color: #a94442;}
+        &:hover { color: #a94442; }
       }
     }
 
-    @include button-size($padding-base-vertical, $padding-base-vertical, $font-size-base, $line-height-base, $border-radius-base);
-    .badge .fa {width: 12px;}
+    .badge .fa { width: 12px; }
+  }
+  button { border: 0; }
+  .tag-form { display: inline; }
+}
+.tagList.loggedin .tag:not(.selected) .badge:hover { background-color: $brand-success; }
+
+
+.citation .pace-car {
+  th,
+  td {
+    border: 0;
+    padding: 0;
   }
-  button {border: 0;}
-  .tag-form {display: inline;}
 }
-.tagList.loggedin .tag:not(.selected) .badge:hover {background-color: $brand-success;}
+.citation th { text-align: right; }
+
+.item-notes ul { padding-left: 2rem; }
 
 .subject-line:hover { color: #999; }
 .subject-line:hover a { color: $link-hover-color; }
@@ -38,15 +111,9 @@
   text-decoration: none;
 }
 
-.record .format::after { content: ", "; }
-.result .record .format::after,
-.record .format:last-child::after { content: ""; }
-
 .marc-row-LEADER,
 .marc-row-006,
 .marc-row-007,
 .marc-row-008 {
   white-space: pre-wrap;
 }
-
-.comment-form textarea.form-control { display: block; }
diff --git a/themes/bootstrap3/scss/components/search.scss b/themes/bootstrap3/scss/components/search.scss
index 4ea08708a52140f707aa3ea9cedac4e42256f787..e4e26dc69f2ef4d3700a326bca5f72c25b88c17d 100644
--- a/themes/bootstrap3/scss/components/search.scss
+++ b/themes/bootstrap3/scss/components/search.scss
@@ -1,93 +1,217 @@
-$thumbnail-width-small: 60px !default;
+// Thumbnail sizes for media items: search results, list entries, record views
+$thumbnail-width-small:   60px !default;
 $thumbnail-width-medium: 100px !default;
-$thumbnail-width-large: 160px !default;
+$thumbnail-width-large:  160px !default;
 
-.bulkActionButtons label {display: inline-block;}
-.bulkActionButtons label input {margin-top: 2px;}
-.grid { @media (max-width: 767px) {min-height: 250px;} }
+// Hide these on mobile
+@media (max-width: 767px) {
+  .bulkActionButtons,
+  #datevispublishDatexWrapper,
+  .result .checkbox { display: none; }
+}
+
+.searchHomeContent { @include clearfix(); }
+.home-facet-list {
+  padding-left: 0;
+  padding-right: 1rem;
+  list-style: none;
+}
+@media (min-width: 768px) {
+  .search-home-facets,
+  .home-facet-container { display: flex; }
+  .home-facet {
+    flex: 1 1 100%;
+    flex-basis: auto;
+  }
+  .home-facet-list { flex: 0 1 100%; }
+}
+
+.searchForm {
+  margin: 0;
+  padding: 0;
+}
+
+header .container.navbar { margin-bottom: 0; }
+
+.search-sort { display: flex; }
+.search-sort label {
+  line-height: $input-height-base;
+  padding-right: .5rem;
+}
+.search-stats {
+  display: block;
+  padding-top: 1rem;
+  padding-bottom: 1rem;
+}
+
+@media (min-width: 768px) {
+  .search-header { display: flex; }
+  .search-stats { flex-grow: 1; }
+  .search-controls { text-align: right; }
+}
+
+.bulk-checkbox,
+.bulkActionButtons label { display: inline-block; }
+.bulkActionButtons label input { margin-top: 2px; }
+.bulkActionButtons { @include clearfix(); }
+@media (max-width: 767px) {
+  .grid { min-height: 250px; }
+}
 .result {
-  padding-top: 1.5rem;
-  .checkbox {
-    float: left;
-    padding-right: .5rem;
+  display: flex;
+  padding-top: 1rem;
+
+  .record-checkbox,
+  .record-number { display: none; }
+
+  .title { font-weight: bold; }
+  .list-tab-content.record .img-col { display: none; }
+  .list-tab-content.record .info-col { width: 100%; }
+  .format {
+    @extend .label;
+    @extend .label-info;
   }
-  .media,
-  .media-body { overflow: visible; }
-  .media-body .row {
-    margin-left: 0;
-    margin-right: 0;
+
+  .checkbox-select-item { float: left; }
+
+  @media (max-width: 767px) {
+    a {
+      max-width: 100%;
+      text-decoration: underline;
+    }
+  }
+  @media (min-width: 768px) {
+    .record-checkbox {
+      display: block;
+      flex: 0;
+      cursor: pointer;
+    }
+    .record-number {
+      display: block;
+      flex: 0 2rem;
+      text-align: center;
+    }
   }
+}
+.record,
+.result {
   .media {
-    margin-top: 0;
-    margin-bottom: 1rem;
-    @include clearfix();
+    flex: 1;
+    margin: 0;
   }
   .media-left,
   .media-right {
-    padding: 0;
     text-align: center;
-    a {
-      display: inline-block;
-      text-align: center;
-    }
     img {
-      max-width: none;
+      max-width: 100%;
       max-height: 300px;
     }
-    &.small a,
-    &.small > img {
+    &.small img,
+    &.medium img,
+    &.large img {
+      display: inline-block;
       width: $thumbnail-width-small;
-      img { max-width: $thumbnail-width-small; }
-    }
-    &.medium a,
-    &.medium > img {
-      width: $thumbnail-width-medium;
-      img { max-width: $thumbnail-width-medium; }
+      max-width: none;
     }
-    &.large a,
-    &.large > img {
-      width: $thumbnail-width-large;
-      img { max-width: $thumbnail-width-large; }
+  }
+
+  @media (min-width: 768px) {
+    .media-left,
+    .media-right {
+      max-width: 25%;
+      padding-right: 10px;
+      padding-left: 10px;
+
+      a {
+        display: inline-block;
+        max-width: 100%;
+        text-align: center;
+        white-space: nowrap;
+        text-decoration: underline;
+      }
+
+      &.small img,
+      &.medium img,
+      &.large img {
+        width: auto;
+        max-width: 100%;
+      }
+      &.small  > a,
+      &.small  > img { width: $thumbnail-width-small; }
+      &.medium > a,
+      &.medium > img { width: $thumbnail-width-medium; }
+      &.large  > a,
+      &.large  > img { width: $thumbnail-width-large; }
     }
   }
-  .media-left { padding-left: 10px; }
-  .media-right { padding-right: 10px; }
-  .title {font-weight: bold;}
-  .list-tab-content.record .img-col { display: none; }
-  .list-tab-content.record .info-col { width: 100%; }
+}
+.record .media-left,
+.record .media-right {
+  &.small img,
+  &.medium img,
+  &.large img { width: auto; }
+}
+.result-body {
+  padding: 0;
+  padding-bottom: .25rem;
+}
+.result-links .alert { margin: 0; }
+.result-formats { margin-bottom: .5rem; }
 
-  @media (max-width: 767px) {
-    a { text-decoration: underline; }
+.btn-bookbag-toggle form { display: inline; }
+.cart-link-icon.fa { margin-right: .3rem; }
+.result .cart-link-icon {
+  color: $text-color;
+  /* .fa-fw */
+  width: 1.28571429em;
+  text-align: center;
+}
+.savedLists {
+  @extend .alert;
+  @extend .alert-info;
+  display: none;
+}
+
+@media (min-width: 768px) {
+  .result-body {
+    float: left;
+    width: 75%;
+  }
+  .result-links {
+    float: left;
+    width: 25%;
+    padding: 0;
   }
-  @media (max-width: 530px) {
-    .checkbox { padding: 0; }
-    .media-left { padding-right: 0; }
+  .savedLists.loaded { display: block; }
+}
+body.rtl {
+  .result .btn-bookbag-toggle .fa {
+    margin-left: .3rem;
+    margin-right: 0;
   }
-
-  .format {
-    @extend .label;
-    @extend .label-info;
+  @media (min-width: 768px) {
+    .result-body,
+    .result-links { float: right; }
   }
 }
-
+/* ------ EMBEDDED RESULTS STYLE ------ */
 .result.embedded {
   .getFull {
     display: block;
-    margin-left: 1.5rem;
-    padding-right: 30px;
+    margin-left: -.5rem;
+    padding-left: .5rem;
     border-left: 1px solid transparent;
   }
   .getFull.expanded {
     @extend .list-group-item;
     margin-top: -11px;
-    margin-left: .75rem;
-    padding-left: .75rem;
+    padding-left: .5rem;
     border-top-left-radius: $border-radius-base;
     border-top-right-radius: $border-radius-base;
     &::before {
       content: '\25BC';
       position: absolute;
-      right: 15px;
+      right: 1rem;
       color: $gray;
     }
   }
@@ -98,7 +222,7 @@ $thumbnail-width-large: 160px !default;
     background: #fff;
   }
   .long-view {
-    margin-left: .75rem;
+    margin-left: -.5rem;
     padding: .5rem;
     border: 1px solid $list-group-border;
     background-color: #fff;
@@ -111,16 +235,72 @@ $thumbnail-width-large: 160px !default;
   .list-tab-content { padding: 1rem; }
 }
 
-.search-controls .alert {margin-bottom: 0;}
-.searchtools a {padding: 0 .5em;}
-.title-in-heading {
-  font-size: inherit;
-  font-style: italic;
+/* ------ GRID VIEW ------ */
+.search-grid::after {
+  display: table;
+  clear: both;
+  content: '';
 }
+.grid-result {
+  display: flex;
+  float: left;
+  width: 50%;
 
-.wikipedia img { margin-right: 1rem; }
+  .grid-body { flex: 1; }
+  .grid-checkbox {
+    flex: 0 0 30px;
+    min-width: 0;
+  }
+  .title { font-weight: bold; }
+  .label,
+  .format {
+    display: inline-block;
+    white-space: normal;
+  }
+}
+.grid-large-break,
+.grid-small-break { clear: both; }
+@media (min-width: 992px) {
+  .grid-result{ width: 25%; }
+  .grid-small-break { display: none; }
+}
+
+.searchtools a {
+  padding: 0 .5rem;
+  white-space: nowrap;
+}
+
+/* ------ COMBINED ------ */
+// No sidebar in combined:
+.template-dir-combined.template-name-results.offcanvas {
+  margin: 0;
+  padding: 0;
+}
 
+@media (min-width: 768px) {
+  .combined-search-container {
+    display: flex;
+
+    .result { margin-left: 0; }
+    .result-body {
+      float: none;
+      width: auto;
+    }
+    .result-links { display: none; }
+  }
+  .combined-column {
+    flex: 0 1 100%;
+    padding-left: 1rem;
+  }
+  .combined-column:last-child { padding-right: 1rem; }
+}
+
+.wikipedia img { margin-right: 1rem; }
 .geoItem {
     font-size: .9em;
     margin: 0px 0px 10px;
 }
+.title-in-heading {
+  font-size: inherit;
+  font-style: italic;
+}
diff --git a/themes/bootstrap3/scss/components/sidebar.scss b/themes/bootstrap3/scss/components/sidebar.scss
index 73ba5087b2e0ae3156962346b5425eea30f971c7..6f550f08f72d99371ff139c2dd3dca9a58d92576 100644
--- a/themes/bootstrap3/scss/components/sidebar.scss
+++ b/themes/bootstrap3/scss/components/sidebar.scss
@@ -1,41 +1,106 @@
-/* Sidebar rounded corners */
-.narrow-toggle { text-align: center; }
-.sidebar {
-  label:not(.list-group-item) {margin-left: 20px;}
-  .list-group.facet .list-group-item.title {
-    cursor: pointer;
-    &.collapsed {
-      border-radius: $border-radius-base;
-      &:after {content: '\25BC';}
+.facet-group {
+  display: block;
+  margin-bottom: 1rem;
+
+  .facet,
+  .title {
+    display: block;
+    padding: 8px 15px;
+    line-height: 1.5rem;
+
+    .badge,
+    .status {
+      float: right;
+
+      body.rtl & { float: left; }
+    }
+    .badge {
+      max-height: 19px;
+      line-height: 1.1rem;
     }
-    &:after {
+  }
+  .facet { border-bottom: 1px solid $list-group-border; }
+  .title {
+    padding-right: 8px;
+    border: 1px solid $list-group-border;
+    font-weight: bold;
+  }
+
+  [data-toggle="collapse"] {
+    cursor: pointer;
+
+    &::after {
       content: '\25B2';
       float: right;
+
+      body.rtl & { float: left; }
     }
   }
-  .collapse,.collapsing {
-    .list-group-item {
-      border-top-left-radius: 0px;
-      border-top-right-radius: 0px;
-      &[id^=more] {
-        border-bottom-left-radius: $border-radius-base;
-        border-bottom-right-radius: $border-radius-base;
-      }
-    }
+  .collapsed::after {content: '\25BC';}
+
+  .collapse,
+  .collapsing,
+  & > .facet {
+    border-left: 1px solid $list-group-border;
+    border-right: 1px solid $list-group-border;
   }
-  #side-collapse-publishDate .list-group-item {
-    border-bottom-left-radius: $border-radius-base;
-    border-bottom-right-radius: $border-radius-base;
+  & > .facet:first-child { border-top: 1px solid $list-group-border; }
+
+  .facetOR .text {
+    display: inline-block;
+    padding-left: 0.5rem;
+    text-indent: -0.5rem;
   }
+
+  .excludable {
+    display: flex;
+    flex-direction: row-reverse;
+    padding-right: 0;
+
+    .badge { flex-shrink: 0; }
+    .text { flex-grow: 1; }
+    .exclude {
+      flex-basis: 2rem;
+      flex-shrink: 0;
+      text-align: center;
+    }
+
+    body.rtl & {
+      padding-left: 0;
+      padding-right: 15px;
+    }
+  }
+}
+
+.checkbox-filter {
+  display: block;
+  padding-bottom: 1rem;
+  font-weight: bold;
+  color: $text-color;
 }
-label.list-group-item {
-  margin-top: 0;
-  padding-left: 35px;
-  font-weight: normal;
-  border-radius: 0;
+.facet-group > .checkbox,
+.sidebar .facet.checkbox {
+  margin: 0;
+  padding-left: 2rem;
 }
-.list-group-item.title {font-weight: bold;}
-.sidebar .facet a {text-decoration: none;}
+
+.active-filters .facet,
+.facet-group .active {
+  padding-right: .65rem;
+  background-color: $brand-primary;
+  color: #fff;
+
+  a { color: #fff; }
+}
+.facet.active .badge,
+.jstree-node.active .badge,
+.jstree-node.active .badge .fa {
+  background-color: #fff;
+  color: $brand-primary;
+}
+
+.narrow-toggle { text-align: center; }
+
 .sidebar .format {
   @extend .label;
   @extend .label-info;
@@ -51,3 +116,10 @@ label.list-group-item {
 }
 
 .full-facet-list { margin-top: 1rem; }
+.full-facet-list .active .fa {
+  float: right;
+  margin-top: .25rem;
+  margin-right: 0.5rem;
+  margin-left: 0.5rem;
+}
+body.rtl .full-facet-list .active .fa { float: left; }
diff --git a/themes/bootstrap3/scss/components/similar-carousel.scss b/themes/bootstrap3/scss/components/similar-carousel.scss
index 1493f611a9ab36a4a9659966000e0afc2a830a30..04ee93d79760a83974a1bc67fe98569e1b659680 100644
--- a/themes/bootstrap3/scss/components/similar-carousel.scss
+++ b/themes/bootstrap3/scss/components/similar-carousel.scss
@@ -5,8 +5,18 @@
       width: 8px;
       height: 8px;
       margin: 2px;
-      background-color: rgba(255,255,255,.3);
-      border-color: $gray-darker;
+      margin-bottom: 4px;
+      background-color: #fff;
+      border: 1px solid $gray-darker;
+      box-shadow: none;
+      transition-duration: .4s;
+      transition-property: width, height, margin;
+
+      &.active {
+        width: 16px;
+        height: 16px;
+        margin-bottom: 0;
+      }
     }
   }
   .hover-overlay {
@@ -33,5 +43,11 @@
     }
     &:hover .content {display: block;}
   }
+  .item {
+    padding: 0 4em;
+    &.prev,
+    &.active,
+    &.next { display: flex; }
+  }
+  .carousel-item { flex-basis: 25%; }
 }
-#similar-items-carousel .item {padding: 0 4em;}
diff --git a/themes/bootstrap3/scss/components/sliders.scss b/themes/bootstrap3/scss/components/sliders.scss
index 6caffdc44865b5edffc17fde5b7d7a942806683b..58d55e5b474c0d47e93f2a162d2bd4b1a2aa8c3d 100644
--- a/themes/bootstrap3/scss/components/sliders.scss
+++ b/themes/bootstrap3/scss/components/sliders.scss
@@ -5,8 +5,8 @@
     width: 100%;
   }
   .slider-track {
-  background:$gray-light;
-  box-shadow:inset 0 1px 0 rgba(0, 0, 0, 0.4);
+    background:$gray-light;
+    box-shadow:inset 0 1px 0 rgba(0, 0, 0, 0.4);
   }
   .slider-handle {
     background:$brand-primary;
diff --git a/themes/bootstrap3/scss/components/variables.scss b/themes/bootstrap3/scss/components/variables.scss
new file mode 100644
index 0000000000000000000000000000000000000000..6562456e358ea4bc3d96ad46427cc6a7aa4e9ac3
--- /dev/null
+++ b/themes/bootstrap3/scss/components/variables.scss
@@ -0,0 +1,52 @@
+// Make sure Font Awesome icons are loaded properly
+$fa-font-path: "../../../../../../themes/bootstrap3/css/fonts" !default;
+
+/**
+ * The following are useful Bootstrap variables that are used throughout the code,
+ * with comments and their defaults. See /themes/bootstrap3/less/vendor/bootstrap/variables.less for more.
+ */
+
+// $padding-base-vertical:   6px !default;  // Buttons, tabs, and other padding
+// $padding-base-horizontal: 12px !default;
+
+// $navbar-height:                    50px !default;
+
+// $border-radius-base: 4px !default;
+
+/* ------ COLORS ------ */
+
+// $gray-base:    #000 !default;
+// $gray-darker:  lighten($gray-base, 13.5%) !default; // #222
+// $gray-dark:    lighten($gray-base, 20.0%) !default; // #333
+// $gray:         lighten($gray-base, 33.5%) !default; // #555
+// $gray-light:   lighten($gray-base, 46.7%) !default; // #777
+// $gray-lighter: lighten($gray-base, 93.5%) !default; // #eee
+//
+// $brand-primary: darken(#428bca, 6.5%) !default; // #337ab7 (primary buttons, links, and active elements)
+// $brand-success: #5cb85c !default;
+// $brand-info:    #5bc0de !default;
+// $brand-warning: #f0ad4e !default;
+// $brand-danger:  #d9534f !default;
+
+// $list-group-border:  #ddd !default; // Borders on menus and sidebars
+
+// $text-color:            $gray-dark !default;
+// $link-color:            $brand-primary !default;
+// $link-hover-color:      darken($link-color, 15%) !default;
+
+// Define colors for form feedback states and, by default, alerts.
+// $state-success-text:             #3c763d !default;
+// $state-success-bg:               #dff0d8 !default;
+// $state-success-border:           darken(adjust-hue($state-success-bg, -10), 5%) !default;
+//
+// $state-info-text:                #31708f !default;
+// $state-info-bg:                  #d9edf7 !default;
+// $state-info-border:              darken(adjust-hue($state-info-bg, -10), 7%) !default;
+//
+// $state-warning-text:             #8a6d3b !default;
+// $state-warning-bg:               #fcf8e3 !default;
+// $state-warning-border:           darken(adjust-hue($state-warning-bg, -10), 5%) !default;
+//
+// $state-danger-text:              #a94442 !default;
+// $state-danger-bg:                #f2dede !default;
+// $state-danger-border:            darken(adjust-hue($state-danger-bg, -10), 5%) !default;
diff --git a/themes/bootstrap3/templates/Auth/AbstractBase/login.phtml b/themes/bootstrap3/templates/Auth/AbstractBase/login.phtml
index b05dc486c325e9c46ac8201654a393e865733abc..77b1f5caf4a093079bf7c6d4bac443f531517770 100644
--- a/themes/bootstrap3/templates/Auth/AbstractBase/login.phtml
+++ b/themes/bootstrap3/templates/Auth/AbstractBase/login.phtml
@@ -1,21 +1,18 @@
 <? $account = $this->auth()->getManager(); ?>
 <? $sessionInitiator = $account->getSessionInitiator($this->serverUrl($this->url('myresearch-home'))); ?>
 <? if (!$sessionInitiator): // display default login form if no login URL provided ?>
-  <form method="post" class="form-horizontal" action="<?=$this->url('myresearch-home')?>" name="loginForm">
+  <form method="post" action="<?=$this->url('myresearch-home')?>" name="loginForm" class="form-login">
     <?=$this->auth()->getLoginFields()?>
     <input type="hidden" name="auth_method" value="<?=$account->getAuthMethod()?>">
     <input type="hidden" name="csrf" value="<?=$this->escapeHtmlAttr($account->getCsrfHash(true))?>" />
     <div class="form-group">
-      <div class="col-sm-offset-3 col-sm-9">
-        <? if ($account->supportsCreation()): ?>
-          <a class="btn btn-link createAccountLink" href="<?=$this->url('myresearch-account') ?>?auth_method=<?=$account->getAuthMethod()?>"><?=$this->transEsc('Create New Account')?></a>
-        <? endif; ?>
-        <input class="btn btn-primary" type="submit" name="processLogin" value="<?=$this->transEsc('Login')?>">
-        <? if ($account->supportsRecovery()): ?>
-          <br/>
-          <a class="btn btn-link" href="<?=$this->url('myresearch-recover') ?>?auth_method=<?=$account->getAuthMethod()?>" data-lightbox-ignore><?=$this->transEsc('Forgot Password')?></a>
-        <? endif; ?>
-      </div>
+      <input class="btn btn-primary" type="submit" name="processLogin" value="<?=$this->transEsc('Login')?>">
+      <? if ($account->supportsCreation()): ?>
+        <a class="btn btn-link createAccountLink" href="<?=$this->url('myresearch-account') ?>?auth_method=<?=$account->getAuthMethod()?>"><?=$this->transEsc('Create New Account')?></a>
+      <? endif; ?>
+      <? if ($account->supportsRecovery()): ?>
+        <a class="btn btn-link" href="<?=$this->url('myresearch-recover') ?>?auth_method=<?=$account->getAuthMethod()?>"><?=$this->transEsc('Forgot Password')?></a>
+      <? endif; ?>
     </div>
   </form>
 <? else: ?>
diff --git a/themes/bootstrap3/templates/Auth/AbstractBase/logindesc.phtml b/themes/bootstrap3/templates/Auth/AbstractBase/logindesc.phtml
index 9f4088f8d270f09bc536fa26d8dd35282a49294a..4d49dc0beba5421241a093c02b3d7939a973a126 100644
--- a/themes/bootstrap3/templates/Auth/AbstractBase/logindesc.phtml
+++ b/themes/bootstrap3/templates/Auth/AbstractBase/logindesc.phtml
@@ -1 +1 @@
-<h3><?=$this->transEsc('Login')?></h3>
\ No newline at end of file
+<h3><?=$this->transEsc('Login')?></h3>
diff --git a/themes/bootstrap3/templates/Auth/AbstractBase/loginfields.phtml b/themes/bootstrap3/templates/Auth/AbstractBase/loginfields.phtml
index cad2d9673d2383057e90a3b9b51b63e171ad8915..275a2b9c898d22ff522cdc14e46732978248f928 100644
--- a/themes/bootstrap3/templates/Auth/AbstractBase/loginfields.phtml
+++ b/themes/bootstrap3/templates/Auth/AbstractBase/loginfields.phtml
@@ -1,12 +1,8 @@
 <div class="form-group">
-  <label class="col-sm-3 control-label" for="login_<?=$this->escapeHtmlAttr($topClass)?>_username"><?=$this->transEsc('Username')?>:</label>
-  <div class="col-sm-9">
-    <input type="text" name="username" id="login_<?=$this->escapeHtmlAttr($topClass)?>_username" value="<?=$this->escapeHtmlAttr($this->request->get('username'))?>" class="form-control"/>
-  </div>
+  <label class="control-label" for="login_<?=$this->escapeHtmlAttr($topClass)?>_username"><?=$this->transEsc('Username')?>:</label>
+  <input type="text" name="username" id="login_<?=$this->escapeHtmlAttr($topClass)?>_username" value="<?=$this->escapeHtmlAttr($this->request->get('username'))?>" class="form-control"/>
 </div>
 <div class="form-group">
-  <label class="col-sm-3 control-label" for="login_<?=$this->escapeHtmlAttr($topClass)?>_password"><?=$this->transEsc('Password')?>:</label>
-  <div class="col-sm-9">
-    <input type="password" name="password" id="login_<?=$this->escapeHtmlAttr($topClass)?>_password" class="form-control"/>
-  </div>
-</div>
\ No newline at end of file
+  <label class="control-label" for="login_<?=$this->escapeHtmlAttr($topClass)?>_password"><?=$this->transEsc('Password')?>:</label>
+  <input type="password" name="password" id="login_<?=$this->escapeHtmlAttr($topClass)?>_password" class="form-control"/>
+</div>
diff --git a/themes/bootstrap3/templates/Auth/AbstractBase/newpassword.phtml b/themes/bootstrap3/templates/Auth/AbstractBase/newpassword.phtml
index df98cd128a887da7765bc9a26a5b2088f9f7279a..934bd49360ec4ec314d00e18bc568f440c0c12e9 100644
--- a/themes/bootstrap3/templates/Auth/AbstractBase/newpassword.phtml
+++ b/themes/bootstrap3/templates/Auth/AbstractBase/newpassword.phtml
@@ -1,18 +1,14 @@
 <? if (isset($this->username)): ?>
   <div class="form-group">
-    <label class="col-sm-3 control-label"><?=$this->transEsc('Username') ?>:</label>
-    <div class="col-sm-9">
-      <p class="form-control-static"><?=$this->username ?></p>
-    </div>
+    <label class="control-label"><?=$this->transEsc('Username') ?>:</label>
+    <p class="form-control-static"><?=$this->username ?></p>
   </div>
 <? endif; ?>
 <? if (isset($this->verifyold) && $this->verifyold || isset($this->oldpwd)): ?>
   <div class="form-group">
-    <label class="col-sm-3 control-label"><?=$this->transEsc('old_password') ?>:</label>
-    <div class="col-sm-9">
-      <input type="password" name="oldpwd" class="form-control"/>
-      <div class="help-block with-errors"></div>
-    </div>
+    <label class="control-label"><?=$this->transEsc('old_password') ?>:</label>
+    <input type="password" name="oldpwd" class="form-control"/>
+    <div class="help-block with-errors"></div>
   </div>
 <? endif; ?>
 <?
@@ -28,23 +24,19 @@
   }
 ?>
 <div class="form-group">
-  <label class="col-sm-3 control-label"><?=$this->transEsc('new_password') ?>:</label>
-  <div class="col-sm-9">
-    <input type="password" id="password" name="password" class="form-control" required aria-required="true"
-      <?=isset($this->passwordPolicy['minLength']) ? ' data-minlength="' . $this->passwordPolicy['minLength'] . '" data-minlength-error="' . $this->escapeHtmlAttr($this->translate('password_minimum_length', array('%%minlength%%' => $this->passwordPolicy['minLength']))) . '"' : '' ?>
-      <?=isset($this->passwordPolicy['maxLength']) ? ' maxlength="' . $this->passwordPolicy['maxLength'] . '"' : '' ?>
-      <?=$pattern ? ' pattern="' . $pattern . '"' : '' ?>
-    />
-    <? if ($this->passwordPolicy['hint']): ?>
-      <div class="help-block"><?=$this->transEsc($this->passwordPolicy['hint']) ?></div>
-    <? endif; ?>
-    <div class="help-block with-errors"></div>
-  </div>
+  <label class="control-label"><?=$this->transEsc('new_password') ?>:</label>
+  <input type="password" id="password" name="password" class="form-control" required aria-required="true"
+    <?=isset($this->passwordPolicy['minLength']) ? ' data-minlength="' . $this->passwordPolicy['minLength'] . '" data-minlength-error="' . $this->escapeHtmlAttr($this->translate('password_minimum_length', array('%%minlength%%' => $this->passwordPolicy['minLength']))) . '"' : '' ?>
+    <?=isset($this->passwordPolicy['maxLength']) ? ' maxlength="' . $this->passwordPolicy['maxLength'] . '"' : '' ?>
+    <?=$pattern ? ' pattern="' . $pattern . '"' : '' ?>
+  />
+  <? if ($this->passwordPolicy['hint']): ?>
+    <div class="help-block"><?=$this->transEsc($this->passwordPolicy['hint']) ?></div>
+  <? endif; ?>
+  <div class="help-block with-errors"></div>
 </div>
 <div class="form-group">
-  <label class="col-sm-3 control-label"><?=$this->transEsc('confirm_new_password') ?>:</label>
-  <div class="col-sm-9">
-    <input type="password" name="password2" class="form-control" required aria-required="true" data-match="#password" data-match-error="<?=$this->escapeHtmlAttr($this->translate('Passwords do not match'))?>"/>
-    <div class="help-block with-errors"></div>
-  </div>
+  <label class="control-label"><?=$this->transEsc('confirm_new_password') ?>:</label>
+  <input type="password" name="password2" class="form-control" required aria-required="true" data-match="#password" data-match-error="<?=$this->escapeHtmlAttr($this->translate('Passwords do not match'))?>"/>
+  <div class="help-block with-errors"></div>
 </div>
diff --git a/themes/bootstrap3/templates/Auth/CAS/logindesc.phtml b/themes/bootstrap3/templates/Auth/CAS/logindesc.phtml
index fab51a92a722fa166127618844ea2ac4bdf3c765..8e64be890ae44081ffce24050217dc0b2283bc97 100644
--- a/themes/bootstrap3/templates/Auth/CAS/logindesc.phtml
+++ b/themes/bootstrap3/templates/Auth/CAS/logindesc.phtml
@@ -1,2 +1,2 @@
 <h3><?=$this->transEsc('Institutional Login')?></h3>
-<p><?=$this->transEsc('institutional_login_desc')?></p>
\ No newline at end of file
+<p><?=$this->transEsc('institutional_login_desc')?></p>
diff --git a/themes/bootstrap3/templates/Auth/ChoiceAuth/login.phtml b/themes/bootstrap3/templates/Auth/ChoiceAuth/login.phtml
index 4c5fe2267ae05b937aee34c78dfdb9bfcd8b46be..34a651e5aa2d382a60ab3bcccf6ec1b3f4641b64 100644
--- a/themes/bootstrap3/templates/Auth/ChoiceAuth/login.phtml
+++ b/themes/bootstrap3/templates/Auth/ChoiceAuth/login.phtml
@@ -10,4 +10,4 @@
   </div>
 <? endforeach ?>
 </div>
-<? $this->auth()->getManager()->setAuthMethod('ChoiceAuth') ?>
\ No newline at end of file
+<? $this->auth()->getManager()->setAuthMethod('ChoiceAuth') ?>
diff --git a/themes/bootstrap3/templates/Auth/Database/create.phtml b/themes/bootstrap3/templates/Auth/Database/create.phtml
index 2afb1f1e2172280bb2f3e1add78f147b31a1c20a..4fe5955feb576ed60f7ff696b5314df22e9d2ddd 100644
--- a/themes/bootstrap3/templates/Auth/Database/create.phtml
+++ b/themes/bootstrap3/templates/Auth/Database/create.phtml
@@ -11,49 +11,37 @@
   }
 ?>
 <div class="form-group">
-  <label class="col-sm-3 control-label" for="account_firstname"><?=$this->transEsc('First Name')?>:</label>
-  <div class="col-sm-9">
-    <input id="account_firstname" type="text" name="firstname" value="<?=$this->escapeHtmlAttr($this->request->get('firstname'))?>" class="form-control"/>
-  </div>
+  <label class="control-label" for="account_firstname"><?=$this->transEsc('First Name')?>:</label>
+  <input id="account_firstname" type="text" name="firstname" value="<?=$this->escapeHtmlAttr($this->request->get('firstname'))?>" class="form-control"/>
 </div>
 <div class="form-group">
-  <label class="col-sm-3 control-label" for="account_lastname"><?=$this->transEsc('Last Name')?>:</label>
-  <div class="col-sm-9">
-    <input id="account_lastname" type="text" name="lastname" value="<?=$this->escapeHtmlAttr($this->request->get('lastname'))?>" class="form-control"/>
-  </div>
+  <label class="control-label" for="account_lastname"><?=$this->transEsc('Last Name')?>:</label>
+  <input id="account_lastname" type="text" name="lastname" value="<?=$this->escapeHtmlAttr($this->request->get('lastname'))?>" class="form-control"/>
 </div>
 <div class="form-group">
-  <label class="col-sm-3 control-label" for="account_email"><?=$this->transEsc('Email Address')?>:</label>
-  <div class="col-sm-9">
-    <input id="account_email" type="email" name="email" required aria-required="true" value="<?=$this->escapeHtmlAttr($this->request->get('email'))?>" class="form-control"/>
-    <div class="help-block with-errors"></div>
-  </div>
+  <label class="control-label" for="account_email"><?=$this->transEsc('Email Address')?>:</label>
+  <input id="account_email" type="email" name="email" required aria-required="true" value="<?=$this->escapeHtmlAttr($this->request->get('email'))?>" class="form-control"/>
+  <div class="help-block with-errors"></div>
 </div>
 <div class="form-group">
-  <label class="col-sm-3 control-label" for="account_username"><?=$this->transEsc('Desired Username')?>:</label>
-  <div class="col-sm-9">
-    <input id="account_username" type="text" name="username" required aria-required="true" value="<?=$this->escapeHtmlAttr($this->request->get('username'))?>" class="form-control"/>
-    <div class="help-block with-errors"></div>
-  </div>
+  <label class="control-label" for="account_username"><?=$this->transEsc('Desired Username')?>:</label>
+  <input id="account_username" type="text" name="username" required aria-required="true" value="<?=$this->escapeHtmlAttr($this->request->get('username'))?>" class="form-control"/>
+  <div class="help-block with-errors"></div>
 </div>
 <div class="form-group">
-  <label class="col-sm-3 control-label" for="account_password"><?=$this->transEsc('Password')?>:</label>
-  <div class="col-sm-9">
-    <input id="account_password" type="password" name="password" required aria-required="true" class="form-control"
-      <?=isset($this->passwordPolicy['minLength']) ? ' data-minlength="' . $this->passwordPolicy['minLength'] . '" data-minlength-error="' . $this->escapeHtmlAttr($this->translate('password_minimum_length', array('%%minlength%%' => $this->passwordPolicy['minLength']))) . '"' : ''?>
-      <?=isset($this->passwordPolicy['maxLength']) ? ' maxlength="' . $this->passwordPolicy['maxLength'] . '"' : ''?>
-      <?=$pattern ? ' pattern="' . $pattern . '"' : '' ?>
-    />
-    <? if ($this->passwordPolicy['hint']): ?>
-      <div class="help-block"><?=$this->transEsc($this->passwordPolicy['hint']) ?></div>
-    <? endif; ?>
-    <div class="help-block with-errors"></div>
-  </div>
+  <label class="control-label" for="account_password"><?=$this->transEsc('Password')?>:</label>
+  <input id="account_password" type="password" name="password" required aria-required="true" class="form-control"
+    <?=isset($this->passwordPolicy['minLength']) ? ' data-minlength="' . $this->passwordPolicy['minLength'] . '" data-minlength-error="' . $this->escapeHtmlAttr($this->translate('password_minimum_length', array('%%minlength%%' => $this->passwordPolicy['minLength']))) . '"' : ''?>
+    <?=isset($this->passwordPolicy['maxLength']) ? ' maxlength="' . $this->passwordPolicy['maxLength'] . '"' : ''?>
+    <?=$pattern ? ' pattern="' . $pattern . '"' : '' ?>
+  />
+  <? if ($this->passwordPolicy['hint']): ?>
+    <div class="help-block"><?=$this->transEsc($this->passwordPolicy['hint']) ?></div>
+  <? endif; ?>
+  <div class="help-block with-errors"></div>
 </div>
 <div class="form-group">
-  <label class="col-sm-3 control-label" for="account_password2"><?=$this->transEsc('Password Again')?>:</label>
-  <div class="col-sm-9">
-    <input id="account_password2" type="password" name="password2" required aria-required="true" class="form-control" data-match="#account_password" data-match-error="<?=$this->escapeHtmlAttr($this->translate('Passwords do not match'))?>"/>
-    <div class="help-block with-errors"></div>
-  </div>
+  <label class="control-label" for="account_password2"><?=$this->transEsc('Password Again')?>:</label>
+  <input id="account_password2" type="password" name="password2" required aria-required="true" class="form-control" data-match="#account_password" data-match-error="<?=$this->escapeHtmlAttr($this->translate('Passwords do not match'))?>"/>
+  <div class="help-block with-errors"></div>
 </div>
diff --git a/themes/bootstrap3/templates/Auth/Database/logindesc.phtml b/themes/bootstrap3/templates/Auth/Database/logindesc.phtml
index 10d39c2498b61e3e4b59cd9f9283eb0b6e3d1b34..3e647409d73939c8985e771f6e67fefc98368f75 100644
--- a/themes/bootstrap3/templates/Auth/Database/logindesc.phtml
+++ b/themes/bootstrap3/templates/Auth/Database/logindesc.phtml
@@ -1,2 +1,2 @@
 <h3><?=$this->transEsc('Local Login')?></h3>
-<p><?=$this->transEsc('local_login_desc')?></p>
\ No newline at end of file
+<p><?=$this->transEsc('local_login_desc')?></p>
diff --git a/themes/bootstrap3/templates/Auth/Database/recovery.phtml b/themes/bootstrap3/templates/Auth/Database/recovery.phtml
index 19d14231f79f86372fdff770e4ed6e1b385f38fd..b9f657abeca3920dbce9ed43d22523da73f56667 100644
--- a/themes/bootstrap3/templates/Auth/Database/recovery.phtml
+++ b/themes/bootstrap3/templates/Auth/Database/recovery.phtml
@@ -1,18 +1,12 @@
 <div class="form-group">
-  <label class="col-sm-3 control-label"><?=$this->transEsc('recovery_by_username') ?>:</label>
-  <div class="col-sm-9 col-md-5">
-    <input type="text" name="username" class="form-control"/>
-  </div>
+  <label class="control-label"><?=$this->transEsc('recovery_by_username') ?>:</label>
+  <input type="text" name="username" class="form-control"/>
 </div>
 <div class="form-group">
-  <label class="col-sm-3 control-label"><?=$this->transEsc('recovery_by_email') ?>:</label>
-  <div class="col-sm-9 col-md-5">
-    <input type="email" name="email" class="form-control"/>
-  </div>
+  <label class="control-label"><?=$this->transEsc('recovery_by_email') ?>:</label>
+  <input type="email" name="email" class="form-control"/>
 </div>
 <?=$this->recaptcha()->html($this->useRecaptcha) ?>
 <div class="form-group">
-  <div class="col-sm-9 col-sm-offset-3">
-    <input class="btn btn-default" name="submit" type="submit" value="<?=$this->transEsc('Recover Account') ?>"/>
-  </div>
-</div>
\ No newline at end of file
+  <input class="btn btn-primary" name="submit" type="submit" value="<?=$this->transEsc('Recover Account') ?>"/>
+</div>
diff --git a/themes/bootstrap3/templates/Auth/ILS/logindesc.phtml b/themes/bootstrap3/templates/Auth/ILS/logindesc.phtml
index 73ac1374e787e6fcedcf9ed95a8293f66808ea10..13d8e166828b77db655a631d826f4cedea44e570 100644
--- a/themes/bootstrap3/templates/Auth/ILS/logindesc.phtml
+++ b/themes/bootstrap3/templates/Auth/ILS/logindesc.phtml
@@ -1,2 +1,2 @@
 <h3><?=$this->transEsc('Catalog Login')?></h3>
-<p><?=$this->transEsc('catalog_login_desc')?></p>
\ No newline at end of file
+<p><?=$this->transEsc('catalog_login_desc')?></p>
diff --git a/themes/bootstrap3/templates/Auth/LDAP/logindesc.phtml b/themes/bootstrap3/templates/Auth/LDAP/logindesc.phtml
index fab51a92a722fa166127618844ea2ac4bdf3c765..8e64be890ae44081ffce24050217dc0b2283bc97 100644
--- a/themes/bootstrap3/templates/Auth/LDAP/logindesc.phtml
+++ b/themes/bootstrap3/templates/Auth/LDAP/logindesc.phtml
@@ -1,2 +1,2 @@
 <h3><?=$this->transEsc('Institutional Login')?></h3>
-<p><?=$this->transEsc('institutional_login_desc')?></p>
\ No newline at end of file
+<p><?=$this->transEsc('institutional_login_desc')?></p>
diff --git a/themes/bootstrap3/templates/Auth/MultiILS/loginfields.phtml b/themes/bootstrap3/templates/Auth/MultiILS/loginfields.phtml
index 8e34e7d16b0f5051950a589de967e5fa71d5ea10..246cee6a636e01f9b188a76eb0a9cb3bf555e5dd 100644
--- a/themes/bootstrap3/templates/Auth/MultiILS/loginfields.phtml
+++ b/themes/bootstrap3/templates/Auth/MultiILS/loginfields.phtml
@@ -1,23 +1,17 @@
 <div class="form-group">
-  <label class="col-sm-3 control-label" for="login_target"><?=$this->transEsc('login_target')?>:</label>
-  <div class="col-sm-9">
-    <?$currentTarget = $this->request->get('target'); if (!$currentTarget) $currentTarget = $this->auth()->getManager()->getDefaultLoginTarget();?>
-    <select id="login_target" name="target" class="form-control">
+  <label class="control-label" for="login_target"><?=$this->transEsc('login_target')?>:</label>
+  <?$currentTarget = $this->request->get('target'); if (!$currentTarget) $currentTarget = $this->auth()->getManager()->getDefaultLoginTarget();?>
+  <select id="login_target" name="target" class="form-control">
     <?foreach ($this->auth()->getManager()->getLoginTargets() as $target):?>
       <option value="<?=$this->escapeHtmlAttr($target)?>"<?=($target == $currentTarget ? ' selected="selected"' : '')?>><?=$this->transEsc("source_$target", null, $target)?></option>
     <? endforeach ?>
-    </select>
-  </div>
+  </select>
 </div>
 <div class="form-group">
-  <label class="col-sm-3 control-label" for="login_<?=$this->escapeHtmlAttr($topClass)?>_username"><?=$this->transEsc('Username')?>:</label>
-  <div class="col-sm-9">
-    <input id="login_<?=$this->escapeHtmlAttr($topClass)?>_username" type="text" name="username" value="<?=$this->escapeHtmlAttr($this->request->get('username'))?>" class="form-control"/>
-  </div>
+  <label class="control-label" for="login_<?=$this->escapeHtmlAttr($topClass)?>_username"><?=$this->transEsc('Username')?>:</label>
+  <input id="login_<?=$this->escapeHtmlAttr($topClass)?>_username" type="text" name="username" value="<?=$this->escapeHtmlAttr($this->request->get('username'))?>" class="form-control"/>
 </div>
 <div class="form-group">
-  <label class="col-sm-3 control-label" for="login_<?=$this->escapeHtmlAttr($topClass)?>_password"><?=$this->transEsc('Password')?>:</label>
-  <div class="col-sm-9">
-    <input id="login_<?=$this->escapeHtmlAttr($topClass)?>_password" type="password" name="password" class="form-control"/>
-  </div>
+  <label class="control-label" for="login_<?=$this->escapeHtmlAttr($topClass)?>_password"><?=$this->transEsc('Password')?>:</label>
+  <input id="login_<?=$this->escapeHtmlAttr($topClass)?>_password" type="password" name="password" class="form-control"/>
 </div>
diff --git a/themes/bootstrap3/templates/Auth/Shibboleth/logindesc.phtml b/themes/bootstrap3/templates/Auth/Shibboleth/logindesc.phtml
index fab51a92a722fa166127618844ea2ac4bdf3c765..8e64be890ae44081ffce24050217dc0b2283bc97 100644
--- a/themes/bootstrap3/templates/Auth/Shibboleth/logindesc.phtml
+++ b/themes/bootstrap3/templates/Auth/Shibboleth/logindesc.phtml
@@ -1,2 +1,2 @@
 <h3><?=$this->transEsc('Institutional Login')?></h3>
-<p><?=$this->transEsc('institutional_login_desc')?></p>
\ No newline at end of file
+<p><?=$this->transEsc('institutional_login_desc')?></p>
diff --git a/themes/bootstrap3/templates/Helpers/email-form-fields.phtml b/themes/bootstrap3/templates/Helpers/email-form-fields.phtml
index 8a982c42399ca501f86ed50094a719ee977faebb..df938f4081960e4e08b0bcaa4813534d89fc8f6f 100644
--- a/themes/bootstrap3/templates/Helpers/email-form-fields.phtml
+++ b/themes/bootstrap3/templates/Helpers/email-form-fields.phtml
@@ -1,52 +1,40 @@
 <div class="form-group">
-  <label class="col-sm-3 control-label" for="email_to"><?=$this->transEsc('To')?>:</label>
-  <div class="col-sm-9">
-    <input type="<?=$this->maxRecipients != 1 ? 'text' : 'email'?>" id="email_to" class="form-control" oninvalid="$('#modal .fa-spinner').remove()" name="to" value="<?=isset($this->to) ? $this->to : ''?>"/>
-    <? if ($this->maxRecipients != 1): ?>
-      <br />
-      <?=$this->transEsc('email_multiple_recipients_note')?>
-      <? if ($this->maxRecipients > 1): ?>
-        <?=$this->transEsc('email_maximum_recipients_note', array('%%max%%' => $this->maxRecipients))?>
-      <? endif; ?>
+  <label class="control-label" for="email_to"><?=$this->transEsc('To')?>:</label>
+  <input type="<?=$this->maxRecipients != 1 ? 'text' : 'email'?>" id="email_to" class="form-control" oninvalid="$('#modal .fa-spinner').remove()" name="to" value="<?=isset($this->to) ? $this->to : ''?>"/>
+  <? if ($this->maxRecipients != 1): ?>
+    <br />
+    <?=$this->transEsc('email_multiple_recipients_note')?>
+    <? if ($this->maxRecipients > 1): ?>
+      <?=$this->transEsc('email_maximum_recipients_note', ['%%max%%' => $this->maxRecipients])?>
     <? endif; ?>
-  </div>
+  <? endif; ?>
 </div>
 <? if (!$this->disableFrom): ?>
   <div class="form-group">
-    <label class="col-sm-3 control-label" for="email_from"><?=$this->transEsc('From')?>:</label>
-    <div class="col-sm-9">
-      <input type="email" id="email_from" oninvalid="$('#modal .fa-spinner').remove()" name="from" value="<?=isset($this->from) ? $this->from : ''?>" size="40" class="form-control"/>
-    </div>
+    <label class="control-label" for="email_from"><?=$this->transEsc('From')?>:</label>
+    <input type="email" id="email_from" oninvalid="$('#modal .fa-spinner').remove()" name="from" value="<?=isset($this->from) ? $this->from : ''?>" size="40" class="form-control"/>
   </div>
 <? endif; ?>
 <? if ($this->editableSubject): ?>
   <div class="form-group">
-    <label class="col-sm-3 control-label" for="email_subject"><?=$this->transEsc('email_subject')?>:</label>
-    <div class="col-sm-9">
-      <input type="text" id="email_subject" oninvalid="$('#modal .fa-spinner').remove()" name="subject" value="<?=isset($this->subject) ? $this->subject : ''?>" size="40" class="form-control"/>
-    </div>
+    <label class="control-label" for="email_subject"><?=$this->transEsc('email_subject')?>:</label>
+    <input type="text" id="email_subject" oninvalid="$('#modal .fa-spinner').remove()" name="subject" value="<?=isset($this->subject) ? $this->subject : ''?>" size="40" class="form-control"/>
   </div>
 <? endif; ?>
 <div class="form-group">
-  <label class="col-sm-3 control-label" for="email_message"><?=$this->transEsc('Message')?>:</label>
-  <div class="col-sm-9">
-    <textarea id="email_message" class="form-control" name="message" rows="4"><?=isset($this->message) ? $this->message : ''?></textarea>
-  </div>
+  <label class="control-label" for="email_message"><?=$this->transEsc('Message')?>:</label>
+  <textarea id="email_message" class="form-control" name="message" rows="4"><?=isset($this->message) ? $this->message : ''?></textarea>
 </div>
 <? if ($this->disableFrom && $this->userEmailInFrom): ?>
   <div class="form-group">
-    <div class="col-sm-9 col-sm-offset-3">
-      <div class="checkbox">
-        <label>
-          <input type="checkbox" name="ccself"/> <?=$this->translate('send_email_copy_to_me'); ?>
-        </label>
-      </div>
+    <div class="checkbox">
+      <label>
+        <input type="checkbox" name="ccself"/> <?=$this->translate('send_email_copy_to_me'); ?>
+      </label>
     </div>
   </div>
 <? endif ?>
 <?=$this->recaptcha()->html($this->useRecaptcha) ?>
 <div class="form-group">
-  <div class="col-sm-9 col-sm-offset-3">
-    <input type="submit" class="btn btn-primary" name="submit" value="<?=$this->transEsc('Send')?>"/>
-  </div>
+  <input type="submit" class="btn btn-primary" name="submit" value="<?=$this->transEsc('Send')?>"/>
 </div>
diff --git a/themes/bootstrap3/templates/Helpers/ils-offline.phtml b/themes/bootstrap3/templates/Helpers/ils-offline.phtml
index 886aaa79b34098f3510bb38ab8be03614a324e64..5dfceac17b4369c73f0504f0a57bf2ea37333852 100644
--- a/themes/bootstrap3/templates/Helpers/ils-offline.phtml
+++ b/themes/bootstrap3/templates/Helpers/ils-offline.phtml
@@ -4,4 +4,4 @@
   <p><?=$this->transEsc($this->offlineModeMsg)?></p>
   <? $supportEmail = $this->escapeHtmlAttr($this->systemEmail()); ?>
   <p><a href="mailto:<?=$supportEmail?>"><?=$supportEmail?></a></p>
-</div>
\ No newline at end of file
+</div>
diff --git a/themes/bootstrap3/templates/Helpers/openurl.phtml b/themes/bootstrap3/templates/Helpers/openurl.phtml
index f68528b4b61a21bea425e56512e188bcf81cd4c1..22d5cac3e2f76b3bebaa00f876ecdacb26d96cc3 100644
--- a/themes/bootstrap3/templates/Helpers/openurl.phtml
+++ b/themes/bootstrap3/templates/Helpers/openurl.phtml
@@ -16,7 +16,7 @@
 
 <span class="openUrlControls<? if ($this->openUrlEmbed): ?> openUrlEmbed<? if ($this->openUrlEmbedAutoLoad): ?> openUrlEmbedAutoLoad<? endif; ?><? endif; ?>">
   <? if (!$this->openUrlImageBasedSrc || $this->openUrlImageBasedMode == 'both'): ?>
-  <a href="<?=$this->escapeHtmlAttr($this->openUrlBase . '?' . $this->openUrl)?>"<?=$class?> data-search-class-id="<?=$this->escapeHtmlAttr($this->searchClassId) ?>">
+  <a href="<?=$this->escapeHtmlAttr($this->resolverUrl)?>"<?=$class?> data-search-class-id="<?=$this->escapeHtmlAttr($this->searchClassId) ?>">
     <? /* put the openUrl here in a span (COinS almost) so we can retrieve it later */ ?>
     <span title="<?=$this->escapeHtmlAttr($this->openUrl)?>" class="openUrl"></span>
     <? if ($this->openUrlGraphic): ?>
diff --git a/themes/bootstrap3/templates/Recommend/AlphaBrowseLink.phtml b/themes/bootstrap3/templates/Recommend/AlphaBrowseLink.phtml
index 632a7f412d0708bd0281e23d8238a0acf906bf66..ff50e683e82fcb3ce855940cb94d8e07893f6613 100644
--- a/themes/bootstrap3/templates/Recommend/AlphaBrowseLink.phtml
+++ b/themes/bootstrap3/templates/Recommend/AlphaBrowseLink.phtml
@@ -11,4 +11,4 @@
     ]
   );
 ?>
-<div class="alert alert-info"><?=$link?></div>
\ No newline at end of file
+<div class="alert alert-info"><?=$link?></div>
diff --git a/themes/bootstrap3/templates/Recommend/AuthorFacets.phtml b/themes/bootstrap3/templates/Recommend/AuthorFacets.phtml
index bc32320f533b31c55736cbfa753e4883dce499e5..678d50f91117cf25236aa2f10bf4c4e62e31d68c 100644
--- a/themes/bootstrap3/templates/Recommend/AuthorFacets.phtml
+++ b/themes/bootstrap3/templates/Recommend/AuthorFacets.phtml
@@ -1,17 +1,17 @@
 <? if ($this->recommend->getResults()->getResultTotal() > 0): ?>
   <? $similarAuthors = $this->recommend->getSimilarAuthors(); ?>
   <? if (!empty($similarAuthors['list'])): ?>
-    <div class="row">
-      <p><?=$this->transEsc('Author Results for')?> <strong><?=$this->escapeHtml($this->recommend->getSearchTerm()) ?></strong></p>
-      <div class="col-sm-4">
+    <p class="author-label"><?=$this->transEsc('Author Results for')?> <strong><?=$this->escapeHtml($this->recommend->getSearchTerm()) ?></strong></p>
+    <div class="author-facets">
+      <div class="author-list">
       <? foreach($similarAuthors['list'] as $i => $author): ?>
         <? if ($i == 5): ?>
-        <a href="<?=$this->url('author-search') . '?lookfor=' . urlencode($this->recommend->getSearchTerm()) ?>"><strong><?=$this->transEsc("see all") ?> <?=(isset($similarAuthors['count']) && $similarAuthors['count']) ? $similarAuthors['count'] : ''?> &raquo;</strong></a>
-      </div>
-      <div class="col-sm-4">
+            <a href="<?=$this->url('author-search') . '?lookfor=' . urlencode($this->recommend->getSearchTerm()) ?>"><strong><?=$this->transEsc("see all") ?> <?=(isset($similarAuthors['count']) && $similarAuthors['count']) ? $similarAuthors['count'] : ''?> &raquo;</strong></a>
+          </div>
+          <div class="author-list">
         <? endif; ?>
         <a href="<?=$this->url('author-home') . '?author=' . urlencode($author['value'])?>"><?=$author['value'] ?><? /* count disabled -- uncomment to add: echo ' - ' . $author['count']; */ ?></a>
-        <? if ($i+1<count($similarAuthors['list'])): ?>
+        <? if ($i+1 < count($similarAuthors['list'])): ?>
           <br/>
         <? endif; ?>
       <? endforeach; ?>
diff --git a/themes/bootstrap3/templates/Recommend/AuthorInfo.phtml b/themes/bootstrap3/templates/Recommend/AuthorInfo.phtml
index 2bbd2c6de7338c92e7b8354cb5eb34b3705e4efc..32a87e6a628d0d3b65d91606a2f500c416285dfe 100644
--- a/themes/bootstrap3/templates/Recommend/AuthorInfo.phtml
+++ b/themes/bootstrap3/templates/Recommend/AuthorInfo.phtml
@@ -11,4 +11,4 @@
 
   <a href="http://<?=$this->info['wiki_lang'] ?>.wikipedia.org/wiki/<?=$this->escapeHtmlAttr($this->info['name']/*url*/) ?>" target="new"><?=$this->transEsc('wiki_link') ?></a>
 </div>
-<? endif; ?>
\ No newline at end of file
+<? endif; ?>
diff --git a/themes/bootstrap3/templates/Recommend/AuthorityRecommend.phtml b/themes/bootstrap3/templates/Recommend/AuthorityRecommend.phtml
index 5a7cbdbfb8b3d7804150cb462e2d4a0daaa15619..6a277a43a4d17e2e75cc3c23294fe0fa3fa895cd 100644
--- a/themes/bootstrap3/templates/Recommend/AuthorityRecommend.phtml
+++ b/themes/bootstrap3/templates/Recommend/AuthorityRecommend.phtml
@@ -16,4 +16,4 @@
       <? endfor; ?>
     </div>
   </div>
-<? endif; ?>
\ No newline at end of file
+<? endif; ?>
diff --git a/themes/bootstrap3/templates/Recommend/CatalogResults.phtml b/themes/bootstrap3/templates/Recommend/CatalogResults.phtml
index d1a0ba511570d4bf2e7bafcecb82070e7a163175..628900def89f0b58667d7e76bdf71e04f1d1a5d1 100644
--- a/themes/bootstrap3/templates/Recommend/CatalogResults.phtml
+++ b/themes/bootstrap3/templates/Recommend/CatalogResults.phtml
@@ -26,4 +26,4 @@
     <? endforeach; ?>
     <a class="list-group-item" href="<?=$this->url($searchObject->getOptions()->getSearchAction()) . $searchObject->getUrlQuery()->setLimit($searchObject->getOptions()->getDefaultLimit())?>"><?=$this->transEsc('More catalog results')?>...</a>
   </ul>
-<? endif ?>
\ No newline at end of file
+<? endif ?>
diff --git a/themes/bootstrap3/templates/Recommend/Channels.phtml b/themes/bootstrap3/templates/Recommend/Channels.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..8fb018c7e03180c273006360c273fad4df645e47
--- /dev/null
+++ b/themes/bootstrap3/templates/Recommend/Channels.phtml
@@ -0,0 +1,9 @@
+<?
+    $results = $this->recommend->getResults();
+    $link = $this->url('channels-search')
+        . $results->getUrlQuery()->getParams(false)
+        . '&source=' . urlencode($results->getParams()->getSearchClassId());
+?>
+<div class="channels-alert alert alert-info">
+  <a href="<?=$this->escapeHtmlAttr($link)?>"><?=$this->transEsc('channel_expand')?></a>
+</div>
diff --git a/themes/bootstrap3/templates/Recommend/CollectionSideFacets.phtml b/themes/bootstrap3/templates/Recommend/CollectionSideFacets.phtml
index cc6d7f476819cb67bbbc44f6a5cc6c650ccfe5d1..f4a0e5545309e7a6b84da043b47f61c2978a7fcc 100644
--- a/themes/bootstrap3/templates/Recommend/CollectionSideFacets.phtml
+++ b/themes/bootstrap3/templates/Recommend/CollectionSideFacets.phtml
@@ -5,16 +5,16 @@
   <?
     $keywordFilter = $this->recommend->getKeywordFilter();
     if (!empty($keywordFilter)) {
-      $this->extraSideFacetFilters = array(
-        'Keyword' => array(
-            array(
+      $this->extraSideFacetFilters = [
+        'Keyword' => [
+            [
               'value' => $keywordFilter,
               'displayText' => $keywordFilter,
               'specialType' => 'keyword',
               'operator' => 'OR'
-            )
-        )
-      );
+            ]
+        ]
+      ];
     }
   ?>
   <? ob_start() ?>
diff --git a/themes/bootstrap3/templates/Recommend/DOI.phtml b/themes/bootstrap3/templates/Recommend/DOI.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..f15e2a6b06a064b48e25bf211f0a2c26f0b36a3c
--- /dev/null
+++ b/themes/bootstrap3/templates/Recommend/DOI.phtml
@@ -0,0 +1,10 @@
+<? $doi = $this->recommend->getDOI(); if (!empty($doi)): ?>
+  <? $url = $this->recommend->getURL(); ?>
+  <div class="alert alert-info">
+    <?=$this->translate('doi_detected_html', ['%%url%%' => $url, '%%doi%%' => $doi])?>
+  </div>
+  <? if ($this->recommend->isFullMatch()): ?>
+    <? $redirect = 'document.location.href = "' . $this->escapeJs($url) . '";'; ?>
+    <?=$this->inlineScript(\Zend\View\Helper\HeadScript::SCRIPT, $redirect, 'SET')?>
+  <? endif; ?>
+<? endif; ?>
diff --git a/themes/bootstrap3/templates/Recommend/DPLATerms.phtml b/themes/bootstrap3/templates/Recommend/DPLATerms.phtml
index 2ad9cd87ce803fe72633fd4e18ed597863a3e111..267c561a9ce4191975969fee3e4d66919f1a32c1 100644
--- a/themes/bootstrap3/templates/Recommend/DPLATerms.phtml
+++ b/themes/bootstrap3/templates/Recommend/DPLATerms.phtml
@@ -15,4 +15,4 @@
       </li>
     <? endforeach; ?>
   </ul>
-<? endif; ?>
\ No newline at end of file
+<? endif; ?>
diff --git a/themes/bootstrap3/templates/Recommend/Deprecated.phtml b/themes/bootstrap3/templates/Recommend/Deprecated.phtml
index 63445d34f9c1ebc4c55c092c9dcf8965c9fd3c66..ff8266ef2c7dcbafc58aa400e648b37946ac45fd 100644
--- a/themes/bootstrap3/templates/Recommend/Deprecated.phtml
+++ b/themes/bootstrap3/templates/Recommend/Deprecated.phtml
@@ -1,2 +1,2 @@
 <? /* do nothing -- this module is a placeholder for old deprecated features
-      to prevent legacy configurations from causing fatal errors. */ ?>
\ No newline at end of file
+      to prevent legacy configurations from causing fatal errors. */ ?>
diff --git a/themes/bootstrap3/templates/Recommend/EuropeanaResults.phtml b/themes/bootstrap3/templates/Recommend/EuropeanaResults.phtml
index 30e6e711a7c66f441c71db78cb5da55469ea1ed8..0b23e82cfb2cdd3b2119301183cb2f7adfe13156 100644
--- a/themes/bootstrap3/templates/Recommend/EuropeanaResults.phtml
+++ b/themes/bootstrap3/templates/Recommend/EuropeanaResults.phtml
@@ -28,4 +28,4 @@
     </div>
   </div>
   <div class="clearfix"></div>
-<? endif; ?>
\ No newline at end of file
+<? endif; ?>
diff --git a/themes/bootstrap3/templates/Recommend/EuropeanaResultsDeferred.phtml b/themes/bootstrap3/templates/Recommend/EuropeanaResultsDeferred.phtml
index 70c5271da00b1ca7ff8d0e94b49eb0e48bf4e7ca..df193c4f4b71930357a14ab019746f7616565873 100644
--- a/themes/bootstrap3/templates/Recommend/EuropeanaResultsDeferred.phtml
+++ b/themes/bootstrap3/templates/Recommend/EuropeanaResultsDeferred.phtml
@@ -6,4 +6,4 @@
 <div id="EuropeanaDeferredRecommend">
     <p><?=$this->transEsc("Loading")?>... <img src="<?=$this->imageLink('ajax_loading.gif')?>" /></p>
     <?=$this->inlineScript(\Zend\View\Helper\HeadScript::SCRIPT, $loadJs, 'SET')?>
-</div>
\ No newline at end of file
+</div>
diff --git a/themes/bootstrap3/templates/Recommend/Libraryh3lp.phtml b/themes/bootstrap3/templates/Recommend/Libraryh3lp.phtml
index 8e6eb942647ecd1905c1b33e5a9b3292bf11f94b..aa7f110a7dc0ec44105a533d296aa3bd2f703f88 100644
--- a/themes/bootstrap3/templates/Recommend/Libraryh3lp.phtml
+++ b/themes/bootstrap3/templates/Recommend/Libraryh3lp.phtml
@@ -1 +1 @@
-<iframe src="https://us.libraryh3lp.com/chat/<?=$this->escapeHtmlAttr($this->recommend->getChatId())?>?skin=<?=urlencode($this->recommend->getSkin())?>"></iframe>
\ No newline at end of file
+<iframe src="https://us.libraryh3lp.com/chat/<?=$this->escapeHtmlAttr($this->recommend->getChatId())?>?skin=<?=urlencode($this->recommend->getSkin())?>"></iframe>
diff --git a/themes/bootstrap3/templates/Recommend/MapSelection.phtml b/themes/bootstrap3/templates/Recommend/MapSelection.phtml
index 4170ec5e442b20bcddcb7c2f43dbae0a14c4787b..6ebcfbaedead9fcbd10bd7b53f22cbc38e746971 100644
--- a/themes/bootstrap3/templates/Recommend/MapSelection.phtml
+++ b/themes/bootstrap3/templates/Recommend/MapSelection.phtml
@@ -17,9 +17,9 @@
   }
   $height = $this->recommend->getHeight();
   $searchParams = $this->recommend->getSearchParams();
-  $params = array(json_encode($geoField), json_encode($coordinates), json_encode($urlpath),
+  $params = [json_encode($geoField), json_encode($coordinates), json_encode($urlpath),
     json_encode($baseUrl), json_encode($searchParams), json_encode($showSelection),
-    json_encode($resultsCoords), json_encode($popupTitle));
+    json_encode($resultsCoords), json_encode($popupTitle)];
   $jsParams = implode(', ', $params);
   $jsLoad = "loadMapSelection(" . $jsParams . ");";
   $addSearchOption = <<<EOF
diff --git a/themes/bootstrap3/templates/Recommend/OpenLibrarySubjects.phtml b/themes/bootstrap3/templates/Recommend/OpenLibrarySubjects.phtml
index 1815d59786440583868b03b0b9f8551e7c3d9aaa..372687659d0c7a6614f79bb70eba10c3117f1236 100644
--- a/themes/bootstrap3/templates/Recommend/OpenLibrarySubjects.phtml
+++ b/themes/bootstrap3/templates/Recommend/OpenLibrarySubjects.phtml
@@ -28,4 +28,4 @@
     </a>
   </p>
 </div>
-<? endif; ?>
\ No newline at end of file
+<? endif; ?>
diff --git a/themes/bootstrap3/templates/Recommend/OpenLibrarySubjectsDeferred.phtml b/themes/bootstrap3/templates/Recommend/OpenLibrarySubjectsDeferred.phtml
index aec3a025b25b974582586aa881cd3ad9b734525e..0e54681e66150fd7df9093e245dc3880529a54be 100644
--- a/themes/bootstrap3/templates/Recommend/OpenLibrarySubjectsDeferred.phtml
+++ b/themes/bootstrap3/templates/Recommend/OpenLibrarySubjectsDeferred.phtml
@@ -6,4 +6,4 @@
 <div id="openLibraryDeferredRecommend">
     <p><?=$this->transEsc("Loading")?>... <img src="<?=$this->imageLink('ajax_loading.gif')?>" /></p>
     <?=$this->inlineScript(\Zend\View\Helper\HeadScript::SCRIPT, $loadJs, 'SET')?>
-</div>
\ No newline at end of file
+</div>
diff --git a/themes/bootstrap3/templates/Recommend/PubDateVisAjax.phtml b/themes/bootstrap3/templates/Recommend/PubDateVisAjax.phtml
index 67f43cad8fdf1624d0108113c3e7d373404dc521..06a770e5a77bad056f657895d8ab7df8b526ad94 100644
--- a/themes/bootstrap3/templates/Recommend/PubDateVisAjax.phtml
+++ b/themes/bootstrap3/templates/Recommend/PubDateVisAjax.phtml
@@ -2,7 +2,7 @@
 <? if ($visFacets): ?>
 
   <? /* load jQuery flot */ ?>
-<?$this->headScript()->appendFile('vendor/flot/excanvas.min.js', null, array('conditional' => 'IE'));
+<?$this->headScript()->appendFile('vendor/flot/excanvas.min.js', null, ['conditional' => 'IE']);
   $this->headScript()->appendFile('vendor/flot/jquery.flot.min.js');
   $this->headScript()->appendFile('vendor/flot/jquery.flot.resize.min.js');
   $this->headScript()->appendFile('vendor/flot/jquery.flot.selection.min.js');
diff --git a/themes/bootstrap3/templates/Recommend/ResultGoogleMapAjax.phtml b/themes/bootstrap3/templates/Recommend/ResultGoogleMapAjax.phtml
deleted file mode 100644
index 790178cf70a9c9f4f5de7b130bd1b36030ddf090..0000000000000000000000000000000000000000
--- a/themes/bootstrap3/templates/Recommend/ResultGoogleMapAjax.phtml
+++ /dev/null
@@ -1,205 +0,0 @@
-<?
-  $searchParams = $this->recommend->getSearchParams();
-
-  $this->headScript()->appendFile('https://maps.googleapis.com/maps/api/js?key=' . urlencode($this->recommend->getGoogleMapApiKey()) . '&sensor=false&language='.$this->layout()->userLang);
-  $this->headScript()->appendFile('vendor/markerclusterer.min.js');
-?>
-<script type="text/javascript">
-/**
- * Overriding clusterer default function for determining the label text and style
- * for a cluster icon.
- *
- * @param {Array.<google.maps.Marker>} markers The array of represented by the cluster.
- * @param {number} numStyles The number of marker styles available.
- * @return {ClusterIconInfo} The information resource for the cluster.
- * @constant
- * @ignore
- */
-MarkerClusterer.CALCULATOR = function (markers, numStyles) {
-  var index = 0;
-  var count = markers.length.toString();
-  var dispText = 0;
-  for (calcMarker in markers){
-    dispText = dispText + parseInt(markers[calcMarker].getTitle());
-  }
-  var dv = dispText;
-  while (dv !== 0) {
-    dv = parseInt(dv / 10, 10);
-    index++;
-  }
-
-  index = Math.min(index, numStyles);
-  return {
-    text: dispText.toString(),
-    index: index
-  };
-};
-
-/**
- * Overriding clusterer adding the icon to the DOM.
- */
-ClusterIcon.prototype.onAdd = function () {
-  var cClusterIcon = this;
-
-  this.div_ = document.createElement("div");
-  this.div_.className = "clusterDiv";
-  if (this.visible_) {
-    $(this).removeClass('hidden');
-  }
-
-  this.getPanes().overlayMouseTarget.appendChild(this.div_);
-
-  google.maps.event.addDomListener(this.div_, "click", function () {
-    var mc = cClusterIcon.cluster_.getMarkerClusterer();
-    google.maps.event.trigger(mc, "click", cClusterIcon.cluster_);
-    google.maps.event.trigger(mc, "clusterclick", cClusterIcon.cluster_); // deprecated name
-
-    // The default click handler follows. Disable it by setting
-    // the zoomOnClick property to false.
-    var mz = mc.getMaxZoom();
-    if (mc.getZoomOnClick()) {
-      // Zoom into the cluster.
-      mc.getMap().fitBounds(cClusterIcon.cluster_.getBounds());
-      // Don't zoom beyond the max zoom level
-      if (mz && (mc.getMap().getZoom() > mz)) {
-        mc.getMap().setZoom(mz + 1);
-      }
-    }
-  });
-
-  google.maps.event.addDomListener(this.div_, "mouseover", function () {
-    var mc = cClusterIcon.cluster_.getMarkerClusterer();
-    google.maps.event.trigger(mc, "mouseover", cClusterIcon.cluster_);
-  });
-
-  google.maps.event.addDomListener(this.div_, "mouseout", function () {
-    var mc = cClusterIcon.cluster_.getMarkerClusterer();
-    google.maps.event.trigger(mc, "mouseout", cClusterIcon.cluster_);
-  });
-};
-
-var markers;
-var mc;
-var markersData;
-var latlng;
-var myOptions;
-var map;
-var infowindow = new google.maps.InfoWindow({maxWidth: 480, minWidth: 480});
-
-function initialize() {
-  var url = VuFind.path+'/AJAX/json?method=getMapData&<?=$searchParams ?>';
-  //alert('go: ' + url);
-  $.getJSON(url, function(data){
-    //alert(data);
-    markersData = data['data'];
-    if (markersData.length <= 0){
-      return;
-    }
-    latlng = new google.maps.LatLng(0, 0);
-    myOptions = {
-      zoom: 1,
-      center: latlng,
-      mapTypeControl: true,
-      mapTypeControlOptions: {
-        style: google.maps.MapTypeControlStyle.DROPDOWN_MENU
-      },
-      mapTypeId: google.maps.MapTypeId.ROADMAP
-    };
-    map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
-
-    var useGmm = document.getElementById('usegmm');
-    google.maps.event.addDomListener(useGmm, 'click', refreshMap);
-    map.addListener('zoom_changed', refreshMap);
-
-    var checkbx = document.getElementById("useCluster");
-    var wrap = document.getElementById("mapWrap");
-    wrap.style.display = "block";
-    checkbx.style.display = "block";
-
-    showMarkers();
-  });
-}
-
-function showMarkers(){
-  markers = [];
-
-  deleteOverlays();
-  if (mc) {
-    mc.clearMarkers();
-  }
-
-  for (var i = 0; i<markersData.length; i++){
-    var disTitle = markersData[i].title;
-    var iconSize = "0.5";
-    if (disTitle>99){
-      iconSize = "0.75";
-    }
-    var markerImg = "https://chart.googleapis.com/chart?chst=d_map_spin&chld="+iconSize+"|0|F44847|10|_|" +  disTitle;
-    var labelXoffset = 1 + disTitle.length * 4;
-    var latLng = new google.maps.LatLng(markersData[i].lat , markersData[i].lon)
-    var marker = new google.maps.Marker({//MarkerWithLabel
-      loc_facet: markersData[i].location_facet,
-      position: latLng,
-      map: map,
-      title: disTitle,
-      icon: markerImg
-    });
-    google.maps.event.addListener(marker, 'click', function() {
-      infowindow.close();
-      //infowindow.setContent(this.html);
-      //infowindow.open(map, this);
-      load_content(this);
-    });
-    markers.push(marker);
-  }
-  if (document.getElementById("usegmm").checked) {
-    mc = new MarkerClusterer(map, markers);
-  } else {
-    for (var i = 0; i < markers.length; i++) {
-      markers[i].setMap(map);
-    }
-  }
-}
-
-function load_content(marker){
-  var ajaxUrl = VuFind.path+'/AJAX/ResultGoogleMapInfo?limit=5&filter[]=long_lat%3A"' + marker.loc_facet+'"&<?=$searchParams ?>';
-  $.ajax(ajaxUrl, { dataType: 'html' }).done(function (html) {
-    infowindow.setContent(html);
-    infowindow.open(map, marker);
-  });
-}
-
-function deleteOverlays() {
-  if (markers) {
-    for (i in markers) {
-      markers[i].setMap(null);
-    }
-    markers.length = 0;
-  }
-}
-
-function refreshMap() {
-  deleteOverlays();
-  showMarkers();
-  // The following two lines are a workaround for a library bug that causes
-  // clusters to disappear after zoom and other events; these may be able to be
-  // removed along with the zoom_changed event hook above in the future if the
-  // library is fixed.
-  mapcenter = map.getCenter();
-  map.setCenter(new google.maps.LatLng((mapcenter.lat() + 0.0000001), mapcenter.lng()));
-}
-
-google.maps.event.addDomListener(window, 'load', initialize);
-</script>
-<div id="mapWrap" onload="initialize()" style="height:479px;display:none;margin-bottom:1em" class="clearfix">
-  <div id="map_canvas" style="width: 100%; height: 100%"></div>
-  <div class="mapClusterToggle" id="useCluster">
-    <div class="checkbox">
-      <label for="usegmm">
-        <input type="checkbox" id="usegmm" checked="true"></input>
-        <?=$this->transEsc('google_map_cluster_points') ?>
-      </label>
-    </div>
-  </div>
-</div>
-<br/>
diff --git a/themes/bootstrap3/templates/Recommend/SideFacets.phtml b/themes/bootstrap3/templates/Recommend/SideFacets.phtml
index bc3233564ae6896e543b5ae93cc7b434f5ec0f6e..c93bd6091f89a4b303399dd26c45fed921ab5fe8 100644
--- a/themes/bootstrap3/templates/Recommend/SideFacets.phtml
+++ b/themes/bootstrap3/templates/Recommend/SideFacets.phtml
@@ -1,231 +1,73 @@
 <?
   $this->headScript()->appendFile('facets.js');
 
-  $results = $this->recommend->getResults();
-  $options = $this->searchOptions($this->searchClassId);
+  // Save results/options to $this so they are available to sub-templates:
+  $this->results = $results = $this->recommend->getResults();
+  $this->options = $options = $this->searchOptions($this->searchClassId);
 ?>
 <? if ($results->getResultTotal() > 0): ?>
   <h4><?=$this->transEsc(isset($this->overrideSideFacetCaption) ? $this->overrideSideFacetCaption : 'Narrow Search')?></h4>
 <? endif; ?>
-<? $checkboxFilters = $results->getParams()->getCheckboxFacets(); if (count($checkboxFilters) > 0): ?>
-<?
-  $html = '';
-  $shown = 0;
-  foreach ($checkboxFilters as $current) {
-    $html .= '<label class="checkbox';
-    if($results->getResultTotal() < 1 && !$current['selected'] && !$current['alwaysVisible']) {
-      $html .= ' hidden';
-    } else {
-      $shown ++;
+<? $checkboxFilters = $results->getParams()->getCheckboxFacets(); ?>
+<? $checkboxesShown = false; ?>
+<? if (count($checkboxFilters) > 0):
+    foreach ($checkboxFilters as $current) {
+      if ($results->getResultTotal() > 0 || $current['selected'] || $current['alwaysVisible']) {
+        $checkboxesShown = true;
+        break;
+      }
     }
-    $html .= '"><input type="checkbox" name="filter[]" value="'.$this->escapeHtmlAttr($current['filter']).'"
-      '. ($current['selected'] ? 'checked="checked"' : '') .' id="'.$this->escapeHtmlAttr(str_replace(' ', '', $current['desc'])).'"
-      onclick="document.location.href=\''.($current['selected'] ? $results->getUrlQuery()->removeFilter($current['filter']) : $results->getUrlQuery()->addFilter($current['filter'])).'\';" />'.$this->transEsc($current['desc']).'</label>';
-  }
-?>
-  <div class="checkboxFilter<?if($shown == 0):?> hidden<? endif; ?>"><?=$html ?></div>
+  ?>
+  <?if ($checkboxesShown):?>
+    <div class="checkboxFilter">
+      <?=$this->context($this)->renderInContext('Recommend/SideFacets/checkbox-filters.phtml', ['checkboxFilters' => $checkboxFilters, 'results' => $results]); ?>
+    </div>
+  <? endif; ?>
 <? endif; ?>
-<? $extraFilters = isset($this->extraSideFacetFilters) ? $this->extraSideFacetFilters : array(); ?>
+<? $extraFilters = isset($this->extraSideFacetFilters) ? $this->extraSideFacetFilters : []; ?>
 <? $collapsedFacets = $this->recommend->getCollapsedFacets() ?>
-<? $hierarchicalFacetSortOptions = $this->recommend->getHierarchicalFacetSortOptions() ?>
-<? $hierarchicalFacets = $this->recommend->getHierarchicalFacets() ?>
-<? $filterList = array_merge($results->getParams()->getFilterList(true), $extraFilters); if (!empty($filterList)): ?>
-  <div class="list-group filters">
-    <div class="list-group-item title"><?=$this->transEsc('Remove Filters')?></div>
-    <? foreach ($filterList as $field => $filters): ?>
-      <? foreach ($filters as $i => $filter): ?>
-        <?
-          $index = isset($filter['field']) ? array_search($filter['field'], $collapsedFacets) : false;
-          if ($index !== false) {
-              unset($collapsedFacets[$index]); // Open if we have a match
-          }
-          if (isset($filter['specialType']) && $filter['specialType'] == 'keyword') {
-            $removeLink = $this->currentPath().$results->getUrlQuery()->replaceTerm($filter['value'], '');
-          } else {
-            $removeLink = $this->currentPath().$results->getUrlQuery()->removeFacet($filter['field'], $filter['value'], true, $filter['operator']);
-          }
-          if ($filter['displayText'] == '[* TO *]') {
-            $filter['displayText'] = $this->translate('filter_wildcard');
-          }
-        ?>
-        <a class="list-group-item active" href="<?=$removeLink?>" title="<?=$this->transEsc('clear_tag_filter') ?>">
-          <span class="pull-right flip"><i class="fa fa-times" aria-hidden="true"></i></span>
-          <? if ($filter['operator'] == 'NOT') echo $this->transEsc('NOT') . ' '; if ($filter['operator'] == 'OR' && $i > 0) echo $this->transEsc('OR') . ' '; ?><?=$this->transEsc($field)?>: <?=$this->escapeHtml($filter['displayText'])?>
-        </a>
-      <? endforeach; ?>
-    <? endforeach; ?>
-  </div>
+<? $filterList = array_merge($results->getParams()->getFilterList(true), $extraFilters); ?>
+<? if (!empty($filterList)): ?>
+  <?=$this->context($this)->renderInContext('Recommend/SideFacets/filter-list.phtml', [
+    'collapsedFacets' => $collapsedFacets,
+    'extraFilters' => $extraFilters,
+    'filterList' => $filterList,
+  ]); ?>
 <? endif; ?>
 <?= isset($this->sideFacetExtraControls) ? $this->sideFacetExtraControls : '' ?>
 <? $sideFacetSet = $this->recommend->getFacetSet(); $rangeFacets = $this->recommend->getAllRangeFacets(); ?>
+<? $hierarchicalFacets = $this->recommend->getHierarchicalFacets() ?>
+<? $hierarchicalFacetSortOptions = $this->recommend->getHierarchicalFacetSortOptions() ?>
 <? if (!empty($sideFacetSet) && $results->getResultTotal() > 0): ?>
   <? foreach ($sideFacetSet as $title => $cluster): ?>
-    <? $allowExclude = $this->recommend->excludeAllowed($title); ?>
-    <? $facets_before_more = $this->recommend->getShowMoreSetting($title); ?>
-    <? $showMoreInLightbox = $this->recommend->getShowInLightboxSetting($title); ?>
-    <div class="list-group facet" id="side-panel-<?=$this->escapeHtmlAttr($title) ?>">
-      <div class="list-group-item title<? if(in_array($title, $collapsedFacets)): ?> collapsed<? endif ?>" data-toggle="collapse" href="#side-collapse-<?=$this->escapeHtmlAttr($title) ?>" >
+    <div class="facet-group" id="side-panel-<?=$this->escapeHtmlAttr($title) ?>">
+      <div class="title<? if(in_array($title, $collapsedFacets)): ?> collapsed<? endif ?>" data-toggle="collapse" href="#side-collapse-<?=$this->escapeHtmlAttr($title) ?>" >
         <?=$this->transEsc($cluster['label'])?>
       </div>
       <div id="side-collapse-<?=$this->escapeHtmlAttr($title) ?>" class="collapse<? if(!in_array($title, $collapsedFacets)): ?> in<? endif ?>">
         <? if (isset($rangeFacets[$title])): ?>
-          <div class="list-group-item">
-            <form name="<?=$this->escapeHtmlAttr($title)?>Filter" id="<?=$this->escapeHtmlAttr($title)?>Filter">
-              <?=$results->getUrlQuery()->asHiddenFields(array('page' => "/./", 'filter' => "/^{$title}:.*/"))?>
-              <input type="hidden" name="<?=$this->escapeHtmlAttr($rangeFacets[$title]['type'])?>range[]" value="<?=$this->escapeHtmlAttr($title)?>"/>
-              <div class="row">
-                <? $extraInputAttribs = ($rangeFacets[$title]['type'] == 'date') ? 'maxlength="4" ' : ''; ?>
-                <div class="col-sm-6">
-                  <label for="<?=$this->escapeHtmlAttr($title)?>from">
-                    <?=$this->transEsc('date_from')?>:
-                  </label>
-                  <input type="text" class="form-control" name="<?=$this->escapeHtmlAttr($title)?>from" id="<?=$this->escapeHtmlAttr($title)?>from" value="<?=isset($rangeFacets[$title]['values'][0])?$this->escapeHtmlAttr($rangeFacets[$title]['values'][0]):''?>" <?=$extraInputAttribs?>/>
-                </div>
-                <div class="col-sm-6">
-                  <label for="<?=$this->escapeHtmlAttr($title)?>to">
-                    <?=$this->transEsc('date_to')?>:
-                  </label>
-                  <input type="text" class="form-control" name="<?=$this->escapeHtmlAttr($title)?>to" id="<?=$this->escapeHtmlAttr($title)?>to" value="<?=isset($rangeFacets[$title]['values'][1])?$this->escapeHtmlAttr($rangeFacets[$title]['values'][1]):''?>" <?=$extraInputAttribs?>/>
-                </div>
-              </div>
-              <? if ($rangeFacets[$title]['type'] == 'date'): ?>
-                <div class="slider-container"><input type="text" class="hidden" id="<?=$this->escapeHtmlAttr($title)?><?=$this->escapeHtml($rangeFacets[$title]['type'])?>Slider"/></div>
-              <? endif; ?>
-              <input class="btn btn-default" type="submit" value="<?=$this->transEsc('Set')?>"/>
-            </form>
-          </div>
-          <? if ($rangeFacets[$title]['type'] == 'date'): ?>
-            <? $this->headScript()->appendFile('vendor/bootstrap-slider.js'); ?>
-            <? $this->headLink()->appendStylesheet('vendor/bootstrap-slider.min.css'); ?>
-            <?
-              $min = !empty($rangeFacets[$title]['values'][0]) ? min($rangeFacets[$title]['values'][0], 1400) : 1400;
-              $future = date('Y', time()+31536000);
-              $max = !empty($rangeFacets[$title]['values'][1]) ? max($future, $rangeFacets[$title]['values'][1]) : $future;
-              $low  = !empty($rangeFacets[$title]['values'][0]) ? $rangeFacets[$title]['values'][0] : $min;
-              $high = !empty($rangeFacets[$title]['values'][1]) ? $rangeFacets[$title]['values'][1] : $max;
-              $reversed = $this->layout()->rtl ? 'true' : 'false';
-              $script = <<<JS
-$(document).ready(function() {
-  var fillTexts = function() {
-  var v = {$this->escapeHtmlAttr($title)}dateSlider.getValue();
-  $('#{$this->escapeHtmlAttr($title)}from').val(v[0]);
-  $('#{$this->escapeHtmlAttr($title)}to').val(v[1]);
-  };
-  var {$this->escapeHtmlAttr($title)}dateSlider = $('#{$this->escapeHtmlAttr($title)}dateSlider')
-  .slider({
-    'min':{$min},
-    'max':{$max},
-    'handle':"square",
-    'tooltip':"hide",
-    'value':[{$low},{$high}],
-    'reversed': {$reversed}
-  })
-  .on('change', fillTexts)
-  .data('slider');
-});
-JS;
-            ?>
-            <?=$this->inlineScript(\Zend\View\Helper\HeadScript::SCRIPT, $script, 'SET'); ?>
-          <? endif; ?>
+          <?=$this->context($this)->renderInContext('Recommend/SideFacets/range-slider.phtml', ['title' => $title, 'facet' => $rangeFacets[$title]]); ?>
         <? else: ?>
+          <? $contextVars = [
+            'allowExclude' => $this->recommend->excludeAllowed($title),
+            'title' => $title,
+            'sortOptions' => isset($hierarchicalFacetSortOptions[$title]) ? $hierarchicalFacetSortOptions[$title] : '',
+            'collapsedFacets' => $collapsedFacets
+          ]; ?>
           <? if (in_array($title, $hierarchicalFacets)): ?>
-            <? $this->headScript()->appendFile('vendor/jsTree/jstree.min.js'); ?>
-            <? $sort = isset($hierarchicalFacetSortOptions[$title]) ? $hierarchicalFacetSortOptions[$title] : ''; ?>
-            <? if (!in_array($title, $collapsedFacets)): ?>
-              <?
-              $script = <<<JS
-$(document).ready(function() {
-  initFacetTree($('#facet_{$this->escapeHtml($title)}'), true);
-});
-JS;
-              ?>
-              <?=$this->inlineScript(\Zend\View\Helper\HeadScript::SCRIPT, $script, 'SET'); ?>
-            <? else: ?>
-              <?
-              $script = <<<JS
-$('#side-collapse-{$this->escapeHtmlAttr($title)}').on('show.bs.collapse', function() {
-  initFacetTree($('#facet_{$this->escapeHtml($title)}'), true);
-});
-JS;
-              ?>
-              <?=$this->inlineScript(\Zend\View\Helper\HeadScript::SCRIPT, $script, 'SET'); ?>
-            <? endif; ?>
-            <li id="facet_<?=$this->escapeHtml($title)?>" class="jstree-facet"
-                  data-facet="<?=$this->escapeHtmlAttr($title)?>"
-                  data-path="<?=$this->currentPath()?>"
-                  data-exclude="<?=$allowExclude?>"
-                  data-operator="<?=$this->recommend->getFacetOperator($title)?>"
-                  data-exclude-title="<?=$this->transEsc('exclude_facet')?>"
-                  data-sort="<?=isset($hierarchicalFacetSortOptions[$title]) ? $hierarchicalFacetSortOptions[$title] : ''?>">
-            </li>
+            <?=$this->context($this)->renderInContext('Recommend/SideFacets/hierarchical-facet.phtml', $contextVars); ?>
             <noscript>
           <? endif; ?>
-          <? foreach ($cluster['list'] as $i=>$thisFacet): ?>
-              <?
-                if(strlen($thisFacet['displayText']) == 0) {
-                  $thisFacet['displayText'] = "-";
-                }
-              ?>
-              <? $moreClass = 'narrowGroupHidden-'.$this->escapeHtmlAttr($title).' hidden'; ?>
-            <? if ($i == $facets_before_more): ?>
-              <? $idAndClass = 'id="more-narrowGroupHidden-'.$this->escapeHtmlAttr($title).'" class="list-group-item narrow-toggle"'; ?>
-              <? if ($facetLightbox = $options->getFacetListAction()): ?>
-                <? $moreUrl = $this->url($facetLightbox) . $results->getUrlQuery()->getParams().'&amp;facet='.$title.'&amp;facetop='.$thisFacet['operator'].'&amp;facetexclude='.($allowExclude ? 1 : 0); ?>
-              <? else: ?>
-                <? $moreUrl = '#'; ?>
-              <? endif; ?>
-              <? if (($showMoreInLightbox && $showMoreInLightbox !== 'more') && $facetLightbox): ?>
-                <a <?=$idAndClass ?> data-lightbox href="<?=$moreUrl ?>" rel="nofollow"><?=$this->transEsc('more')?> ...</a>
-                <? break; ?>
-              <? else: ?>
-                <a <?=$idAndClass ?> href="<?=$moreUrl ?>" onclick="return moreFacets('narrowGroupHidden-<?=$this->escapeHtmlAttr($title) ?>')" rel="nofollow"><?=$this->transEsc('more')?> ...</a>
-              <? endif; ?>
-            <? endif; ?>
-            <? if ($thisFacet['isApplied']): ?>
-              <a class="list-group-item active<? if ($i >= $facets_before_more): ?><?=$moreClass ?><?endif ?><? if ($thisFacet['operator'] == 'OR'): ?> facetOR applied<? endif ?>" href="<?=$this->currentPath().$results->getUrlQuery()->removeFacet($title, $thisFacet['value'], true, $thisFacet['operator']) ?>" title="<?=$this->transEsc('applied_filter') ?>">
-                <? if ($thisFacet['operator'] == 'OR'): ?>
-                  <i class="fa fa-check-square-o" aria-hidden="true"></i>
-                <? else: ?>
-                  <span class="pull-right flip"><i class="fa fa-check" aria-hidden="true"></i></span>
-                <? endif; ?>
-                <?=$this->escapeHtml($thisFacet['displayText'])?>
-              </a>
-            <? else: ?>
-              <? $addURL = $this->currentPath().$results->getUrlQuery()->addFacet($title, $thisFacet['value'], $thisFacet['operator']); ?>
-              <? if ($allowExclude): ?>
-                <div class="list-group-item facet<?=$thisFacet['operator'] ?><? if ($i >= $facets_before_more): ?> <?=$moreClass ?><?endif ?>">
-              <? else: ?>
-                <a href="<?=$addURL ?>" class="list-group-item facet<?=$thisFacet['operator'] ?><? if ($i >= $facets_before_more): ?> <?=$moreClass ?><?endif ?>">
-              <? endif; ?>
-              <span class="badge">
-                <?=$this->localizedNumber($thisFacet['count'])?>
-                <? if ($allowExclude): ?>
-                  <a href="<?=$this->currentPath().$results->getUrlQuery()->addFacet($title, $thisFacet['value'], 'NOT') ?>" title="<?=$this->transEsc('exclude_facet') ?>"><i class="fa fa-times" aria-hidden="true"></i></a>
-                <? endif; ?>
-              </span>
-              <? if ($allowExclude): ?>
-                <a href="<?=$addURL ?>">
-              <? endif; ?>
-              <? if($thisFacet['operator'] == 'OR'): ?>
-                <i class="fa fa-square-o" aria-hidden="true"></i>
-              <? endif; ?>
-              <?=$this->escapeHtml($thisFacet['displayText'])?>
-              <? if ($allowExclude): ?>
-                  </a>
-                </div>
-              <? else: ?>
-                </a>
-              <? endif; ?>
-            <? endif; ?>
-          <? endforeach; ?>
-          <? if ($showMoreInLightbox === 'more' && $facetLightbox = $options->getFacetListAction()): ?>
-            <? $moreUrl = $this->url($facetLightbox) . $results->getUrlQuery()->getParams().'&amp;facet='.$title.'&amp;facetop='.$thisFacet['operator'].'&amp;facetexclude='.($allowExclude ? 1 : 0); ?>
-            <a class="list-group-item narrow-toggle <?=$moreClass ?>" data-lightbox href="<?=$moreUrl ?>" rel="nofollow"><?=$this->transEsc('see all')?> ...</a>
+          <? $contextVars = [
+            'options' => $options,
+            'allowExclude' => $this->recommend->excludeAllowed($title),
+            'facets_before_more' => $this->recommend->getShowMoreSetting($title),
+            'showMoreInLightbox' => $this->recommend->getShowInLightboxSetting($title)
+          ]; ?>
+          <?=$this->context($this)->renderInContext('Recommend/SideFacets/cluster-list.phtml', array_merge($contextVars, ['title' => $title, 'cluster' => $cluster])); ?>
+          <? if (in_array($title, $hierarchicalFacets)): ?>
+            </noscript>
           <? endif; ?>
-          <? if ($i >= $facets_before_more): ?><a class="list-group-item narrow-toggle <?=$moreClass ?>" href="#" onclick="return lessFacets('narrowGroupHidden-<?=$this->escapeHtmlAttr($title) ?>')"><?=$this->transEsc('less')?> ...</a><? endif; ?>
-        <? endif; ?>
-        <? if (in_array($title, $hierarchicalFacets)): ?>
-          </noscript>
         <? endif; ?>
       </div>
     </div>
diff --git a/themes/bootstrap3/templates/Recommend/SideFacets/checkbox-filters.phtml b/themes/bootstrap3/templates/Recommend/SideFacets/checkbox-filters.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..320c479ca0c98f6e3d16770fab672ead9a76ba18
--- /dev/null
+++ b/themes/bootstrap3/templates/Recommend/SideFacets/checkbox-filters.phtml
@@ -0,0 +1,6 @@
+<? foreach ($checkboxFilters as $current): ?>
+  <a class="checkbox-filter<? if(!($results->getResultTotal() > 0 || $current['selected'] || $current['alwaysVisible'])): ?> hidden<? endif; ?>" href="<?=$current['selected'] ? $results->getUrlQuery()->removeFilter($current['filter']) : $results->getUrlQuery()->addFilter($current['filter']);?>">
+    <i class="fa fa-<?=$current['selected'] ? 'check-square-o' : 'square-o' ?>"></i>
+    <?=$this->transEsc($current['desc']) ?>
+  </a>
+<? endforeach; ?>
diff --git a/themes/bootstrap3/templates/Recommend/SideFacets/cluster-list.phtml b/themes/bootstrap3/templates/Recommend/SideFacets/cluster-list.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..f9d78e1d6e0c11e27292d77e36330b8158fe6bc5
--- /dev/null
+++ b/themes/bootstrap3/templates/Recommend/SideFacets/cluster-list.phtml
@@ -0,0 +1,73 @@
+<? $idAndClass = 'id="more-narrowGroupHidden-'.$this->escapeHtmlAttr($this->title).'" class="facet narrow-toggle"'; ?>
+<? $moreClass = 'narrowGroupHidden-'.$this->escapeHtmlAttr($this->title).' hidden'; ?>
+<? foreach ($this->cluster['list'] as $i => $thisFacet): ?>
+  <?
+    if(empty($thisFacet['displayText'])) {
+      $thisFacet['displayText'] = "-";
+    }
+  ?>
+  <? /* MORE link */ ?>
+  <? if ($i == $this->facets_before_more): ?>
+    <? if ($facetLightbox = $this->options->getFacetListAction()): ?>
+      <? $moreUrl = $this->url($facetLightbox) . $results->getUrlQuery()->getParams() . '&amp;facet=' . $this->title . '&amp;facetop=' . $thisFacet['operator'] . '&amp;facetexclude=' . ($this->allowExclude ? 1 : 0); ?>
+    <? else: ?>
+      <? $moreUrl = '#'; ?>
+    <? endif; ?>
+    <? if (($this->showMoreInLightbox && $this->showMoreInLightbox !== 'more') && $facetLightbox): ?>
+      <a <?=$idAndClass ?> data-lightbox href="<?=$moreUrl ?>" rel="nofollow"><?=$this->transEsc('more')?> ...</a>
+      <? break; ?>
+    <? endif; ?>
+    <a <?=$idAndClass ?> href="<?=$moreUrl ?>" onclick="return moreFacets('narrowGroupHidden-<?=$this->escapeHtmlAttr($this->title) ?>')" rel="nofollow"><?=$this->transEsc('more')?> ...</a>
+  <? endif; ?>
+
+  <?
+    $affectiveURL = $thisFacet['isApplied']
+      ? $this->currentPath() . $results->getUrlQuery()->removeFacet($this->title, $thisFacet['value'], $thisFacet['operator'])
+      : $this->currentPath() . $results->getUrlQuery()->addFacet($this->title, $thisFacet['value'], $thisFacet['operator']);
+  ?>
+  <? if (!$thisFacet['isApplied'] && $this->allowExclude): ?>
+    <div class="facet excludable facet<?=$thisFacet['operator'] ?><? if ($thisFacet['isApplied']): ?> active<? endif; ?><? if ($i >= $this->facets_before_more): ?> <?=$moreClass ?><?endif ?>">
+      <? $excludeURL = $thisFacet['isApplied']
+        ? $this->currentPath() . $results->getUrlQuery()->removeFacet($this->title, $thisFacet['value'], $thisFacet['operator'])->addFacet($this->title, $thisFacet['value'], 'NOT')
+        : $this->currentPath() . $results->getUrlQuery()->addFacet($this->title, $thisFacet['value'], 'NOT');
+      ?>
+      <a href="<?=$excludeURL ?>" title="<?=$this->transEsc('exclude_facet') ?>" class="exclude"><i class="fa fa-times" aria-hidden="true"></i></a>
+  <? else: ?>
+    <a href="<?=$affectiveURL ?>" class="facet facet<?=$thisFacet['operator'] ?><? if ($thisFacet['isApplied']): ?> active<? endif; ?><? if ($i >= $this->facets_before_more): ?> <?=$moreClass ?><?endif ?>">
+  <? endif; ?>
+
+  <? if ($thisFacet['isApplied']): ?>
+    <span class="status"><i class="fa fa-check" aria-hidden="true"></i></span>
+  <? else: ?>
+    <span class="badge"><?=$this->localizedNumber($thisFacet['count'])?></span>
+  <? endif; ?>
+
+  <? if (!$thisFacet['isApplied'] && $this->allowExclude): ?>
+    <a href="<?=$affectiveURL ?>" class="text">
+  <? else: ?>
+    <span class="text">
+  <? endif; ?>
+
+  <? if ($thisFacet['operator'] == 'OR'): ?>
+    <i class="fa <?=$thisFacet['isApplied'] ? 'fa-check-square-o' : 'fa-square-o' ?>" aria-hidden="true"></i>
+  <? endif; ?>
+
+  <?=$this->escapeHtml($thisFacet['displayText'])?>
+
+  <? if (!$thisFacet['isApplied'] && $this->allowExclude): ?>
+      </a>
+    </div>
+  <? else: ?>
+      </span>
+    </a>
+  <? endif; ?>
+<? endforeach; ?>
+
+<? /* LESS and SEE MORE links */ ?>
+<? if ($i >= $this->facets_before_more): ?>
+  <? if ($this->showMoreInLightbox === 'more' && $facetLightbox = $options->getFacetListAction()): ?>
+    <? $moreUrl = $this->url($facetLightbox) . $results->getUrlQuery()->getParams().'&amp;facet='.$this->title.'&amp;facetop='.$thisFacet['operator'].'&amp;facetexclude='.($this->allowExclude ? 1 : 0); ?>
+    <a class="facet narrow-toggle <?=$moreClass ?>" data-lightbox href="<?=$moreUrl ?>" rel="nofollow"><?=$this->transEsc('see all')?> ...</a>
+  <? endif; ?>
+  <a class="facet narrow-toggle <?=$moreClass ?>" href="#" onclick="return lessFacets('narrowGroupHidden-<?=$this->escapeHtmlAttr($this->title) ?>')"><?=$this->transEsc('less')?> ...</a>
+<? endif; ?>
diff --git a/themes/bootstrap3/templates/Recommend/SideFacets/filter-list.phtml b/themes/bootstrap3/templates/Recommend/SideFacets/filter-list.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..085d50cbc00e309ce3f5d7466c0cb26439873d8a
--- /dev/null
+++ b/themes/bootstrap3/templates/Recommend/SideFacets/filter-list.phtml
@@ -0,0 +1,27 @@
+<div class="facet-group active-filters">
+  <div class="title"><?=$this->transEsc('Remove Filters')?></div>
+  <? foreach ($filterList as $field => $filters): ?>
+    <? foreach ($filters as $i => $filter): ?>
+      <?
+        $index = isset($filter['field']) ? array_search($filter['field'], $collapsedFacets) : false;
+        if ($index !== false) {
+          unset($collapsedFacets[$index]); // Open if we have a match
+        }
+        if (isset($filter['specialType']) && $filter['specialType'] == 'keyword') {
+          $removeLink = $this->currentPath() . $results->getUrlQuery()->replaceTerm($filter['value'], '');
+        } else {
+          $removeLink = $this->currentPath() . $results->getUrlQuery()->removeFacet($filter['field'], $filter['value'], $filter['operator']);
+        }
+        if ($filter['displayText'] == '[* TO *]') {
+          $filter['displayText'] = $this->translate('filter_wildcard');
+        }
+      ?>
+      <a class="facet" href="<?=$removeLink ?>" title="<?=$this->transEsc('clear_tag_filter') ?>">
+        <span class="status"><i class="fa fa-times" aria-hidden="true"></i></span>
+        <? if ($filter['operator'] == 'NOT'): ?><?=$this->transEsc('NOT') ?><? endif; ?>
+        <? if ($filter['operator'] == 'OR' && $i > 0): ?><?=$this->transEsc('OR') ?><? endif; ?>
+        <?=$this->transEsc($field) ?>: <?=$this->escapeHtml($filter['displayText']) ?>
+      </a>
+    <? endforeach; ?>
+  <? endforeach; ?>
+</div>
diff --git a/themes/bootstrap3/templates/Recommend/SideFacets/hierarchical-facet.phtml b/themes/bootstrap3/templates/Recommend/SideFacets/hierarchical-facet.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..cf26f37cad77e7a7bd4a5e1839d080bb38261c3f
--- /dev/null
+++ b/themes/bootstrap3/templates/Recommend/SideFacets/hierarchical-facet.phtml
@@ -0,0 +1,28 @@
+<? $this->headScript()->appendFile('vendor/jsTree/jstree.min.js'); ?>
+<? if (!in_array($this->title, $this->collapsedFacets)): ?>
+  <?
+    $script = <<<JS
+$(document).ready(function() {
+  initFacetTree($('#facet_{$this->escapeHtml($this->title)}'), true);
+});
+JS;
+  ?>
+  <?=$this->inlineScript(\Zend\View\Helper\HeadScript::SCRIPT, $script, 'SET'); ?>
+<? else: ?>
+  <?
+  $script = <<<JS
+$('#side-collapse-{$this->escapeHtmlAttr($this->title)}').on('show.bs.collapse', function() {
+  initFacetTree($('#facet_{$this->escapeHtml($this->title)}'), true);
+});
+JS;
+  ?>
+  <?=$this->inlineScript(\Zend\View\Helper\HeadScript::SCRIPT, $script, 'SET'); ?>
+<? endif; ?>
+<li id="facet_<?=$this->escapeHtml($this->title)?>" class="jstree-facet"
+    data-facet="<?=$this->escapeHtmlAttr($this->title)?>"
+    data-path="<?=$this->currentPath()?>"
+    data-exclude="<?=$this->allowExclude?>"
+    data-operator="<?=$this->recommend->getFacetOperator($this->title)?>"
+    data-exclude-title="<?=$this->transEsc('exclude_facet')?>"
+    data-sort="<?=isset($this->sortOptions) ? $this->sortOptions : ''?>">
+</li>
diff --git a/themes/bootstrap3/templates/Recommend/SideFacets/range-slider.phtml b/themes/bootstrap3/templates/Recommend/SideFacets/range-slider.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..4dae71c02fd4102d83b25846307805530570a477
--- /dev/null
+++ b/themes/bootstrap3/templates/Recommend/SideFacets/range-slider.phtml
@@ -0,0 +1,69 @@
+<div class="facet">
+  <form name="<?=$this->escapeHtmlAttr($this->title)?>Filter" id="<?=$this->escapeHtmlAttr($this->title)?>Filter">
+    <?=$results->getUrlQuery()->asHiddenFields(['page' => "/./", 'filter' => "/^{$this->title}:.*/"])?>
+    <input type="hidden" name="<?=$this->escapeHtmlAttr($this->facet['type'])?>range[]" value="<?=$this->escapeHtmlAttr($this->title)?>"/>
+    <div class="date-fields">
+      <? $extraInputAttribs = ($this->facet['type'] == 'date') ? 'maxlength="4" ' : ''; ?>
+      <div class="date-from">
+        <label for="<?=$this->escapeHtmlAttr($this->title)?>from">
+          <?=$this->transEsc('date_from')?>:
+        </label>
+        <input type="text" class="form-control" name="<?=$this->escapeHtmlAttr($this->title)?>from" id="<?=$this->escapeHtmlAttr($this->title)?>from" value="<?=isset($this->facet['values'][0])?$this->escapeHtmlAttr($this->facet['values'][0]):''?>" <?=$extraInputAttribs?>/>
+      </div>
+      <div class="date-to">
+        <label for="<?=$this->escapeHtmlAttr($this->title)?>to">
+          <?=$this->transEsc('date_to')?>:
+        </label>
+        <input type="text" class="form-control" name="<?=$this->escapeHtmlAttr($this->title)?>to" id="<?=$this->escapeHtmlAttr($this->title)?>to" value="<?=isset($this->facet['values'][1])?$this->escapeHtmlAttr($this->facet['values'][1]):''?>" <?=$extraInputAttribs?>/>
+      </div>
+    </div>
+    <? if ($this->facet['type'] == 'date'): ?>
+      <div class="slider-container"><input type="text" class="hidden" id="<?=$this->escapeHtmlAttr($this->title)?><?=$this->escapeHtml($this->facet['type'])?>Slider"/></div>
+    <? endif; ?>
+    <input class="btn btn-default" type="submit" value="<?=$this->transEsc('Set')?>"/>
+  </form>
+</div>
+<? if ($this->facet['type'] == 'date'): ?>
+  <? $this->headScript()->appendFile('vendor/bootstrap-slider.min.js'); ?>
+  <? $this->headLink()->appendStylesheet('vendor/bootstrap-slider.min.css'); ?>
+  <?
+    $min = !empty($this->facet['values'][0]) ? min($this->facet['values'][0], 1400) : 1400;
+    $future = date('Y', time()+31536000); // next year
+    $max = !empty($this->facet['values'][1]) ? max($future, $this->facet['values'][1]) : $future;
+    $low  = !empty($this->facet['values'][0]) ? $this->facet['values'][0] : $min;
+    $high = !empty($this->facet['values'][1]) ? $this->facet['values'][1] : $max;
+    $script = <<<JS
+$(document).ready(function() {
+  var fillTexts = function() {
+    var v = {$this->escapeHtmlAttr($this->title)}dateSlider.getValue();
+    $('#{$this->escapeHtmlAttr($this->title)}from').val(v[0]);
+    $('#{$this->escapeHtmlAttr($this->title)}to').val(v[1]);
+  };
+  var {$this->escapeHtmlAttr($this->title)}dateSlider = $('#{$this->escapeHtmlAttr($this->title)}dateSlider')
+    .slider({
+      'min':{$min},
+      'max':{$max},
+      'handle':"square",
+      'tooltip':"hide",
+      'value':[{$low},{$high}]
+    })
+    .on('change', fillTexts)
+    .data('slider');
+});
+
+$('#{$this->escapeHtmlAttr($this->title)}from, #{$this->escapeHtmlAttr($this->title)}to').change(function () {
+  var fromValue = Number($('#{$this->escapeHtmlAttr($this->title)}from').val());
+  var toValue = Number($('#{$this->escapeHtmlAttr($this->title)}to').val());
+  $('#{$this->escapeHtmlAttr($this->title)}dateSlider').slider(
+    'setValue',
+    [
+      isNaN(fromValue) || fromValue <= 0 ? {$min} : fromValue,
+      isNaN(toValue) || toValue <= 0 ? {$max} : toValue
+    ],
+    true
+  );
+});
+JS;
+  ?>
+  <?=$this->inlineScript(\Zend\View\Helper\HeadScript::SCRIPT, $script, 'SET'); ?>
+<? endif; ?>
diff --git a/themes/bootstrap3/templates/Recommend/SummonBestBetsDeferred.phtml b/themes/bootstrap3/templates/Recommend/SummonBestBetsDeferred.phtml
index 52acf074161dc152fd67284b523ade1bbe09de18..276d1da69e9c47db01d724e8d664ff27a97ecc2d 100644
--- a/themes/bootstrap3/templates/Recommend/SummonBestBetsDeferred.phtml
+++ b/themes/bootstrap3/templates/Recommend/SummonBestBetsDeferred.phtml
@@ -6,4 +6,4 @@
 <div id="SummonDeferredBestBets">
   <p><?=$this->transEsc("Loading")?>... <i class="fa fa-spinner" aria-hidden="true"></i></p>
   <?=$this->inlineScript(\Zend\View\Helper\HeadScript::SCRIPT, $loadJs, 'SET')?>
-</div>
\ No newline at end of file
+</div>
diff --git a/themes/bootstrap3/templates/Recommend/SummonDatabases.phtml b/themes/bootstrap3/templates/Recommend/SummonDatabases.phtml
index 507840f253d1ed4a9266f5c5ff48a3732988f5a0..2888ef723efbc220d02a78e439843c2ee84378a9 100644
--- a/themes/bootstrap3/templates/Recommend/SummonDatabases.phtml
+++ b/themes/bootstrap3/templates/Recommend/SummonDatabases.phtml
@@ -5,4 +5,4 @@
     <p><a href="<?=$this->escapeHtmlAttr($current['link'])?>"><?=$this->escapeHtml($current['title'])?></a><br/><?=$this->escapeHtml($current['description'])?></p>
   <? endforeach; ?>
 </div>
-<? endif; ?>
\ No newline at end of file
+<? endif; ?>
diff --git a/themes/bootstrap3/templates/Recommend/SummonDatabasesDeferred.phtml b/themes/bootstrap3/templates/Recommend/SummonDatabasesDeferred.phtml
index ef58352d86afaab2311699f5e6f40103a9a749cc..6d5270d39541a4d25179e8e05f2aa01881834550 100644
--- a/themes/bootstrap3/templates/Recommend/SummonDatabasesDeferred.phtml
+++ b/themes/bootstrap3/templates/Recommend/SummonDatabasesDeferred.phtml
@@ -6,4 +6,4 @@
 <div id="SummonDeferredDatabases">
   <p><?=$this->transEsc("Loading")?>... <i class="fa fa-spinner" aria-hidden="true"></i></p>
   <?=$this->inlineScript(\Zend\View\Helper\HeadScript::SCRIPT, $loadJs, 'SET')?>
-</div>
\ No newline at end of file
+</div>
diff --git a/themes/bootstrap3/templates/Recommend/SummonResults.phtml b/themes/bootstrap3/templates/Recommend/SummonResults.phtml
index b86702cb741a90e261187ef4b6eb02cea73562ad..0a539c4edf8db08fccb2a534b18e4ea1457a7431 100644
--- a/themes/bootstrap3/templates/Recommend/SummonResults.phtml
+++ b/themes/bootstrap3/templates/Recommend/SummonResults.phtml
@@ -19,4 +19,4 @@
     <? endforeach; ?>
     <a class="list-group-item" href="<?=$this->url($searchObject->getOptions()->getSearchAction()) . $searchObject->getUrlQuery()->setLimit($searchObject->getOptions()->getDefaultLimit())?>"><?=$this->transEsc('More Summon results')?>...</a>
   </div>
-<? endif ?>
\ No newline at end of file
+<? endif ?>
diff --git a/themes/bootstrap3/templates/Recommend/SummonResultsDeferred.phtml b/themes/bootstrap3/templates/Recommend/SummonResultsDeferred.phtml
index 991f8baa00e5b6c1142c298d343eef650f1a2cd0..49fff6ea945810962854eace729c824937a07512 100644
--- a/themes/bootstrap3/templates/Recommend/SummonResultsDeferred.phtml
+++ b/themes/bootstrap3/templates/Recommend/SummonResultsDeferred.phtml
@@ -7,4 +7,4 @@
   <h3><?=$this->transEsc("Summon Results")?></h3>
   <p><?=$this->transEsc("Loading")?>... <i class="fa fa-spinner" aria-hidden="true"></i></p>
   <?=$this->inlineScript(\Zend\View\Helper\HeadScript::SCRIPT, $loadJs, 'SET')?>
-</div>
\ No newline at end of file
+</div>
diff --git a/themes/bootstrap3/templates/Recommend/SummonTopics.phtml b/themes/bootstrap3/templates/Recommend/SummonTopics.phtml
index 076c8895617d1d2a1943e75eb9674d7deff45f1e..de7de6adfb92d0a955260e68b313a5fa42202cd9 100644
--- a/themes/bootstrap3/templates/Recommend/SummonTopics.phtml
+++ b/themes/bootstrap3/templates/Recommend/SummonTopics.phtml
@@ -15,4 +15,4 @@
     </p>
   <? endif; ?>
 </div>
-<? endif; ?>
\ No newline at end of file
+<? endif; ?>
diff --git a/themes/bootstrap3/templates/Recommend/SwitchQuery.phtml b/themes/bootstrap3/templates/Recommend/SwitchQuery.phtml
index c4b98e50976ddd55d7d218aa1c025f1156ccbabd..ea7bb52c81e595c8b676dec428c601660a937880 100644
--- a/themes/bootstrap3/templates/Recommend/SwitchQuery.phtml
+++ b/themes/bootstrap3/templates/Recommend/SwitchQuery.phtml
@@ -7,4 +7,4 @@
       <? endforeach; ?>
     </ul>
   </div>
-<? endif; ?>
\ No newline at end of file
+<? endif; ?>
diff --git a/themes/bootstrap3/templates/Recommend/SwitchTab.phtml b/themes/bootstrap3/templates/Recommend/SwitchTab.phtml
index 35541ccf4cf17a823c06fcfaf2e7d52c0c08229b..8a95b293c79c2a90583d846777079019efbc56f9 100644
--- a/themes/bootstrap3/templates/Recommend/SwitchTab.phtml
+++ b/themes/bootstrap3/templates/Recommend/SwitchTab.phtml
@@ -4,7 +4,7 @@
 ?>
 <? if (count($searchTabs) > 0): ?>
   <div class="alert alert-info">
-    <?=$this->transEsc('nohit_change_tab', array('%%activeTab%%' => $this->translate($this->recommend->getActiveTab($searchTabs)['label'])))?>
+    <?=$this->transEsc('nohit_change_tab', ['%%activeTab%%' => $this->translate($this->recommend->getActiveTab($searchTabs)['label'])])?>
     <ul>
     <? $inactiveTabs = $this->recommend->getInactiveTabs($searchTabs); ?>
     <? foreach ($inactiveTabs as $tab): ?>
diff --git a/themes/bootstrap3/templates/Recommend/SwitchType.phtml b/themes/bootstrap3/templates/Recommend/SwitchType.phtml
index 498fa27af08bf98f06d28be4f075ba25af7770f3..5c174ca1adc246ac81b7dab4c4aaf62d8cc074ba 100644
--- a/themes/bootstrap3/templates/Recommend/SwitchType.phtml
+++ b/themes/bootstrap3/templates/Recommend/SwitchType.phtml
@@ -3,4 +3,4 @@
     <?=$this->transEsc('widen_prefix')?>
     <a href="<?=$this->recommend->getResults()->getUrlQuery()->setHandler($handler)?>"><?=$this->transEsc($this->recommend->getNewHandlerName())?></a>.
   </div>
-<? endif; ?>
\ No newline at end of file
+<? endif; ?>
diff --git a/themes/bootstrap3/templates/Recommend/TopFacets.phtml b/themes/bootstrap3/templates/Recommend/TopFacets.phtml
index c35d26b21a80197d788d62e17354bb22534dc8ce..58ff1d326cea772f899be9de156a2b215b207be9 100644
--- a/themes/bootstrap3/templates/Recommend/TopFacets.phtml
+++ b/themes/bootstrap3/templates/Recommend/TopFacets.phtml
@@ -5,46 +5,48 @@
   $results = $this->recommend->getResults();
 ?>
 <? if (isset($topFacetSet)): ?>
-  <? $row=0; foreach($topFacetSet as $title => $cluster): ?>
+  <? foreach($topFacetSet as $title => $cluster): ?>
     <? $moreClass = ' NarrowGroupHidden_'.$this->escapeHtml($title).' hidden'; ?>
     <? $allowExclude = $this->recommend->excludeAllowed($title); ?>
-    <strong><?=$this->transEsc($cluster['label'])?></strong><?=$this->transEsc("top_facet_suffix") ?>
-    <div class="row top-row">
-    <? $iter=1;$corner=$topFacetSettings['rows']*$topFacetSettings['cols']; ?>
-    <? foreach($cluster['list'] as $thisFacet): ?>
-      <? /* More link */ ?>
-      <? if ($iter == $corner+1): ?>
-        </div><div id="more-NarrowGroupHidden_<?=$this->escapeHtml($title)?>" class="row top-row">
-          <span class="col-sm-12 narrow-toggle"><a href="#" onclick="moreFacets('NarrowGroupHidden_<?=$this->escapeHtml($title)?>'); return false;"><?=$this->transEsc('more') ?> ...</a></span>
-        </div><div class="row top-row <?=$moreClass ?>">
-      <? endif; ?>
-      <? /* Columns */ ?>
-      <span class="col-sm-<?=floor(12/$topFacetSettings['cols'])?><? if ($iter == $corner+1) echo $moreClass ?>">
-        <? if ($thisFacet['isApplied']):
-          if (isset($thisFacet['specialType']) && $thisFacet['specialType'] == 'keyword') {
-            $removeLink = $this->currentPath().$results->getUrlQuery()->replaceTerm($thisFacet['value'], '');
-          } else {
-            $removeLink = $this->currentPath().$results->getUrlQuery()->removeFacet($title, $thisFacet['value'], true, $thisFacet['operator']);
-          } ?>
-          <a href="<?=$removeLink ?>" class="applied">
-            <?=$this->escapeHtml($thisFacet['displayText'])?> <i class="fa fa-check" aria-hidden="true"></i>
-          </a>
-        <? else: ?>
-          <a href="<?=$this->currentPath().$results->getUrlQuery()->addFacet($title, $thisFacet['value'], $thisFacet['operator'])?>"><?=$this->escapeHtml($thisFacet['displayText'])?></a> <span class="badge"><?=$this->localizedNumber($thisFacet['count']) ?>
-          <? if ($allowExclude): ?>
-            <a href="<?=$this->currentPath().$results->getUrlQuery()->addFacet($title, $thisFacet['value'], 'NOT')?>" title="<?=$this->transEsc('exclude_facet')?>"><i class="fa fa-times" aria-hidden="true"></i></a>
+    <div class="top-facets">
+      <strong><?=$this->transEsc('top_facet_label', ['%%label%%' => $cluster['label']]) ?></strong><br />
+      <? $limit = $topFacetSettings['rows'] * $topFacetSettings['cols']; ?>
+      <? foreach($cluster['list'] as $index => $thisFacet): ?>
+        <span class="facet <?=$index > $limit ? $moreClass : '' ?>">
+          <? if ($thisFacet['isApplied']):
+            if (isset($thisFacet['specialType']) && $thisFacet['specialType'] == 'keyword') {
+              $removeLink = $this->currentPath().$results->getUrlQuery()->replaceTerm($thisFacet['value'], '');
+            } else {
+              $removeLink = $this->currentPath().$results->getUrlQuery()->removeFacet($title, $thisFacet['value'], $thisFacet['operator']);
+            } ?>
+            <a href="<?=$removeLink ?>" class="applied">
+              <?=$this->escapeHtml($thisFacet['displayText'])?> <i class="fa fa-check" aria-hidden="true"></i><!--
+         --></a>
+          <? else: ?>
+            <a href="<?=$this->currentPath().$results->getUrlQuery()->addFacet($title, $thisFacet['value'], $thisFacet['operator'])?>">
+              <?=$this->escapeHtml($thisFacet['displayText'])?><!--
+         --></a>
+            <span class="badge"><?=$this->localizedNumber($thisFacet['count']) ?>
+              <? if ($allowExclude): ?>
+                <a href="<?=$this->currentPath().$results->getUrlQuery()->addFacet($title, $thisFacet['value'], 'NOT')?>" title="<?=$this->transEsc('exclude_facet')?>"><i class="fa fa-times" aria-hidden="true"></i></a>
+              <? endif; ?>
+            </span>
           <? endif; ?>
+        </span>
+        <? /* More link */ ?>
+        <? if ($index == $limit): ?>
+          <span id="more-NarrowGroupHidden_<?=$this->escapeHtml($title)?>" class="narrow-toggle">
+            <a href="#" onclick="moreFacets('NarrowGroupHidden_<?=$this->escapeHtml($title)?>'); return false;">
+              <?=$this->transEsc('more') ?> ...
+            </a>
           </span>
         <? endif; ?>
-      </span>
-      <? /* Close rows */ ?>
-      <? if ($iter%$topFacetSettings['cols'] == 0 && $iter > 0): ?></div><div class="row top-row<? if(++$row > $topFacetSettings['rows']) echo $moreClass ?>"><? endif; ?>
-      <? /* Less link */ ?>
-      <? if (count($cluster['list']) > $corner && $iter == count($cluster['list'])): ?>
-        <a class="col-sm-12 narrow-toggle" href="#" onclick="lessFacets('NarrowGroupHidden_<?=$title ?>'); return false;"><?=$this->transEsc('less') ?> ...</a>
+      <? endforeach; ?>
+      <? if (count($cluster['list']) > $limit): ?>
+        <a class="narrow-toggle <?=$moreClass ?>" href="#" onclick="lessFacets('NarrowGroupHidden_<?=$title ?>'); return false;">
+          <?=$this->transEsc('less') ?> ...
+        </a>
       <? endif; ?>
-      <? $iter++; ?>
-    <? endforeach; ?>
     </div>
   <? endforeach; ?>
 <? endif; ?>
diff --git a/themes/bootstrap3/templates/Recommend/VisualFacets.phtml b/themes/bootstrap3/templates/Recommend/VisualFacets.phtml
index 38f748b184361cb12a0a9a42036c9c58f2c1ab17..9ef8e1e630da1929365d50f8056af15a48634002 100644
--- a/themes/bootstrap3/templates/Recommend/VisualFacets.phtml
+++ b/themes/bootstrap3/templates/Recommend/VisualFacets.phtml
@@ -4,16 +4,16 @@
   $visualFacetSet = $this->recommend->getPivotFacetSet();
 
   if (isset($visualFacetSet->children)) {
-    $flarechildren = array();
+    $flarechildren = [];
 
     foreach ($visualFacetSet->children as $toplevelfacet) {
-      $toplevelinfo = array();
-      $toplevelchildren = array();
+      $toplevelinfo = [];
+      $toplevelchildren = [];
       $toplevelinfo['name'] = $toplevelfacet['value'];
       $toplevelinfo['field'] = $toplevelfacet['field'];
       $toplevelinfo['size'] = $toplevelfacet['count'];
       foreach($toplevelfacet['pivot'] as $secondlevelfacet) {
-        $secondlevelinfo = array();
+        $secondlevelinfo = [];
         $secondlevelinfo['name'] = $secondlevelfacet['value'];
         $secondlevelinfo['size'] = $secondlevelfacet['count'];
         $secondlevelinfo['field'] = $secondlevelfacet['field'];
@@ -30,8 +30,7 @@
 
 <? if (isset($visualFacetSet)): ?>
   <script type="text/javascript">
-  <? $pivotdata = json_encode($visualFacetSet);
-  echo "var pivotdata = " . $pivotdata . ";"; ?>
+  var pivotdata = <?=json_encode($visualFacetSet);?>;
   jQuery(document).ready(function(data) {
   if (!d3.select("#visualResults").empty()) {
     $('.limitSelect').css('display', 'none');
diff --git a/themes/bootstrap3/templates/Recommend/WebResults.phtml b/themes/bootstrap3/templates/Recommend/WebResults.phtml
index 055b21a3617be2295913a250402992ca1e3b4a87..e72f1f5ed1c226b4f9bc45146106f83148811cc4 100644
--- a/themes/bootstrap3/templates/Recommend/WebResults.phtml
+++ b/themes/bootstrap3/templates/Recommend/WebResults.phtml
@@ -20,4 +20,4 @@
   </ul>
   <p><a href="<?=$this->url($searchObject->getOptions()->getSearchAction()) . $searchObject->getUrlQuery()->setLimit($searchObject->getOptions()->getDefaultLimit())?>"><?=$this->transEsc('Find More')?>...</a></p>
 </div>
-<? endif ?>
\ No newline at end of file
+<? endif ?>
diff --git a/themes/bootstrap3/templates/RecordDriver/EDS/core.phtml b/themes/bootstrap3/templates/RecordDriver/EDS/core.phtml
index 812ac1daa9edcedcbed94e9217b7056113f2e6b0..c686dd3bb8e1a38465228aaab7abe6f5c8a69702 100644
--- a/themes/bootstrap3/templates/RecordDriver/EDS/core.phtml
+++ b/themes/bootstrap3/templates/RecordDriver/EDS/core.phtml
@@ -8,14 +8,12 @@
     $accessLevel = $this->driver->getAccessLevel();
     $restrictedView = empty($accessLevel) ? false : true;
 ?>
-<div class="row" vocab="http://schema.org/" resource="#record" typeof="<?=$this->driver->getSchemaOrgFormats()?> Product">
-  <div class="col-sm-3 img-col">
+<div class="media" vocab="http://schema.org/" resource="#record" typeof="<?=$this->driver->getSchemaOrgFormats()?> Product">
+  <div class="media-left medium img-col">
     <? if ($thumb): ?>
-        <img src="<?=$this->escapeHtmlAttr($thumb)?>" class="recordcover" alt="<?=$this->transEsc('Cover Image')?>"/>
+      <img src="<?=$this->escapeHtmlAttr($thumb)?>" class="recordcover" alt="<?=$this->transEsc('Cover Image')?>"/>
     <? else: ?>
-      <div class="clearfix">
-        <span class="recordcover pt-icon pt-<?=$this->driver->getPubTypeId()?>"></span>
-      </div>
+      <span class="recordcover pt-icon pt-<?=$this->driver->getPubTypeId()?>"></span>
     <? endif; ?>
     <? if ($pubType): ?>
       <p><?=$this->transEsc($pubType)?></p>
@@ -47,7 +45,7 @@
       <? endif; ?>
     </div>
   </div>
-  <div class="col-sm-9 info-col">
+  <div class="media-body info-col">
     <h3 property="name"><?=$this->driver->getTitle()?></h3>
 
     <table class="table table-striped" summary="<?=$this->transEsc('Bibliographic Details')?>">
diff --git a/themes/bootstrap3/templates/RecordDriver/EDS/result-list.phtml b/themes/bootstrap3/templates/RecordDriver/EDS/result-list.phtml
index 8534df4198a271c5dedfdae02de610c35e14f743..65337cb47df032a9a6c5506eae11fbedf357a6e5 100644
--- a/themes/bootstrap3/templates/RecordDriver/EDS/result-list.phtml
+++ b/themes/bootstrap3/templates/RecordDriver/EDS/result-list.phtml
@@ -27,108 +27,110 @@
     <?=$thumbnail ?>
   <? endif; ?>
   <div class="media-body">
-    <div class="row short-view">
-      <div class="col-sm-8 middle">
-        <? $items = $this->driver->getItems();
-          if (isset($items) && !empty($items)):
-            foreach ($items as $item):
-              if (!empty($item)): ?>
-                <div class="resultItemLine1">
-                  <? if('Ti' == $item['Group']): ?>
-                    <a href="<?=$this->recordLink()->getUrl($this->driver)?>" class="title getFull _record_link"  data-view="<?=$this->params->getOptions()->getListViewOption()?>">
-                    <?=$item['Data']?> </a>
-                  <? else:?>
-                    <p>
-                      <b><?=$this->transEsc($item['Label'])?>:</b>
-                      <?=$item['Data']?>
-                    </p>
-                  <? endif;?>
-                </div>
-              <? endif;
-            endforeach;
-          elseif ($restrictedView): ?>
-            <div class="resultItemLine1">
-              <p>
-                <?=$this->transEsc('This result is not displayed to guests')?>
-                <br />
-                <a class="login" href="<?=$this->url('myresearch-home')?>">
-                  <strong><?=$this->transEsc('Login for full access')?></strong>
-                </a>
-              </p>
-            </div>
-          <? endif; ?>
-
-        <div class="resultItemLine4 custom-links">
-          <? $customLinks = array_merge($this->driver->getFTCustomLinks(), $this->driver->getCustomLinks());
-          if (!empty($customLinks)): ?>
-            <? foreach ($customLinks as $customLink): ?>
-            <? $url = isset($customLink['Url']) ? $customLink['Url'] : '';
-                $mot = isset($customLink['MouseOverText'])? $customLink['MouseOverText'] : '';
-                $icon = isset ($customLink['Icon']) ? $customLink['Icon'] : '';
-                $name = isset($customLink['Text']) ? $customLink['Text'] : '';
-            ?>
-            <span>
-              <a href="<?=$this->escapeHtmlAttr($url)?>" target="_blank" title="<?=$this->escapeHtmlAttr($mot)?>" class="custom-link">
-                <? if ($icon): ?><img src="<?=$this->escapeHtmlAttr($icon)?>" /> <? endif; ?><?=$this->escapeHtml($name)?>
+    <div class="result-body">
+      <? $items = $this->driver->getItems();
+        if (isset($items) && !empty($items)):
+          foreach ($items as $item):
+            if (!empty($item)): ?>
+              <div class="resultItemLine1">
+                <? if('Ti' == $item['Group']): ?>
+                  <a href="<?=$this->recordLink()->getUrl($this->driver)?>" class="title getFull _record_link"  data-view="<?=$this->params->getOptions()->getListViewOption()?>">
+                  <?=$item['Data']?> </a>
+                <? else:?>
+                  <p>
+                    <b><?=$this->transEsc($item['Label'])?>:</b>
+                    <?=$item['Data']?>
+                  </p>
+                <? endif;?>
+              </div>
+            <? endif;
+          endforeach;
+        elseif ($restrictedView): ?>
+          <div class="resultItemLine1">
+            <p>
+              <?=$this->transEsc('This result is not displayed to guests')?>
+              <br />
+              <a class="login" href="<?=$this->url('myresearch-home')?>">
+                <strong><?=$this->transEsc('Login for full access')?></strong>
               </a>
-            </span>
-            <? endforeach; ?>
-          <? endif; ?>
-        </div>
-
-        <? if ($this->driver->hasHTMLFullTextAvailable()): ?>
-          <a href="<?= $this->recordLink()->getUrl($this->driver, 'fulltext') ?>#html" class="icon html fulltext _record_link" target="_blank">
-            <?=$this->transEsc('HTML Full Text')?>
-          </a>
-          &nbsp; &nbsp;
+            </p>
+          </div>
         <? endif; ?>
 
-        <? if ($this->driver->hasPdfAvailable()): ?>
-          <a href="<?= $this->recordLink()->getUrl($this->driver).'/PDF'; ?>" class="icon pdf fulltext" target="_blank">
-            <?=$this->transEsc('PDF Full Text')?>
-          </a>
-        <? endif; ?>
-      </div>
-      <div class="col-sm-4 right hidden-print">
-        <? /* Display qrcode if appropriate: */ ?>
-        <? if ($QRCode = $this->record($this->driver)->getQRCode("results")): ?>
-          <?
-            // Add JS Variables for QrCode
-            $this->jsTranslations()->addStrings(array('qrcode_hide' => 'qrcode_hide', 'qrcode_show' => 'qrcode_show'));
+      <div class="resultItemLine4 custom-links">
+        <? $customLinks = array_merge($this->driver->getFTCustomLinks(), $this->driver->getCustomLinks());
+        if (!empty($customLinks)): ?>
+          <? foreach ($customLinks as $customLink): ?>
+          <? $url = isset($customLink['Url']) ? $customLink['Url'] : '';
+              $mot = isset($customLink['MouseOverText'])? $customLink['MouseOverText'] : '';
+              $icon = isset ($customLink['Icon']) ? $customLink['Icon'] : '';
+              $name = isset($customLink['Text']) ? $customLink['Text'] : '';
           ?>
-          <span class="hidden-xs">
-            <i class="fa fa-fw fa-qrcode" aria-hidden="true"></i> <a href="<?=$this->escapeHtmlAttr($QRCode);?>" class="qrcodeLink"><?=$this->transEsc('qrcode_show')?></a>
-            <div class="qrcode hidden">
-              <script type="text/template" class="qrCodeImgTag">
-                <img alt="<?=$this->transEsc('QR Code')?>" src="<?=$this->escapeHtmlAttr($QRCode);?>"/>
-              </script>
-            </div><br/>
+          <span>
+            <a href="<?=$this->escapeHtmlAttr($url)?>" target="_blank" title="<?=$this->escapeHtmlAttr($mot)?>" class="custom-link">
+              <? if ($icon): ?><img src="<?=$this->escapeHtmlAttr($icon)?>" /> <? endif; ?><?=$this->escapeHtml($name)?>
+            </a>
           </span>
+          <? endforeach; ?>
         <? endif; ?>
+      </div>
 
-        <? if ($this->userlist()->getMode() !== 'disabled'): ?>
-          <? /* Add to favorites */ ?>
-          <i class="fa fa-fw fa-star" aria-hidden="true"></i> <a href="<?=$this->recordLink()->getActionUrl($this->driver, 'Save')?>" class="save-record" data-lightbox id="<?=$this->driver->getUniqueId() ?>" title="<?=$this->transEsc('Add to favorites')?>"><?=$this->transEsc('Add to favorites')?></a><br/>
+      <? if ($this->driver->hasHTMLFullTextAvailable()): ?>
+        <a href="<?= $this->recordLink()->getUrl($this->driver, 'fulltext') ?>#html" class="icon html fulltext _record_link" target="_blank">
+          <?=$this->transEsc('HTML Full Text')?>
+        </a>
+        &nbsp; &nbsp;
+      <? endif; ?>
 
-          <? /* Saved lists */ ?>
-          <div class="savedLists alert alert-info hidden">
-            <strong><?=$this->transEsc("Saved in")?>:</strong>
-          </div>
-        <? endif; ?>
+      <? if ($this->driver->hasPdfAvailable()): ?>
+        <a href="<?= $this->recordLink()->getUrl($this->driver).'/PDF'; ?>" class="icon pdf fulltext" target="_blank">
+          <?=$this->transEsc('PDF Full Text')?>
+        </a>
+      <? endif; ?>
+    </div>
+    <div class="result-links hidden-print">
+      <? /* Display qrcode if appropriate: */ ?>
+      <? if ($QRCode = $this->record($this->driver)->getQRCode("results")): ?>
+        <?
+          // Add JS Variables for QrCode
+          $this->jsTranslations()->addStrings(array('qrcode_hide' => 'qrcode_hide', 'qrcode_show' => 'qrcode_show'));
+        ?>
+        <span class="hidden-xs">
+          <i class="fa fa-fw fa-qrcode" aria-hidden="true"></i> <a href="<?=$this->escapeHtmlAttr($QRCode);?>" class="qrcodeLink"><?=$this->transEsc('qrcode_show')?></a>
+          <div class="qrcode hidden">
+            <script type="text/template" class="qrCodeImgTag">
+              <img alt="<?=$this->transEsc('QR Code')?>" src="<?=$this->escapeHtmlAttr($QRCode);?>"/>
+            </script>
+          </div><br/>
+        </span>
+      <? endif; ?>
 
-        <? /* Hierarchy tree link */ ?>
-        <? $trees = $this->driver->tryMethod('getHierarchyTrees'); if (!empty($trees)): ?>
-          <? foreach ($trees as $hierarchyID => $hierarchyTitle): ?>
-            <div class="hierarchyTreeLink">
-              <input type="hidden" value="<?=$this->escapeHtmlAttr($hierarchyID)?>" class="hiddenHierarchyId" />
-              <i class="fa fa-fw fa-sitemap" aria-hidden="true"></i>
-              <a class="hierarchyTreeLinkText" data-lightbox href="<?=$this->recordLink()->getTabUrl($this->driver, 'HierarchyTree')?>?hierarchy=<?=urlencode($hierarchyID)?>#tabnav" title="<?=$this->transEsc('hierarchy_tree')?>">
-                <?=$this->transEsc('hierarchy_view_context')?><? if (count($trees) > 1): ?>: <?=$this->escapeHtml($hierarchyTitle)?><? endif; ?>
-              </a>
-            </div>
-          <? endforeach; ?>
-        <? endif; ?>
-      </div>
+      <? if ($this->cart()->isActiveInSearch() && $this->params->getOptions()->supportsCart() && $this->cart()->isActive()): ?>
+        <?=$this->render('record/cart-buttons.phtml', ['id' => $this->driver->getUniqueId(), 'source' => $this->driver->getSourceIdentifier()]); ?><br/>
+      <? endif; ?>
+
+      <? if ($this->userlist()->getMode() !== 'disabled'): ?>
+        <? /* Add to favorites */ ?>
+        <i class="fa fa-fw fa-star" aria-hidden="true"></i> <a href="<?=$this->recordLink()->getActionUrl($this->driver, 'Save')?>" class="save-record" data-lightbox id="<?=$this->driver->getUniqueId() ?>" title="<?=$this->transEsc('Add to favorites')?>"><?=$this->transEsc('Add to favorites')?></a><br/>
+
+        <? /* Saved lists */ ?>
+        <div class="savedLists alert alert-info hidden">
+          <strong><?=$this->transEsc("Saved in")?>:</strong>
+        </div>
+      <? endif; ?>
+
+      <? /* Hierarchy tree link */ ?>
+      <? $trees = $this->driver->tryMethod('getHierarchyTrees'); if (!empty($trees)): ?>
+        <? foreach ($trees as $hierarchyID => $hierarchyTitle): ?>
+          <div class="hierarchyTreeLink">
+            <input type="hidden" value="<?=$this->escapeHtmlAttr($hierarchyID)?>" class="hiddenHierarchyId" />
+            <i class="fa fa-fw fa-sitemap" aria-hidden="true"></i>
+            <a class="hierarchyTreeLinkText" data-lightbox href="<?=$this->recordLink()->getTabUrl($this->driver, 'HierarchyTree')?>?hierarchy=<?=urlencode($hierarchyID)?>#tabnav" title="<?=$this->transEsc('hierarchy_tree')?>">
+              <?=$this->transEsc('hierarchy_view_context')?><? if (count($trees) > 1): ?>: <?=$this->escapeHtml($hierarchyTitle)?><? endif; ?>
+            </a>
+          </div>
+        <? endforeach; ?>
+      <? endif; ?>
     </div>
   </div>
   <? if ($thumbnail && $thumbnailAlignment == 'right'): ?>
diff --git a/themes/bootstrap3/templates/RecordDriver/Pazpar2/link-author.phtml b/themes/bootstrap3/templates/RecordDriver/Pazpar2/link-author.phtml
index 34ec85e9849867608a0a901e72ab8ff8f452cfe1..3f0d870b7d0a693f8d9a2e5bb81216da338e2bee 100644
--- a/themes/bootstrap3/templates/RecordDriver/Pazpar2/link-author.phtml
+++ b/themes/bootstrap3/templates/RecordDriver/Pazpar2/link-author.phtml
@@ -1 +1 @@
-<?=$this->url('pazpar2-search')?>?lookfor=<?=urlencode($this->lookfor)?>&amp;type=author
\ No newline at end of file
+<?=$this->url('pazpar2-search')?>?lookfor=<?=urlencode($this->lookfor)?>&amp;type=author
diff --git a/themes/bootstrap3/templates/RecordDriver/Pazpar2/link-series.phtml b/themes/bootstrap3/templates/RecordDriver/Pazpar2/link-series.phtml
index 203012a0d1e20fd416074e7aeabf72b45f06f3c5..46c47c4ec8d03dd9870963599e56ade19bcb1191 100644
--- a/themes/bootstrap3/templates/RecordDriver/Pazpar2/link-series.phtml
+++ b/themes/bootstrap3/templates/RecordDriver/Pazpar2/link-series.phtml
@@ -1 +1 @@
-<?=$this->url('pazpar2-search')?>?lookfor=%22<?=urlencode($this->lookfor)?>%22&amp;type=series
\ No newline at end of file
+<?=$this->url('pazpar2-search')?>?lookfor=%22<?=urlencode($this->lookfor)?>%22&amp;type=series
diff --git a/themes/bootstrap3/templates/RecordDriver/Pazpar2/link-subject.phtml b/themes/bootstrap3/templates/RecordDriver/Pazpar2/link-subject.phtml
index 12428b058b52d3d15abe04107fd9a063b3d719b6..746f384808ee90b0c8f979849e98d66fa870ae2f 100644
--- a/themes/bootstrap3/templates/RecordDriver/Pazpar2/link-subject.phtml
+++ b/themes/bootstrap3/templates/RecordDriver/Pazpar2/link-subject.phtml
@@ -1 +1 @@
-<?=$this->url('pazpar2-search')?>?lookfor=%22<?=urlencode($this->lookfor)?>%22&amp;type=subject
\ No newline at end of file
+<?=$this->url('pazpar2-search')?>?lookfor=%22<?=urlencode($this->lookfor)?>%22&amp;type=subject
diff --git a/themes/bootstrap3/templates/RecordDriver/Pazpar2/link-title.phtml b/themes/bootstrap3/templates/RecordDriver/Pazpar2/link-title.phtml
index f0f81ef686c85302fd1beb62b9e565bd305602f7..c3ba934b4a666eb6fd8ee866535c4515e069128e 100644
--- a/themes/bootstrap3/templates/RecordDriver/Pazpar2/link-title.phtml
+++ b/themes/bootstrap3/templates/RecordDriver/Pazpar2/link-title.phtml
@@ -1 +1 @@
-<?=$this->url('pazpar2-search')?>?lookfor=%22<?=urlencode($this->lookfor)?>%22&amp;type=title
\ No newline at end of file
+<?=$this->url('pazpar2-search')?>?lookfor=%22<?=urlencode($this->lookfor)?>%22&amp;type=title
diff --git a/themes/bootstrap3/templates/RecordDriver/Pazpar2/result-list.phtml b/themes/bootstrap3/templates/RecordDriver/Pazpar2/result-list.phtml
index f59217ae4f1620d3ae424252880b6b2fa82976dc..c11935a4fca558dee7043aa1911ea260b027c3be 100644
--- a/themes/bootstrap3/templates/RecordDriver/Pazpar2/result-list.phtml
+++ b/themes/bootstrap3/templates/RecordDriver/Pazpar2/result-list.phtml
@@ -94,14 +94,19 @@
         <? endif; ?>
       <? endif; ?>
 
-      <?=$this->record($this->driver)->getFormatList() ?>
+      <div class="result-formats">
+        <?=$this->record($this->driver)->getFormatList() ?>
 
-      <? if (!$openUrlActive && empty($urls) && $this->driver->supportsAjaxStatus()): ?>
-        <span class="status ajax-availability small">
-          <span class="label label-default"><?=$this->transEsc('Loading')?>...</span>
-        </span>
-      <? endif; ?>
-      <?=$this->record($this->driver)->getPreviews()?>
+        <? if (!$openUrlActive && empty($urls) && $this->driver->supportsAjaxStatus()): ?>
+          <span class="status ajax-availability small">
+            <span class="label label-default"><?=$this->transEsc('Loading')?>...</span>
+          </span>
+        <? endif; ?>
+      </div>
+
+      <div class="result-previews">
+        <?=$this->record($this->driver)->getPreviews()?>
+      </div>
 
       <?=$this->driver->supportsCoinsOpenUrl()?'<span class="Z3988" title="'.$this->escapeHtmlAttr($this->driver->getCoinsOpenUrl()).'"></span>':''?>
     </div>
diff --git a/themes/bootstrap3/templates/RecordDriver/Primo/format-class.phtml b/themes/bootstrap3/templates/RecordDriver/Primo/format-class.phtml
index 6702f4f504060de147dca96d74fd5cae34f5f159..a035c93fc8fb4cb01000f71449640b679aa417ba 100644
--- a/themes/bootstrap3/templates/RecordDriver/Primo/format-class.phtml
+++ b/themes/bootstrap3/templates/RecordDriver/Primo/format-class.phtml
@@ -44,4 +44,4 @@
           echo 'journal';
           break;
   }
-?>
\ No newline at end of file
+?>
diff --git a/themes/bootstrap3/templates/RecordDriver/Primo/link-journaltitle.phtml b/themes/bootstrap3/templates/RecordDriver/Primo/link-journaltitle.phtml
index 5b35541ccd0bd6e546408aa741d6e98c27ac9424..53c0b8e446a32e6d263223245e5172909961ce80 100644
--- a/themes/bootstrap3/templates/RecordDriver/Primo/link-journaltitle.phtml
+++ b/themes/bootstrap3/templates/RecordDriver/Primo/link-journaltitle.phtml
@@ -1 +1 @@
-<?=$this->url('primo-search')?>?lookfor=%22<?=urlencode($this->lookfor)?>%22&amp;type=AllFields
\ No newline at end of file
+<?=$this->url('primo-search')?>?lookfor=%22<?=urlencode($this->lookfor)?>%22&amp;type=AllFields
diff --git a/themes/bootstrap3/templates/RecordDriver/Primo/link-title.phtml b/themes/bootstrap3/templates/RecordDriver/Primo/link-title.phtml
index 863c2e40063faf1c2a2774906a506eca80dd4a74..19a5b20d85b92e3a1520dac32bbf9287397bc374 100644
--- a/themes/bootstrap3/templates/RecordDriver/Primo/link-title.phtml
+++ b/themes/bootstrap3/templates/RecordDriver/Primo/link-title.phtml
@@ -1 +1 @@
-<?=$this->url('primo-search')?>?lookfor=%22<?=urlencode($this->lookfor)?>%22&amp;type=Title
\ No newline at end of file
+<?=$this->url('primo-search')?>?lookfor=%22<?=urlencode($this->lookfor)?>%22&amp;type=Title
diff --git a/themes/bootstrap3/templates/RecordDriver/SolrDefault/collection-info.phtml b/themes/bootstrap3/templates/RecordDriver/SolrDefault/collection-info.phtml
index fd5bc8a049f822c75f28764fb97c15858e32c260..a88aeba6e005f11cfa3f4ca4dd74dd45d4d513d5 100644
--- a/themes/bootstrap3/templates/RecordDriver/SolrDefault/collection-info.phtml
+++ b/themes/bootstrap3/templates/RecordDriver/SolrDefault/collection-info.phtml
@@ -1,11 +1,13 @@
 <? $this->headScript()->appendFile('collection_record.js'); ?>
-<div class="row">
-  <? $QRCode = $this->record($this->driver)->getQRCode("core");
-     $cover = $this->record($this->driver)->getCover('collection-info', 'medium', $this->record($this->driver)->getThumbnail('large'));
-     $preview = $this->record($this->driver)->getPreviews(); ?>
+<div class="media">
+  <?
+    $QRCode = $this->record($this->driver)->getQRCode("core");
+    $coverDetails = $this->record($this->driver)->getCoverDetails('collection-info', 'medium', $this->record($this->driver)->getThumbnail('large'));
+    $cover = $coverDetails['html'];
+    $preview = $this->record($this->driver)->getPreviews();
+  ?>
   <? if ($QRCode || $cover || $preview): ?>
-  <div class="col-sm-3">
-    <div class="text-center">
+    <div class="media-left <?=$this->escapeHtmlAttr($coverDetails['size'])?>">
       <? /* Display thumbnail if appropriate: */ ?>
       <? if($cover): ?>
         <?=$cover?>
@@ -17,15 +19,11 @@
           <br/><img alt="<?=$this->transEsc('QR Code')?>" class="qrcode" src="<?=$this->escapeHtmlAttr($QRCode);?>"/>
         </span>
       <? endif; ?>
-    </div>
-
-    <? if ($preview): ?><?=$preview?><? endif; ?>
-  </div>
 
-  <div class="col-sm-6">
-  <? else: ?>
-  <div class="col-sm-9">
+      <? if ($preview): ?><?=$preview?><? endif; ?>
+    </div>
   <? endif; ?>
+  <div class="media-body">
 
     <h2><?=$this->escapeHtml($this->driver->getShortTitle() . ' ' . $this->driver->getSubtitle() . ' ' . $this->driver->getTitleSection())?></h2>
 
@@ -35,191 +33,23 @@
     <? endif; ?>
 
     <? /* Display the lists that this record is saved to */ ?>
-    <div class="savedLists hidden alert alert-info" id="savedLists">
+    <div class="savedLists" id="savedLists">
       <strong><?=$this->transEsc("Saved in")?>:</strong>
     </div>
 
     <a id="moreInfoToggle" href="#" class="hidden"><?=$this->transEsc('more_info_toggle')?></a>
     <?/* Display Main Details */?>
-    <table id="collectionInfo" class="table table-striped" summary="<?=$this->transEsc('Bibliographic Details')?>">
-      <? $authors = $this->driver->getDeduplicatedAuthors(); ?>
-      <? if (isset($authors['main']) && !empty($authors['main'])): ?>
-      <tr>
-        <th><?=$this->transEsc(count($authors['main']) > 1 ? 'Main Authors' : 'Main Author')?>: </th>
-        <td>
-          <? $i = 0; foreach ($authors['main'] as $author => $roles): ?><?=($i++ == 0)?'':', '?><a href="<?=$this->record($this->driver)->getLink('author', $author)?>"><?=$this->escapeHtml($author)?></a><? if (count($roles) > 0): ?> (<? $j = 0; foreach ($roles as $role): ?><?=($j++ == 0)?'':', '?><?=$this->transEsc("CreatorRoles::" . $role)?><? endforeach; ?>)<? endif; ?><? endforeach; ?>
-        </td>
-      </tr>
-      <? endif; ?>
-
-      <? if (isset($authors['corporate']) && !empty($authors['corporate'])): ?>
-      <tr>
-        <th><?=$this->transEsc(count($authors['corporate']) > 1 ? 'Corporate Author' : 'Corporate Authors')?>: </th>
-        <td>
-          <? $i = 0; foreach ($authors['corporate'] as $corporate => $roles): ?><?=($i++ == 0)?'':', '?><a href="<?=$this->record($this->driver)->getLink('author', $corporate)?>"><?=$this->escapeHtml($corporate)?></a><? if (count($roles) > 0): ?> (<? $j = 0; foreach ($roles as $role): ?><?=($j++ == 0)?'':', '?><?=$this->transEsc("CreatorRoles::" . $role)?><? endforeach; ?>)<? endif; ?><? endforeach; ?>
-        </td>
-      </tr>
-      <? endif; ?>
-
-      <? if (isset($authors['secondary']) && !empty($authors['secondary'])): ?>
-      <tr>
-        <th><?=$this->transEsc('Other Authors')?>: </th>
-        <td>
-          <? $i = 0; foreach ($authors['secondary'] as $author => $roles): ?><?=($i++ == 0)?'':', '?><a href="<?=$this->record($this->driver)->getLink('author', $author)?>"><?=$this->escapeHtml($author)?></a><? if (count($roles) > 0): ?> (<? $j = 0; foreach ($roles as $role): ?><?=($j++ == 0)?'':', '?><?=$this->transEsc("CreatorRoles::" . $role)?><? endforeach; ?>)<? endif; ?><? endforeach; ?>
-        </td>
-      </tr>
-      <? endif; ?>
-
-      <? if (count($summary) > 1): ?>
-        <tr>
-          <th><?=$this->transEsc('Summary')?>: </th>
-          <td>
-            <? foreach (array_slice($summary, 1) as $field): ?>
-              <?=$this->escapeHtml($field)?><br/>
-            <? endforeach; ?>
-          </td>
-        </tr>
-      <? endif; ?>
-
-      <? $formats = $this->driver->getFormats(); if (!empty($formats)): ?>
-        <tr>
-          <th><?=$this->transEsc('Format')?>: </th>
-          <td><?=$this->record($this->driver)->getFormatList()?></td>
-        </tr>
-      <? endif; ?>
-
-      <? $langs = $this->driver->getLanguages(); if (!empty($langs)): ?>
-        <tr>
-          <th><?=$this->transEsc('Language')?>: </th>
-          <td><? foreach ($langs as $lang): ?><?= $this->escapeHtml($lang)?><br/><? endforeach; ?></td>
-        </tr>
-      <? endif; ?>
-
-      <? $publications = $this->driver->getPublicationDetails(); if (!empty($publications)): ?>
-      <tr>
-        <th><?=$this->transEsc('Published')?>: </th>
-        <td>
-          <? foreach ($publications as $field): ?>
-            <?=$this->escapeHtml($field)?><br/>
-          <? endforeach; ?>
-        </td>
-      </tr>
-      <? endif; ?>
-
-      <? $edition = $this->driver->getEdition(); if (!empty($edition)): ?>
-      <tr>
-        <th><?=$this->transEsc('Edition')?>: </th>
-        <td><?=$this->escapeHtml($edition)?></td>
-      </tr>
-      <? endif; ?>
-
-      <?/* Display series section if at least one series exists. */?>
-      <? $series = $this->driver->getSeries(); if (!empty($series)): ?>
-      <tr>
-        <th><?=$this->transEsc('Series')?>: </th>
-        <td>
-          <? foreach ($series as $field): ?>
-            <?/* Depending on the record driver, $field may either be an array with
-               "name" and "number" keys or a flat string containing only the series
-               name.  We should account for both cases to maximize compatibility. */?>
-            <? if (is_array($field)): ?>
-              <? if (!empty($field['name'])): ?>
-                <a href="<?=$this->record($this->driver)->getLink('series', $field['name'])?>"><?=$this->escapeHtml($field['name'])?></a>
-                <? if (!empty($field['number'])): ?>
-                  <?=$this->escapeHtml($field['number'])?>
-                <? endif; ?>
-                <br/>
-              <? endif; ?>
-            <? else: ?>
-              <a href="<?=$this->record($this->driver)->getLink('series', $field)?>"><?=$this->escapeHtml($field)?></a><br/>
-            <? endif; ?>
-          <? endforeach; ?>
-        </td>
-      </tr>
-      <? endif; ?>
-
-      <? $subjects = $this->driver->getAllSubjectHeadings(); if (!empty($subjects)): ?>
-      <tr>
-        <th><?=$this->transEsc('Subjects')?>: </th>
-        <td>
-          <? foreach ($subjects as $field): ?>
-          <div class="subjectLine">
-            <? $subject = ''; ?>
-            <? $i = 0; foreach ($field as $subfield): ?>
-              <?=($i++ == 0) ? '' : ' &gt; '?>
-              <? $subject = trim($subject . ' ' . $subfield); ?>
-              <a title="<?=$this->escapeHtmlAttr($subject)?>" href="<?=$this->record($this->driver)->getLink('subject', $subject)?>" class="subjectHeading" rel="nofollow"><?=$this->escapeHtml($subfield)?></a>
-            <? endforeach; ?>
-          </div>
-          <? endforeach; ?>
-        </td>
-      </tr>
-      <? endif; ?>
-
-      <?
-        $openUrl = $this->openUrl($this->driver, 'record');
-        $openUrlActive = $openUrl->isActive();
-        // Account for replace_other_urls setting
-        $urls = $this->record($this->driver)->getLinkDetails($openUrlActive);
-      ?>
-      <? if (!empty($urls) || $openUrlActive): ?>
-      <tr>
-        <th><?=$this->transEsc('Online Access')?>: </th>
-        <td>
-          <? foreach ($urls as $current): ?>
-            <a href="<?=$this->escapeHtmlAttr($this->proxyUrl($current['url']))?>"><?=$this->escapeHtml($current['desc'])?></a><br/>
-          <? endforeach; ?>
-          <? if ($openUrlActive): ?>
-            <?=$openUrl->renderTemplate()?><br/>
-          <? endif; ?>
-        </td>
-      </tr>
-      <? endif; ?>
-
-      <? $notes = $this->driver->getGeneralNotes(); if (!empty($notes)): ?>
-        <tr>
-          <th><?=$this->transEsc('Notes')?>: </th>
-          <td>
-            <? foreach ($notes as $field): ?>
-              <?=$this->escapeHtml($field)?><br/>
-            <? endforeach; ?>
-          </td>
-        </tr>
-      <? endif; ?>
-
-      <? $credits = $this->driver->getProductionCredits(); if (!empty($credits)): ?>
-        <tr>
-          <th><?=$this->transEsc('Production Credits')?>: </th>
-          <td>
-            <? foreach ($credits as $field): ?>
-              <?=$this->escapeHtml($field)?><br/>
-            <? endforeach; ?>
-          </td>
-        </tr>
-      <? endif; ?>
-
-      <? $isbns = $this->driver->getISBNs(); if (!empty($isbns)): ?>
-        <tr>
-          <th><?=$this->transEsc('ISBN')?>: </th>
-          <td>
-            <? foreach ($isbns as $field): ?>
-              <?=$this->escapeHtml($field)?><br/>
-            <? endforeach; ?>
-          </td>
-        </tr>
-      <? endif; ?>
-
-      <? $issns = $this->driver->getISSNs(); if (!empty($issns)): ?>
-        <tr>
-          <th><?=$this->transEsc('ISSN')?>: </th>
-          <td>
-            <? foreach ($issns as $field): ?>
-              <?=$this->escapeHtml($field)?><br/>
-            <? endforeach; ?>
-          </td>
-        </tr>
-      <? endif; ?>
-    </table>
+    <?
+      $formatter = $this->recordDataFormatter();
+      $fields = $formatter->getData($driver, $formatter->getDefaults('collection-info'));
+    ?>
+    <? if (!empty($fields)): ?>
+      <table id="collectionInfo" class="table table-striped" summary="<?=$this->transEsc('Bibliographic Details')?>">
+        <? foreach ($fields as $key => $current): ?>
+          <tr><th><?=$this->transEsc($key)?>:</th><td><?=$current['value']?></td></tr>
+        <? endforeach; ?>
+      </table>
+    <? endif; ?>
     <?/* End Main Details */?>
   </div>
 </div>
diff --git a/themes/bootstrap3/templates/RecordDriver/SolrDefault/collection-record.phtml b/themes/bootstrap3/templates/RecordDriver/SolrDefault/collection-record.phtml
index 528895de85d1f9049147d7e19040fdb1679be759..64ce05a7b5dcbde529a8202366bbc2d785f7ad27 100644
--- a/themes/bootstrap3/templates/RecordDriver/SolrDefault/collection-record.phtml
+++ b/themes/bootstrap3/templates/RecordDriver/SolrDefault/collection-record.phtml
@@ -1,67 +1,14 @@
 <h2><?=$this->escapeHtml($this->driver->getShortTitle() . ' ' . $this->driver->getSubtitle() . ' ' . $this->driver->getTitleSection())?></h2>
 <a href="<?=$this->recordLink()->getUrl($this->driver)?>"><?=$this->transEsc('View Full ' . ($this->driver->isCollection() ? 'Collection' : 'Record'))?></a>
 
-<table class="table table-striped" summary="<?=$this->transEsc('Bibliographic Details')?>">
-  <? $summary = $this->driver->getSummary(); $summary = isset($summary[0]) ? $summary[0] : false; ?>
-  <? if ($summary): ?>
-    <tr valign="top">
-      <th><?=$this->transEsc('Description')?>: </th>
-      <td><?=$this->escapeHtml($summary)?></td>
-    </tr>
-  <? endif; ?>
-
-  <? $authors = $this->driver->getDeduplicatedAuthors(); ?>
-  <? if (isset($authors['main']) && !empty($authors['main'])): ?>
-    <tr valign="top">
-      <th><?=$this->transEsc(count($authors['main']) > 1 ? 'Main Authors' : 'Main Author')?>: </th>
-      <td>
-        <? $i = 0; foreach ($authors['main'] as $author => $roles): ?><?=($i++ == 0)?'':', '?><a href="<?=$this->record($this->driver)->getLink('author', $author)?>"><?=$this->escapeHtml($author)?></a><? if (count($roles) > 0): ?> (<? $j = 0; foreach ($roles as $role): ?><?=($j++ == 0)?'':', '?><?=$this->transEsc("CreatorRoles::" . $role)?><? endforeach; ?>)<? endif; ?><? endforeach; ?>
-      </td>
-    </tr>
-  <? endif; ?>
-
-  <? if (isset($authors['corporate']) && !empty($authors['corporate'])): ?>
-    <tr valign="top">
-      <th><?=$this->transEsc(count($authors['corporate']) > 1 ? 'Corporate Author' : 'Corporate Authors')?>: </th>
-      <td>
-        <? $i = 0; foreach ($authors['corporate'] as $corporate => $roles): ?><?=($i++ == 0)?'':', '?><a href="<?=$this->record($this->driver)->getLink('author', $corporate)?>"><?=$this->escapeHtml($corporate)?></a><? if (count($roles) > 0): ?> (<? $j = 0; foreach ($roles as $role): ?><?=($j++ == 0)?'':', '?><?=$this->transEsc("CreatorRoles::" . $role)?><? endforeach; ?>)<? endif; ?><? endforeach; ?>
-      </td>
-    </tr>
-  <? endif; ?>
-
-  <? $langs = $this->driver->getLanguages(); if (!empty($langs)): ?>
-    <tr valign="top">
-      <th><?=$this->transEsc('Language')?>: </th>
-      <td><? foreach ($langs as $lang): ?><?= $this->escapeHtml($lang)?><br/><? endforeach; ?></td>
-    </tr>
-  <? endif; ?>
-
-  <? $formats = $this->driver->getFormats(); if (!empty($formats)): ?>
-    <tr valign="top">
-      <th><?=$this->transEsc('Format')?>: </th>
-      <td><?=$this->record($this->driver)->getFormatList()?></td>
-    </tr>
-  <? endif; ?>
-
-  <? $access = $this->driver->getAccessRestrictions(); if (!empty($access)): ?>
-    <tr valign="top">
-      <th><?=$this->transEsc('Access')?>: </th>
-      <td>
-        <? foreach ($access as $field): ?>
-          <?=$this->escapeHtml($field)?><br/>
-        <? endforeach; ?>
-      </td>
-    </tr>
-  <? endif; ?>
-
-  <? $related = $this->driver->getRelationshipNotes(); if (!empty($related)): ?>
-    <tr valign="top">
-      <th><?=$this->transEsc('Related Items')?>: </th>
-      <td>
-        <? foreach ($related as $field): ?>
-          <?=$this->escapeHtml($field)?><br/>
-        <? endforeach; ?>
-      </td>
-    </tr>
-  <? endif; ?>
-</table>
\ No newline at end of file
+<?
+  $formatter = $this->recordDataFormatter();
+  $fields = $formatter->getData($driver, $formatter->getDefaults('collection-record'));
+?>
+<? if (!empty($fields)): ?>
+  <table class="table table-striped" summary="<?=$this->transEsc('Bibliographic Details')?>">
+    <? foreach ($fields as $key => $current): ?>
+      <tr><th><?=$this->transEsc($key)?>:</th><td><?=$current['value']?></td></tr>
+    <? endforeach; ?>
+  </table>
+<? endif; ?>
diff --git a/themes/bootstrap3/templates/RecordDriver/SolrDefault/core-qrcode.phtml b/themes/bootstrap3/templates/RecordDriver/SolrDefault/core-qrcode.phtml
index 52da09f1ae1f2b71e1d35f77c283d48504bc9cbb..e162a0f98f11a5abfaa18b05e1f5c118850948d8 100644
--- a/themes/bootstrap3/templates/RecordDriver/SolrDefault/core-qrcode.phtml
+++ b/themes/bootstrap3/templates/RecordDriver/SolrDefault/core-qrcode.phtml
@@ -1 +1 @@
-<?=$this->serverUrl($this->recordLink()->getUrl($this->driver))?>
\ No newline at end of file
+<?=$this->serverUrl($this->recordLink()->getUrl($this->driver))?>
diff --git a/themes/bootstrap3/templates/RecordDriver/SolrDefault/core.phtml b/themes/bootstrap3/templates/RecordDriver/SolrDefault/core.phtml
index 0d411fb74252041c5e994c502fd6583c838022f2..bb5d1cf94611a36c68f80699912ef34632265cbe 100644
--- a/themes/bootstrap3/templates/RecordDriver/SolrDefault/core.phtml
+++ b/themes/bootstrap3/templates/RecordDriver/SolrDefault/core.phtml
@@ -1,29 +1,12 @@
-<?
-  if($loggedin = $this->auth()->isLoggedIn()) {
-    $user_id = $loggedin->id;
-    $loggedin = true;
-  } else {
-    $user_id = false;
-  }
-
-  $formatRoles = function ($roles) {
-    if (count($roles) == 0) {
-      return '';
-    }
-    $that = $this;
-    $translate = function ($str) use ($that) {
-      return $that->transEsc('CreatorRoles::' . $str);
-    };
-    return ' (' . implode(', ', array_unique(array_map($translate, $roles))) . ')';
-  };
-?>
-<div class="row" vocab="http://schema.org/" resource="#record" typeof="<?=$this->driver->getSchemaOrgFormats()?> Product">
-  <? $QRCode = $this->record($this->driver)->getQRCode("core");
-     $cover = $this->record($this->driver)->getCover('core', 'medium', $this->record($this->driver)->getThumbnail('large'));
-     $preview = $this->record($this->driver)->getPreviews(); ?>
+<div class="media" vocab="http://schema.org/" resource="#record" typeof="<?=$this->driver->getSchemaOrgFormats()?> Product">
+  <?
+    $QRCode = $this->record($this->driver)->getQRCode("core");
+    $coverDetails = $this->record($this->driver)->getCoverDetails('core', 'medium', $this->record($this->driver)->getThumbnail('large'));
+    $cover = $coverDetails['html'];
+    $preview = $this->record($this->driver)->getPreviews();
+  ?>
   <? if ($QRCode || $cover || $preview): ?>
-  <div class="col-sm-3 img-col">
-    <div class="text-center">
+    <div class="media-left <?=$this->escapeHtmlAttr($coverDetails['size'])?> img-col">
       <? /* Display thumbnail if appropriate: */ ?>
       <? if($cover): ?>
         <?=$cover?>
@@ -35,19 +18,19 @@
           <br/><img alt="<?=$this->transEsc('QR Code')?>" class="qrcode" src="<?=$this->escapeHtmlAttr($QRCode);?>"/>
         </span>
       <? endif; ?>
-    </div>
 
-    <? // if you have a preview tab but want to move or remove the preview link
-       // from this area of the record view, this can be split into
-       // getPreviewData() (should stay here) and
-       // getPreviewLink() (can go in your desired tab) ?>
-    <? if ($preview): ?><?=$preview?><? endif; ?>
-  </div>
-
-  <div class="col-sm-9 info-col">
-  <? else: ?>
-  <div class="col-sm-12">
+      <? // if you have a preview tab but want to move or remove the preview link
+         // from this area of the record view, this can be split into
+         // getPreviewData() (should stay here) and
+         // getPreviewLink() (can go in your desired tab) ?>
+      <? if ($preview): ?>
+        <div class="record-previews">
+          <?=$preview?>
+        </div>
+      <? endif; ?>
+    </div>
   <? endif; ?>
+  <div class="media-body">
 
     <h3 property="name"><?=$this->escapeHtml($this->driver->getShortTitle() . ' ' . $this->driver->getSubtitle() . ' ' . $this->driver->getTitleSection())?></h3>
 
@@ -62,227 +45,23 @@
 
     <? if ($this->userlist()->getMode() !== 'disabled'): ?>
       <? /* Display the lists that this record is saved to */ ?>
-      <div class="savedLists hidden alert alert-info">
+      <div class="savedLists">
         <strong><?=$this->transEsc("Saved in")?>:</strong>
       </div>
     <? endif; ?>
 
     <?/* Display Main Details */?>
-    <table class="table table-striped" summary="<?=$this->transEsc('Bibliographic Details')?>">
-      <? $journalTitle = $this->driver->getContainerTitle(); if (!empty($journalTitle)): ?>
-      <tr>
-        <th><?=$this->transEsc('Published in')?>:</th>
-        <td>
-          <?
-            $containerSource = $this->driver->getSourceIdentifier();
-            $containerID = $this->driver->getContainerRecordID();
-          ?>
-          <a href="<?=($containerID ? $this->recordLink()->getUrl("$containerSource|$containerID") : $this->record($this->driver)->getLink('journaltitle', $journalTitle))?>"><?=$this->escapeHtml($journalTitle)?></a>
-          <? $ref = $this->driver->getContainerReference(); if (!empty($ref)) { echo $this->escapeHtml($ref); } ?>
-        </td>
-      </tr>
-      <? endif; ?>
-
-      <? $nextTitles = $this->driver->getNewerTitles(); $prevTitles = $this->driver->getPreviousTitles(); ?>
-      <? if (!empty($nextTitles)): ?>
-      <tr>
-        <th><?=$this->transEsc('New Title')?>: </th>
-        <td>
-          <? foreach($nextTitles as $field): ?>
-            <a href="<?=$this->record($this->driver)->getLink('title', $field)?>"><?=$this->escapeHtml($field)?></a><br/>
-          <? endforeach; ?>
-        </td>
-      </tr>
-      <? endif; ?>
-
-      <? if (!empty($prevTitles)): ?>
-      <tr>
-        <th><?=$this->transEsc('Previous Title')?>: </th>
-        <td>
-          <? foreach($prevTitles as $field): ?>
-            <a href="<?=$this->record($this->driver)->getLink('title', $field)?>"><?=$this->escapeHtml($field)?></a><br/>
-          <? endforeach; ?>
-        </td>
-      </tr>
-      <? endif; ?>
-
-      <? $authors = $this->driver->getDeduplicatedAuthors(); ?>
-      <? if (isset($authors['main']) && !empty($authors['main'])): ?>
-        <tr>
-          <th><?=$this->transEsc(count($authors['main']) > 1 ? 'Main Authors' : 'Main Author')?>: </th>
-          <td>
-            <? $i = 0; foreach ($authors['main'] as $author => $roles): ?><?=($i++ == 0)?'':', '?><span property="author"><a href="<?=$this->record($this->driver)->getLink('author', $author)?>"><?=$this->escapeHtml($author)?></a><?=$formatRoles($roles)?></span><? endforeach; ?>
-          </td>
-        </tr>
-      <? endif; ?>
-
-      <? if (isset($authors['corporate']) && !empty($authors['corporate'])): ?>
-        <tr>
-          <th><?=$this->transEsc(count($authors['corporate']) > 1 ? 'Corporate Author' : 'Corporate Authors')?>: </th>
-          <td>
-            <? $i = 0; foreach ($authors['corporate'] as $corporate => $roles): ?><?=($i++ == 0)?'':', '?><span property="creator"><a href="<?=$this->record($this->driver)->getLink('author', $corporate)?>"><?=$this->escapeHtml($corporate)?></a><?=$formatRoles($roles)?></span><? endforeach; ?>
-          </td>
-        </tr>
-      <? endif; ?>
-
-      <? if (isset($authors['secondary']) && !empty($authors['secondary'])): ?>
-        <tr>
-          <th><?=$this->transEsc('Other Authors')?>: </th>
-          <td>
-            <? $i = 0; foreach ($authors['secondary'] as $author => $roles): ?><?=($i++ == 0)?'':', '?><span property="contributor"><a href="<?=$this->record($this->driver)->getLink('author', $author)?>"><?=$this->escapeHtml($author)?></a><?=$formatRoles($roles)?></span><? endforeach; ?>
-          </td>
-        </tr>
-      <? endif; ?>
-
-      <? if (count($this->driver->getFormats()) > 0): ?>
-        <tr>
-          <th><?=$this->transEsc('Format')?>: </th>
-          <td><?=$this->record($this->driver)->getFormatList()?></td>
-        </tr>
-      <? endif; ?>
-
-      <? $langs = $this->driver->getLanguages(); if (!empty($langs)): ?>
-        <tr>
-          <th><?=$this->transEsc('Language')?>: </th>
-          <td><? foreach ($langs as $lang): ?><?= $this->escapeHtml($lang)?><br/><? endforeach; ?></td>
-        </tr>
-      <? endif; ?>
-
-      <? $publications = $this->driver->getPublicationDetails(); if (!empty($publications)): ?>
-      <tr>
-        <th><?=$this->transEsc('Published')?>: </th>
-        <td>
-          <? foreach ($publications as $field): ?>
-            <span property="publisher" typeof="Organization">
-            <? $pubPlace = $field->getPlace(); if (!empty($pubPlace)): ?>
-              <span property="location"><?=$this->escapeHtml($pubPlace)?></span>
-            <? endif; ?>
-            <? $pubName = $field->getName(); if (!empty($pubName)): ?>
-              <span property="name"><?=$this->escapeHtml($pubName)?></span>
-            <? endif; ?>
-            </span>
-            <? $pubDate = $field->getDate(); if (!empty($pubDate)): ?>
-              <span property="publicationDate"><?=$this->escapeHtml($pubDate)?></span>
-            <? endif; ?>
-            <br/>
-          <? endforeach; ?>
-        </td>
-      </tr>
-      <? endif; ?>
-
-      <? $edition = $this->driver->getEdition(); if (!empty($edition)): ?>
-      <tr>
-        <th><?=$this->transEsc('Edition')?>: </th>
-        <td property="bookEdition"><?=$this->escapeHtml($edition)?></td>
-      </tr>
-      <? endif; ?>
-
-      <?/* Display series section if at least one series exists. */?>
-      <? $series = $this->driver->getSeries(); if (!empty($series)): ?>
-      <tr>
-        <th><?=$this->transEsc('Series')?>: </th>
-        <td>
-          <? foreach ($series as $field): ?>
-            <?/* Depending on the record driver, $field may either be an array with
-               "name" and "number" keys or a flat string containing only the series
-               name.  We should account for both cases to maximize compatibility. */?>
-            <? if (is_array($field)): ?>
-              <? if (!empty($field['name'])): ?>
-                <a href="<?=$this->record($this->driver)->getLink('series', $field['name'])?>"><?=$this->escapeHtml($field['name'])?></a>
-                <? if (!empty($field['number'])): ?>
-                  <?=$this->escapeHtml($field['number'])?>
-                <? endif; ?>
-                <br/>
-              <? endif; ?>
-            <? else: ?>
-              <a href="<?=$this->record($this->driver)->getLink('series', $field)?>"><?=$this->escapeHtml($field)?></a><br/>
-            <? endif; ?>
-          <? endforeach; ?>
-        </td>
-      </tr>
-      <? endif; ?>
-
-      <? $subjects = $this->driver->getAllSubjectHeadings(); if (!empty($subjects)): ?>
-      <tr>
-        <th><?=$this->transEsc('Subjects')?>: </th>
-        <td>
-          <? foreach ($subjects as $field): ?>
-          <div class="subject-line" property="keywords">
-            <? $subject = ''; ?>
-            <? if(count($field) == 1) $field = explode('--', $field[0]); ?>
-            <? $i = 0; foreach ($field as $subfield): ?>
-              <?=($i++ == 0) ? '' : ' &gt; '?>
-              <? $subject = trim($subject . ' ' . $subfield); ?>
-              <a title="<?=$this->escapeHtmlAttr($subject)?>" href="<?=$this->record($this->driver)->getLink('subject', $subject)?>" rel="nofollow"><?=trim($this->escapeHtml($subfield))?></a>
-            <? endforeach; ?>
-          </div>
-          <? endforeach; ?>
-        </td>
-      </tr>
-      <? endif; ?>
-
-      <? $childRecordCount = $this->driver->tryMethod('getChildRecordCount'); if ($childRecordCount): ?>
-      <tr>
-        <th><?=$this->transEsc('child_records')?>: </th>
-        <td>
-          <a href="<?=$this->recordLink()->getChildRecordSearchUrl($this->driver)?>"><?=$this->transEsc('child_record_count', array('%%count%%' => $childRecordCount))?></a>
-        </td>
-      </tr>
-      <? endif; ?>
-
-      <?
-        $openUrl = $this->openUrl($this->driver, 'record');
-        $openUrlActive = $openUrl->isActive();
-        // Account for replace_other_urls setting
-        $urls = $this->record($this->driver)->getLinkDetails($openUrlActive);
-      ?>
-      <? if (!empty($urls) || $openUrlActive): ?>
-      <tr>
-        <th><?=$this->transEsc('Online Access')?>: </th>
-        <td>
-          <? foreach ($urls as $current): ?>
-            <a href="<?=$this->escapeHtmlAttr($this->proxyUrl($current['url']))?>"><?=$this->escapeHtml($current['desc'])?></a><br/>
-          <? endforeach; ?>
-          <? if ($openUrlActive): ?>
-            <?=$openUrl->renderTemplate()?><br/>
-          <? endif; ?>
-        </td>
-      </tr>
-      <? endif; ?>
-
-      <? $recordLinks = $this->driver->getAllRecordLinks(); ?>
-      <? if(!empty($recordLinks)): ?>
-        <tr>
-          <th><?=$this->transEsc('Related Items')?>:</th>
-          <td>
-            <? foreach ($recordLinks as $recordLink): ?>
-              <?=$this->transEsc($recordLink['title'])?>:
-              <a href="<?=$this->recordLink()->related($recordLink['link'])?>"><?=$this->escapeHtml($recordLink['value'])?></a><br />
-            <? endforeach; ?>
-            <? /* if we have record links, display relevant explanatory notes */
-              $related = $this->driver->getRelationshipNotes();
-              if (!empty($related)): ?>
-                <? foreach ($related as $field): ?>
-                  <?=$this->escapeHtml($field)?><br/>
-                <? endforeach; ?>
-            <? endif; ?>
-          </td>
-        </tr>
-      <? endif; ?>
-
-      <? if ($this->usertags()->getMode() !== 'disabled'): ?>
-        <? $tagList = $this->driver->getTags(null, null, 'count', $user_id); ?>
-        <tr>
-          <th><?=$this->transEsc('Tags')?>: </th>
-          <td>
-            <a class="tag-record btn btn-link pull-right flip" href="<?=$this->recordLink()->getActionUrl($this->driver, 'AddTag')?>" data-lightbox>
-              <i class="fa fa-plus" aria-hidden="true"></i> <?=$this->transEsc('Add Tag')?>
-            </a>
-            <?=$this->context($this)->renderInContext('record/taglist', array('tagList'=>$tagList, 'loggedin'=>$loggedin)) ?>
-          </td>
-        </tr>
-      <? endif; ?>
-    </table>
+    <?
+      $formatter = $this->recordDataFormatter();
+      $coreFields = $formatter->getData($driver, $formatter->getDefaults('core'));
+    ?>
+    <? if (!empty($coreFields)): ?>
+      <table class="table table-striped" summary="<?=$this->transEsc('Bibliographic Details')?>">
+        <? foreach ($coreFields as $key => $current): ?>
+          <tr><th><?=$this->transEsc($key)?>:</th><td><?=$current['value']?></td></tr>
+        <? endforeach; ?>
+      </table>
+    <? endif; ?>
     <?/* End Main Details */?>
   </div>
 </div>
diff --git a/themes/bootstrap3/templates/RecordDriver/SolrDefault/data-allRecordLinks.phtml b/themes/bootstrap3/templates/RecordDriver/SolrDefault/data-allRecordLinks.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..f2a8dfd40071bd23a629c0da0f371ec89e9bbf75
--- /dev/null
+++ b/themes/bootstrap3/templates/RecordDriver/SolrDefault/data-allRecordLinks.phtml
@@ -0,0 +1,11 @@
+<? foreach ($data as $recordLink): ?>
+  <?=$this->transEsc($recordLink['title'])?>:
+  <a href="<?=$this->recordLink()->related($recordLink['link'])?>"><?=$this->escapeHtml($recordLink['value'])?></a><br />
+<? endforeach; ?>
+<? /* if we have record links, display relevant explanatory notes */
+  $related = $this->driver->getRelationshipNotes();
+  if (!empty($related)): ?>
+    <? foreach ($related as $field): ?>
+      <?=$this->escapeHtml($field)?><br/>
+    <? endforeach; ?>
+<? endif; ?>
diff --git a/themes/bootstrap3/templates/RecordDriver/SolrDefault/data-allSubjectHeadings.phtml b/themes/bootstrap3/templates/RecordDriver/SolrDefault/data-allSubjectHeadings.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..2ab86fa7b88170ea16733f059a1e751582338470
--- /dev/null
+++ b/themes/bootstrap3/templates/RecordDriver/SolrDefault/data-allSubjectHeadings.phtml
@@ -0,0 +1,11 @@
+<? foreach ($data as $field): ?>
+  <div class="subject-line" property="keywords">
+    <? $subject = ''; ?>
+    <? if(count($field) == 1) $field = explode('--', $field[0]); ?>
+    <? $i = 0; foreach ($field as $subfield): ?>
+      <?=($i++ == 0) ? '' : ' &gt; '?>
+      <? $subject = trim($subject . ' ' . $subfield); ?>
+      <a title="<?=$this->escapeHtmlAttr($subject)?>" href="<?=$this->record($this->driver)->getLink('subject', $subject)?>" rel="nofollow"><?=trim($this->escapeHtml($subfield))?></a>
+    <? endforeach; ?>
+  </div>
+<? endforeach; ?>
diff --git a/themes/bootstrap3/templates/RecordDriver/SolrDefault/data-authorNotes.phtml b/themes/bootstrap3/templates/RecordDriver/SolrDefault/data-authorNotes.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..1d58594cea1c5d24e940fc9c794ce6738613d710
--- /dev/null
+++ b/themes/bootstrap3/templates/RecordDriver/SolrDefault/data-authorNotes.phtml
@@ -0,0 +1,8 @@
+<? $isbn = $this->driver->getCleanISBN(); ?>
+<? $authorNotes = empty($isbn) ? [] : $this->authorNotes($isbn); if (!empty($authorNotes)): ?>
+  <? foreach ($authorNotes as $provider => $list): ?>
+    <? foreach ($list as $field): ?>
+      <?=$field['Content']?><br />
+    <? endforeach; ?>
+  <? endforeach; ?>
+<? endif; ?>
diff --git a/themes/bootstrap3/templates/RecordDriver/SolrDefault/data-authors.phtml b/themes/bootstrap3/templates/RecordDriver/SolrDefault/data-authors.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..bbc3a63584b902dacbc53ce54f71de7923e3f243
--- /dev/null
+++ b/themes/bootstrap3/templates/RecordDriver/SolrDefault/data-authors.phtml
@@ -0,0 +1,42 @@
+<?
+$formatProperty = function ($datafield, $name, $label) {
+    if (count($datafield) == 0) {
+        return '';
+    }
+    $that = $this;
+    $translate = function ($str) use ($that, $label) {
+        return $that->transEsc($label . $str);
+    };
+    return '<span class="author-property-' . $name . '">(' . implode(', ', array_unique(array_map($translate, $datafield))) . ')</span>';
+};
+$formattedAuthors = [];
+?>
+<? if (!empty($data[$type])): ?>
+  <? foreach ($data[$type] as $author => $dataFields): ?>
+    <? ob_start(); ?>
+    <span class="author-data" property="<?=$this->escapeHtml($schemaLabel)?>">
+      <a href="<?=$this->record($this->driver)->getLink('author', $author)?>">
+        <?=$this->escapeHtml($author)?>
+      </a>
+      <?
+        // Display additional data using the appropriate translation prefix
+        // (for example, to render author roles correctly):
+        if (!empty($requiredDataFields)) {
+          foreach ($requiredDataFields as $field) {
+              $name = $field['name'];
+              $prefix = isset($field['prefix']) ? $field['prefix'] : '';
+              if (isset($dataFields[$name])) {
+                  echo $formatProperty($dataFields[$name], $name, $prefix);
+              }
+          }
+        }
+      ?>
+    </span>
+    <?
+      // Strip whitespace before close tags to avoid spaces in front of commas:
+      $formattedAuthors[] = trim(preg_replace('/\s+<\//', '</', ob_get_contents()));
+      ob_end_clean();
+    ?>
+  <? endforeach; ?>
+<? endif; ?>
+<?=implode(', ', $formattedAuthors)?>
diff --git a/themes/bootstrap3/templates/RecordDriver/SolrDefault/data-childRecords.phtml b/themes/bootstrap3/templates/RecordDriver/SolrDefault/data-childRecords.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..cb6ad882fa2384d79a1bc135aa78646efd0c3f45
--- /dev/null
+++ b/themes/bootstrap3/templates/RecordDriver/SolrDefault/data-childRecords.phtml
@@ -0,0 +1 @@
+<a href="<?=$this->recordLink()->getChildRecordSearchUrl($this->driver)?>"><?=$this->transEsc('child_record_count', array('%%count%%' => $data))?></a>
diff --git a/themes/bootstrap3/templates/RecordDriver/SolrDefault/data-containerTitle.phtml b/themes/bootstrap3/templates/RecordDriver/SolrDefault/data-containerTitle.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..ff678db3e458bc3ac9614008e8c05996f67df079
--- /dev/null
+++ b/themes/bootstrap3/templates/RecordDriver/SolrDefault/data-containerTitle.phtml
@@ -0,0 +1,10 @@
+<?
+  $containerSource = $this->driver->getSourceIdentifier();
+  $containerID = $this->driver->getContainerRecordID();
+  $ref = $this->driver->getContainerReference();
+  $link = $containerID
+    ? $this->recordLink()->getUrl("$containerSource|$containerID")
+    : $this->record($this->driver)->getLink('journaltitle', $data);
+?>
+<a href="<?=$link?>"><?=$this->escapeHtml($data)?></a>
+<?=empty($ref) ? '' : $this->escapeHtml($ref)?>
diff --git a/themes/bootstrap3/templates/RecordDriver/SolrDefault/data-onlineAccess.phtml b/themes/bootstrap3/templates/RecordDriver/SolrDefault/data-onlineAccess.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..2ddb8a1bddf8262010ebed547753f9ff47ba493d
--- /dev/null
+++ b/themes/bootstrap3/templates/RecordDriver/SolrDefault/data-onlineAccess.phtml
@@ -0,0 +1,14 @@
+<?
+  $openUrl = $this->openUrl($this->driver, 'record');
+  $openUrlActive = $openUrl->isActive();
+  // Account for replace_other_urls setting
+  $urls = $this->record($this->driver)->getLinkDetails($openUrlActive);
+?>
+<? if (!empty($urls) || $openUrlActive): ?>
+  <? foreach ($urls as $current): ?>
+    <a href="<?=$this->escapeHtmlAttr($this->proxyUrl($current['url']))?>"><?=$this->escapeHtml($current['desc'])?></a><br/>
+  <? endforeach; ?>
+  <? if ($openUrlActive): ?>
+    <?=$openUrl->renderTemplate()?><br/>
+  <? endif; ?>
+<? endif; ?>
diff --git a/themes/bootstrap3/templates/RecordDriver/SolrDefault/data-publicationDetails.phtml b/themes/bootstrap3/templates/RecordDriver/SolrDefault/data-publicationDetails.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..c8b7a78a2eb308d3b131cdd829b8b56626947762
--- /dev/null
+++ b/themes/bootstrap3/templates/RecordDriver/SolrDefault/data-publicationDetails.phtml
@@ -0,0 +1,14 @@
+<? foreach ($data as $field): ?>
+  <span property="publisher" typeof="Organization">
+  <? $pubPlace = $field->getPlace(); if (!empty($pubPlace)): ?>
+    <span property="location"><?=$this->escapeHtml($pubPlace)?></span>
+  <? endif; ?>
+  <? $pubName = $field->getName(); if (!empty($pubName)): ?>
+    <span property="name"><?=$this->escapeHtml($pubName)?></span>
+  <? endif; ?>
+  </span>
+  <? $pubDate = $field->getDate(); if (!empty($pubDate)): ?>
+    <span property="publicationDate"><?=$this->escapeHtml($pubDate)?></span>
+  <? endif; ?>
+  <br/>
+<? endforeach; ?>
diff --git a/themes/bootstrap3/templates/RecordDriver/SolrDefault/data-series.phtml b/themes/bootstrap3/templates/RecordDriver/SolrDefault/data-series.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..b71c03ebc2fa09a215c236b743e2816f2b65a048
--- /dev/null
+++ b/themes/bootstrap3/templates/RecordDriver/SolrDefault/data-series.phtml
@@ -0,0 +1,16 @@
+<? foreach ($data as $field): ?>
+  <?/* Depending on the record driver, $field may either be an array with
+     "name" and "number" keys or a flat string containing only the series
+     name.  We should account for both cases to maximize compatibility. */?>
+  <? if (is_array($field)): ?>
+    <? if (!empty($field['name'])): ?>
+      <a href="<?=$this->record($this->driver)->getLink('series', $field['name'])?>"><?=$this->escapeHtml($field['name'])?></a>
+      <? if (!empty($field['number'])): ?>
+        <?=$this->escapeHtml($field['number'])?>
+      <? endif; ?>
+      <br/>
+    <? endif; ?>
+  <? else: ?>
+    <a href="<?=$this->record($this->driver)->getLink('series', $field)?>"><?=$this->escapeHtml($field)?></a><br/>
+  <? endif; ?>
+<? endforeach; ?>
diff --git a/themes/bootstrap3/templates/RecordDriver/SolrDefault/data-tags.phtml b/themes/bootstrap3/templates/RecordDriver/SolrDefault/data-tags.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..285e4ea0d319845dc9002386936b4e7b58af630e
--- /dev/null
+++ b/themes/bootstrap3/templates/RecordDriver/SolrDefault/data-tags.phtml
@@ -0,0 +1,15 @@
+<?
+  if($loggedin = $this->auth()->isLoggedIn()) {
+    $user_id = $loggedin->id;
+    $loggedin = true;
+  } else {
+    $user_id = false;
+  }
+?>
+<? if ($this->usertags()->getMode() !== 'disabled'): ?>
+  <? $tagList = $this->driver->getTags(null, null, 'count', $user_id); ?>
+    <a class="tag-record btn btn-link pull-right flip" href="<?=$this->recordLink()->getActionUrl($this->driver, 'AddTag')?>" data-lightbox>
+      <i class="fa fa-plus" aria-hidden="true"></i> <?=$this->transEsc('Add Tag')?>
+    </a>
+    <?=$this->context($this)->renderInContext('record/taglist', array('tagList'=>$tagList, 'loggedin'=>$loggedin)) ?>
+<? endif; ?>
diff --git a/themes/bootstrap3/templates/RecordDriver/SolrDefault/format-class.phtml b/themes/bootstrap3/templates/RecordDriver/SolrDefault/format-class.phtml
index 2e2ce73b628f19dc2eb4028d1dad39cad505c089..effdcc22ace54702453d5426699af57c3989ed2f 100644
--- a/themes/bootstrap3/templates/RecordDriver/SolrDefault/format-class.phtml
+++ b/themes/bootstrap3/templates/RecordDriver/SolrDefault/format-class.phtml
@@ -1 +1 @@
-<?=preg_replace('/[^a-z0-9]/', '', strtolower($this->format))?>
\ No newline at end of file
+<?=preg_replace('/[^a-z0-9]/', '', strtolower($this->format))?>
diff --git a/themes/bootstrap3/templates/RecordDriver/SolrDefault/link-author.phtml b/themes/bootstrap3/templates/RecordDriver/SolrDefault/link-author.phtml
index 1ef515fe458f58dbc0a53af91c01a7cbb097086e..fdd7fe966a2d7d2667fe9236afbe083b3c190a32 100644
--- a/themes/bootstrap3/templates/RecordDriver/SolrDefault/link-author.phtml
+++ b/themes/bootstrap3/templates/RecordDriver/SolrDefault/link-author.phtml
@@ -1 +1 @@
-<?=$this->url('author-home')?>?author=<?=urlencode($this->lookfor)?>
\ No newline at end of file
+<?=$this->url('author-home')?>?author=<?=urlencode($this->lookfor)?>
diff --git a/themes/bootstrap3/templates/RecordDriver/SolrDefault/link-journaltitle.phtml b/themes/bootstrap3/templates/RecordDriver/SolrDefault/link-journaltitle.phtml
index 5987653afd9f7c4fff7a830588128fde1077c8a4..154b38cbbb1d9899e131d99f74d19c5be8477e60 100644
--- a/themes/bootstrap3/templates/RecordDriver/SolrDefault/link-journaltitle.phtml
+++ b/themes/bootstrap3/templates/RecordDriver/SolrDefault/link-journaltitle.phtml
@@ -1 +1 @@
-<?=$this->url('search-results')?>?lookfor=%22<?=urlencode($this->lookfor)?>%22&amp;type=JournalTitle
\ No newline at end of file
+<?=$this->url('search-results')?>?lookfor=%22<?=urlencode($this->lookfor)?>%22&amp;type=JournalTitle
diff --git a/themes/bootstrap3/templates/RecordDriver/SolrDefault/link-series.phtml b/themes/bootstrap3/templates/RecordDriver/SolrDefault/link-series.phtml
index bf7507d0a50c08a2edefcb6054506c4ca4c4dee1..3b0406eeff76aa9ae5e463083713810713b7e265 100644
--- a/themes/bootstrap3/templates/RecordDriver/SolrDefault/link-series.phtml
+++ b/themes/bootstrap3/templates/RecordDriver/SolrDefault/link-series.phtml
@@ -1 +1 @@
-<?=$this->url('search-results')?>?lookfor=%22<?=urlencode($this->lookfor)?>%22&amp;type=Series
\ No newline at end of file
+<?=$this->url('search-results')?>?lookfor=%22<?=urlencode($this->lookfor)?>%22&amp;type=Series
diff --git a/themes/bootstrap3/templates/RecordDriver/SolrDefault/link-subject.phtml b/themes/bootstrap3/templates/RecordDriver/SolrDefault/link-subject.phtml
index 07a34f729d9e6eda12dbc8cbd2bb8b8b3ded9791..6424a15c8860a6df7df0bb882ebbf82093c1f078 100644
--- a/themes/bootstrap3/templates/RecordDriver/SolrDefault/link-subject.phtml
+++ b/themes/bootstrap3/templates/RecordDriver/SolrDefault/link-subject.phtml
@@ -1 +1 @@
-<?=$this->url('search-results')?>?lookfor=%22<?=urlencode($this->lookfor)?>%22&amp;type=Subject
\ No newline at end of file
+<?=$this->url('search-results')?>?lookfor=%22<?=urlencode($this->lookfor)?>%22&amp;type=Subject
diff --git a/themes/bootstrap3/templates/RecordDriver/SolrDefault/link-title.phtml b/themes/bootstrap3/templates/RecordDriver/SolrDefault/link-title.phtml
index eca8c06502d139dd4ea37d34bb01aa516b9bd08e..163ccdcb55b7fe8e9a02c4eceff950af447096e7 100644
--- a/themes/bootstrap3/templates/RecordDriver/SolrDefault/link-title.phtml
+++ b/themes/bootstrap3/templates/RecordDriver/SolrDefault/link-title.phtml
@@ -1 +1 @@
-<?=$this->url('search-results')?>?lookfor=%22<?=urlencode($this->lookfor)?>%22&amp;type=Title
\ No newline at end of file
+<?=$this->url('search-results')?>?lookfor=%22<?=urlencode($this->lookfor)?>%22&amp;type=Title
diff --git a/themes/bootstrap3/templates/RecordDriver/SolrDefault/list-entry.phtml b/themes/bootstrap3/templates/RecordDriver/SolrDefault/list-entry.phtml
index 5ca54d335fa2e006dd82971768594827629a8123..78350beb278990fd9ca6a4f2f8716224a47062cf 100644
--- a/themes/bootstrap3/templates/RecordDriver/SolrDefault/list-entry.phtml
+++ b/themes/bootstrap3/templates/RecordDriver/SolrDefault/list-entry.phtml
@@ -25,172 +25,168 @@
 <div class="result<? if($this->driver->supportsAjaxStatus()): ?> ajaxItem<? endif ?>">
   <input type="hidden" value="<?=$this->escapeHtmlAttr($id) ?>" class="hiddenId"/>
   <input type="hidden" value="<?=$this->escapeHtmlAttr($source) ?>" class="hiddenSource"/>
-  <div class="checkbox hidden-print">
-    <label><?=$this->record($this->driver)->getCheckbox()?></label>
-  </div>
+  <?=$this->record($this->driver)->getCheckbox()?>
   <div class="media">
     <? if ($thumbnail && $thumbnailAlignment == 'left'): ?>
       <?=$thumbnail ?>
     <? endif; ?>
     <div class="media-body">
-      <div class="row short-view">
-        <div class="col-sm-8">
-          <div class="resultItemLine1">
-            <? $missing = $this->driver instanceof \VuFind\RecordDriver\Missing; ?>
-            <? if (!$missing): ?><a href="<?=$this->recordLink()->getUrl($this->driver)?>" class="getFull" data-view="<?=$this->params->getOptions()->getListViewOption() ?>"><? endif; ?>
-              <span class="title"><?=$this->record($this->driver)->getTitleHtml()?></span>
-            <? if (!$missing): ?></a><? endif; ?>
-          </div>
+      <div class="result-body">
+        <div class="resultItemLine1">
+          <? $missing = $this->driver instanceof \VuFind\RecordDriver\Missing; ?>
+          <? if (!$missing): ?><a href="<?=$this->recordLink()->getUrl($this->driver)?>" class="getFull" data-view="<?=$this->params->getOptions()->getListViewOption() ?>"><? endif; ?>
+            <span class="title"><?=$this->record($this->driver)->getTitleHtml()?></span>
+          <? if (!$missing): ?></a><? endif; ?>
+        </div>
 
-          <div class="resultItemLine2">
-            <? if($this->driver->isCollection()): ?>
-              <?=implode('<br>', array_map(array($this, 'escapeHtml'), $this->driver->getSummary())); ?>
-            <? else: ?>
-              <? $summAuthors = $this->driver->getPrimaryAuthors(); if (!empty($summAuthors)): ?>
-                <?=$this->transEsc('by')?>
-                <? $authorCount = count($summAuthors); foreach ($summAuthors as $i => $summAuthor): ?>
-                  <a href="<?=$this->record($this->driver)->getLink('author', $summAuthor)?>"><?=$this->escapeHtml($summAuthor)?></a><?=($i + 1 < $authorCount ? ';' : '') ?>
-                <? endforeach; ?>
-              <? endif; ?>
+        <div class="resultItemLine2">
+          <? if($this->driver->isCollection()): ?>
+            <?=implode('<br>', array_map(array($this, 'escapeHtml'), $this->driver->getSummary())); ?>
+          <? else: ?>
+            <? $summAuthors = $this->driver->getPrimaryAuthors(); if (!empty($summAuthors)): ?>
+              <?=$this->transEsc('by')?>
+              <? $authorCount = count($summAuthors); foreach ($summAuthors as $i => $summAuthor): ?>
+                <a href="<?=$this->record($this->driver)->getLink('author', $summAuthor)?>"><?=$this->escapeHtml($summAuthor)?></a><?=($i + 1 < $authorCount ? ';' : '') ?>
+              <? endforeach; ?>
+            <? endif; ?>
 
-              <? $journalTitle = $this->driver->getContainerTitle(); $summDate = $this->driver->getPublicationDates(); ?>
-              <? if (!empty($journalTitle)): ?>
-                <?=!empty($summAuthor) ? '<br/>' : ''?>
-                <?=/* TODO: handle highlighting more elegantly here */ $this->transEsc('Published in') . ' <a href="' . $this->record($this->driver)->getLink('journaltitle', str_replace(array('{{{{START_HILITE}}}}', '{{{{END_HILITE}}}}'), '', $journalTitle)) . '">' . $this->highlight($journalTitle) . '</a>';?>
-                <?=!empty($summDate) ? ' (' . $this->escapeHtml($summDate[0]) . ')' : ''?>
-              <? elseif (!empty($summDate)): ?>
-                <?=!empty($summAuthor) ? '<br/>' : ''?>
-                <?=$this->transEsc('Published') . ' ' . $this->escapeHtml($summDate[0])?>
-              <? endif; ?>
-              <? $summInCollection = $this->driver->getContainingCollections(); if (false && !empty($summInCollection)): ?>
-                <? foreach ($summInCollection as $collId => $collText): ?>
-                  <div>
-                    <b><?=$this->transEsc("in_collection_label")?></b>
-                    <a class="collectionLinkText" href="<?=$this->url('collection', array('id' => $collId))?>?recordID=<?=urlencode($this->driver->getUniqueID())?>">
-                      <?=$this->escapeHtml($collText)?>
-                    </a>
-                  </div>
-                <? endforeach; ?>
-              <? endif; ?>
+            <? $journalTitle = $this->driver->getContainerTitle(); $summDate = $this->driver->getPublicationDates(); ?>
+            <? if (!empty($journalTitle)): ?>
+              <?=!empty($summAuthor) ? '<br/>' : ''?>
+              <?=/* TODO: handle highlighting more elegantly here */ $this->transEsc('Published in') . ' <a href="' . $this->record($this->driver)->getLink('journaltitle', str_replace(array('{{{{START_HILITE}}}}', '{{{{END_HILITE}}}}'), '', $journalTitle)) . '">' . $this->highlight($journalTitle) . '</a>';?>
+              <?=!empty($summDate) ? ' (' . $this->escapeHtml($summDate[0]) . ')' : ''?>
+            <? elseif (!empty($summDate)): ?>
+              <?=!empty($summAuthor) ? '<br/>' : ''?>
+              <?=$this->transEsc('Published') . ' ' . $this->escapeHtml($summDate[0])?>
             <? endif; ?>
-          </div>
+            <? $summInCollection = $this->driver->getContainingCollections(); if (false && !empty($summInCollection)): ?>
+              <? foreach ($summInCollection as $collId => $collText): ?>
+                <div>
+                  <b><?=$this->transEsc("in_collection_label")?></b>
+                  <a class="collectionLinkText" href="<?=$this->url('collection', array('id' => $collId))?>?recordID=<?=urlencode($this->driver->getUniqueID())?>">
+                    <?=$this->escapeHtml($collText)?>
+                  </a>
+                </div>
+              <? endforeach; ?>
+            <? endif; ?>
+          <? endif; ?>
+        </div>
 
-          <div class="last">
-            <? if(!$this->driver->isCollection()) {
-                if ($snippet = $this->driver->getHighlightedSnippet()) {
-                  if (!empty($snippet['caption'])) {
-                    echo '<strong>' . $this->transEsc($snippet['caption']) . ':</strong> ';
-                  }
-                  if (!empty($snippet['snippet'])) {
-                    echo '<span class="quotestart">&#8220;</span>...' . $this->highlight($snippet['snippet']) . '...<span class="quoteend">&#8221;</span><br/>';
-                  }
+        <div class="last">
+          <? if(!$this->driver->isCollection()) {
+              if ($snippet = $this->driver->getHighlightedSnippet()) {
+                if (!empty($snippet['caption'])) {
+                  echo '<strong>' . $this->transEsc($snippet['caption']) . ':</strong> ';
                 }
-              } ?>
+                if (!empty($snippet['snippet'])) {
+                  echo '<span class="quotestart">&#8220;</span>...' . $this->highlight($snippet['snippet']) . '...<span class="quoteend">&#8221;</span><br/>';
+                }
+              }
+            } ?>
 
-            <? $listTags = ($this->usertags()->getMode() !== 'disabled') ? $this->driver->getTags(
-                null === $list_id ? true : $list_id, // get tags for all lists if no single list is selected
-                $user_id, 'tag'
-               ) : array();
-            ?>
-            <? if (count($listTags) > 0): ?>
-              <strong><?=$this->transEsc('Your Tags')?>:</strong>
-              <? foreach ($listTags as $tag): ?>
-                <a href="<?=$this->currentPath() . $results->getUrlQuery()->addFacet('tags', $tag->tag)?>"><?=$this->escapeHtml($tag->tag)?></a>
+          <? $listTags = ($this->usertags()->getMode() !== 'disabled') ? $this->driver->getTags(
+              null === $list_id ? true : $list_id, // get tags for all lists if no single list is selected
+              $user_id, 'tag'
+             ) : array();
+          ?>
+          <? if (count($listTags) > 0): ?>
+            <strong><?=$this->transEsc('Your Tags')?>:</strong>
+            <? foreach ($listTags as $tag): ?>
+              <a href="<?=$this->currentPath() . $results->getUrlQuery()->addFacet('tags', $tag->tag)?>"><?=$this->escapeHtml($tag->tag)?></a>
+            <? endforeach; ?>
+            <br/>
+          <? endif; ?>
+          <? $listNotes = $this->driver->getListNotes($list_id, $user_id); ?>
+          <? if (count($listNotes) > 0): ?>
+            <strong><?=$this->transEsc('Notes')?>:</strong>
+            <? if (count($listNotes) > 1): ?><br/><? endif; ?>
+            <? foreach ($listNotes as $note): ?>
+              <?=$this->escapeHtml($note)?><br/>
+            <? endforeach; ?>
+          <? endif; ?>
+
+          <? if (count($this->lists) > 0): ?>
+              <strong><?=$this->transEsc('Saved in')?>:</strong>
+              <? $i=0;foreach($this->lists as $current): ?>
+                  <a href="<?=$this->url('userList', array('id' => $current->id))?>"><?=$this->escapeHtml($current->title)?></a><? if($i++ < count($this->lists)-1): ?>,<? endif; ?>
               <? endforeach; ?>
               <br/>
-            <? endif; ?>
-            <? $listNotes = $this->driver->getListNotes($list_id, $user_id); ?>
-            <? if (count($listNotes) > 0): ?>
-              <strong><?=$this->transEsc('Notes')?>:</strong>
-              <? if (count($listNotes) > 1): ?><br/><? endif; ?>
-              <? foreach ($listNotes as $note): ?>
-                <?=$this->escapeHtml($note)?><br/>
-              <? endforeach; ?>
-            <? endif; ?>
-
-            <? if (count($this->lists) > 0): ?>
-                <strong><?=$this->transEsc('Saved in')?>:</strong>
-                <? $i=0;foreach($this->lists as $current): ?>
-                    <a href="<?=$this->url('userList', array('id' => $current->id))?>"><?=$this->escapeHtml($current->title)?></a><? if($i++ < count($this->lists)-1): ?>,<? endif; ?>
-                <? endforeach; ?>
-                <br/>
-            <? endif; ?>
+          <? endif; ?>
 
-            <div class="callnumAndLocation ajax-availability hidden">
-              <? if ($this->driver->supportsAjaxStatus()): ?>
-                <strong class="hideIfDetailed"><?=$this->transEsc('Call Number')?>:</strong>
-                <span class="callnumber ajax-availability hidden">
-                  <?=$this->transEsc('Loading')?>...<br/>
-                </span>
-                <strong><?=$this->transEsc('Located')?>:</strong>
-                <span class="location ajax-availability hidden">
-                  <?=$this->transEsc('Loading')?>...
-                </span>
-                <div class="locationDetails"></div>
-              <? else: ?>
-                <? $summCallNo = $this->driver->getCallNumber(); if (!empty($summCallNo)): ?>
-                  <strong><?=$this->transEsc('Call Number')?>:</strong> <?=$this->escapeHtml($summCallNo)?>
-                <? endif; ?>
+          <div class="callnumAndLocation ajax-availability hidden">
+            <? if ($this->driver->supportsAjaxStatus()): ?>
+              <strong class="hideIfDetailed"><?=$this->transEsc('Call Number')?>:</strong>
+              <span class="callnumber ajax-availability hidden">
+                <?=$this->transEsc('Loading')?>...<br/>
+              </span>
+              <strong><?=$this->transEsc('Located')?>:</strong>
+              <span class="location ajax-availability hidden">
+                <?=$this->transEsc('Loading')?>...
+              </span>
+              <div class="locationDetails"></div>
+            <? else: ?>
+              <? $summCallNo = $this->driver->getCallNumber(); if (!empty($summCallNo)): ?>
+                <strong><?=$this->transEsc('Call Number')?>:</strong> <?=$this->escapeHtml($summCallNo)?>
               <? endif; ?>
-            </div>
+            <? endif; ?>
+          </div>
 
-            <? /* We need to find out if we're supposed to display an OpenURL link ($openUrlActive),
-                  but even if we don't plan to display the link, we still want to get the $openUrl
-                  value for use in generating a COinS (Z3988) tag -- see bottom of file.
-                */
-              $openUrl = $this->openUrl($this->driver, 'results');
-              $openUrlActive = $openUrl->isActive();
-              // Account for replace_other_urls setting
-              $urls = $this->record($this->driver)->getLinkDetails($openUrlActive);
+          <? /* We need to find out if we're supposed to display an OpenURL link ($openUrlActive),
+                but even if we don't plan to display the link, we still want to get the $openUrl
+                value for use in generating a COinS (Z3988) tag -- see bottom of file.
+              */
+            $openUrl = $this->openUrl($this->driver, 'results');
+            $openUrlActive = $openUrl->isActive();
+            // Account for replace_other_urls setting
+            $urls = $this->record($this->driver)->getLinkDetails($openUrlActive);
 
-              if ($openUrlActive || !empty($urls)):
-            ?>
-              <? if ($openUrlActive): ?>
-                <br/>
-                <?=$openUrl->renderTemplate()?>
-              <? endif;?>
+            if ($openUrlActive || !empty($urls)):
+          ?>
+            <? if ($openUrlActive): ?>
+              <br/>
+              <?=$openUrl->renderTemplate()?>
+            <? endif;?>
 
-              <? if (!is_array($urls)) { $urls = array(); }
-                if(!$this->driver->isCollection()):
-                  foreach ($urls as $current): ?>
-                    <a href="<?=$this->escapeHtmlAttr($this->proxyUrl($current['url']))?>" class="fulltext" target="new"><i class="fa fa-external-link" aria-hidden="true"></i> <?=($current['url'] == $current['desc']) ? $this->transEsc('Get full text') : $this->escapeHtml($current['desc'])?></a>
-                  <? endforeach; ?>
-                <? endif; ?>
+            <? if (!is_array($urls)) { $urls = array(); }
+              if(!$this->driver->isCollection()):
+                foreach ($urls as $current): ?>
+                  <a href="<?=$this->escapeHtmlAttr($this->proxyUrl($current['url']))?>" class="fulltext" target="new"><i class="fa fa-external-link" aria-hidden="true"></i> <?=($current['url'] == $current['desc']) ? $this->transEsc('Get full text') : $this->escapeHtml($current['desc'])?></a>
+                <? endforeach; ?>
               <? endif; ?>
-            <br/>
+            <? endif; ?>
+          <br/>
 
-            <?=$this->record($this->driver)->getFormatList() ?>
+          <?=$this->record($this->driver)->getFormatList() ?>
 
-            <? if (!$openUrlActive && empty($urls) && $this->driver->supportsAjaxStatus()): ?>
-              <span class="status ajax-availability hidden"><?=$this->transEsc('Loading')?>...</span>
-              <br/><br/>
-            <? endif; ?>
-            <?=$this->record($this->driver)->getPreviews()?>
-          </div>
+          <? if (!$openUrlActive && empty($urls) && $this->driver->supportsAjaxStatus()): ?>
+            <span class="status ajax-availability hidden"><?=$this->transEsc('Loading')?>...</span>
+            <br/><br/>
+          <? endif; ?>
+          <?=$this->record($this->driver)->getPreviews()?>
         </div>
+      </div>
 
-        <div class="col-sm-4 right">
-          <i class="fa fa-fw fa-edit" aria-hidden="true"></i> <a href="<?=$this->url('myresearch-edit')?>?id=<?=urlencode($id)?>&amp;source=<?=urlencode($source)?><? if (!is_null($list_id)):?>&amp;list_id=<?=urlencode($list_id)?><? endif; ?>" class="edit tool"><?=$this->transEsc('Edit')?></a><br/>
-          <? /* Use a different delete URL if we're removing from a specific list or the overall favorites: */
-            $deleteUrl = null === $list_id
-                ? $this->url('myresearch-favorites')
-                : $this->url('userList', array('id' => $list_id));
-            $deleteUrlGet = $deleteUrl . '?delete=' . urlencode($id) . '&amp;source=' . urlencode($source);
+      <div class="result-links hidden-print">
+        <i class="fa fa-fw fa-edit" aria-hidden="true"></i> <a href="<?=$this->url('myresearch-edit')?>?id=<?=urlencode($id)?>&amp;source=<?=urlencode($source)?><? if (!is_null($list_id)):?>&amp;list_id=<?=urlencode($list_id)?><? endif; ?>" class="edit tool"><?=$this->transEsc('Edit')?></a><br/>
+        <? /* Use a different delete URL if we're removing from a specific list or the overall favorites: */
+          $deleteUrl = null === $list_id
+              ? $this->url('myresearch-favorites')
+              : $this->url('userList', array('id' => $list_id));
+          $deleteUrlGet = $deleteUrl . '?delete=' . urlencode($id) . '&amp;source=' . urlencode($source);
 
-            $dLabel = 'delete-label-' . preg_replace('[\W]','-',$id);
-          ?>
-          <div class="dropdown">
-            <i class="fa fa-fw fa-trash-o" aria-hidden="true"></i> <a class="dropdown-toggle" id="<?=$dLabel ?>" role="button" data-toggle="dropdown" data-target="#" href="<?=$deleteUrlGet ?>">
-              <?=$this->transEsc('Delete') ?>
-            </a>
-            <ul class="dropdown-menu" role="menu" aria-labelledby="<?=$dLabel ?>">
-              <li><a onClick="$.post('<?=$deleteUrl?>', {'delete':'<?=$this->escapeJs($id) ?>','source':'<?=$this->escapeJs($source) ?>','confirm':true},function(){location.reload(true)})" title="<?=$this->transEsc('confirm_delete_brief')?>"><?=$this->transEsc('confirm_dialog_yes')?></a></li>
-              <li><a><?=$this->transEsc('confirm_dialog_no')?></a></li>
-            </ul>
-          </div>
-
-          <?=$this->driver->supportsCoinsOpenUrl()?'<span class="Z3988" title="'.$this->escapeHtmlAttr($this->driver->getCoinsOpenUrl()).'"></span>':''?>
+          $dLabel = 'delete-label-' . preg_replace('[\W]','-',$id);
+        ?>
+        <div class="dropdown">
+          <i class="fa fa-fw fa-trash-o" aria-hidden="true"></i> <a class="dropdown-toggle" id="<?=$dLabel ?>" role="button" data-toggle="dropdown" data-target="#" href="<?=$deleteUrlGet ?>">
+            <?=$this->transEsc('Delete') ?>
+          </a>
+          <ul class="dropdown-menu" role="menu" aria-labelledby="<?=$dLabel ?>">
+            <li><a onClick="$.post('<?=$deleteUrl?>', {'delete':'<?=$this->escapeJs($id) ?>','source':'<?=$this->escapeJs($source) ?>','confirm':true},function(){location.reload(true)})" title="<?=$this->transEsc('confirm_delete_brief')?>"><?=$this->transEsc('confirm_dialog_yes')?></a></li>
+            <li><a><?=$this->transEsc('confirm_dialog_no')?></a></li>
+          </ul>
         </div>
+
+        <?=$this->driver->supportsCoinsOpenUrl()?'<span class="Z3988" title="'.$this->escapeHtmlAttr($this->driver->getCoinsOpenUrl()).'"></span>':''?>
       </div>
     </div>
     <? if ($thumbnail && $thumbnailAlignment == 'right'): ?>
diff --git a/themes/bootstrap3/templates/RecordDriver/SolrDefault/result-grid.phtml b/themes/bootstrap3/templates/RecordDriver/SolrDefault/result-grid.phtml
index d0c012dae9fee972f67a50acd037d2a365d09448..2cbe7bb326ab6a17014869d8b391827c667497c0 100644
--- a/themes/bootstrap3/templates/RecordDriver/SolrDefault/result-grid.phtml
+++ b/themes/bootstrap3/templates/RecordDriver/SolrDefault/result-grid.phtml
@@ -9,35 +9,39 @@ $openUrlActive = $openUrl->isActive();
 $urls = $this->record($this->driver)->getLinkDetails($openUrlActive);
 ?>
 
-<div class="result <?=$this->driver->supportsAjaxStatus()?' ajaxItem':''?>">
+<div class="grid-result<?=$this->driver->supportsAjaxStatus()?' ajaxItem':''?>">
   <input type="hidden" value="<?=$this->escapeHtmlAttr($this->driver->getUniqueID())?>" class="hiddenId" />
-  <? if ((isset($this->showCartControls) && $this->showCartControls)
-      || (isset($this->showBulkOptions) && $this->showBulkOptions)): ?>
-    <?=$this->record($this->driver)->getCheckbox() ?></br>
+  <? if (isset($this->showCheckboxes) && $this->showCheckboxes): ?>
+    <label class="grid-checkbox">
+      <?=$this->record($this->driver)->getCheckbox('', 'search-cart-form') ?>
+    </label>
   <? endif; ?>
-  <div class="text-center">
+  <div class="grid-body">
     <?=$this->record($this->driver)->getCover('result-grid', 'small', $this->recordLink()->getUrl($this->driver)); ?>
-  </div>
-  <? if (!$openUrlActive && empty($urls)): ?>
-    <? if ($this->driver->supportsAjaxStatus()): ?>
-      <div class="status ajax-availability hidden text-center"><span class="label label-default"><?=$this->transEsc('Loading')?>...</span></div>
-    <? endif; ?>
-  <? endif; ?>
-  <div>
-    <a class="title" href="<?=$this->recordLink()->getUrl($this->driver)?>">
-      <?=$this->record($this->driver)->getTitleHtml(80)?>
-    </a>
-    <? if ($openUrlActive || !empty($urls)): ?>
-      <br/><br/>
-      <? if ($openUrlActive): ?>
-        <?=$openUrl->renderTemplate()?><br />
+    <? if (!$openUrlActive && empty($urls)): ?>
+      <? if ($this->driver->supportsAjaxStatus()): ?>
+        <div class="result-formats status ajax-availability hidden">
+          <span class="label label-default"><?=$this->transEsc('Loading')?>...</span>
+        </div>
       <? endif; ?>
-      <? if (!is_array($urls)) $urls = array(); foreach ($urls as $current): ?>
-        <a href="<?=$this->escapeHtmlAttr($this->proxyUrl($current['url']))?>" class="fulltext" target="new"><i class="fa fa-external-link" aria-hidden="true"></i> <?=($current['url'] == $current['desc']) ? $this->transEsc('Get full text') : $this->escapeHtml($current['desc'])?></a>
-        <br/>
-      <? endforeach; ?>
     <? endif; ?>
+    <div>
+      <a class="title" href="<?=$this->recordLink()->getUrl($this->driver)?>">
+        <?=$this->record($this->driver)->getTitleHtml(80)?>
+      </a>
+      <? if ($openUrlActive || !empty($urls)): ?>
+        <br/><br/>
+        <? if ($openUrlActive): ?>
+          <?=$openUrl->renderTemplate()?><br />
+        <? endif; ?>
+        <? if (!is_array($urls)) $urls = array(); foreach ($urls as $current): ?>
+          <a href="<?=$this->escapeHtmlAttr($this->proxyUrl($current['url']))?>" class="fulltext" target="new"><i class="fa fa-external-link" aria-hidden="true"></i> <?=($current['url'] == $current['desc']) ? $this->transEsc('Get full text') : $this->escapeHtml($current['desc'])?></a>
+          <br/>
+        <? endforeach; ?>
+      <? endif; ?>
+    </div>
   </div>
+
+  <?=$this->driver->supportsCoinsOpenUrl()?'<span class="Z3988" title="'.$this->escapeHtmlAttr($this->driver->getCoinsOpenUrl()).'"></span>':''?>
 </div>
 
-<?=$this->driver->supportsCoinsOpenUrl()?'<span class="Z3988" title="'.$this->escapeHtmlAttr($this->driver->getCoinsOpenUrl()).'"></span>':''?>
diff --git a/themes/bootstrap3/templates/RecordDriver/SolrDefault/result-list.phtml b/themes/bootstrap3/templates/RecordDriver/SolrDefault/result-list.phtml
index b1c1204e8c354288177164b672c5de555b168e38..97232352659b8cee5d4e27a5c63b142720139b27 100644
--- a/themes/bootstrap3/templates/RecordDriver/SolrDefault/result-list.phtml
+++ b/themes/bootstrap3/templates/RecordDriver/SolrDefault/result-list.phtml
@@ -18,126 +18,126 @@
     <?=$thumbnail ?>
   <? endif ?>
   <div class="media-body">
-    <div class="row short-view">
-      <div class="col-sm-8 middle">
-        <div>
-          <a href="<?=$this->recordLink()->getUrl($this->driver)?>" class="title getFull" data-view="<?=$this->params->getOptions()->getListViewOption() ?>">
-            <?=$this->record($this->driver)->getTitleHtml()?>
-          </a>
-        </div>
+    <div class="result-body">
+      <div>
+        <a href="<?=$this->recordLink()->getUrl($this->driver)?>" class="title getFull" data-view="<?=$this->params->getOptions()->getListViewOption() ?>">
+          <?=$this->record($this->driver)->getTitleHtml()?>
+        </a>
+      </div>
 
-        <div>
-          <? if($this->driver->isCollection()): ?>
-            <?=implode('<br>', array_map(array($this, 'escapeHtml'), $this->driver->getSummary())); ?>
-          <? else: ?>
-            <? $summAuthors = $this->driver->getPrimaryAuthorsWithHighlighting(); if (!empty($summAuthors)): ?>
-              <?=$this->transEsc('by')?>
-              <? $authorCount = count($summAuthors); foreach ($summAuthors as $i => $summAuthor): ?>
-                <a href="<?=$this->record($this->driver)->getLink('author', $this->highlight($summAuthor, null, true, false))?>"><?=$this->highlight($summAuthor)?></a><?=$i + 1 < $authorCount ? ',' : ''?>
-              <? endforeach; ?>
-            <? endif; ?>
+      <div>
+        <? if($this->driver->isCollection()): ?>
+          <?=implode('<br>', array_map(array($this, 'escapeHtml'), $this->driver->getSummary())); ?>
+        <? else: ?>
+          <? $summAuthors = $this->driver->getPrimaryAuthorsWithHighlighting(); if (!empty($summAuthors)): ?>
+            <?=$this->transEsc('by')?>
+            <? $authorCount = count($summAuthors); foreach ($summAuthors as $i => $summAuthor): ?>
+              <a href="<?=$this->record($this->driver)->getLink('author', $this->highlight($summAuthor, null, true, false))?>"><?=$this->highlight($summAuthor)?></a><?=$i + 1 < $authorCount ? ',' : ''?>
+            <? endforeach; ?>
+          <? endif; ?>
 
-            <? $journalTitle = $this->driver->getContainerTitle(); $summDate = $this->driver->getPublicationDates(); ?>
-            <? if (!empty($journalTitle)): ?>
-              <?=!empty($summAuthor) ? '<br />' : ''?>
-              <?=$this->transEsc('Published in')?>
-              <? $containerSource = $this->driver->getSourceIdentifier(); ?>
-              <? $containerID = $this->driver->getContainerRecordID(); ?>
-              <? /* TODO: handle highlighting more elegantly here: */?>
-              <a href="<?=($containerID ? $this->recordLink()->getUrl("$containerSource|$containerID") : $this->record($this->driver)->getLink('journaltitle', str_replace(array('{{{{START_HILITE}}}}', '{{{{END_HILITE}}}}'), '', $journalTitle)))?>"><?=$this->highlight($journalTitle) ?></a>
-              <?=!empty($summDate) ? ' (' . $this->escapeHtml($summDate[0]) . ')' : ''?>
-            <? elseif (!empty($summDate)): ?>
-              <?=!empty($summAuthor) ? '<br />' : ''?>
-              <?=$this->transEsc('Published') . ' ' . $this->escapeHtml($summDate[0])?>
-            <? endif; ?>
-            <? $summInCollection = $this->driver->getContainingCollections(); if (!empty($summInCollection)): ?>
-              <? foreach ($summInCollection as $collId => $collText): ?>
-                <div>
-                  <b><?=$this->transEsc("in_collection_label")?></b>
-                  <a class="collectionLinkText" href="<?=$this->url('collection', array('id' => $collId))?>?recordID=<?=urlencode($this->driver->getUniqueID())?>">
-                    <?=$this->escapeHtml($collText)?>
-                  </a>
-                </div>
-              <? endforeach; ?>
-            <? endif; ?>
+          <? $journalTitle = $this->driver->getContainerTitle(); $summDate = $this->driver->getPublicationDates(); ?>
+          <? if (!empty($journalTitle)): ?>
+            <?=!empty($summAuthor) ? '<br />' : ''?>
+            <?=$this->transEsc('Published in')?>
+            <? $containerSource = $this->driver->getSourceIdentifier(); ?>
+            <? $containerID = $this->driver->getContainerRecordID(); ?>
+            <? /* TODO: handle highlighting more elegantly here: */?>
+            <a href="<?=($containerID ? $this->recordLink()->getUrl("$containerSource|$containerID") : $this->record($this->driver)->getLink('journaltitle', str_replace(array('{{{{START_HILITE}}}}', '{{{{END_HILITE}}}}'), '', $journalTitle)))?>"><?=$this->highlight($journalTitle) ?></a>
+            <?=!empty($summDate) ? ' (' . $this->escapeHtml($summDate[0]) . ')' : ''?>
+          <? elseif (!empty($summDate)): ?>
+            <?=!empty($summAuthor) ? '<br />' : ''?>
+            <?=$this->transEsc('Published') . ' ' . $this->escapeHtml($summDate[0])?>
           <? endif; ?>
-        </div>
+          <? $summInCollection = $this->driver->getContainingCollections(); if (!empty($summInCollection)): ?>
+            <? foreach ($summInCollection as $collId => $collText): ?>
+              <div>
+                <b><?=$this->transEsc("in_collection_label")?></b>
+                <a class="collectionLinkText" href="<?=$this->url('collection', array('id' => $collId))?>?recordID=<?=urlencode($this->driver->getUniqueID())?>">
+                  <?=$this->escapeHtml($collText)?>
+                </a>
+              </div>
+            <? endforeach; ?>
+          <? endif; ?>
+        <? endif; ?>
+      </div>
 
-        <? if(!$this->driver->isCollection()): ?>
-          <? if ($snippet = $this->driver->getHighlightedSnippet()): ?>
-            <? if (!empty($snippet['caption'])): ?>
-              <strong><?=$this->transEsc($snippet['caption']) ?>:</strong> ';
-            <? endif; ?>
-            <? if (!empty($snippet['snippet'])): ?>
-              <span class="quotestart">&#8220;</span>...<?=$this->highlight($snippet['snippet']) ?>...<span class="quoteend">&#8221;</span><br/>
-            <? endif; ?>
+      <? if(!$this->driver->isCollection()): ?>
+        <? if ($snippet = $this->driver->getHighlightedSnippet()): ?>
+          <? if (!empty($snippet['caption'])): ?>
+            <strong><?=$this->transEsc($snippet['caption']) ?>:</strong> ';
+          <? endif; ?>
+          <? if (!empty($snippet['snippet'])): ?>
+            <span class="quotestart">&#8220;</span>...<?=$this->highlight($snippet['snippet']) ?>...<span class="quoteend">&#8221;</span><br/>
           <? endif; ?>
         <? endif; ?>
+      <? endif; ?>
 
+      <?
+      /* Display information on duplicate records if available */
+      if ($dedupData = $this->driver->getDedupData()): ?>
+        <div class="dedupInformation">
         <?
-        /* Display information on duplicate records if available */
-        if ($dedupData = $this->driver->getDedupData()): ?>
-          <div class="dedupInformation">
-          <?
-            $i = 0;
-            foreach ($dedupData as $source => $current) {
-              if (++$i == 1) {
-                ?><span class="currentSource"><a href="<?=$this->recordLink()->getUrl($this->driver)?>"><?=$this->transEsc("source_$source", array(), $source)?></a></span><?
+          $i = 0;
+          foreach ($dedupData as $source => $current) {
+            if (++$i == 1) {
+              ?><span class="currentSource"><a href="<?=$this->recordLink()->getUrl($this->driver)?>"><?=$this->transEsc("source_$source", array(), $source)?></a></span><?
+            } else {
+              if ($i == 2) {
+                ?> <span class="otherSources">(<?=$this->transEsc('Other Sources')?>: <?
               } else {
-                if ($i == 2) {
-                  ?> <span class="otherSources">(<?=$this->transEsc('Other Sources')?>: <?
-                } else {
-                  ?>, <?
-                }
-                ?><a href="<?=$this->recordLink()->getUrl($current['id'])?>"><?=$this->transEsc("source_$source", array(), $source)?></a><?
+                ?>, <?
               }
+              ?><a href="<?=$this->recordLink()->getUrl($current['id'])?>"><?=$this->transEsc("source_$source", array(), $source)?></a><?
             }
-            if ($i > 1) {
-              ?>)</span><?
-            }?>
-          </div>
-        <? endif; ?>
+          }
+          if ($i > 1) {
+            ?>)</span><?
+          }?>
+        </div>
+      <? endif; ?>
 
-        <div class="callnumAndLocation ajax-availability hidden">
-          <? if ($this->driver->supportsAjaxStatus()): ?>
-            <strong class="hideIfDetailed"><?=$this->transEsc('Call Number')?>:</strong>
-            <span class="callnumber ajax-availability hidden">
-              <?=$this->transEsc('Loading')?>...<br/>
-            </span>
-            <strong><?=$this->transEsc('Located')?>:</strong>
-            <span class="location ajax-availability hidden">
-              <?=$this->transEsc('Loading')?>...
-            </span>
-            <div class="locationDetails"></div>
-          <? else: ?>
-            <? $summCallNo = $this->driver->getCallNumber(); if (!empty($summCallNo)): ?>
-              <strong><?=$this->transEsc('Call Number')?>:</strong> <?=$this->escapeHtml($summCallNo)?>
-            <? endif; ?>
+      <div class="callnumAndLocation ajax-availability hidden">
+        <? if ($this->driver->supportsAjaxStatus()): ?>
+          <strong class="hideIfDetailed"><?=$this->transEsc('Call Number')?>:</strong>
+          <span class="callnumber ajax-availability hidden">
+            <?=$this->transEsc('Loading')?>...<br/>
+          </span>
+          <strong><?=$this->transEsc('Located')?>:</strong>
+          <span class="location ajax-availability hidden">
+            <?=$this->transEsc('Loading')?>...
+          </span>
+          <div class="locationDetails"></div>
+        <? else: ?>
+          <? $summCallNo = $this->driver->getCallNumber(); if (!empty($summCallNo)): ?>
+            <strong><?=$this->transEsc('Call Number')?>:</strong> <?=$this->escapeHtml($summCallNo)?>
           <? endif; ?>
-        </div>
+        <? endif; ?>
+      </div>
 
-        <? /* We need to find out if we're supposed to display an OpenURL link ($openUrlActive),
-              but even if we don't plan to display the link, we still want to get the $openUrl
-              value for use in generating a COinS (Z3988) tag -- see bottom of file.
-            */
-          $openUrl = $this->openUrl($this->driver, 'results');
-          $openUrlActive = $openUrl->isActive();
-          // Account for replace_other_urls setting
-          $urls = $this->record($this->driver)->getLinkDetails($openUrlActive);
+      <? /* We need to find out if we're supposed to display an OpenURL link ($openUrlActive),
+            but even if we don't plan to display the link, we still want to get the $openUrl
+            value for use in generating a COinS (Z3988) tag -- see bottom of file.
+          */
+        $openUrl = $this->openUrl($this->driver, 'results');
+        $openUrlActive = $openUrl->isActive();
+        // Account for replace_other_urls setting
+        $urls = $this->record($this->driver)->getLinkDetails($openUrlActive);
 
-          if ($openUrlActive || !empty($urls)): ?>
-          <? if ($openUrlActive): ?>
-            <br/>
-            <?=$openUrl->renderTemplate()?>
-          <? endif; ?>
-          <? if (!is_array($urls)) $urls = array();
-            if(!$this->driver->isCollection()):
-              foreach ($urls as $current): ?>
-                <a href="<?=$this->escapeHtmlAttr($this->proxyUrl($current['url']))?>" class="fulltext" target="new"><i class="fa fa-external-link" aria-hidden="true"></i> <?=($current['url'] == $current['desc']) ? $this->transEsc('Get full text') : $this->escapeHtml($current['desc'])?></a><br/>
-            <? endforeach; ?>
-          <? endif; ?>
+        if ($openUrlActive || !empty($urls)): ?>
+        <? if ($openUrlActive): ?>
+          <br/>
+          <?=$openUrl->renderTemplate()?>
         <? endif; ?>
+        <? if (!is_array($urls)) $urls = array();
+          if(!$this->driver->isCollection()):
+            foreach ($urls as $current): ?>
+              <a href="<?=$this->escapeHtmlAttr($this->proxyUrl($current['url']))?>" class="fulltext" target="new"><i class="fa fa-external-link" aria-hidden="true"></i> <?=($current['url'] == $current['desc']) ? $this->transEsc('Get full text') : $this->escapeHtml($current['desc'])?></a><br/>
+          <? endforeach; ?>
+        <? endif; ?>
+      <? endif; ?>
 
+      <div class="result-formats">
         <?=$this->record($this->driver)->getFormatList() ?>
 
         <? if (!$openUrlActive && empty($urls) && $this->driver->supportsAjaxStatus()): ?>
@@ -145,49 +145,57 @@
             <span class="label label-default"><?=$this->transEsc('Loading')?>...</span>
           </span>
         <? endif; ?>
+      </div>
+
+      <div class="result-previews">
         <?=$this->record($this->driver)->getPreviews()?>
       </div>
-      <div class="col-sm-4 right hidden-print">
-        <? /* Display qrcode if appropriate: */ ?>
-        <? if ($QRCode = $this->record($this->driver)->getQRCode("results")): ?>
-          <?
-            // Add JS Variables for QrCode
-            $this->jsTranslations()->addStrings(array('qrcode_hide' => 'qrcode_hide', 'qrcode_show' => 'qrcode_show'));
-          ?>
-          <span class="hidden-xs">
-            <i class="fa fa-fw fa-qrcode" aria-hidden="true"></i> <a href="<?=$this->escapeHtmlAttr($QRCode);?>" class="qrcodeLink"><?=$this->transEsc('qrcode_show')?></a>
-            <div class="qrcode hidden">
-              <script type="text/template" class="qrCodeImgTag">
-                <img alt="<?=$this->transEsc('QR Code')?>" src="<?=$this->escapeHtmlAttr($QRCode);?>"/>
-              </script>
-            </div><br/>
-          </span>
-        <? endif; ?>
+    </div>
+    <div class="result-links hidden-print">
+      <? /* Display qrcode if appropriate: */ ?>
+      <? if ($QRCode = $this->record($this->driver)->getQRCode("results")): ?>
+        <?
+          // Add JS Variables for QrCode
+          $this->jsTranslations()->addStrings(array('qrcode_hide' => 'qrcode_hide', 'qrcode_show' => 'qrcode_show'));
+        ?>
+        <span class="hidden-xs">
+          <i class="fa fa-fw fa-qrcode" aria-hidden="true"></i> <a href="<?=$this->escapeHtmlAttr($QRCode);?>" class="qrcodeLink"><?=$this->transEsc('qrcode_show')?></a>
+          <div class="qrcode hidden">
+            <script type="text/template" class="qrCodeImgTag">
+              <img alt="<?=$this->transEsc('QR Code')?>" src="<?=$this->escapeHtmlAttr($QRCode);?>"/>
+            </script>
+          </div><br/>
+        </span>
+      <? endif; ?>
 
-        <? if ($this->userlist()->getMode() !== 'disabled'): ?>
-          <? /* Add to favorites */ ?>
-          <i class="fa fa-fw fa-star" aria-hidden="true"></i> <a href="<?=$this->recordLink()->getActionUrl($this->driver, 'Save')?>" data-lightbox class="save-record" data-id="<?=$this->escapeHtmlAttr($this->driver->getUniqueId()) ?>"><?=$this->transEsc('Add to favorites')?></a><br/>
-          <? /* Saved lists */ ?>
-          <div class="savedLists alert alert-info hidden">
-            <strong><?=$this->transEsc("Saved in")?>:</strong>
-          </div>
-        <? endif; ?>
+      <? if ($this->cart()->isActiveInSearch() && $this->params->getOptions()->supportsCart() && $this->cart()->isActive()): ?>
+        <?=$this->render('record/cart-buttons.phtml', ['id' => $this->driver->getUniqueId(), 'source' => $this->driver->getSourceIdentifier()]); ?><br/>
+      <? endif; ?>
 
-        <? /* Hierarchy tree link */ ?>
-        <? $trees = $this->driver->tryMethod('getHierarchyTrees'); if (!empty($trees)): ?>
-          <? foreach ($trees as $hierarchyID => $hierarchyTitle): ?>
-            <div class="hierarchyTreeLink">
-              <input type="hidden" value="<?=$this->escapeHtmlAttr($hierarchyID)?>" class="hiddenHierarchyId" />
-              <i class="fa fa-fw fa-sitemap" aria-hidden="true"></i>
-              <a class="hierarchyTreeLinkText" data-lightbox href="<?=$this->recordLink()->getTabUrl($this->driver, 'HierarchyTree')?>?hierarchy=<?=urlencode($hierarchyID)?>#tabnav" title="<?=$this->transEsc('hierarchy_tree')?>" data-lightbox-href="<?=$this->recordLink()->getTabUrl($this->driver, 'AjaxTab')?>?hierarchy=<?=urlencode($hierarchyID)?>" data-lightbox-post="tab=hierarchytree">
-                <?=$this->transEsc('hierarchy_view_context')?><? if (count($trees) > 1): ?>: <?=$this->escapeHtml($hierarchyTitle)?><? endif; ?>
-              </a>
-            </div>
-          <? endforeach; ?>
-        <? endif; ?>
+      <? if ($this->userlist()->getMode() !== 'disabled'): ?>
+        <? /* Add to favorites */ ?>
+        <i class="result-link-icon fa fa-fw fa-star" aria-hidden="true"></i>
+        <a href="<?=$this->recordLink()->getActionUrl($this->driver, 'Save')?>" data-lightbox class="save-record result-link-label" data-id="<?=$this->escapeHtmlAttr($this->driver->getUniqueId()) ?>"><?=$this->transEsc('Add to favorites')?></a><br/>
+        <? /* Saved lists */ ?>
+        <div class="savedLists">
+          <strong><?=$this->transEsc("Saved in")?>:</strong>
+        </div>
+      <? endif; ?>
 
-        <?=$this->driver->supportsCoinsOpenUrl()?'<span class="Z3988" title="'.$this->escapeHtmlAttr($this->driver->getCoinsOpenUrl()).'"></span>':''?>
-      </div>
+      <? /* Hierarchy tree link */ ?>
+      <? $trees = $this->driver->tryMethod('getHierarchyTrees'); if (!empty($trees)): ?>
+        <? foreach ($trees as $hierarchyID => $hierarchyTitle): ?>
+          <div class="hierarchyTreeLink">
+            <input type="hidden" value="<?=$this->escapeHtmlAttr($hierarchyID)?>" class="hiddenHierarchyId" />
+            <i class="result-link-icon fa fa-fw fa-sitemap" aria-hidden="true"></i>
+            <a class="hierarchyTreeLinkText result-link-label" data-lightbox href="<?=$this->recordLink()->getTabUrl($this->driver, 'HierarchyTree')?>?hierarchy=<?=urlencode($hierarchyID)?>#tabnav" title="<?=$this->transEsc('hierarchy_tree')?>" data-lightbox-href="<?=$this->recordLink()->getTabUrl($this->driver, 'AjaxTab')?>?hierarchy=<?=urlencode($hierarchyID)?>" data-lightbox-post="tab=hierarchytree">
+              <?=$this->transEsc('hierarchy_view_context')?><? if (count($trees) > 1): ?>: <?=$this->escapeHtml($hierarchyTitle)?><? endif; ?>
+            </a>
+          </div>
+        <? endforeach; ?>
+      <? endif; ?>
+
+      <?=$this->driver->supportsCoinsOpenUrl()?'<span class="Z3988" title="'.$this->escapeHtmlAttr($this->driver->getCoinsOpenUrl()).'"></span>':''?>
     </div>
   </div>
   <? if ($thumbnail && $thumbnailAlignment == 'right'): ?>
diff --git a/themes/bootstrap3/templates/RecordDriver/SolrDefault/results-qrcode.phtml b/themes/bootstrap3/templates/RecordDriver/SolrDefault/results-qrcode.phtml
index 52da09f1ae1f2b71e1d35f77c283d48504bc9cbb..e162a0f98f11a5abfaa18b05e1f5c118850948d8 100644
--- a/themes/bootstrap3/templates/RecordDriver/SolrDefault/results-qrcode.phtml
+++ b/themes/bootstrap3/templates/RecordDriver/SolrDefault/results-qrcode.phtml
@@ -1 +1 @@
-<?=$this->serverUrl($this->recordLink()->getUrl($this->driver))?>
\ No newline at end of file
+<?=$this->serverUrl($this->recordLink()->getUrl($this->driver))?>
diff --git a/themes/bootstrap3/templates/RecordDriver/SolrDefault/toolbar.phtml b/themes/bootstrap3/templates/RecordDriver/SolrDefault/toolbar.phtml
index 013497adf9ec58782a8b187889ed4ff6f8598581..6445ed461f2d80ca57eb92e594560776d05c71a2 100644
--- a/themes/bootstrap3/templates/RecordDriver/SolrDefault/toolbar.phtml
+++ b/themes/bootstrap3/templates/RecordDriver/SolrDefault/toolbar.phtml
@@ -3,16 +3,14 @@
   if (!empty($addThis)) {
     $this->headScript()->appendFile('https://s7.addthis.com/js/250/addthis_widget.js?pub=' . urlencode($addThis));
   }
-
-  // Set up some variables for convenience:
-  $cart = $this->cart();
-  $cartId = $this->driver->getSourceIdentifier() . '|' . $this->driver->getUniqueId();
 ?>
-<ul class="nav nav-pills hidden-print">
+<ul class="record-nav nav nav-pills hidden-print">
   <? if (count($this->driver->getCitationFormats()) > 0): ?>
     <li><a class="cite-record" data-lightbox href="<?=$this->recordLink()->getActionUrl($this->driver, 'Cite')?>" rel="nofollow"><i class="fa fa-asterisk" aria-hidden="true"></i> <?=$this->transEsc('Cite this')?></a></li>
   <? endif; ?>
-  <li><a class="sms-record" data-lightbox href="<?=$this->recordLink()->getActionUrl($this->driver, 'SMS')?>" rel="nofollow"><i class="fa fa-mobile" aria-hidden="true"></i> <?=$this->transEsc('Text this')?></a></li>
+  <? if ($this->accountCapabilities()->getSmsSetting() !== 'disabled'): ?>
+    <li><a class="sms-record" data-lightbox href="<?=$this->recordLink()->getActionUrl($this->driver, 'SMS')?>" rel="nofollow"><i class="fa fa-mobile" aria-hidden="true"></i> <?=$this->transEsc('Text this')?></a></li>
+  <? endif; ?>
   <li><a class="mail-record" data-lightbox href="<?=$this->recordLink()->getActionUrl($this->driver, 'Email')?>" rel="nofollow"><i class="fa fa-envelope" aria-hidden="true"></i> <?=$this->transEsc('Email this')?></a></li>
 
   <? $exportFormats = $this->export()->getFormatsForRecord($this->driver); ?>
@@ -33,21 +31,5 @@
   <? if (!empty($addThis)): ?>
     <li><a class="addThis addthis_button" href="https://www.addthis.com/bookmark.php?v=250&amp;pub=<?=urlencode($addThis)?>"><i class="fa fa-bookmark" aria-hidden="true"></i> <?=$this->transEsc('Bookmark')?></a></li>
   <? endif; ?>
-  <? if ($cart->isActive()): ?>
-    <li class="bookbag-menu">
-      <input class="cartId" type="hidden" name="ids[]" value="<?=$this->escapeHtmlAttr($cartId)?>" />
-      <a class="cart-add hidden<? if(!$cart->contains($cartId)): ?> correct<? endif ?>" href="#"><i class="fa fa-plus" aria-hidden="true"></i> <?=$this->transEsc('Add to Book Bag') ?></a>
-      <a class="cart-remove hidden<? if($cart->contains($cartId)): ?> correct<? endif ?>"href="#"><i class="fa fa-minus-circle" aria-hidden="true"></i> <?=$this->transEsc('Remove from Book Bag') ?></a>
-      <noscript>
-        <form method="post" name="addForm" action="<?=$this->url('cart-processor')?>">
-          <input type="hidden" name="ids[]" value="<?=$this->escapeHtmlAttr($cartId)?>" />
-          <? if ($cart->contains($cartId)): ?>
-            <input class="btn btn-default" type="submit" name="delete" value="<?=$this->transEsc('Remove from Book Bag')?>"/>
-          <? else: ?>
-            <input class="btn btn-default" type="submit" name="add" value="<?=$this->transEsc('Add to Book Bag')?>"/>
-          <? endif; ?>
-        </form>
-      </noscript>
-    </li>
-  <? endif; ?>
-</ul>
\ No newline at end of file
+  <?=$this->render('record/cart-buttons.phtml', ['id' => $this->driver->getUniqueId(), 'source' => $this->driver->getSourceIdentifier()]); ?>
+</ul>
diff --git a/themes/bootstrap3/templates/RecordDriver/SolrWeb/result-list.phtml b/themes/bootstrap3/templates/RecordDriver/SolrWeb/result-list.phtml
index f6ca14f38305c92275774cc7ea773a89d5fa2442..3cf9f42b6fc0474eebaaf7211016dbccf8415e14 100644
--- a/themes/bootstrap3/templates/RecordDriver/SolrWeb/result-list.phtml
+++ b/themes/bootstrap3/templates/RecordDriver/SolrWeb/result-list.phtml
@@ -26,4 +26,4 @@
       <? endif; ?>
     </div>
   </div>
-</div>
\ No newline at end of file
+</div>
diff --git a/themes/bootstrap3/templates/RecordDriver/Summon/format-class.phtml b/themes/bootstrap3/templates/RecordDriver/Summon/format-class.phtml
index 5601e7f5710eb1c0cfd601f580dcdb2eeed2b292..ee5e6148494c74efc4a9ff2690f34ef0b525c1c4 100644
--- a/themes/bootstrap3/templates/RecordDriver/Summon/format-class.phtml
+++ b/themes/bootstrap3/templates/RecordDriver/Summon/format-class.phtml
@@ -41,4 +41,4 @@
           echo 'journal';
           break;
   }
-?>
\ No newline at end of file
+?>
diff --git a/themes/bootstrap3/templates/RecordDriver/Summon/link-author.phtml b/themes/bootstrap3/templates/RecordDriver/Summon/link-author.phtml
index 5aebd76f472dedf0a45e8d96de75376ed44caa8e..92b2b7e0c88d69608f8842a5d6cccad156c72dfe 100644
--- a/themes/bootstrap3/templates/RecordDriver/Summon/link-author.phtml
+++ b/themes/bootstrap3/templates/RecordDriver/Summon/link-author.phtml
@@ -1 +1 @@
-<?=$this->url('summon-search')?>?lookfor=%22<?=urlencode($this->lookfor)?>%22&amp;type=Author
\ No newline at end of file
+<?=$this->url('summon-search')?>?lookfor=%22<?=urlencode($this->lookfor)?>%22&amp;type=Author
diff --git a/themes/bootstrap3/templates/RecordDriver/Summon/link-journaltitle.phtml b/themes/bootstrap3/templates/RecordDriver/Summon/link-journaltitle.phtml
index 5536935b4f4be76c407a7dd867e1d3f1365c31aa..c59ac07df930cdf8bdea4703f9f84a82b5f197d6 100644
--- a/themes/bootstrap3/templates/RecordDriver/Summon/link-journaltitle.phtml
+++ b/themes/bootstrap3/templates/RecordDriver/Summon/link-journaltitle.phtml
@@ -1 +1 @@
-<?=$this->url('summon-search')?>?lookfor=%22<?=urlencode($this->lookfor)?>%22&amp;type=PublicationTitle
\ No newline at end of file
+<?=$this->url('summon-search')?>?lookfor=%22<?=urlencode($this->lookfor)?>%22&amp;type=PublicationTitle
diff --git a/themes/bootstrap3/templates/RecordDriver/Summon/link-series.phtml b/themes/bootstrap3/templates/RecordDriver/Summon/link-series.phtml
index 26a9524f15a53509bf7ac0cb7d8416536fbdbbda..e976f888e2df97dabbee5af2566cdd997ec64fbd 100644
--- a/themes/bootstrap3/templates/RecordDriver/Summon/link-series.phtml
+++ b/themes/bootstrap3/templates/RecordDriver/Summon/link-series.phtml
@@ -1 +1 @@
-<?=$this->url('summon-search')?>?lookfor=%22<?=urlencode($this->lookfor)?>%22&amp;type=PublicationSeriesTitle
\ No newline at end of file
+<?=$this->url('summon-search')?>?lookfor=%22<?=urlencode($this->lookfor)?>%22&amp;type=PublicationSeriesTitle
diff --git a/themes/bootstrap3/templates/RecordDriver/Summon/link-subject.phtml b/themes/bootstrap3/templates/RecordDriver/Summon/link-subject.phtml
index cf66f99c10196f7e8380bf6955a933fc2730e6e9..04c12d143e671a4840ece3c3172394c86c7ada85 100644
--- a/themes/bootstrap3/templates/RecordDriver/Summon/link-subject.phtml
+++ b/themes/bootstrap3/templates/RecordDriver/Summon/link-subject.phtml
@@ -1 +1 @@
-<?=$this->url('summon-search')?>?lookfor=%22<?=urlencode($this->lookfor)?>%22&amp;type=Subject
\ No newline at end of file
+<?=$this->url('summon-search')?>?lookfor=%22<?=urlencode($this->lookfor)?>%22&amp;type=Subject
diff --git a/themes/bootstrap3/templates/RecordDriver/Summon/link-title.phtml b/themes/bootstrap3/templates/RecordDriver/Summon/link-title.phtml
index 57cdc24f2d6d29a12d49a08447a5d08928a47b85..a0c3d42e7c7adda27d38c46c5f196136973e2c37 100644
--- a/themes/bootstrap3/templates/RecordDriver/Summon/link-title.phtml
+++ b/themes/bootstrap3/templates/RecordDriver/Summon/link-title.phtml
@@ -1 +1 @@
-<?=$this->url('summon-search')?>?lookfor=%22<?=urlencode($this->lookfor)?>%22&amp;type=Title
\ No newline at end of file
+<?=$this->url('summon-search')?>?lookfor=%22<?=urlencode($this->lookfor)?>%22&amp;type=Title
diff --git a/themes/bootstrap3/templates/RecordDriver/WorldCat/link-series.phtml b/themes/bootstrap3/templates/RecordDriver/WorldCat/link-series.phtml
index d95ad084838175f0a631beffe32ea08268c1dd06..89d53346e5acba78792203c9aa4911f4ab008653 100644
--- a/themes/bootstrap3/templates/RecordDriver/WorldCat/link-series.phtml
+++ b/themes/bootstrap3/templates/RecordDriver/WorldCat/link-series.phtml
@@ -1 +1 @@
-<?=$this->url('worldcat-search')?>?lookfor=%22<?=urlencode($this->lookfor)?>%22&amp;type=srw.se
\ No newline at end of file
+<?=$this->url('worldcat-search')?>?lookfor=%22<?=urlencode($this->lookfor)?>%22&amp;type=srw.se
diff --git a/themes/bootstrap3/templates/RecordDriver/WorldCat/link-subject.phtml b/themes/bootstrap3/templates/RecordDriver/WorldCat/link-subject.phtml
index 6b6bb5c92351d841d4bb25b8cf4b28bdd27e4013..43af476c9d2a070414eedb9f559e2024fb23ef95 100644
--- a/themes/bootstrap3/templates/RecordDriver/WorldCat/link-subject.phtml
+++ b/themes/bootstrap3/templates/RecordDriver/WorldCat/link-subject.phtml
@@ -1 +1 @@
-<?=$this->url('worldcat-search')?>?lookfor=%22<?=urlencode($this->lookfor)?>%22&amp;type=srw.su
\ No newline at end of file
+<?=$this->url('worldcat-search')?>?lookfor=%22<?=urlencode($this->lookfor)?>%22&amp;type=srw.su
diff --git a/themes/bootstrap3/templates/RecordDriver/WorldCat/link-title.phtml b/themes/bootstrap3/templates/RecordDriver/WorldCat/link-title.phtml
index 03f8d524558d20d3a643d5ea3b36e76553d3a8e2..dd9e85bd2a38f342bcf4f7691c253cc9e0e1a9ad 100644
--- a/themes/bootstrap3/templates/RecordDriver/WorldCat/link-title.phtml
+++ b/themes/bootstrap3/templates/RecordDriver/WorldCat/link-title.phtml
@@ -1 +1 @@
-<?=$this->url('worldcat-search')?>?lookfor=%22<?=urlencode($this->lookfor)?>%22&amp;type=srw.ti%3Asrw.se
\ No newline at end of file
+<?=$this->url('worldcat-search')?>?lookfor=%22<?=urlencode($this->lookfor)?>%22&amp;type=srw.ti%3Asrw.se
diff --git a/themes/bootstrap3/templates/RecordTab/collectionhierarchytree.phtml b/themes/bootstrap3/templates/RecordTab/collectionhierarchytree.phtml
index a4bda17e27b1d8bcb20f26a91556221f8d8f50a5..a03b1fc56c9b98263128caee84e5ea33a4eea3ef 100644
--- a/themes/bootstrap3/templates/RecordTab/collectionhierarchytree.phtml
+++ b/themes/bootstrap3/templates/RecordTab/collectionhierarchytree.phtml
@@ -1,22 +1,16 @@
-<?
-    $this->mainTreeClass = 'col-sm-6';
-    $this->treeContext = 'Collection';
-?>
-<div class="row">
-  <div class="col-sm-6">
+<? $this->treeContext = 'Collection'; ?>
+
+<div class="collection-hierarchytree">
+  <div class="tree-panel">
     <?=$this->render('RecordTab/hierarchytree.phtml')?>
   </div>
-  <div class="col-sm-6">
-    <div id="hierarchyRecordHolder">
-      <div id="hierarchyRecord">
-        <? if (($collectionRecord = $this->tab->getActiveRecord()) !== false): ?>
-          <? if ($collectionRecord === null): ?>
-            <?=$this->render('collection/collection-record-error.phtml')?>
-          <? else: ?>
-            <?=html_entity_decode($this->record($collectionRecord)->getCollectionBriefRecord())?>
-          <? endif; ?>
-        <? endif; ?>
-      </div>
-    </div>
+  <div id="tree-preview">
+    <? if (($collectionRecord = $this->tab->getActiveRecord()) !== false): ?>
+      <? if ($collectionRecord === null): ?>
+        <?=$this->render('collection/collection-record-error.phtml')?>
+      <? else: ?>
+        <?=html_entity_decode($this->record($collectionRecord)->getCollectionBriefRecord())?>
+      <? endif; ?>
+    <? endif; ?>
   </div>
 </div>
diff --git a/themes/bootstrap3/templates/RecordTab/collectionlist.phtml b/themes/bootstrap3/templates/RecordTab/collectionlist.phtml
index 7519425906264a442365d1b55090deb0671109a1..6d7b52855b637dcac464e0f1356cc40265f1206d 100644
--- a/themes/bootstrap3/templates/RecordTab/collectionlist.phtml
+++ b/themes/bootstrap3/templates/RecordTab/collectionlist.phtml
@@ -5,7 +5,7 @@
   // Get search results
   $results = $this->tab->getResults();
   $params = $this->tab->getParams();
-  $searchDetails = array('results' => $results, 'params' => $params, 'indexStart' => 1);
+  $searchDetails = ['results' => $results, 'params' => $params, 'indexStart' => 1];
 ?>
 <? if (($recordTotal = $results->getResultTotal()) > 0): // only display these at very top if we have results ?>
   <? foreach ($results->getRecommendations('top') as $current): ?>
@@ -13,10 +13,17 @@
   <? endforeach; ?>
   <div class="clearfix hidden-print">
     <div class="pull-left flip">
-      <?=$this->transEsc("Showing")?>
-      <strong><?=$this->localizedNumber($results->getStartRecord())?></strong> - <strong><?=$this->localizedNumber($results->getEndRecord())?></strong>
+      <?
+        $transParams = [
+          '%%start%%' => $this->localizedNumber($results->getStartRecord()),
+          '%%end%%'   => $this->localizedNumber($results->getEndRecord()),
+          '%%total%%' => $this->localizedNumber($recordTotal)
+        ];
+      ?>
       <? if (!isset($this->skipTotalCount)): ?>
-        <?=$this->transEsc('of')?> <strong><?=$this->localizedNumber($recordTotal)?></strong> <?=$this->transEsc('Items')?>
+        <?=$this->translate('showing_items_of_html', $transParams); ?>
+      <? else: ?>
+        <?=$this->translate('showing_items_html', $transParams); ?>
       <? endif; ?>
     </div>
     <div class="pull-right flip">
@@ -25,9 +32,9 @@
     </div>
   </div>
   <form class="form-inline" method="post" name="bulkActionForm" action="<?=$this->url('cart-searchresultsbulk')?>">
-    <?=$this->context($this)->renderInContext('search/bulk-action-buttons.phtml', $searchDetails + array('idPrefix' => ''))?>
+    <?=$this->context($this)->renderInContext('search/bulk-action-buttons.phtml', $searchDetails + ['idPrefix' => ''])?>
     <?=$this->render('search/list-' . $results->getParams()->getView() . '.phtml', $searchDetails)?>
-    <?=$this->paginationControl($results->getPaginator(), 'Sliding', 'search/pagination.phtml', array('results' => $results))?>
+    <?=$this->paginationControl($results->getPaginator(), 'Sliding', 'search/pagination.phtml', ['results' => $results])?>
   </form>
 <? else: ?>
   <?=$this->transEsc('collection_empty')?>
diff --git a/themes/bootstrap3/templates/RecordTab/description.phtml b/themes/bootstrap3/templates/RecordTab/description.phtml
index f4de972c4e7ba06562396f5164647b5a6df85e54..3d73373ffc50f983c38e8046f959e60cd5c6e6fc 100644
--- a/themes/bootstrap3/templates/RecordTab/description.phtml
+++ b/themes/bootstrap3/templates/RecordTab/description.phtml
@@ -2,237 +2,15 @@
     // Set page title.
     $this->headTitle($this->translate('Description') . ': ' . $this->driver->getBreadcrumb());
 
-    // Grab clean ISBN for convenience:
-    $isbn = $this->driver->getCleanISBN();
+    $formatter = $this->recordDataFormatter();
+    $mainFields = $formatter->getData($driver, $formatter->getDefaults('description'));
 ?>
 <table class="table table-striped" summary="<?=$this->transEsc('Description')?>">
-  <? $summ = $this->driver->getSummary(); if (!empty($summ)): ?>
-    <? $contentDisplayed = true; ?>
-    <tr>
-      <th><?=$this->transEsc('Summary')?>: </th>
-      <td>
-        <? foreach ($summ as $field): ?>
-          <?=$this->escapeHtml($field)?><br/>
-        <? endforeach; ?>
-      </td>
-    </tr>
-  <? endif; ?>
-
-  <? $dateSpan = $this->driver->getDateSpan(); if (!empty($dateSpan)): ?>
-    <? $contentDisplayed = true; ?>
-    <tr>
-      <th><?=$this->transEsc('Published')?>: </th>
-      <td>
-        <? foreach ($dateSpan as $field): ?>
-          <?=$this->escapeHtml($field)?><br/>
-        <? endforeach; ?>
-      </td>
-    </tr>
-  <? endif; ?>
-
-  <? $notes = $this->driver->getGeneralNotes(); if (!empty($notes)): ?>
-    <? $contentDisplayed = true; ?>
-    <tr>
-      <th><?=$this->transEsc('Item Description')?>: </th>
-      <td>
-        <? foreach ($notes as $field): ?>
-          <?=$this->escapeHtml($field)?><br/>
-        <? endforeach; ?>
-      </td>
-    </tr>
-  <? endif; ?>
-
-  <? $physical = $this->driver->getPhysicalDescriptions(); if (!empty($physical)): ?>
-    <? $contentDisplayed = true; ?>
-    <tr>
-      <th><?=$this->transEsc('Physical Description')?>: </th>
-      <td>
-        <? foreach ($physical as $field): ?>
-          <?=$this->escapeHtml($field)?><br/>
-        <? endforeach; ?>
-      </td>
-    </tr>
-  <? endif; ?>
-
-  <? $freq = $this->driver->getPublicationFrequency(); if (!empty($freq)): ?>
-    <? $contentDisplayed = true; ?>
-    <tr>
-      <th><?=$this->transEsc('Publication Frequency')?>: </th>
-      <td>
-        <? foreach ($freq as $field): ?>
-          <?=$this->escapeHtml($field)?><br/>
-        <? endforeach; ?>
-      </td>
-    </tr>
-  <? endif; ?>
-
-  <? $playTime = $this->driver->getPlayingTimes(); if (!empty($playTime)): ?>
-    <? $contentDisplayed = true; ?>
-    <tr>
-      <th><?=$this->transEsc('Playing Time')?>: </th>
-      <td>
-        <? foreach ($playTime as $field): ?>
-          <?=$this->escapeHtml($field)?><br/>
-        <? endforeach; ?>
-      </td>
-    </tr>
-  <? endif; ?>
-
-  <? $system = $this->driver->getSystemDetails(); if (!empty($system)): ?>
-    <? $contentDisplayed = true; ?>
-    <tr>
-      <th><?=$this->transEsc('Format')?>: </th>
-      <td>
-        <? foreach ($system as $field): ?>
-          <?=$this->escapeHtml($field)?><br/>
-        <? endforeach; ?>
-      </td>
-    </tr>
-  <? endif; ?>
-
-  <? $audience = $this->driver->getTargetAudienceNotes(); if (!empty($audience)): ?>
-    <? $contentDisplayed = true; ?>
-    <tr>
-      <th><?=$this->transEsc('Audience')?>: </th>
-      <td>
-        <? foreach ($audience as $field): ?>
-          <?=$this->escapeHtml($field)?><br/>
-        <? endforeach; ?>
-      </td>
-    </tr>
-  <? endif; ?>
-
-  <? $awards = $this->driver->getAwards(); if (!empty($awards)): ?>
-    <? $contentDisplayed = true; ?>
-    <tr>
-      <th><?=$this->transEsc('Awards')?>: </th>
-      <td>
-        <? foreach ($awards as $field): ?>
-          <?=$this->escapeHtml($field)?><br/>
-        <? endforeach; ?>
-      </td>
-    </tr>
-  <? endif; ?>
-
-  <? $credits = $this->driver->getProductionCredits(); if (!empty($credits)): ?>
-    <? $contentDisplayed = true; ?>
-    <tr>
-      <th><?=$this->transEsc('Production Credits')?>: </th>
-      <td>
-        <? foreach ($credits as $field): ?>
-          <?=$this->escapeHtml($field)?><br/>
-        <? endforeach; ?>
-      </td>
-    </tr>
-  <? endif; ?>
-
-  <? $bib = $this->driver->getBibliographyNotes(); if (!empty($bib)): ?>
-    <? $contentDisplayed = true; ?>
-    <tr>
-      <th><?=$this->transEsc('Bibliography')?>: </th>
-      <td>
-        <? foreach ($bib as $field): ?>
-          <?=$this->escapeHtml($field)?><br/>
-        <? endforeach; ?>
-      </td>
-    </tr>
-  <? endif; ?>
-
-  <? $isbns = $this->driver->getISBNs(); if (!empty($isbns)): ?>
-    <? $contentDisplayed = true; ?>
-    <tr>
-      <th><?=$this->transEsc('ISBN')?>: </th>
-      <td>
-        <? foreach ($isbns as $field): ?>
-          <?=$this->escapeHtml($field)?><br/>
-        <? endforeach; ?>
-      </td>
-    </tr>
-  <? endif; ?>
-
-  <? $issns = $this->driver->getISSNs(); if (!empty($issns)): ?>
-    <? $contentDisplayed = true; ?>
-    <tr>
-      <th><?=$this->transEsc('ISSN')?>: </th>
-      <td>
-        <? foreach ($issns as $field): ?>
-          <?=$this->escapeHtml($field)?><br/>
-        <? endforeach; ?>
-      </td>
-    </tr>
-  <? endif; ?>
-
-  <? $doi = $this->driver->tryMethod('getCleanDOI'); if (!empty($doi)): ?>
-    <? $contentDisplayed = true; ?>
-    <tr>
-      <th><?=$this->transEsc('DOI')?>: </th>
-      <td><?=$this->escapeHtml($doi)?></td>
-    </tr>
-  <? endif; ?>
-
-  <? $related = $this->driver->getRelationshipNotes(); if (!empty($related)): ?>
-    <? $contentDisplayed = true; ?>
-    <tr>
-      <th><?=$this->transEsc('Related Items')?>: </th>
-      <td>
-        <? foreach ($related as $field): ?>
-          <?=$this->escapeHtml($field)?><br/>
-        <? endforeach; ?>
-      </td>
-    </tr>
-  <? endif; ?>
-
-  <? $access = $this->driver->getAccessRestrictions(); if (!empty($access)): ?>
-    <? $contentDisplayed = true; ?>
-    <tr>
-      <th><?=$this->transEsc('Access')?>: </th>
-      <td>
-        <? foreach ($access as $field): ?>
-          <?=$this->escapeHtml($field)?><br/>
-        <? endforeach; ?>
-      </td>
-    </tr>
-  <? endif; ?>
-
-  <? $findingAids = $this->driver->getFindingAids(); if (!empty($findingAids)): ?>
-    <? $contentDisplayed = true; ?>
-    <tr>
-      <th><?=$this->transEsc('Finding Aid')?>: </th>
-      <td>
-        <? foreach ($findingAids as $field): ?>
-          <?=$this->escapeHtml($field)?><br/>
-        <? endforeach; ?>
-      </td>
-    </tr>
-  <? endif; ?>
-
-  <? $publicationPlaces = $this->driver->getHierarchicalPlaceNames(); if (!empty($publicationPlaces)): ?>
-    <? $contentDisplayed = true; ?>
-    <tr>
-      <th><?=$this->transEsc('Publication_Place')?>: </th>
-      <td>
-        <? foreach ($publicationPlaces as $field): ?>
-          <?=$this->escapeHtml($field)?><br/>
-        <? endforeach; ?>
-      </td>
-    </tr>
-  <? endif; ?>
-
-  <? $authorNotes = empty($isbn) ? array() : $this->authorNotes($isbn); if (!empty($authorNotes)): ?>
-    <? $contentDisplayed = true; ?>
-    <tr>
-      <th><?=$this->transEsc('Author Notes')?>: </th>
-      <td>
-        <? foreach ($authorNotes as $provider => $list): ?>
-          <? foreach ($list as $field): ?>
-            <?=$field['Content']?><br/>
-          <? endforeach; ?>
-        <? endforeach; ?>
-      </td>
-    </tr>
-  <? endif; ?>
-
-  <? if (!isset($contentDisplayed) || !$contentDisplayed): // Avoid errors if there were no rows above ?>
+  <? if (!empty($mainFields)): ?>
+    <? foreach ($mainFields as $key => $current): ?>
+      <tr><th><?=$this->transEsc($key)?>:</th><td><?=$current['value']?></td></tr>
+    <? endforeach; ?>
+  <? else: ?>
     <tr><td><?=$this->transEsc('no_description')?></td></tr>
   <? endif; ?>
 </table>
diff --git a/themes/bootstrap3/templates/RecordTab/hierarchytree.phtml b/themes/bootstrap3/templates/RecordTab/hierarchytree.phtml
index 710844ba4504c12787b9108f386ca7bdcccb9136..3a788b8cdebfcca74c3305aed128d6afa7456e61 100644
--- a/themes/bootstrap3/templates/RecordTab/hierarchytree.phtml
+++ b/themes/bootstrap3/templates/RecordTab/hierarchytree.phtml
@@ -13,7 +13,7 @@
      'SET'
   );
   $this->jsTranslations()->addStrings(
-    array('showTree' => 'hierarchy_show_tree', 'hideTree' => 'hierarchy_hide_tree')
+    ['showTree' => 'hierarchy_show_tree', 'hideTree' => 'hierarchy_hide_tree']
   );
   $this->inlineScript(\Zend\View\Helper\HeadScript::FILE, 'vendor/jsTree/jstree.min.js');
   $this->inlineScript(\Zend\View\Helper\HeadScript::FILE, 'hierarchyTree.js');
@@ -43,7 +43,7 @@
         <i id="treeSearchLoadingImg" class="fa fa-spinner fa-spin hidden" aria-hidden="true"></i>
       </div>
       <div id="treeSearchNoResults" class="alert alert-danger hidden"><?=$this->translate('nohit_heading')?></div>
-      <div id="treeSearchLimitReached" class="alert alert-danger hidden"><?=$this->translate('tree_search_limit_reached_html', array('%%url%%' => $this->url('search-results'), '%%limit%%' => $this->tab->getSearchLimit()))?></div>
+      <div id="treeSearchLimitReached" class="alert alert-danger hidden"><?=$this->translate('tree_search_limit_reached_html', ['%%url%%' => $this->url('search-results'), '%%limit%%' => $this->tab->getSearchLimit()])?></div>
     <? endif; ?>
     <div id="hierarchyLoading" class="hide"><i class="fa fa-spinner fa-spin" aria-hidden="true"></i> <?=$this->transEsc("Loading")?>...</div>
     <div id="hierarchyTree" class="hierarchy-tree">
diff --git a/themes/bootstrap3/templates/RecordTab/holdingsils.phtml b/themes/bootstrap3/templates/RecordTab/holdingsils.phtml
index 683f14c74a5415fe374fe24c81c2415f9032d877..2ef3ceeb56e13cb368ced08596e2b0df3146e113 100644
--- a/themes/bootstrap3/templates/RecordTab/holdingsils.phtml
+++ b/themes/bootstrap3/templates/RecordTab/holdingsils.phtml
@@ -10,31 +10,37 @@
     try {
         $holdings = $this->driver->getRealTimeHoldings();
     } catch (\VuFind\Exception\ILS $e) {
-        $holdings = [];
+        $holdings = ['holdings' => []];
         $offlineMode = 'ils-offline';
     }
     // Set page title.
     $this->headTitle($this->translate('Holdings') . ': ' . $this->driver->getBreadcrumb());
 ?>
 
-<?=$this->context($this)->renderInContext('librarycards/selectcard.phtml', array('user' => $this->auth()->isLoggedIn())); ?>
+<?=$this->context($this)->renderInContext('librarycards/selectcard.phtml', ['user' => $this->auth()->isLoggedIn()]); ?>
+
+<? if (!empty($holdings['blocks'])):?>
+  <div id="account-block-msg" class="alert alert-danger">
+    <?=$this->transEsc('account_block_options_missing', ['%%details%%' => implode('; ', $holdings['blocks'])]) ?>
+  </div>
+<? endif; ?>
 
 <?=($offlineMode == "ils-offline") ? $this->render('Helpers/ils-offline.phtml', ['offlineModeMsg' => 'ils_offline_holdings_message']) : ''?>
-<? if (($this->ils()->getHoldsMode() == 'driver' && !empty($holdings)) || $this->ils()->getTitleHoldsMode() == 'driver'): ?>
+<? if (($this->ils()->getHoldsMode() == 'driver' && !empty($holdings['holdings'])) || $this->ils()->getTitleHoldsMode() == 'driver'): ?>
   <? if ($account->loginEnabled() && $offlineMode != 'ils-offline'): ?>
     <? if (!$user): ?>
       <div class="alert alert-info">
-        <a href="<?=$this->recordLink()->getTabUrl($this->driver, 'Holdings')?>?login=true&amp;catalogLogin=true" data-lightbox><?=$this->transEsc("Login")?></a> <?=$this->transEsc("hold_login")?>
+        <a href="<?=$this->recordLink()->getTabUrl($this->driver, 'Holdings')?>?login=true&amp;catalogLogin=true" data-lightbox><?=$this->transEsc("hold_login")?></a>
       </div>
     <? elseif (!$user->cat_username): ?>
       <div class="alert alert-info">
-        <?=$this->translate("hold_profile_html", array('%%url%%' => $this->recordLink()->getTabUrl($this->driver, 'Holdings') . '?catalogLogin=true'))?>
+        <?=$this->translate("hold_profile_html", ['%%url%%' => $this->recordLink()->getTabUrl($this->driver, 'Holdings') . '?catalogLogin=true'])?>
       </div>
     <? endif; ?>
   <? endif; ?>
 <? endif; ?>
 <? $holdingTitleHold = $this->driver->tryMethod('getRealTimeTitleHold'); if (!empty($holdingTitleHold)): ?>
-    <a class="placehold" data-lightbox title="<?=$this->transEsc('request_place_text')?>" href="<?=$this->recordLink()->getRequestUrl($holdingTitleHold)?>"><i class="fa fa-flag" aria-hidden="true"></i>&nbsp;<?=$this->transEsc('title_hold_place')?></a>
+  <a class="placehold" data-lightbox title="<?=$this->transEsc('request_place_text')?>" href="<?=$this->recordLink()->getRequestUrl($holdingTitleHold)?>"><i class="fa fa-flag" aria-hidden="true"></i>&nbsp;<?=$this->transEsc('title_hold_place')?></a>
 <? endif; ?>
 <? if (!empty($urls) || $openUrlActive): ?>
   <h3><?=$this->transEsc("Internet")?></h3>
@@ -45,16 +51,16 @@
   <? endif; ?>
   <? if ($openUrlActive): ?><?=$openUrl->renderTemplate()?><? endif; ?>
 <? endif; ?>
-<? foreach ($holdings as $holding): ?>
+<? foreach ($holdings['holdings'] as $holding): ?>
 <h3>
-  <? $locationText = $this->transEsc('location_' . $holding['location'], array(), $holding['location']); ?>
+  <? $locationText = $this->transEsc('location_' . $holding['location'], [], $holding['location']); ?>
   <? if (isset($holding['locationhref']) && $holding['locationhref']): ?>
     <a href="<?=$holding['locationhref']?>" target="_blank"><?=$locationText?></a>
   <? else: ?>
     <?=$locationText?>
   <? endif; ?>
 </h3>
-<table class="table table-striped" summary="<?=$this->transEsc('Holdings details from')?> <?=$this->transEsc($holding['location'])?>">
+<table class="table table-striped" summary="<?=$this->transEsc('holdings_details_from', ['%%location%%' => $this->transEsc($holding['location'])]) ?>">
   <? $callNos = $this->tab->getUniqueCallNumbers($holding['items']); if (!empty($callNos)): ?>
   <tr>
     <th><?=$this->transEsc("Call Number")?>: </th>
@@ -87,10 +93,6 @@
       $check = isset($row['check']) && $row['check'];
       $checkStorageRetrievalRequest = isset($row['checkStorageRetrievalRequest']) && $row['checkStorageRetrievalRequest'];
       $checkILLRequest = isset($row['checkILLRequest']) && $row['checkILLRequest'];
-      // AJAX block record?
-      $block = !$check && isset($row['addLink']) && $row['addLink'] === 'block';
-      $blockStorageRetrievalRequest = !$checkStorageRetrievalRequest && isset($row['addStorageRetrievalRequestLink']) && $row['addStorageRetrievalRequestLink'] === 'block';
-      $blockILLRequest = !$checkILLRequest && isset($row['addILLRequestLink']) && $row['addILLRequestLink'] === 'block';
     ?>
     <? if (isset($row['barcode']) && $row['barcode'] != ""): ?>
       <tr vocab="http://schema.org/" typeof="Offer">
@@ -106,13 +108,13 @@
             <? if ($row['availability']): ?>
               <? /* Begin Available Items (Holds) */ ?>
                <span class="text-success"><?=$this->transEsc("Available")?><link property="availability" href="http://schema.org/InStock" /></span>
-              <? if (!$block && isset($row['link']) && $row['link']): ?>
-                <a class="<?=$check ? 'checkRequest ' : ''?>placehold" data-lightbox href="<?=$this->recordLink()->getRequestUrl($row['link'])?>"><i class="fa fa-flag" aria-hidden="true"></i>&nbsp;<?=$this->transEsc($check ? "Check Hold" : "Place a Hold")?></a>
+              <? if (isset($row['link']) && $row['link']): ?>
+                <a class="<?=$check ? 'checkRequest ' : ''?>placehold" <? if (!empty($row['linkLightbox'])): ?>data-lightbox <? endif; ?>href="<?=$this->recordLink()->getRequestUrl($row['link'])?>"><i class="fa fa-flag" aria-hidden="true"></i>&nbsp;<?=$this->transEsc($check ? "Check Hold" : "Place a Hold")?></a>
               <? endif; ?>
-              <? if (!$blockStorageRetrievalRequest && isset($row['storageRetrievalRequestLink']) && $row['storageRetrievalRequestLink']): ?>
+              <? if (isset($row['storageRetrievalRequestLink']) && $row['storageRetrievalRequestLink']): ?>
                 <a class="<?=$checkStorageRetrievalRequest ? 'checkStorageRetrievalRequest ' : ''?> placeStorageRetrievalRequest" data-lightbox href="<?=$this->recordLink()->getRequestUrl($row['storageRetrievalRequestLink'])?>"><i class="fa fa-flag" aria-hidden="true"></i>&nbsp;<?=$this->transEsc($checkStorageRetrievalRequest ? "storage_retrieval_request_check_text" : "storage_retrieval_request_place_text")?></a>
               <? endif; ?>
-              <? if (!$blockILLRequest && isset($row['ILLRequestLink']) && $row['ILLRequestLink']): ?>
+              <? if (isset($row['ILLRequestLink']) && $row['ILLRequestLink']): ?>
                 <a class="<?=$checkILLRequest ? 'checkILLRequest ' : ''?>placeILLRequest" data-lightbox href="<?=$this->recordLink()->getRequestUrl($row['ILLRequestLink'])?>"><i class="fa fa-flag" aria-hidden="true"></i>&nbsp;<?=$this->transEsc($checkILLRequest ? "ill_request_check_text" : "ill_request_place_text")?></a>
               <? endif; ?>
             <? else: ?>
@@ -125,8 +127,8 @@
               <? if (isset($row['requests_placed']) && $row['requests_placed'] > 0): ?>
                 <span><?=$this->transEsc("Requests")?>: <?=$this->escapeHtml($row['requests_placed'])?></span>
               <? endif; ?>
-              <? if (!$block && isset($row['link']) && $row['link']): ?>
-                <a class="<?=$check ? 'checkRequest' : ''?> placehold" data-lightbox href="<?=$this->recordLink()->getRequestUrl($row['link'])?>"><i class="fa fa-flag" aria-hidden="true"></i>&nbsp;<?=$this->transEsc($check ? "Check Recall" : "Recall This")?></a>
+              <? if (isset($row['link']) && $row['link']): ?>
+                <a class="<?=$check ? 'checkRequest' : ''?> placehold" <? if (!empty($row['linkLightbox'])): ?>data-lightbox <? endif; ?>href="<?=$this->recordLink()->getRequestUrl($row['link'])?>"><i class="fa fa-flag" aria-hidden="true"></i>&nbsp;<?=$this->transEsc($check ? "Check Recall" : "Recall This")?></a>
               <? endif; ?>
             <? endif; ?>
             <? if (isset($row['item_notes'])): ?>
diff --git a/themes/bootstrap3/templates/RecordTab/holdingsworldcat.phtml b/themes/bootstrap3/templates/RecordTab/holdingsworldcat.phtml
index 57c0267ecdd6307f26865dec6a0ec4e42dc0b5a0..a0e7f0a8f982984ae19e92f9b9450fc0945e8ab8 100644
--- a/themes/bootstrap3/templates/RecordTab/holdingsworldcat.phtml
+++ b/themes/bootstrap3/templates/RecordTab/holdingsworldcat.phtml
@@ -21,4 +21,4 @@
   </tr>
 <? endforeach; ?>
 </table>
-<? endif; ?>
\ No newline at end of file
+<? endif; ?>
diff --git a/themes/bootstrap3/templates/RecordTab/map.phtml b/themes/bootstrap3/templates/RecordTab/map.phtml
index 462bcbbfe9056ba87975088eeea2a8da8dbcdce0..34ce75b7aee77f2669a945e02b9b6cd3de839c27 100644
--- a/themes/bootstrap3/templates/RecordTab/map.phtml
+++ b/themes/bootstrap3/templates/RecordTab/map.phtml
@@ -5,75 +5,11 @@
   $this->headLink()->appendStylesheet('vendor/ol/ol.css');
   $mapTabData = $this->tab->getMapTabData();
   $popupTitle = $this->transEsc('map_results_label');
-  $params = array(json_encode($mapTabData), json_encode($popupTitle));
+  $params = [json_encode($mapTabData), json_encode($popupTitle)];
   $jsParams = implode(', ', $params);
   $jsLoad = "loadMapTab(" . $jsParams . ");"; ?>
   <div id="wrap" style="width: 674px; height: 479px">
     <div id="map-canvas" style="width: 100%; height: 100%"><div id="popup"></div></div>
     <?=$this->inlineScript(\Zend\View\Helper\HeadScript::SCRIPT, $jsLoad, 'SET');?>
   </div>
-<? endif; ?>
-<? if (isset($mapType) && ($mapType == 'google')) : ?>
-  <script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?key=<?=$this->tab->getGoogleMapApiKey()?>&amp;language=<?=$this->layout()->userLang?>"></script>
-  <script type="text/javascript">
-  var markers;
-  var markersData;
-  var latlng;
-  var myOptions;
-  var map;
-  var infowindow = new google.maps.InfoWindow({maxWidth: 480, minWidth: 480});
-  function initialize() {
-    markersData = <?=$this->tab->getGoogleMapMarker()?>;
-    latlng = new google.maps.LatLng(0, 0);
-    myOptions = {
-      zoom: 1,
-      center: latlng,
-      mapTypeControl: true,
-      mapTypeControlOptions: {
-          style: google.maps.MapTypeControlStyle.DROPDOWN_MENU
-        },
-      mapTypeId: google.maps.MapTypeId.ROADMAP
-    };
-    map = new google.maps.Map(document.getElementById("map_canvas"),
-      myOptions);
-    showMarkers();
-  }
-  function showMarkers(){
-    deleteOverlays();
-    markers = [];
-    for (var i = 0; i<markersData.length; i++){
-      var disTitle = markersData[i][0].title ? markersData[i][0].title : '';
-      var iconTitle = disTitle;
-      if (disTitle.length>25){
-          iconTitle = disTitle.substring(0,25) + "...";
-      }
-      var markerImg = "https://chart.googleapis.com/chart?chst=d_bubble_text_small&chld=edge_bc|" + iconTitle +"|EEEAE3|";
-      var labelXoffset = 1 + disTitle.length * 4;
-      var latLng = new google.maps.LatLng(markersData[i][0].lat , markersData[i][0].lon)
-      var marker = new google.maps.Marker({
-        position: latLng,
-        map: map,
-        title: disTitle,
-        icon: markerImg
-      });
-      markers.push(marker);
-    }
-  }
-  function deleteOverlays() {
-      if (markers) {
-        for (i in markers) {
-          markers[i].setMap(null);
-        }
-        markers.length = 0;
-      }
-  }
-  function refreshMap() {
-    showMarkers();
-  }
-  google.maps.event.addDomListener(window, 'load', initialize);
-</script>
-
-<div id="wrap" onload="initialize()" style="width: 674px; height: 479px">
-  <div id="map_canvas" style="width: 100%; height: 100%"></div>
-</div>
-<? endif; ?>
+<? endif; ?>
\ No newline at end of file
diff --git a/themes/bootstrap3/templates/RecordTab/similaritemscarousel.phtml b/themes/bootstrap3/templates/RecordTab/similaritemscarousel.phtml
index c4f61873124ad969fdb2df935480e56673edf5ee..c2e591b20bc4d1a281dbdf08e255133d68820dc8 100644
--- a/themes/bootstrap3/templates/RecordTab/similaritemscarousel.phtml
+++ b/themes/bootstrap3/templates/RecordTab/similaritemscarousel.phtml
@@ -14,33 +14,29 @@
     <!-- Wrapper for slides -->
     <div class="carousel-inner">
       <div class="item active">
-        <div class="row">
-          <? foreach ($similarRecords as $index=>$data): ?>
-            <div class="col-sm-<?=floor(12/$perPage) ?>">
-              <a class="hover-overlay" href="<?=$this->recordLink()->getUrl($data)?>">
-                <? $thumb = $this->record($data)->getThumbnail('large'); ?>
-                <img src="<?=$thumb ?>" title="<?=$data->getTitle() ?>"/>
-                <div class="content">
-                  <? $formats = $data->getFormats(); ?>
-                  <i class="fa fa-x<? if (count($formats) > 0): ?> fa-<?=preg_replace('/[^a-z0-9]/', '', strtolower($formats[0]))?>" title="<?=$formats[0] ?><? endif; ?>"></i>
-                  <b><?=$this->escapeHtml($data->getTitle())?></b>
-                  <? $authors = $data->getPrimaryAuthors(); if (!empty($authors)): ?>
-                    <br/><?=$this->transEsc('by')?>: <?=$this->escapeHtml($authors[0]);?><? if (count($authors) > 1): ?>, <?=$this->transEsc('more_authors_abbrev')?><? endif; ?>
-                  <? endif; ?>
-                  <? $pubDates = $data->getPublicationDates(); if (!empty($pubDates)): ?>
-                    <br/><?=$this->transEsc('Published')?>: (<?=$this->escapeHtml($pubDates[0])?>)
-                  <? endif; ?>
-                </div>
-              </a>
-            </div>
-            <? if(($index+1) % $perPage == 0 && $index < count($similarRecords)-1): ?>
+        <? foreach ($similarRecords as $index=>$data): ?>
+          <div class="carousel-item">
+            <a class="hover-overlay" href="<?=$this->recordLink()->getUrl($data)?>">
+              <? $thumb = $this->record($data)->getThumbnail('large'); ?>
+              <img src="<?=$thumb ?>" title="<?=$data->getTitle() ?>"/>
+              <div class="content">
+                <? $formats = $data->getFormats(); ?>
+                <i class="fa fa-x<? if (count($formats) > 0): ?> fa-<?=preg_replace('/[^a-z0-9]/', '', strtolower($formats[0]))?>" title="<?=$formats[0] ?><? endif; ?>"></i>
+                <b><?=$this->escapeHtml($data->getTitle())?></b>
+                <? $authors = $data->getPrimaryAuthors(); if (!empty($authors)): ?>
+                  <br/><?=$this->transEsc('by')?>: <?=$this->escapeHtml($authors[0]);?><? if (count($authors) > 1): ?>, <?=$this->transEsc('more_authors_abbrev')?><? endif; ?>
+                <? endif; ?>
+                <? $pubDates = $data->getPublicationDates(); if (!empty($pubDates)): ?>
+                  <br/><?=$this->transEsc('Published')?>: (<?=$this->escapeHtml($pubDates[0])?>)
+                <? endif; ?>
+              </div>
+            </a>
           </div>
-        </div>
-        <div class="item">
-          <div class="row">
-            <? endif; ?>
-          <? endforeach; ?>
-        </div>
+          <? if(($index+1) % $perPage == 0 && $index < count($similarRecords)-1): ?>
+      </div>
+      <div class="item">
+          <? endif; ?>
+        <? endforeach; ?>
       </div>
     </div>
 
diff --git a/themes/bootstrap3/templates/RecordTab/staffviewarray.phtml b/themes/bootstrap3/templates/RecordTab/staffviewarray.phtml
index f098cdd690f0f6cbeb7d21a37c95cfe1d4816061..e4e80bd770d851cb2b8907a07d459a717075ff03 100644
--- a/themes/bootstrap3/templates/RecordTab/staffviewarray.phtml
+++ b/themes/bootstrap3/templates/RecordTab/staffviewarray.phtml
@@ -7,11 +7,11 @@
     <tr>
       <th><?=$this->escapeHtml($field)?></th>
       <td>
-        <? if (!is_array($values)) { $values = array($values); } ?>
+        <? if (!is_array($values)) { $values = [$values]; } ?>
         <? foreach ($values as $value): ?>
           <?=$this->escapeHtml(is_array($value) ? print_r($value, true) : $value)?><br />
         <? endforeach; ?>
       </td>
     </tr>
   <? endforeach; ?>
-</table>
\ No newline at end of file
+</table>
diff --git a/themes/bootstrap3/templates/RecordTab/staffviewmarc.phtml b/themes/bootstrap3/templates/RecordTab/staffviewmarc.phtml
index cc89c983995ada977b5bafc4efa71b2dd0f67420..e00ee857b49c8868f643efd9c2be7eed9341a7e3 100644
--- a/themes/bootstrap3/templates/RecordTab/staffviewmarc.phtml
+++ b/themes/bootstrap3/templates/RecordTab/staffviewmarc.phtml
@@ -2,4 +2,4 @@
     // Set page title.
     $this->headTitle($this->translate('Staff View') . ': ' . $this->driver->getBreadcrumb());
 ?>
-<?=\VuFind\XSLT\Processor::process('record-marc.xsl', $this->driver->getXML('marc21'))?>
\ No newline at end of file
+<?=\VuFind\XSLT\Processor::process('record-marc.xsl', $this->driver->getXML('marc21'))?>
diff --git a/themes/bootstrap3/templates/RecordTab/toc.phtml b/themes/bootstrap3/templates/RecordTab/toc.phtml
index 46d9a5921ad34961c90ad7aea64346a32cc66901..e0fa6787a9b4db7b15e66018a7db2e98c8655eca 100644
--- a/themes/bootstrap3/templates/RecordTab/toc.phtml
+++ b/themes/bootstrap3/templates/RecordTab/toc.phtml
@@ -13,4 +13,4 @@
   </ul>
 <? else: ?>
   <?=$this->transEsc("Table of Contents unavailable")?>.
-<? endif; ?>
\ No newline at end of file
+<? endif; ?>
diff --git a/themes/bootstrap3/templates/RecordTab/usercomments.phtml b/themes/bootstrap3/templates/RecordTab/usercomments.phtml
index e00d5eaaffc30893cdbbf1b12b81efa4fca169e8..7fe6ab303d31668cf50c191f647fe1c5ac3de368 100644
--- a/themes/bootstrap3/templates/RecordTab/usercomments.phtml
+++ b/themes/bootstrap3/templates/RecordTab/usercomments.phtml
@@ -7,25 +7,19 @@
   <?=$this->render('record/comments-list.phtml')?>
 </div>
 <form class="comment-form" name="commentRecord" action="<?=$this->recordLink()->getActionUrl($this->driver, 'AddComment')?>" method="post">
-  <div class="row">
-    <div class="col-sm-3 name">
-      <input type="hidden" name="id" value="<?=$this->escapeHtmlAttr($this->driver->getUniqueId())?>"/>
-      <input type="hidden" name="source" value="<?=$this->escapeHtmlAttr($this->driver->getSourceIdentifier())?>"/>
-      <strong><?=$this->transEsc("Your Comment")?></strong>
-    </div>
-    <div class="col-sm-9">
-      <? $user = $this->auth()->isLoggedIn() ?>
-      <? if($user): ?>
-        <textarea name="comment" class="form-control" rows="3" required></textarea><br/>
-        <? if ($this->tab->isRecaptchaActive()): ?>
-          <?=$this->recaptcha()->html(true, false) ?><br/>
-        <? else: ?>
-          <script>/* workaround for nested form bug */</script>
-        <? endif; ?>
-        <input class="btn btn-primary" data-loading-text="<?=$this->transEsc('Submitting') ?>..." type="submit" value="<?=$this->transEsc("Add your comment")?>"/>
-      <? else: ?>
-        <a href="<?=$this->url('myresearch-userlogin') ?>" class="btn btn-primary" data-lightbox title="Login"><i class="fa fa-sign-in" aria-hidden="true"></i> <?=$this->transEsc("You must be logged in first") ?></a>
+  <input type="hidden" name="id" value="<?=$this->escapeHtmlAttr($this->driver->getUniqueId())?>"/>
+  <input type="hidden" name="source" value="<?=$this->escapeHtmlAttr($this->driver->getSourceIdentifier())?>"/>
+  <label class="comment-label"><?=$this->transEsc("Your Comment")?></label>
+  <? $user = $this->auth()->isLoggedIn() ?>
+  <? if($user): ?>
+    <div class="text-form">
+      <textarea name="comment" class="form-control" rows="3" required></textarea>
+      <? if ($this->tab->isRecaptchaActive()): ?>
+        <?=$this->recaptcha()->html(true, false) ?>
       <? endif; ?>
+      <input class="btn btn-primary" data-loading-text="<?=$this->transEsc('Submitting') ?>..." type="submit" value="<?=$this->transEsc("Add your comment")?>"/>
     </div>
-  </div>
+  <? else: ?>
+    <a href="<?=$this->url('myresearch-userlogin') ?>" class="btn btn-primary" data-lightbox title="Login"><i class="fa fa-sign-in" aria-hidden="true"></i> <?=$this->transEsc("You must be logged in first") ?></a>
+  <? endif; ?>
 </form>
diff --git a/themes/bootstrap3/templates/Related/Channels.phtml b/themes/bootstrap3/templates/Related/Channels.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..a4a3b046c8ee5441044705ab5c26b0aba0d8188b
--- /dev/null
+++ b/themes/bootstrap3/templates/Related/Channels.phtml
@@ -0,0 +1,9 @@
+<?
+    $driver = $this->related->getDriver();
+    $link = $this->url('channels-record')
+        . '?id=' . urlencode($driver->getUniqueId())
+        . '&source=' . urlencode($driver->getSourceIdentifier());
+?>
+<div class="channels-alert alert alert-info">
+  <a href="<?=$this->escapeHtmlAttr($link)?>"><?=$this->transEsc('channel_expand')?></a>
+</div>
diff --git a/themes/bootstrap3/templates/Related/Deprecated.phtml b/themes/bootstrap3/templates/Related/Deprecated.phtml
index 63445d34f9c1ebc4c55c092c9dcf8965c9fd3c66..ff8266ef2c7dcbafc58aa400e648b37946ac45fd 100644
--- a/themes/bootstrap3/templates/Related/Deprecated.phtml
+++ b/themes/bootstrap3/templates/Related/Deprecated.phtml
@@ -1,2 +1,2 @@
 <? /* do nothing -- this module is a placeholder for old deprecated features
-      to prevent legacy configurations from causing fatal errors. */ ?>
\ No newline at end of file
+      to prevent legacy configurations from causing fatal errors. */ ?>
diff --git a/themes/bootstrap3/templates/Related/Similar.phtml b/themes/bootstrap3/templates/Related/Similar.phtml
index 40280a0fdc7b8e36dad64f3d370da5b7678071fb..94047e13130fbc35777d7574d90555dfa83ad2a9 100644
--- a/themes/bootstrap3/templates/Related/Similar.phtml
+++ b/themes/bootstrap3/templates/Related/Similar.phtml
@@ -20,4 +20,4 @@
   </ul>
 <? else: ?>
   <p><?=$this->transEsc('Cannot find similar records')?></p>
-<? endif; ?>
\ No newline at end of file
+<? endif; ?>
diff --git a/themes/bootstrap3/templates/admin/config/home.phtml b/themes/bootstrap3/templates/admin/config/home.phtml
index f3bf5ef0b99c5e3ee39c57e4a8b559e841da00e5..8a97b35c69eae28d2aab7ceac0124498187c0f0b 100644
--- a/themes/bootstrap3/templates/admin/config/home.phtml
+++ b/themes/bootstrap3/templates/admin/config/home.phtml
@@ -2,21 +2,19 @@
   // Set page title.
   $this->headTitle($this->translate('VuFind Administration - Configuration'));
 ?>
-<div class="row">
-  <div class="<?=$this->layoutClass('mainbody')?>">
-    <h2><?=$this->transEsc('Configuration')?></h2>
-    <?=$this->flashmessages()?>
-    <p>Most VuFind configuration is handled by editing the configuration files in <strong><?=$this->escapeHtml($this->baseConfigPath)?></strong>.</p>
-    <p>Some basic settings can also be adjusted through the auto-configuration tool.</p>
-    <? if (!$this->showInstallLink): ?>
-      <p><?=$this->transEsc('Auto configuration is currently disabled') ?>.</p>
-      <p><a href="<?=$this->url('admin/config', array('action' => 'EnableAutoConfig'))?>"><?=$this->transEsc('Enable Auto Config')?></a></p>
-    <? else: ?>
-      <p><a href="<?=$this->url('install-home')?>"><?=$this->transEsc('auto_configure_title')?></a></p>
-    <? endif; ?>
-  </div>
+<div class="<?=$this->layoutClass('mainbody')?>">
+  <h2><?=$this->transEsc('Configuration')?></h2>
+  <?=$this->flashmessages()?>
+  <p>Most VuFind configuration is handled by editing the configuration files in <strong><?=$this->escapeHtml($this->baseConfigPath)?></strong>.</p>
+  <p>Some basic settings can also be adjusted through the auto-configuration tool.</p>
+  <? if (!$this->showInstallLink): ?>
+    <p><?=$this->transEsc('Auto configuration is currently disabled') ?>.</p>
+    <p><a href="<?=$this->url('admin/config', array('action' => 'EnableAutoConfig'))?>"><?=$this->transEsc('Enable Auto Config')?></a></p>
+  <? else: ?>
+    <p><a href="<?=$this->url('install-home')?>"><?=$this->transEsc('auto_configure_title')?></a></p>
+  <? endif; ?>
+</div>
 
-  <div class="<?=$this->layoutClass('sidebar')?>">
-    <?=$this->render("admin/menu.phtml")?>
-  </div>
-</div>
\ No newline at end of file
+<div class="<?=$this->layoutClass('sidebar')?>">
+  <?=$this->render("admin/menu.phtml")?>
+</div>
diff --git a/themes/bootstrap3/templates/admin/disabled.phtml b/themes/bootstrap3/templates/admin/disabled.phtml
index 851a6116c644c1c53d8f233e710b2a20616fb898..93c58b55026db07409f9648a80bb0bef2d5c01d3 100644
--- a/themes/bootstrap3/templates/admin/disabled.phtml
+++ b/themes/bootstrap3/templates/admin/disabled.phtml
@@ -1,3 +1,3 @@
 <p class="error">
   <b>The Admin module is currently disabled.</b> To turn it on, see the admin_enabled setting in the [Site] section of config.ini.
-</p>
\ No newline at end of file
+</p>
diff --git a/themes/bootstrap3/templates/admin/home.phtml b/themes/bootstrap3/templates/admin/home.phtml
index ff6c1da76d08b7f48c2d9604486200380480112a..59e43f64b71c4412dcda022c57e7127c2ef44918 100644
--- a/themes/bootstrap3/templates/admin/home.phtml
+++ b/themes/bootstrap3/templates/admin/home.phtml
@@ -3,47 +3,44 @@
   $this->headTitle($this->translate('VuFind Administration - Home'));
 
   // Set up map of core name => label
-  $coreLabels = array(
+  $coreLabels = [
     'biblio' => $this->translate('Bibliographic Index'),
     'authority' => $this->translate('Authority Index'),
     'stats' => $this->translate('Usage Statistics Index')
-  );
+  ];
 ?>
+<div class="<?=$this->layoutClass('mainbody')?>">
+  <h2><?=$this->transEsc('VuFind Administration')?></h2>
+  <? $cores = is_object($this->xml) ? $this->xml->xpath('/response/lst[@name="status"]/lst') : []; ?>
+  <? foreach ($cores as $core): ?>
+    <? $coreName = (string)$core['name']; ?>
+    <? $coreLabel = isset($coreLabels[$coreName]) ? $coreLabels[$coreName] : ucwords($coreName) . ' Index'; ?>
+    <h3><?=$this->transEsc($coreLabel)?></h3>
+    <table class="table table-striped">
+      <tr>
+        <th><?=$this->transEsc('Record Count')?>: </th>
+        <? $recordCount = $core->xpath('//lst[@name="' . $coreName . '"]/lst/int[@name="numDocs"]') ?>
+        <td><?=$this->escapeHtml((string)array_pop($recordCount))?></td>
+      </tr>
+      <tr>
+        <th><?=$this->transEsc('Start Time')?>: </th>
+        <? $startTime = $core->xpath('//lst[@name="' . $coreName . '"]/date[@name="startTime"]') ?>
+        <td><?=$this->escapeHtml(strftime("%b %d, %Y %l:%M:%S%p", strtotime((string)array_pop($startTime))))?></td>
+      </tr>
+      <tr>
+        <th><?=$this->transEsc('Last Modified')?>: </th>
+        <? $lastModified = $core->xpath('//lst[@name="' . $coreName . '"]/lst/date[@name="lastModified"]') ?>
+        <td><?=$this->escapeHtml(strftime("%b %d, %Y %l:%M:%S%p", strtotime((string)array_pop($lastModified))))?></td>
+      </tr>
+      <tr>
+        <th><?=$this->transEsc('Uptime')?>: </th>
+        <? $uptime = $core->xpath('//lst[@name="' . $coreName . '"]/long[@name="uptime"]') ?>
+        <td><?=$this->printms((string)array_pop($uptime))?></td>
+      </tr>
+    </table>
+  <? endforeach; ?>
+</div>
 
-<div class="row">
-  <div class="<?=$this->layoutClass('mainbody')?>">
-    <h2><?=$this->transEsc('VuFind Administration')?></h2>
-    <? $cores = is_object($this->xml) ? $this->xml->xpath('/response/lst[@name="status"]/lst') : array(); ?>
-    <? foreach ($cores as $core): ?>
-      <? $coreName = (string)$core['name']; ?>
-      <? $coreLabel = isset($coreLabels[$coreName]) ? $coreLabels[$coreName] : ucwords($coreName) . ' Index'; ?>
-      <h3><?=$this->transEsc($coreLabel)?></h3>
-      <table class="table table-striped">
-        <tr>
-          <th><?=$this->transEsc('Record Count')?>: </th>
-          <? $recordCount = $core->xpath('//lst[@name="' . $coreName . '"]/lst/int[@name="numDocs"]') ?>
-          <td><?=$this->escapeHtml((string)array_pop($recordCount))?></td>
-        </tr>
-        <tr>
-          <th><?=$this->transEsc('Start Time')?>: </th>
-          <? $startTime = $core->xpath('//lst[@name="' . $coreName . '"]/date[@name="startTime"]') ?>
-          <td><?=$this->escapeHtml(strftime("%b %d, %Y %l:%M:%S%p", strtotime((string)array_pop($startTime))))?></td>
-        </tr>
-        <tr>
-          <th><?=$this->transEsc('Last Modified')?>: </th>
-          <? $lastModified = $core->xpath('//lst[@name="' . $coreName . '"]/lst/date[@name="lastModified"]') ?>
-          <td><?=$this->escapeHtml(strftime("%b %d, %Y %l:%M:%S%p", strtotime((string)array_pop($lastModified))))?></td>
-        </tr>
-        <tr>
-          <th><?=$this->transEsc('Uptime')?>: </th>
-          <? $uptime = $core->xpath('//lst[@name="' . $coreName . '"]/long[@name="uptime"]') ?>
-          <td><?=$this->printms((string)array_pop($uptime))?></td>
-        </tr>
-      </table>
-    <? endforeach; ?>
-  </div>
-
-  <div class="<?=$this->layoutClass('sidebar')?>">
-    <?=$this->render("admin/menu.phtml")?>
-  </div>
-</div>
\ No newline at end of file
+<div class="<?=$this->layoutClass('sidebar')?>">
+  <?=$this->render("admin/menu.phtml")?>
+</div>
diff --git a/themes/bootstrap3/templates/admin/maintenance/home.phtml b/themes/bootstrap3/templates/admin/maintenance/home.phtml
index 5d5f627ef052f65e46798f8013d2f2506e8a4100..e5c98577a04499897f3149ca42dc6f44a4a5adb9 100644
--- a/themes/bootstrap3/templates/admin/maintenance/home.phtml
+++ b/themes/bootstrap3/templates/admin/maintenance/home.phtml
@@ -2,34 +2,35 @@
     // Set page title.
     $this->headTitle($this->translate('VuFind Administration - System Maintenance'));
 ?>
-<div class="row">
-  <div class="<?=$this->layoutClass('mainbody')?>">
-    <h2><?=$this->transEsc('System Maintenance')?></h2>
+<div class="<?=$this->layoutClass('mainbody')?>">
+  <h2><?=$this->transEsc('System Maintenance')?></h2>
 
-    <h3>Utilities</h3>
-    <?=$this->flashmessages()?>
-    <form method="get" action="<?=$this->url('admin/maintenance', array('action' => 'DeleteExpiredSearches'))?>">
-      <label for="del_daysOld">Delete unsaved user search histories older than</label>
-      <input id="del_daysOld" type="text" name="daysOld" size="5" value="2"/> days.
-      <input type="submit" name="submit" value="<?=$this->transEsc('Submit')?>"/>
-    </form>
-    <hr />
-    <form method="get" action="<?=$this->url('admin/maintenance', array('action' => 'DeleteExpiredSessions'))?>">
-      <label for="delsess_daysOld">Delete user sessions older than</label>
-      <input id="delsess_daysOld" type="text" name="daysOld" size="5" value="2"/> days.
-      <input type="submit" name="submit" value="<?=$this->transEsc('Submit')?>"/>
-    </form>
-    <hr />
-    <form method="get" action="<?=$this->url('admin/maintenance', array('action' => 'ClearCache'))?>">
-      Clear cache(s):
-      <? foreach ($caches as $cache): ?>
-        <input type="checkbox" checked="checked" name="cache[]" value="<?=$this->escapeHtmlAttr($cache)?>" /> <?=$this->escapeHtml($cache) ?>
-      <? endforeach; ?>
-      <input type="submit" name="submit" value="<?=$this->transEsc('Submit')?>"/>
-    </form>
-  </div>
+  <h3>Utilities</h3>
+  <?=$this->flashmessages()?>
+  <form class="form-admin-maintenance expired-searches" method="get" action="<?=$this->url('admin/maintenance', array('action' => 'DeleteExpiredSearches'))?>">
+    <label for="del_daysOld">Delete unsaved user search histories older than</label>
+    <input id="del_daysOld" type="number" name="daysOld" size="5" value="2" class="form-control"/> days.
+    <input type="submit" name="submit" value="<?=$this->transEsc('Submit')?>" class="btn btn-danger"/>
+  </form>
+  <hr />
+  <form class="form-admin-maintenance expired-sessions" method="get" action="<?=$this->url('admin/maintenance', array('action' => 'DeleteExpiredSessions'))?>">
+    <label for="delsess_daysOld">Delete user sessions older than</label>
+    <input id="delsess_daysOld" type="number" name="daysOld" size="5" value="2" class="form-control"/> days.
+    <input type="submit" name="submit" value="<?=$this->transEsc('Submit')?>" class="btn btn-danger"/>
+  </form>
+  <hr />
+  <form class="form-admin-maintenance clear-cache" method="get" action="<?=$this->url('admin/maintenance', array('action' => 'ClearCache'))?>">
+    Clear cache(s):
+    <? foreach ($caches as $cache): ?>
+      <label>
+        <input type="checkbox" checked="checked" name="cache[]" value="<?=$this->escapeHtmlAttr($cache)?>" />
+        <?=$this->escapeHtml($cache) ?>
+      </label>
+    <? endforeach; ?>
+    <input type="submit" name="submit" value="<?=$this->transEsc('Submit')?>" class="btn btn-danger"/>
+  </form>
+</div>
 
-  <div class="<?=$this->layoutClass('sidebar')?>">
-    <?=$this->render("admin/menu.phtml")?>
-  </div>
-</div>
\ No newline at end of file
+<div class="<?=$this->layoutClass('sidebar')?>">
+  <?=$this->render("admin/menu.phtml")?>
+</div>
diff --git a/themes/bootstrap3/templates/admin/menu.phtml b/themes/bootstrap3/templates/admin/menu.phtml
index 404fbdfc95b1a153cde0eb080db738b21367d011..ec41087884865e7840504e064d461c7d9e3f0818 100644
--- a/themes/bootstrap3/templates/admin/menu.phtml
+++ b/themes/bootstrap3/templates/admin/menu.phtml
@@ -1,7 +1,6 @@
 <div class="list-group">
   <a href="<?=$this->url('admin')?>" class="list-group-item<?=strtolower($this->layout()->templateName) == "home" ? ' active' : ''?>"><?=$this->transEsc('Home')?></a>
   <a href="<?=$this->url('admin/social')?>" class="list-group-item<?=strtolower($this->layout()->templateName) == "socialstats" ? ' active' : ''?>"><?=$this->transEsc('Social Statistics')?></a>
-  <a href="<?=$this->url('admin/statistics')?>" class="list-group-item<?=strtolower($this->layout()->templateName) == "statistics" ? ' active' : ''?>"><?=$this->transEsc('Statistics')?></a>
   <a href="<?=$this->url('admin/config')?>" class="list-group-item<?=strtolower($this->layout()->templateName) == "config" ? ' active' : ''?>"><?=$this->transEsc('Configuration')?></a>
   <a href="<?=$this->url('admin/maintenance')?>" class="list-group-item<?=strtolower($this->layout()->templateName) == "maintenance" ? ' active' : ''?>"><?=$this->transEsc('System Maintenance')?></a>
   <a href="<?=$this->url('admin/tags')?>" class="list-group-item<?=strtolower($this->layout()->templateName) == "tags" ? ' active' : ''?>"><?=$this->transEsc('Tag Maintenance')?></a>
diff --git a/themes/bootstrap3/templates/admin/socialstats/home.phtml b/themes/bootstrap3/templates/admin/socialstats/home.phtml
index 8f881ecf7d461673c7edc43d86615504dc8077b7..7fb0f9c2d799276cc1235ac091bc6b85c253685e 100644
--- a/themes/bootstrap3/templates/admin/socialstats/home.phtml
+++ b/themes/bootstrap3/templates/admin/socialstats/home.phtml
@@ -2,31 +2,28 @@
     // Set page title.
     $this->headTitle($this->translate('VuFind Administration - Social Statistics'));
 ?>
+<div class="<?=$this->layoutClass('mainbody')?>">
+  <h2><?=$this->transEsc('Social Statistics')?></h2>
 
-<div class="row">
-  <div class="<?=$this->layoutClass('mainbody')?>">
-    <h2><?=$this->transEsc('Social Statistics')?></h2>
+  <h3>Comments</h3>
+  <table class="table table-striped">
+    <tr><th>Total Users</th><th>Total Resources</th><th>Total Comments</th></tr>
+    <tr><td><?=$comments['users']?></td><td><?=$comments['resources']?></td><td><?=$comments['total']?></td></tr>
+  </table>
 
-    <h3>Comments</h3>
-    <table class="table table-striped">
-      <tr><th>Total Users</th><th>Total Resources</th><th>Total Comments</th></tr>
-      <tr><td><?=$comments['users']?></td><td><?=$comments['resources']?></td><td><?=$comments['total']?></td></tr>
-    </table>
+  <h3>Favorites</h3>
+  <table class="table table-striped">
+    <tr><th>Total Users</th><th>Total Resources</th><th>Total Lists</th><th>Total Saved Items</th></tr>
+    <tr><td><?=$favorites['users']?></td><td><?=$favorites['resources']?></td><td><?=$favorites['lists']?></td><td><?=$favorites['total']?></td></tr>
+  </table>
 
-    <h3>Favorites</h3>
-    <table class="table table-striped">
-      <tr><th>Total Users</th><th>Total Resources</th><th>Total Lists</th><th>Total Saved Items</th></tr>
-      <tr><td><?=$favorites['users']?></td><td><?=$favorites['resources']?></td><td><?=$favorites['lists']?></td><td><?=$favorites['total']?></td></tr>
-    </table>
+  <h3>Tags</h3>
+  <table class="table table-striped">
+    <tr><th>Total Users</th><th>Total Resources</th><th>Total Tags</th></tr>
+    <tr><td><?=$tags['users']?></td><td><?=$tags['resources']?></td><td><?=$tags['total']?></td></tr>
+  </table>
+</div>
 
-    <h3>Tags</h3>
-    <table class="table table-striped">
-      <tr><th>Total Users</th><th>Total Resources</th><th>Total Tags</th></tr>
-      <tr><td><?=$tags['users']?></td><td><?=$tags['resources']?></td><td><?=$tags['total']?></td></tr>
-    </table>
-  </div>
-
-  <div class="<?=$this->layoutClass('sidebar')?>">
-    <?=$this->render("admin/menu.phtml")?>
-  </div>
-</div>
\ No newline at end of file
+<div class="<?=$this->layoutClass('sidebar')?>">
+  <?=$this->render("admin/menu.phtml")?>
+</div>
diff --git a/themes/bootstrap3/templates/admin/statistics/home.phtml b/themes/bootstrap3/templates/admin/statistics/home.phtml
deleted file mode 100644
index 66064a236b4aa5f3fd76e405af2362158a2a8c2b..0000000000000000000000000000000000000000
--- a/themes/bootstrap3/templates/admin/statistics/home.phtml
+++ /dev/null
@@ -1,95 +0,0 @@
-<?
-  // Set page title.
-  $this->headTitle($this->translate('VuFind Administration - Statistics'));
-?>
-<style>
-  table {
-    table-layout: fixed;
-    width: 100%;
-  }
-  tr td:first-child {
-    width:50%;
-  }
-</style>
-
-<div class="row">
-  <div class="<?=$this->layoutClass('mainbody')?>">
-    <h2><?=$this->transEsc('Statistics')?></h2>
-
-    <? if(null !== $this->totalSearches || null !== $this->emptySearches || null !== $this->totalRecordViews): ?>
-      <h3>Executive Summary</h3>
-      <table class="table table-striped">
-        <? if(null !== $this->totalSearches): ?><tr><td>Total Searches</td><td><?=$this->totalSearches ?></td></tr><? endif; ?>
-        <? if(null !== $this->emptySearches): ?><tr><td>0 Hit Searches</td><td><?=$this->emptySearches ?></td></tr><? endif; ?>
-        <? if(null !== $this->totalRecordViews): ?><tr><td>Total Record Views</td><td><?=$this->totalRecordViews ?></td></tr><? endif; ?>
-      </table>
-    <? endif; ?>
-
-    <? if(!empty($this->topSearches)): ?>
-      <h3>Top Searches<? if($this->searchesBySource): ?> by Source<? endif; ?></h3>
-      <? if($this->searchesBySource): ?>
-        <? foreach($this->topSearches as $source=>$searches): ?>
-          <?=$source ?>
-          <table class="table table-striped">
-          <? foreach($searches as $search): ?>
-            <tr><td><?=$search['value'] ?></td><td><?=$this->localizedNumber($search['count']) ?></td></tr>
-          <? endforeach; ?>
-          </table>
-        <? endforeach; ?>
-      <? else: ?>
-        <table class="table table-striped">
-          <? foreach($this->topSearches as $search): ?>
-            <tr><td><?=$search['value'] ?></td><td><?=$this->localizedNumber($search['count']) ?></td><td><?=$search['source'] ?></td></tr>
-          <? endforeach; ?>
-        </table>
-      <? endif; ?>
-    <? endif; ?>
-
-    <? if(!empty($this->topRecords)): ?>
-      <h3>Top Records<? if($this->recordsBySource): ?> by Source<? endif; ?></h3>
-      <? if($this->recordsBySource): ?>
-        <? foreach($this->topRecords as $source=>$records): ?>
-          <?=$source ?>
-          <table class="table table-striped">
-          <? foreach($records as $record): ?>
-            <tr><td><?=$record['value'] ?></td><td><?=$this->localizedNumber($record['count']) ?></td></tr>
-          <? endforeach; ?>
-          </table>
-        <? endforeach; ?>
-      <? else: ?>
-        <table class="table table-striped">
-          <? foreach($this->topRecords as $record): ?>
-            <tr><td><?=$record['value'] ?></td><td><?=$this->localizedNumber($record['count']) ?></td><td><?=$record['source'] ?></td></tr>
-          <? endforeach; ?>
-        </table>
-      <? endif; ?>
-    <? endif; ?>
-
-    <? if(!empty($this->browserStats)): ?>
-      <h3>Browser Usage</h3>
-      <?
-        $total = 0;
-        foreach($this->browserStats as $browser) {
-            $total += $browser['count'];
-        }
-      ?>
-      <table class="table table-striped">
-      <? foreach($this->browserStats as $browser): ?>
-        <tr><td><?=$browser['browserName'] ?></td><td><?=$this->localizedNumber($browser['count']) ?></td><td><?=$this->localizedNumber($browser['count']*100/$total, 2) ?>%</td></tr>
-      <? endforeach; ?>
-      </table>
-      <h4>Top Versions</h4>:
-      <? foreach($this->topVersions as $i=>$browser): ?>
-        <span<? if($this->currentBrowser == $browser['browserName']): ?> class="currentBrowser"<? endif; ?>><?=$browser['browserName'] ?> (<?=$this->localizedNumber($browser['count']) ?>)</span><? if(++$i < count($this->topVersions)): ?>,<? endif; ?>
-      <? endforeach; ?>
-    <? endif; ?>
-
-    <? if(empty($this->topSearches) && empty($this->topRecords) && empty($this->browserStats)): ?>
-      No statistic sources.
-    <? endif; ?>
-  </div>
-
-  <div class="<?=$this->layoutClass('sidebar')?>">
-    <?=$this->render("admin/menu.phtml")?>
-  </div>
-</div>
\ No newline at end of file
diff --git a/themes/bootstrap3/templates/admin/tags/checkbox.phtml b/themes/bootstrap3/templates/admin/tags/checkbox.phtml
index 75bf67473ecfe2f1d90832ff6165f1cdb0036e82..3ddf4574d5f1698695668053f4e047054dab3bac 100644
--- a/themes/bootstrap3/templates/admin/tags/checkbox.phtml
+++ b/themes/bootstrap3/templates/admin/tags/checkbox.phtml
@@ -3,4 +3,4 @@
     <input id="<?=$this->prefix?>checkbox_<?=$this->tag['id']?>" type="checkbox" name="ids[]" value="<?=$this->escapeHtmlAttr($this->tag['id'])?>" class="checkbox_ui"/>
     <input type="hidden" name="idsAll[]" value="<?=$this->escapeHtmlAttr($this->tag['id'])?>" />
   </label>
-</div>
\ No newline at end of file
+</div>
diff --git a/themes/bootstrap3/templates/admin/tags/home.phtml b/themes/bootstrap3/templates/admin/tags/home.phtml
index 46f5be1cf31635f70c0476c0f789f608f8ba9149..0a8f646b427c180ed4615e6603b1171a666175d4 100644
--- a/themes/bootstrap3/templates/admin/tags/home.phtml
+++ b/themes/bootstrap3/templates/admin/tags/home.phtml
@@ -2,21 +2,19 @@
   // Set page title.
   $this->headTitle($this->translate('VuFind Administration - Tag Management'));
 ?>
-<div class="row">
-  <div class="<?=$this->layoutClass('mainbody')?>">
-    <h2><?=$this->translate('Tag Management')?></h2>
+<div class="<?=$this->layoutClass('mainbody')?>">
+  <h2><?=$this->translate('Tag Management')?></h2>
 
-    <?=$this->render("admin/tags/menu.phtml")?>
+  <?=$this->render("admin/tags/menu.phtml")?>
 
-    <h3><?=$this->translate('Statistics')?></h3>
-    <table class="table table-striped">
-      <tr><th><?=$this->transEsc('total_users')?></th><th><?=$this->transEsc('total_resources')?></th><th><?=$this->transEsc('total_tags')?></th><th><?=$this->transEsc('unique_tags')?></th><th><?=$this->transEsc('anonymous_tags')?></th></tr>
-      <tr><td><?=$statistics['users']?></td><td><?=$statistics['resources']?></td><td><?=$statistics['total']?></td><td><?=$statistics['unique']?></td><td><?=$statistics['anonymous']?></td></tr>
-    </table>
+  <h3><?=$this->translate('Statistics')?></h3>
+  <table class="table table-striped">
+    <tr><th><?=$this->transEsc('total_users')?></th><th><?=$this->transEsc('total_resources')?></th><th><?=$this->transEsc('total_tags')?></th><th><?=$this->transEsc('unique_tags')?></th><th><?=$this->transEsc('anonymous_tags')?></th></tr>
+    <tr><td><?=$statistics['users']?></td><td><?=$statistics['resources']?></td><td><?=$statistics['total']?></td><td><?=$statistics['unique']?></td><td><?=$statistics['anonymous']?></td></tr>
+  </table>
 
-  </div>
+</div>
 
-  <div class="<?=$this->layoutClass('sidebar')?>">
-    <?=$this->render("admin/menu.phtml")?>
-  </div>
-</div>
\ No newline at end of file
+<div class="<?=$this->layoutClass('sidebar')?>">
+  <?=$this->render("admin/menu.phtml")?>
+</div>
diff --git a/themes/bootstrap3/templates/admin/tags/list.phtml b/themes/bootstrap3/templates/admin/tags/list.phtml
index b6eb25e25951845b834526ac9fc1f4c39c686a92..edf5daabbef6187a2740a346a1ba4aa647835a02 100644
--- a/themes/bootstrap3/templates/admin/tags/list.phtml
+++ b/themes/bootstrap3/templates/admin/tags/list.phtml
@@ -3,108 +3,99 @@
   $this->headTitle($this->translate('VuFind Administration - Tag Management'));
 ?>
 
-<div class="row">
-  <div class="<?=$this->layoutClass('mainbody')?>">
-    <h2><?=$this->translate('Tag Management')?></h2>
-    <h3><?=$this->translate('List Tags')?></h3>
+<h2><?=$this->translate('Tag Management')?></h2>
+<div class="<?=$this->layoutClass('mainbody')?>">
+  <h3><?=$this->translate('List Tags')?></h3>
 
-    <?=$this->render("admin/tags/menu.phtml")?>
+  <?=$this->render("admin/tags/menu.phtml", ['active' => 'list'])?>
 
-    <?=$this->flashmessages()?>
+  <?=$this->flashmessages()?>
 
-    <div class="tagForm">
-      <form action="<?= $this->url('admin/tags', array('action' => 'List'))?>" method="get">
-
-        <fieldset>
-          <legend><?=$this->translate('filter_tags')?></legend>
-
-          <div class="row">
-            <div class="col-sm-3">
-              <label for="user_id"><?=$this->translate('Username')?></label>
-              <select name="user_id" id="user_id" class="form-control">
-                <option value="ALL"><?=$this->translate('All')?></option>
-                <? foreach($this->uniqueUsers as $user):?>
-                  <option value="<?= $user['user_id'] ?>"<? if(isset($this->params['user_id']) && $user['user_id'] == $this->params['user_id']): ?> selected="selected"<? endif;?>>
-                    <?=$user['username'] ?>
-                  </option>
-                <? endforeach;?>
-              </select>
-            </div>
-            <div class="col-sm-3">
-              <label for="tag_id"><?=$this->translate('Tag')?></label>
-              <select name="tag_id" id="tag_id" class="form-control">
-                <option value="ALL"><?=$this->translate('All')?></option>
-                <? foreach($this->uniqueTags as $tag):?>
-                <option value="<?= $tag['tag_id'] ?>"<? if(isset($this->params['tag_id']) && $tag['tag_id'] == $this->params['tag_id']): ?> selected="selected"<? endif;?>>
-                    <?=$tag['tag'] ?>
-                </option>
-                <? endforeach;?>
-              </select>
-            </div>
-            <div class="col-sm-3">
-              <label for="resource_id"><?=$this->translate('Title')?></label>
-              <select name="resource_id" id="resource_id" class="form-control">
-                <option value="ALL"><?=$this->translate('All')?></option>
-                <? foreach($this->uniqueResources as $resource):?>
-                <option value="<?= $resource['resource_id']; ?>" title="<?=$resource['title'] ?>"<? if(isset($this->params['resource_id']) && $resource['resource_id'] == $this->params['resource_id']): ?> selected="selected"<? endif;?>>
-                    <?=$this->truncate($resource['title'], 80) ?> (<?=$resource['resource_id'] ?>)
-                </option>
-                <? endforeach;?>
-              </select>
-            </div>
-            <div class="col-sm-3">
-              <label for="taglistsubmit">&nbsp;</label><br />
-              <input type="submit" id="taglistsubmit" value="<?=$this->transEsc('Filter')?>" class="btn btn-primary">
-              <? if((isset($this->params['user_id']) && !is_null($this->params['user_id'])) || (isset($this->params['tag_id']) && !is_null($this->params['tag_id'])) || (isset($this->params['resource_id']) && !is_null($this->params['resource_id']))):?>
-                <a href="<?= $this->url('admin/tags', array('action' => 'List')); ?>"><?=$this->translate('clear_tag_filter')?></a>
-              <? endif;?>
-            </div>
-          </div>
-
-        </fieldset>
-
-      </form>
+  <form class="form-tags-list" action="<?= $this->url('admin/tags', array('action' => 'List'))?>" method="get">
+    <h3><?=$this->translate('filter_tags')?></h3>
+    <div class="tag-controls">
+      <label for="user_id">
+        <?=$this->translate('Username')?>
+        <select name="user_id" id="user_id" class="form-control">
+          <option value="ALL"><?=$this->translate('All')?></option>
+          <? foreach($this->uniqueUsers as $user):?>
+            <option value="<?= $user['user_id'] ?>"<? if(isset($this->params['user_id']) && $user['user_id'] == $this->params['user_id']): ?> selected="selected"<? endif;?>>
+              <?=$user['username'] ?>
+            </option>
+          <? endforeach;?>
+        </select>
+      </label>
+      <label for="tag_id">
+        <?=$this->translate('Tag')?>
+        <select name="tag_id" id="tag_id" class="form-control">
+          <option value="ALL"><?=$this->translate('All')?></option>
+          <? foreach($this->uniqueTags as $tag):?>
+          <option value="<?= $tag['tag_id'] ?>"<? if(isset($this->params['tag_id']) && $tag['tag_id'] == $this->params['tag_id']): ?> selected="selected"<? endif;?>>
+              <?=$tag['tag'] ?>
+          </option>
+          <? endforeach;?>
+        </select>
+      </label>
+      <label for="resource_id">
+        <?=$this->translate('Title')?>
+        <select name="resource_id" id="resource_id" class="form-control">
+          <option value="ALL"><?=$this->translate('All')?></option>
+          <? foreach($this->uniqueResources as $resource):?>
+          <option value="<?= $resource['resource_id']; ?>" title="<?=$resource['title'] ?>"<? if(isset($this->params['resource_id']) && $resource['resource_id'] == $this->params['resource_id']): ?> selected="selected"<? endif;?>>
+              <?=$this->truncate($resource['title'], 80) ?> (<?=$resource['resource_id'] ?>)
+          </option>
+          <? endforeach;?>
+        </select>
+      </label>
+      <label for="taglistsubmit">
+        <input type="submit" id="taglistsubmit" value="<?=$this->transEsc('Filter')?>" class="btn btn-primary">
+        <? if((isset($this->params['user_id']) && !is_null($this->params['user_id'])) || (isset($this->params['tag_id']) && !is_null($this->params['tag_id'])) || (isset($this->params['resource_id']) && !is_null($this->params['resource_id']))):?>
+          <a href="<?= $this->url('admin/tags', array('action' => 'List')); ?>"><?=$this->translate('clear_tag_filter')?></a>
+        <? endif;?>
+      </label>
     </div>
+  </form>
 
-    <? if(count($this->results) > 0):?>
-      <div class="tagsList">
-        <form action="<?= $this->url('admin/tags', array('action' => 'Delete'))?>" method="post">
-          <input type="hidden" name="user_id" value="<?=isset($this->params['user_id']) ? $this->params['user_id'] : '' ?>" />
-          <input type="hidden" name="tag_id" value="<?=isset($this->params['tag_id']) ? $this->params['tag_id'] : '' ?>" />
-          <input type="hidden" name="resource_id" value="<?=isset($this->params['resource_id']) ? $this->params['resource_id'] : '' ?>" />
-          <input type="hidden" name="origin" value="list" />
+  <? if(count($this->results) > 0):?>
+    <form action="<?= $this->url('admin/tags', array('action' => 'Delete'))?>" method="post">
+      <input type="hidden" name="user_id" value="<?=isset($this->params['user_id']) ? $this->params['user_id'] : '' ?>" />
+      <input type="hidden" name="tag_id" value="<?=isset($this->params['tag_id']) ? $this->params['tag_id'] : '' ?>" />
+      <input type="hidden" name="resource_id" value="<?=isset($this->params['resource_id']) ? $this->params['resource_id'] : '' ?>" />
+      <input type="hidden" name="origin" value="list" />
 
-          <table class="table table-striped">
-            <tr>
-              <th>&nbsp;</th>
-              <th><?=$this->translate('Username')?></th>
-              <th><?=$this->translate('Tag')?></th>
-              <th><?=$this->translate('Title')?></th>
-            </tr>
+      <table class="table table-striped">
+        <tr>
+          <th><?=$this->translate('Tag')?></th>
+          <th><?=$this->translate('Username')?></th>
+          <th><?=$this->translate('Title')?></th>
+        </tr>
 
-            <? foreach ($this->results as $tag): ?>
-              <tr>
-                <td><?=$this->render('admin/tags/checkbox', array('tag'=>$tag)) ; ?></td>
-                <td><?=$tag->username ?> (<?= $tag->user_id?>)</td>
-                <td><?=$tag->tag?> (<?= $tag->tag_id?>)</td>
-                <td><?=$tag->title?> (<?= $tag->resource_id?>)</td>
-              </tr>
-            <? endforeach;?>
-          </table>
+        <? foreach ($this->results as $tag): ?>
+          <tr>
+            <td>
+              <label for="<?=$this->prefix?>checkbox_<?=$tag['id']?>">
+                <input id="<?=$this->prefix?>checkbox_<?=$tag['id']?>" type="checkbox" name="ids[]" value="<?=$this->escapeHtmlAttr($tag['id'])?>" class="checkbox_ui"/>
+                <input type="hidden" name="idsAll[]" value="<?=$this->escapeHtmlAttr($tag['id'])?>" />
+                <?=$tag->tag?> (<?= $tag->tag_id?>)
+              </label>
+            </td>
+            <td><?=$tag->username ?> (<?= $tag->user_id?>)</td>
+            <td><?=$tag->title?> (<?= $tag->resource_id?>)</td>
+          </tr>
+        <? endforeach;?>
+      </table>
 
-          <input type="submit" name="deleteSelected" value="<?=$this->transEsc('delete_selected')?>" class="btn btn-default">
-          <input type="submit" name="deletePage" value="<?=$this->transEsc('delete_page')?>" class="btn btn-default">
-          <input type="submit" name="deleteFilter" value="<?=$this->transEsc('delete_all')?>" class="btn btn-default">
+      <input type="submit" name="deleteSelected" value="<?=$this->transEsc('delete_selected')?>" class="btn btn-default">
+      <input type="submit" name="deletePage" value="<?=$this->transEsc('delete_page')?>" class="btn btn-default">
+      <input type="submit" name="deleteFilter" value="<?=$this->transEsc('delete_all')?>" class="btn btn-danger">
 
-        </form>
-      </div>
-      <?=$this->paginationControl($this->results, 'Sliding', 'Helpers/pagination.phtml', array('params' => $this->params))?>
-    <? else:?>
-      <p><?=$this->translate('tag_filter_empty')?></p>
-    <? endif;?>
-  </div>
+    </form>
+    <?=$this->paginationControl($this->results, 'Sliding', 'Helpers/pagination.phtml', array('params' => $this->params))?>
+  <? else:?>
+    <p><?=$this->translate('tag_filter_empty')?></p>
+  <? endif;?>
+</div>
 
-  <div class="<?=$this->layoutClass('sidebar')?>">
-    <?=$this->render("admin/menu.phtml")?>
-  </div>
-</div>
\ No newline at end of file
+<div class="<?=$this->layoutClass('sidebar')?>">
+  <?=$this->render("admin/menu.phtml")?>
+</div>
diff --git a/themes/bootstrap3/templates/admin/tags/manage.phtml b/themes/bootstrap3/templates/admin/tags/manage.phtml
index 181cc9d5bbaa90a336842a3321f72dee9bd6fbc4..426b2d51398bb38117c92d05798c787d33724179 100644
--- a/themes/bootstrap3/templates/admin/tags/manage.phtml
+++ b/themes/bootstrap3/templates/admin/tags/manage.phtml
@@ -2,90 +2,72 @@
   // Set page title.
   $this->headTitle($this->translate('VuFind Administration - Tag Maintenance'));
 ?>
-<div class="row">
-  <div class="<?=$this->layoutClass('mainbody')?>">
-    <h2><?=$this->translate('Tag Management')?></h2>
-    <h3><?=$this->translate('Manage Tags')?></h3>
 
-    <?=$this->render("admin/tags/menu.phtml")?>
+<h2><?=$this->translate('Tag Management')?></h2>
+<div class="<?=$this->layoutClass('mainbody')?>">
+  <h3><?=$this->translate('Manage Tags')?></h3>
 
-    <?=$this->flashmessages()?>
+  <?=$this->render("admin/tags/menu.phtml", ['active' => 'manage'])?>
 
-    <form class="form-horizontal" action="<?= $this->url('admin/tags', array('action' => 'Manage'));?>" method="post" role="form">
-      <div class="form-group">
-        <label for="type" class="col-sm-2 control-label"><?=$this->translate('delete_tags_by')?>:</label>
-        <div class="col-sm-6">
-          <select id="type" name="type" class="form-control">
-            <option value="user" <? if("user" == $this->type) echo " selected=selected";?>><?=$this->translate('Username')?></option>
-            <option value="tag" <? if("tag" == $this->type) echo " selected=selected";?>><?=$this->translate('Tag')?></option>
-            <option value="resource" <? if("resource" == $this->type) echo " selected=selected";?>><?=$this->translate('Title')?></option>
+  <?=$this->flashmessages()?>
+
+  <form class="form-tags-manage" action="<?= $this->url('admin/tags', array('action' => 'Manage'));?>" method="post" role="form">
+    <div class="form-group">
+      <label for="type" class="control-label"><?=$this->translate('delete_tags_by')?>:</label>
+      <select id="type" name="type" class="form-control">
+        <option value="user" <? if("user" == $this->type) echo " selected=selected";?>><?=$this->translate('Username')?></option>
+        <option value="tag" <? if("tag" == $this->type) echo " selected=selected";?>><?=$this->translate('Tag')?></option>
+        <option value="resource" <? if("resource" == $this->type) echo " selected=selected";?>><?=$this->translate('Title')?></option>
+      </select>
+      <input type="submit" value="<?=$this->translate('Submit')?>" class="btn btn-primary"/>
+    </div>
+  </form>
+
+  <? if(false !== $this->type):?>
+    <form class="form-tags-manage" action="<?= $this->url('admin/tags', array('action' => 'Delete'))?>" method="post">
+      <input type="hidden" name="origin" value="manage" />
+      <input type="hidden" name="type" value="<?= $this->type; ?>" />
+      <? if("user" == $type):?>
+        <div class="form-group">
+          <label for="user_id" class="control-label"><?=$this->translate('Username')?></label>
+          <select name="user_id" id="user_id" class="form-control">
+            <? foreach($this->uniqueUsers as $user):?>
+              <option value="<?= $user['user_id'] ?>">
+                <?= $user['username'] ?>
+              </option>
+            <? endforeach;?>
           </select>
+          <input type="submit"  name="deleteFilter" value="<?=$this->translate('delete_tags')?>" class="btn btn-primary"/>
         </div>
-        <div class="col-sm-4">
-          <input type="submit" value="<?=$this->translate('Submit')?>" class="btn btn-primary"/>
+      <? elseif("tag" == $type):?>
+        <div class="form-group">
+          <label for="tag_id" class="control-label"><?=$this->translate('Tag')?></label>
+          <select name="tag_id" id="tag_id" class="form-control">
+            <? foreach($this->uniqueTags as $tag):?>
+              <option value="<?= $tag['tag_id'] ?>">
+                <?= $tag['tag'] ?>
+              </option>
+            <? endforeach;?>
+          </select>
+          <input type="submit" name="deleteFilter" value="<?=$this->translate('delete_tags')?>" class="btn btn-primary"/>
         </div>
-      </div>
+      <? elseif("resource" == $type):?>
+        <div class="form-group">
+          <label for="resource_id" class="control-label"><?=$this->translate('Title')?></label>
+          <select name="resource_id" id="resource_id" class="form-control">
+            <? foreach($this->uniqueResources as $resource):?>
+              <option value="<?=$resource['resource_id'] ?>" title="<?=$resource['title'] ?>">
+                <?=$this->truncate($resource['title'], 80) ?> (<?= $resource['resource_id'] ?>)
+              </option>
+            <? endforeach;?>
+          </select>
+          <input type="submit" name="deleteFilter" value="<?=$this->translate('delete_tags')?>" class="btn btn-primary"/>
+        </div>
+      <? endif;?>
     </form>
+  <? endif;?>
+</div>
 
-    <? if(false !== $this->type):?>
-      <form class="form-horizontal" action="<?= $this->url('admin/tags', array('action' => 'Delete'))?>" method="post">
-        <input type="hidden" name="origin" value="manage" />
-        <input type="hidden" name="type" value="<?= $this->type; ?>" />
-        <? if("user" == $type):?>
-          <div class="form-group">
-            <label for="user_id" class="col-sm-2 control-label"><?=$this->translate('Username')?></label>
-            <div class="col-sm-6">
-              <select name="user_id" id="user_id" class="form-control">
-                <? foreach($this->uniqueUsers as $user):?>
-                <option value="<?= $user['user_id'] ?>">
-                  <?= $user['username'] ?>
-                </option>
-                <? endforeach;?>
-              </select>
-            </div>
-            <div class="col-sm-4">
-              <input type="submit"  name="deleteFilter" value="<?=$this->translate('delete_tags')?>" class="btn btn-primary"/>
-            </div>
-          </div>
-        <? elseif("tag" == $type):?>
-          <div class="form-group">
-            <label for="tag_id" class="col-sm-2 control-label"><?=$this->translate('Tag')?></label>
-            <div class="col-sm-6">
-              <select name="tag_id" id="tag_id" class="form-control">
-                <? foreach($this->uniqueTags as $tag):?>
-                <option value="<?= $tag['tag_id'] ?>">
-                    <?= $tag['tag'] ?>
-                </option>
-                <? endforeach;?>
-              </select>
-            </div>
-            <div class="col-sm-4">
-              <input type="submit" name="deleteFilter" value="<?=$this->translate('delete_tags')?>" class="btn btn-primary"/>
-            </div>
-          </div>
-        <? elseif("resource" == $type):?>
-          <div class="form-group">
-            <label for="resource_id" class="col-sm-2 control-label"><?=$this->translate('Title')?></label>
-            <div class="col-sm-6">
-              <select name="resource_id" id="resource_id" class="form-control">
-                <? foreach($this->uniqueResources as $resource):?>
-                <option value="<?=$resource['resource_id'] ?>" title="<?=$resource['title'] ?>">
-                  <?=$this->truncate($resource['title'], 80) ?> (<?= $resource['resource_id'] ?>)
-                </option>
-                <? endforeach;?>
-              </select>
-            </div>
-            <div class="col-sm-4">
-              <input type="submit" name="deleteFilter" value="<?=$this->translate('delete_tags')?>" class="btn btn-primary"/>
-            </div>
-          </div>
-        <? endif;?>
-      </form>
-    <? endif;?>
-
-  </div>
-
-  <div class="<?=$this->layoutClass('sidebar')?>">
-    <?=$this->render("admin/menu.phtml")?>
-  </div>
-</div>
\ No newline at end of file
+<div class="<?=$this->layoutClass('sidebar')?>">
+  <?=$this->render("admin/menu.phtml")?>
+</div>
diff --git a/themes/bootstrap3/templates/admin/tags/menu.phtml b/themes/bootstrap3/templates/admin/tags/menu.phtml
index 7630b6ab9a7ed78a27a44a3763f3a0203f787ec6..ad57f45fa96eeae9c490b245a9e9953e30c29d7d 100644
--- a/themes/bootstrap3/templates/admin/tags/menu.phtml
+++ b/themes/bootstrap3/templates/admin/tags/menu.phtml
@@ -1,6 +1,6 @@
-<div class="toolbar">
+<div class="nav navbar">
   <ul class="nav nav-pills">
-    <li<?=strtolower($this->layout()->templateName) == "tagslist" ? ' class="active"' : ''?>><a href="<?=$this->url('admin/tags', array('action' => 'List'))?>"><?=$this->transEsc('List Tags')?></a></li>
-    <li<?=strtolower($this->layout()->templateName) == "tagsmanage" ? ' class="active"' : ''?>><a href="<?=$this->url('admin/tags', array('action' => 'Manage'))?>"><?=$this->transEsc('Manage Tags')?></a></li>
+    <li<?=strtolower($this->active) == "list" ? ' class="active"' : ''?>><a href="<?=$this->url('admin/tags', array('action' => 'List'))?>"><?=$this->transEsc('List Tags')?></a></li>
+    <li<?=strtolower($this->active) == "manage" ? ' class="active"' : ''?>><a href="<?=$this->url('admin/tags', array('action' => 'Manage'))?>"><?=$this->transEsc('Manage Tags')?></a></li>
   </ul>
 </div>
diff --git a/themes/bootstrap3/templates/ajax/export-favorites.phtml b/themes/bootstrap3/templates/ajax/export-favorites.phtml
index 63648f8b29f09716eed353e348b81d66d3c63a1c..8caa049b958ff241a5d8aa40e1bf82265b1b0dde 100644
--- a/themes/bootstrap3/templates/ajax/export-favorites.phtml
+++ b/themes/bootstrap3/templates/ajax/export-favorites.phtml
@@ -3,8 +3,8 @@
     <?=$this->transEsc('export_success'); ?>&nbsp;&mdash;&nbsp;
     <a class="btn btn-primary" href="<?=$this->escapeHtmlAttr($this->url)?>"<?=$this->export()->needsRedirect($this->format) ? ' target="_blank"' : ''?>><?=
         $this->export()->needsRedirect($this->format)
-            ? $this->transEsc('export_redirect', array('%%service%%' => $this->translate($this->export()->getLabelForFormat($this->format))))
+            ? $this->transEsc('export_redirect', ['%%service%%' => $this->translate($this->export()->getLabelForFormat($this->format))])
             : $this->transEsc('export_download')
       ?></a>
   </div>
-</div>
\ No newline at end of file
+</div>
diff --git a/themes/bootstrap3/templates/ajax/resolverLinks.phtml b/themes/bootstrap3/templates/ajax/resolverLinks.phtml
index 735b8f2b51aab051c602d2111d154b7fad71ea9b..2a602e55378d41c14fe27fe6820b37445041bbcf 100644
--- a/themes/bootstrap3/templates/ajax/resolverLinks.phtml
+++ b/themes/bootstrap3/templates/ajax/resolverLinks.phtml
@@ -32,7 +32,7 @@
     </div>
   <? endif; ?>
   <div class="openurls">
-    <strong><a href="<?=$this->escapeHtmlAttr($this->openUrlBase)?>?<?=$this->escapeHtmlAttr($this->openUrl)?>"><?=$this->transEsc('More options')?></a></strong>
+    <? if (!empty($this->moreOptionsLink)): ?><strong><a href="<?=$this->escapeHtmlAttr($this->moreOptionsLink)?>"><?=$this->transEsc('More options')?></a></strong><?endif; ?>
     <? if (!empty($this->services)): ?>
       <ul>
         <? foreach ($this->services as $link): ?>
diff --git a/themes/bootstrap3/templates/ajax/status-available.phtml b/themes/bootstrap3/templates/ajax/status-available.phtml
index fe60ff791a18a29990442830483cdea5b06e64c4..f5de1467dbe0e745944381ab166671bfece4a54e 100644
--- a/themes/bootstrap3/templates/ajax/status-available.phtml
+++ b/themes/bootstrap3/templates/ajax/status-available.phtml
@@ -1 +1 @@
-<span class="label label-success"><?=$this->transEsc("Available")?></span>
\ No newline at end of file
+<span class="label label-success"><?=$this->transEsc("Available")?></span>
diff --git a/themes/bootstrap3/templates/ajax/status-full.phtml b/themes/bootstrap3/templates/ajax/status-full.phtml
index a04420f3b63f42ea6a9a6737b5433a825845fadb..4c72e03f9377a7c2b21e2eb7e8807773cb1db42b 100644
--- a/themes/bootstrap3/templates/ajax/status-full.phtml
+++ b/themes/bootstrap3/templates/ajax/status-full.phtml
@@ -8,7 +8,7 @@
     <? if (++$i == 5) break; // Show no more than 5 items ?>
     <tr>
       <td class="fullLocation">
-        <? $locationText = $this->transEsc('location_' . $item['location'], array(), $item['location']); ?>
+        <? $locationText = $this->transEsc('location_' . $item['location'], [], $item['location']); ?>
         <? if (isset($item['locationhref']) && $item['locationhref']): ?>
           <a href="<?=$item['locationhref']?>" target="_blank"><?=$locationText?></a>
         <? else: ?>
@@ -34,6 +34,6 @@
     </tr>
   <? endforeach; ?>
 <? if (count($this->statusItems) > 5): ?>
-  <tr><td colspan="3"><a href="<?=$this->url('record', array('id' => $this->statusItems[0]['id']))?>"><?=count($this->statusItems) - 5?> <?=$this->transEsc('more')?> ...</a></td></tr>
+  <tr><td colspan="3"><a href="<?=$this->url('record', ['id' => $this->statusItems[0]['id']])?>"><?=count($this->statusItems) - 5?> <?=$this->transEsc('more')?> ...</a></td></tr>
 <? endif; ?>
 </table>
diff --git a/themes/bootstrap3/templates/ajax/status-unknown.phtml b/themes/bootstrap3/templates/ajax/status-unknown.phtml
index 90859f902e99f686f3291579a691a5031e05197d..c1b066dbd6437b61569225a0df98db995001b29b 100644
--- a/themes/bootstrap3/templates/ajax/status-unknown.phtml
+++ b/themes/bootstrap3/templates/ajax/status-unknown.phtml
@@ -1 +1 @@
-<span class="label label-default"><?=$this->transEsc("status_unknown_message")?></span>
\ No newline at end of file
+<span class="label label-default"><?=$this->transEsc("status_unknown_message")?></span>
diff --git a/themes/bootstrap3/templates/alphabrowse/home.phtml b/themes/bootstrap3/templates/alphabrowse/home.phtml
index 1faf64bbf0b2b037a60cbe005f198a5dcff7cc7c..f835972082287f7dfa0107b83311751bce137b95 100644
--- a/themes/bootstrap3/templates/alphabrowse/home.phtml
+++ b/themes/bootstrap3/templates/alphabrowse/home.phtml
@@ -1,20 +1,20 @@
 <?
   $this->headTitle($this->translate('Browse the Collection Alphabetically'));
   $this->layout()->breadcrumbs = '<a href="' . $this->url('alphabrowse-home') . '">' . $this->transEsc('Browse Alphabetically') . '</a>';
-  $baseQuery = array('source' => $this->source, 'from' => $this->from);
+  $baseQuery = ['source' => $this->source, 'from' => $this->from];
 ?>
 
 <? /* LOAD THE LINK INFORMATION INTO $pageLinks, similar to smarty's {capture} */ ?>
 <? ob_start(); ?>
   <ul class="pager">
     <? if (isset($this->prevpage)): ?>
-      <li><a href="<?=$this->escapeHtmlAttr($this->url('alphabrowse-home', array(), array('query' => $baseQuery + array('page' => $this->prevpage))))?>">&laquo; <?=$this->transEsc('Prev')?></a></li>
+      <li><a href="<?=$this->escapeHtmlAttr($this->url('alphabrowse-home', [], ['query' => $baseQuery + ['page' => $this->prevpage]]))?>">&laquo; <?=$this->transEsc('Prev')?></a></li>
     <? else: ?>
       <li class="disabled"><a href="#">&laquo; <?=$this->transEsc('Prev')?></a></li>
     <? endif; ?>
 
     <? if (isset($this->nextpage)): ?>
-      <li><a href="<?=$this->escapeHtmlAttr($this->url('alphabrowse-home', array(), array('query' => $baseQuery + array('page' => $this->nextpage))))?>"><?=$this->transEsc('Next')?> &raquo;</a></li>
+      <li><a href="<?=$this->escapeHtmlAttr($this->url('alphabrowse-home', [], ['query' => $baseQuery + ['page' => $this->nextpage]]))?>"><?=$this->transEsc('Next')?> &raquo;</a></li>
     <? else: ?>
       <li class="disabled"><a href="#"><?=$this->transEsc('Next')?> &raquo;</a></li>
     <? endif; ?>
@@ -31,7 +31,7 @@
   </select>
   <label for="alphaBrowseForm_from"><?=$this->transEsc('starting from') ?></label>
   <input type="text" name="from" id="alphaBrowseForm_from" value="<?=$this->escapeHtmlAttr($this->from) ?>" class="form-control"/>
-  <input class="btn btn-default" type="submit" value="<?=$this->transEsc('Browse') ?>"/>
+  <input class="btn btn-primary" type="submit" value="<?=$this->transEsc('Browse') ?>"/>
 </form>
 
 <? if ($this->result): ?>
@@ -76,7 +76,7 @@
                 <?=$this->transEsc('Use instead') ?>:
                 <ul>
                   <? foreach ($item['useInstead'] as $heading): ?>
-                  <li><a href="<?=$this->escapeHtmlAttr($this->url('alphabrowse-home', array(), array('query' => array('from' => $heading) + $baseQuery)))?>"><?=$this->escapeHtml($heading)?></a></li>
+                  <li><a href="<?=$this->escapeHtmlAttr($this->url('alphabrowse-home', [], ['query' => ['from' => $heading] + $baseQuery]))?>"><?=$this->escapeHtml($heading)?></a></li>
                   <? endforeach; ?>
                 </ul>
               </div>
@@ -87,7 +87,7 @@
                 <?=$this->transEsc('See also') ?>:
                 <ul>
                   <? foreach ($item['seeAlso'] as $heading): ?>
-                  <li><a href="<?=$this->escapeHtmlAttr($this->url('alphabrowse-home', array(), array('query' => array('from' => $heading) + $baseQuery)))?>"><?=$this->escapeHtml($heading)?></a></li>
+                  <li><a href="<?=$this->escapeHtmlAttr($this->url('alphabrowse-home', [], ['query' => ['from' => $heading] + $baseQuery]))?>"><?=$this->escapeHtml($heading)?></a></li>
                   <? endforeach; ?>
                 </ul>
               </div>
@@ -106,7 +106,7 @@
           <? foreach ($this->extras as $extraName): ?>
             <td>
               <?
-                $extraDisplayArray = array();
+                $extraDisplayArray = [];
                 foreach ($item['extras'][$extraName] as $j => $e):
                   $extraDisplayArray = array_unique(array_merge($extraDisplayArray, $e));
                 endforeach;
diff --git a/themes/bootstrap3/templates/author/home.phtml b/themes/bootstrap3/templates/author/home.phtml
index b3c2f8279e888ea00da97edec28bce90cfcf1a3d..8f633380032565d703bcb04d832e841862a9b473 100644
--- a/themes/bootstrap3/templates/author/home.phtml
+++ b/themes/bootstrap3/templates/author/home.phtml
@@ -8,5 +8,5 @@
 <form class="form-inline" method="get" action="<?=$this->url('author-search')?>">
   <label for="author_lookfor"><?=$this->transEsc('Author Results for')?>:</label></br>
   <input class="form-control" type="text" id="author_lookfor" name="lookfor" />
-  <input class="btn btn-default" type="submit" value="<?=$this->transEsc('Find')?>" />
+  <input class="btn btn-primary" type="submit" value="<?=$this->transEsc('Find')?>" />
 </form>
diff --git a/themes/bootstrap3/templates/author/results.phtml b/themes/bootstrap3/templates/author/results.phtml
index 5f83e8ccea863d4cb47a166fcf34a43040700812..d0859ea035a51c1210476a4c6e9ada7cb6245c44 100644
--- a/themes/bootstrap3/templates/author/results.phtml
+++ b/themes/bootstrap3/templates/author/results.phtml
@@ -8,7 +8,7 @@
     $this->headTitle($this->translate('Author Search Results'));
 
     // Set up empty search box (we want Author search boxes to point at the Solr search screen):
-    $this->layout()->searchbox = $this->context($this)->renderInContext('search/searchbox.phtml', array('searchClassId' => 'Solr'));
+    $this->layout()->searchbox = $this->context($this)->renderInContext('search/searchbox.phtml', ['searchClassId' => 'Solr']);
 
     // Set up breadcrumbs:
     $this->layout()->breadcrumbs = '<li><a href="' . $this->url('author-home') . '">' . $this->transEsc('Author') . '</a></li><li class="active">' . $this->escapeHtml($this->params->getDisplayQuery()) . '</li>';
diff --git a/themes/bootstrap3/templates/author/search.phtml b/themes/bootstrap3/templates/author/search.phtml
index e613c5829181b8d81ec8fbd0d8e34c2131c29a2c..a26bf7846c41845fd6d1e5b2461c8337832a173c 100644
--- a/themes/bootstrap3/templates/author/search.phtml
+++ b/themes/bootstrap3/templates/author/search.phtml
@@ -13,9 +13,9 @@
     $this->headTitle($this->translate('Author Browse'));
 
     // Set up empty search box pointing at Solr module:
-    $this->layout()->searchbox = $this->context($this)->renderInContext('search/searchbox.phtml', array('searchClassId' => 'Solr'));
+    $this->layout()->searchbox = $this->context($this)->renderInContext('search/searchbox.phtml', ['searchClassId' => 'Solr']);
 
     // Set up breadcrumbs:
     $this->layout()->breadcrumbs = '<li><a href="' . $this->url('author-home') . '">' . $this->transEsc('Author') . '</a></li> '
          . '<li class="active">' . $this->transEsc('Author Results for') . ' ' . $this->escapeHtml($this->params->getDisplayQuery()) . '</li>';
-?>
\ No newline at end of file
+?>
diff --git a/themes/bootstrap3/templates/authority/home.phtml b/themes/bootstrap3/templates/authority/home.phtml
index d13d4348c1e39e2222b5f16ce7d65ecd7816ef92..bc5b700660ea8e7baee8cc01de0600b0b4611521 100644
--- a/themes/bootstrap3/templates/authority/home.phtml
+++ b/themes/bootstrap3/templates/authority/home.phtml
@@ -1 +1 @@
-<?=$this->render('search/home.phtml');?>
\ No newline at end of file
+<?=$this->render('search/home.phtml');?>
diff --git a/themes/bootstrap3/templates/authority/record.phtml b/themes/bootstrap3/templates/authority/record.phtml
index 9ad570830df18afbd2aef08af7b3b346a229f7bc..b13625d56ea1fdc48a3b7680c9d667c34f3ee6e0 100644
--- a/themes/bootstrap3/templates/authority/record.phtml
+++ b/themes/bootstrap3/templates/authority/record.phtml
@@ -1,2 +1,2 @@
 <? $this->layout()->breadcrumbs = false; ?>
-<?=$this->record($this->driver)->getTab($this->tabs['Details'])?>
\ No newline at end of file
+<?=$this->record($this->driver)->getTab($this->tabs['Details'])?>
diff --git a/themes/bootstrap3/templates/authority/search.phtml b/themes/bootstrap3/templates/authority/search.phtml
index c1797c1cd4a1ebb2ccad84718b1e225e51cac6a8..a0c6dd4bbf5077e0b43b335e98733b44bba7b4e6 100644
--- a/themes/bootstrap3/templates/authority/search.phtml
+++ b/themes/bootstrap3/templates/authority/search.phtml
@@ -1,4 +1,4 @@
 <?
     // Load standard settings from the default search results screen:
     echo $this->render('search/results.phtml');
-?>
\ No newline at end of file
+?>
diff --git a/themes/bootstrap3/templates/breadcrumbs/default.phtml b/themes/bootstrap3/templates/breadcrumbs/default.phtml
index 17d0d06fbcfdabfb2daa33ebcad2ff75b0deb186..d3ae32c8f4449ac2c972f82cb97967fd045ab58e 100644
--- a/themes/bootstrap3/templates/breadcrumbs/default.phtml
+++ b/themes/bootstrap3/templates/breadcrumbs/default.phtml
@@ -1,11 +1,11 @@
 <li><a href="<?=$this->url('home')?>"><?=$this->transEsc('Home')?></a></li>
 <? $current = $this->layout()->breadcrumbs; $current = current($current); ?>
 <? foreach($current as $id=>$parent): ?>
-  <li><a href="<?=$this->url('collection', array('id'=>$id)) ?>"><?=$parent ?></a></li>
+  <li><a href="<?=$this->url('collection', ['id'=>$id]) ?>"><?=$parent ?></a></li>
 <? endforeach; ?>
 <? if(isset($this->layout()->end)): ?>
   <li title="<?=$this->layout()->title ?>"><?=$this->truncate($this->layout()->title, 100) ?></li>
   <li class="active"><?=$this->layout()->end ?></li>
 <? else: ?>
   <li class="active" title="<?=$this->layout()->title ?>"><?=$this->truncate($this->layout()->title, 100) ?></li>
-<? endif; ?>
\ No newline at end of file
+<? endif; ?>
diff --git a/themes/bootstrap3/templates/browse/home.phtml b/themes/bootstrap3/templates/browse/home.phtml
index 4c6f2197d0c30a968ad973956cc4090bf62d4d08..10881e1d0b80813d99bd5a4909f9b85432e23982 100644
--- a/themes/bootstrap3/templates/browse/home.phtml
+++ b/themes/bootstrap3/templates/browse/home.phtml
@@ -10,10 +10,10 @@
   <h2><?=$this->transEsc('Choose a Category to Begin Browsing') ?>:</h2>
 <? endif; ?>
 
-<div class="row">
-  <div class="browse list-group col-sm-3<? if (!empty($this->categoryList)): ?> hidden-xs<? endif ?>" id="list1">
+<div class="browse-container">
+  <div class="browse-list<? if (!empty($this->categoryList) || !empty($this->secondaryList)): ?> hidden-xs<? endif ?>" id="list1">
     <? foreach ($this->browseOptions as $item=>$currentOption): ?>
-      <a href="<?=$this->url('browse-' . strtolower($currentOption['action'])); ?>" class="list-group-item<? if($currentOption['action'] == $this->currentAction): ?> active<? endif; ?>">
+      <a href="<?=$this->url('browse-' . strtolower($currentOption['action'])); ?>" class="browse-item<? if($currentOption['action'] == $this->currentAction): ?> active<? endif; ?>">
         <?=$this->transEsc($currentOption['description']) ?>
         <span class="pull-right flip"><i class="fa fa-angle-right" title="<?=$this->transEsc('more') ?>"></i></span>
       </a>
@@ -21,9 +21,9 @@
   </div>
 
   <? if (!empty($this->categoryList)): ?>
-    <div class="browse list-group col-sm-3<? if (!empty($this->secondaryList) || !empty($this->resultList)): ?> hidden-xs<? endif ?>" id="list2">
+    <div class="browse-list<? if (!empty($this->secondaryList) || !empty($this->resultList)): ?> hidden-xs<? endif ?>" id="list2">
       <? foreach($this->categoryList as $findby=>$category): ?>
-        <a href="<?=$BROWSE_BASE ?>?findby=<?=urlencode($findby) ?>&amp;query_field=<?=$this->browse()->getSolrField($findby, $this->currentAction) ?>" class="list-group-item clearfix<? if ($this->findby == $findby): ?> active<? endif; ?>">
+        <a href="<?=$BROWSE_BASE ?>?findby=<?=urlencode($findby) ?>&amp;query_field=<?=$this->browse()->getSolrField($findby, $this->currentAction) ?>" class="browse-item<? if (!is_string($category)): ?> with-badge<? endif; ?><? if ($this->findby == $findby): ?> active<? endif; ?>">
           <? if(is_string($category)): ?>
             <?=$this->transEsc($category)?>
             <span class="pull-right flip"><i class="fa fa-angle-right" title="<?=$this->transEsc('more') ?>"></i></span>
@@ -37,7 +37,7 @@
   <? endif; ?>
 
   <? if (!empty($this->secondaryList)): ?>
-    <div class="browse list-group col-sm-3<? if (!empty($this->resultList)): ?> hidden-xs<? endif ?>" id="list3">
+    <div class="browse-list<? if (!empty($this->resultList)): ?> hidden-xs<? endif ?>" id="list3">
     <? foreach($this->secondaryList as $secondary): ?>
       <? $url = $BROWSE_BASE . '?findby=' . urlencode($this->findby)
           . '&amp;category=' . urlencode($this->category)
@@ -51,34 +51,35 @@
           }
         }
         $viewRecord = !empty($this->categoryList) && $this->currentAction != 'Tag' && $this->findby != 'alphabetical';
+        $hasBadge = $this->findby != 'alphabetical' && isset($secondary['count']);
       ?>
-      <a href="<?=$url ?>" class="list-group-item clearfix<? if ($this->query == $secondary['value'].'' || $this->query == $secondary['value'].'*'): ?> active<? endif; ?>">
+      <a href="<?=$url ?>" class="browse-item<? if ($hasBadge): ?> with-badge<? endif; ?><? if ($this->query == $secondary['value'].'' || $this->query == $secondary['value'].'*'): ?> active<? endif; ?>">
         <?=$this->escapeHtml($secondary['displayText']) ?>
-        <? if ($this->findby != 'alphabetical' && isset($secondary['count'])): ?>
+        <? if ($hasBadge): ?>
           <span class="badge"><?=number_format($secondary['count']) ?></span>
         <? else: ?>
           <span class="pull-right flip"><i class="fa fa-angle-right" title="<?=$this->transEsc('more') ?>"></i></span>
         <? endif; ?>
       </a>
       <? if($viewRecord): ?>
-        <a class="list-group-item view-record" href="<?=$SEARCH_BASE ?>?lookfor=<? if ($this->filter): ?>&amp;filter[]=<?=urlencode($this->filter) ?>%3A<?=str_replace('+AND+','&amp;filter[]=', urlencode($secondary['value'])) ?><? endif; ?>&amp;filter[]=<?=$this->browse()->getSolrField($this->currentAction) ?>%3A[* TO *]<? if($this->dewey_flag):?>&amp;sort=dewey-sort<?endif;?>"><?=$this->transEsc('View Records') ?></a>
+        <a class="browse-item view-record" href="<?=$SEARCH_BASE ?>?lookfor=<? if ($this->filter): ?>&amp;filter[]=<?=urlencode($this->filter) ?>%3A<?=str_replace('+AND+','&amp;filter[]=', urlencode($secondary['value'])) ?><? endif; ?>&amp;filter[]=<?=$this->browse()->getSolrField($this->currentAction) ?>%3A[* TO *]<? if($this->dewey_flag):?>&amp;sort=dewey-sort<?endif;?>"><?=$this->transEsc('View Records') ?></a>
       <? endif; ?>
     <? endforeach; ?>
     </div>
   <? endif; ?>
 
   <? if (!empty($this->resultList)): ?>
-    <div class="browse list-group col-sm-3" id="list4">
+    <div class="browse-list" id="list4">
     <? foreach($this->resultList as $result): ?>
-      <a class="list-group-item clearfix" href="<?=$SEARCH_BASE ?>?<?=$this->paramTitle ?><?=urlencode($result['value']) ?><? if ($this->searchParams): foreach($this->searchParams as $var=>$val): ?>&amp;<?=$var ?>=<?=urlencode($val) ?><? endforeach;endif; ?>">
+      <a class="browse-item with-badge" href="<?=$SEARCH_BASE ?>?<?=$this->paramTitle ?><?=urlencode($result['value']) ?><? if ($this->searchParams): foreach($this->searchParams as $var=>$val): ?>&amp;<?=$var ?>=<?=urlencode($val) ?><? endforeach;endif; ?>">
         <?=$this->escapeHtml($result['displayText'])?>
         <span class="badge"><?=number_format($result['count']) ?></span>
       </a>
     <? endforeach; ?>
     </div>
   <? elseif (isset($this->query)): ?>
-    <ul class="browse list-group col-sm-3" id="list4">
-      <li class="list-group-item"><?=$this->transEsc('nohit_heading') ?></li>
-    </ul>
+    <div class="browse-list" id="list4">
+      <span class="browse-item"><?=$this->transEsc('nohit_heading') ?></li>
+    </div>
   <? endif; ?>
 </div>
diff --git a/themes/bootstrap3/templates/cart/cart.phtml b/themes/bootstrap3/templates/cart/cart.phtml
index dfd5c6c2e57b915a21ab2fd605b8e1845c469b80..d0ae574863b28e79267935218617e0e4946957c3 100644
--- a/themes/bootstrap3/templates/cart/cart.phtml
+++ b/themes/bootstrap3/templates/cart/cart.phtml
@@ -34,7 +34,7 @@
         </button>
       <? endif; ?>
       <button type="submit" class="btn btn-default dropdown-toggle" name="print" title="<?=$this->transEsc('print_selected')?>" value="1">
-        <i class="fa fa-print" aria-hidden="true"></i>
+        <i class="fa fa-printer" aria-hidden="true"></i>
         <?=$this->transEsc('Print')?>
       </button>
       <div class="btn-group" id="cartDelete">
@@ -70,4 +70,4 @@
   }
 JS;
 ?>
-<?=$this->inlineScript(\Zend\View\Helper\HeadScript::SCRIPT, $script, 'SET') ?>
\ No newline at end of file
+<?=$this->inlineScript(\Zend\View\Helper\HeadScript::SCRIPT, $script, 'SET') ?>
diff --git a/themes/bootstrap3/templates/cart/contents.phtml b/themes/bootstrap3/templates/cart/contents.phtml
index 73da319f6cf4f558158816658bf7e7bba06ab334..40fefe4ce7461bf375c01ec2905945ea2d6526b1 100644
--- a/themes/bootstrap3/templates/cart/contents.phtml
+++ b/themes/bootstrap3/templates/cart/contents.phtml
@@ -14,4 +14,4 @@
   </ul>
 <? else: ?>
   <p class="alert alert-info"><?=$this->transEsc('bookbag_is_empty')?>.</p>
-<? endif; ?>
\ No newline at end of file
+<? endif; ?>
diff --git a/themes/bootstrap3/templates/cart/email.phtml b/themes/bootstrap3/templates/cart/email.phtml
index 5ecf13338a71e45fd6250263ffc7662cac39949c..bbea929f5ae29eb424e7c8dbc5a4ed27f64d004e 100644
--- a/themes/bootstrap3/templates/cart/email.phtml
+++ b/themes/bootstrap3/templates/cart/email.phtml
@@ -9,28 +9,26 @@
 ?>
 <h2><?=$this->transEsc('bookbag_email_selected') ?></h2>
 <?=$this->flashmessages()?>
-<form class="form-horizontal" action="<?=$this->url('cart-email')?>" method="post"  name="bulkEmail">
+<form class="form-cart-email" action="<?=$this->url('cart-email')?>" method="post"  name="bulkEmail">
   <? foreach ($this->records as $current): ?>
     <input type="hidden" name="ids[]" value="<?=$this->escapeHtmlAttr($current->getSourceIdentifier() . '|' . $current->getUniqueId())?>" />
   <? endforeach; ?>
   <div class="form-group">
-    <label class="col-sm-3 control-label"><?=$this->transEsc('Title')?></label>
-    <div class="col-sm-9">
+    <label class="control-label"><?=$this->transEsc('Title')?>:</label>
     <? if(count($this->records) > 1): ?>
-        <button type="button" class="btn btn-default hidden" data-toggle="collapse" data-target="#itemhide">
-          <?=count($this->records).' '.$this->transEsc('items') ?>
-        </button>
-        <div id="itemhide" class="collapse in">
-          <ul>
-            <? foreach ($this->records as $current): ?>
-              <li><?=$this->escapeHtml($current->getBreadcrumb())?></li>
-            <? endforeach; ?>
-          </ul>
-        </div>
+      <button type="button" class="btn btn-default hidden" data-toggle="collapse" data-target="#itemhide">
+        <?=count($this->records).' '.$this->transEsc('items') ?>
+      </button>
+      <div id="itemhide" class="collapse in">
+        <ul>
+          <? foreach ($this->records as $current): ?>
+            <li><?=$this->escapeHtml($current->getBreadcrumb())?></li>
+          <? endforeach; ?>
+        </ul>
+      </div>
     <? else: ?>
       <p class="form-control-static"><?=$this->records[0]->getBreadcrumb() ?></p>
     <? endif; ?>
-    </div>
   </div>
   <?=$this->render('Helpers/email-form-fields.phtml')?>
 </form>
@@ -40,4 +38,4 @@
     $('#itemhide').removeClass('in');
 JS;
 ?>
-<?=$this->inlineScript(\Zend\View\Helper\HeadScript::SCRIPT, $script, 'SET') ?>
\ No newline at end of file
+<?=$this->inlineScript(\Zend\View\Helper\HeadScript::SCRIPT, $script, 'SET') ?>
diff --git a/themes/bootstrap3/templates/cart/export.phtml b/themes/bootstrap3/templates/cart/export.phtml
index bc064adfe8b7bb4b8b6522af771fc7bbd78c293c..9a218882ca453a2a358ef568a7ce148c9dd8eb3f 100644
--- a/themes/bootstrap3/templates/cart/export.phtml
+++ b/themes/bootstrap3/templates/cart/export.phtml
@@ -12,13 +12,12 @@
 <?=$this->flashmessages()?>
 
 <? if (!empty($this->exportOptions)): ?>
-  <form class="form-horizontal" method="post" action="<?=$this->url('cart-export')?>" name="exportForm" title="<?=$this->transEsc('Export Items')?>">
+  <form class="form-cart-export" method="post" action="<?=$this->url('cart-export')?>" name="exportForm" title="<?=$this->transEsc('Export Items')?>">
     <? foreach ($this->records as $current): ?>
       <input type="hidden" name="ids[]" value="<?=$this->escapeHtmlAttr($current->getSourceIdentifier() . '|' . $current->getUniqueId())?>" />
     <? endforeach; ?>
     <div class="form-group">
-      <label class="col-sm-3 control-label"><?=$this->transEsc('Title')?></label>
-      <div class="col-sm-9">
+      <label class="control-label"><?=$this->transEsc('Title')?>:</label>
       <? if(count($this->records) > 1): ?>
         <button type="button" class="btn btn-default hidden" data-toggle="collapse" data-target="#itemhide">
           <?=count($this->records).' '.$this->transEsc('items') ?>
@@ -33,24 +32,19 @@
       <? else: ?>
         <p class="form-control-static"><?=$this->records[0]->getBreadcrumb() ?></p>
       <? endif; ?>
-      </div>
     </div>
     <div class="form-group">
-      <label for="format" class="col-sm-3 control-label"><?=$this->transEsc('Format')?>:</label>
-      <div class="col-sm-9">
-        <select name="format" id="format" class="form-control">
-          <? $firstOption = null; ?>
-          <? foreach ($this->exportOptions as $exportOption): ?>
-            <? if ($firstOption == null) $firstOption = $exportOption; ?>
-            <option value="<?=$this->escapeHtmlAttr($exportOption)?>"<? if($this->export()->needsRedirect($exportOption)): ?> data-redirect<? endif; ?>><?=$this->transEsc($this->export()->getLabelForFormat($exportOption))?></option>
-          <? endforeach; ?>
-        </select>
-      </div>
+    <label for="format" class="control-label"><?=$this->transEsc('Format')?>:</label>
+      <select name="format" id="format" class="form-control">
+        <? $firstOption = null; ?>
+        <? foreach ($this->exportOptions as $exportOption): ?>
+          <? if ($firstOption == null) $firstOption = $exportOption; ?>
+          <option value="<?=$this->escapeHtmlAttr($exportOption)?>"<? if($this->export()->needsRedirect($exportOption)): ?> data-redirect<? endif; ?>><?=$this->transEsc($this->export()->getLabelForFormat($exportOption))?></option>
+        <? endforeach; ?>
+      </select>
     </div>
     <div class="form-group">
-      <div class="col-sm-9 col-sm-offset-3">
-        <input class="export btn btn-default" type="submit" name="submit" value="<?=$this->transEsc('Export')?>"<? if($this->export()->needsRedirect($firstOption)): ?> data-lightbox-ignore<? endif; ?>/>
-      </div>
+      <input class="export btn btn-primary" type="submit" name="submit" value="<?=$this->transEsc('Export')?>"<? if($this->export()->needsRedirect($firstOption)): ?> data-lightbox-ignore<? endif; ?>/>
     </div>
   </form>
 <? endif; ?>
@@ -58,13 +52,20 @@
   $script = <<<JS
   $('button.btn.hidden').removeClass('hidden');
   $('#itemhide').removeClass('in');
+  $('.export.btn').click(function exportButtonClick() {
+    if (typeof $('#format option:selected').attr('data-redirect') !== 'undefined') {
+      VuFind.modal('hide');
+    }
+  });
   $('#format').change(function exportFormatChange(e) {
     if (this.selectedOptions[0].getAttribute('data-redirect') === null) {
       $('.export.btn').removeAttr('data-lightbox-ignore');
+      $('form[name=exportForm]').removeAttr('target');
     } else {
       $('.export.btn').attr('data-lightbox-ignore', '1');
+      $('form[name=exportForm]').attr('target', this.selectedOptions[0].value + 'Main');
     }
-  });
+  }).trigger('change');
 JS;
 ?>
-<?=$this->inlineScript(\Zend\View\Helper\HeadScript::SCRIPT, $script, 'SET') ?>
\ No newline at end of file
+<?=$this->inlineScript(\Zend\View\Helper\HeadScript::SCRIPT, $script, 'SET') ?>
diff --git a/themes/bootstrap3/templates/cart/save.phtml b/themes/bootstrap3/templates/cart/save.phtml
index a982ee7952ebfaf9ce43a6b3ecf1425c3fa8918f..80a149db085604475a81bf0c65c43f0141e8af45 100644
--- a/themes/bootstrap3/templates/cart/save.phtml
+++ b/themes/bootstrap3/templates/cart/save.phtml
@@ -10,15 +10,14 @@
 
 <?=$this->flashmessages()?>
 
-<form class="form-horizontal" method="post" action="<?=$this->url('cart-save')?>" name="bulkSave">
-  <? $idParams = array(); ?>
+<form class="form-cart-save" method="post" action="<?=$this->url('cart-save')?>" name="bulkSave">
+  <? $idParams = []; ?>
   <? foreach ($this->records as $current): ?>
     <? $idParams[] = urlencode('ids[]') . '=' . urlencode($current->getSourceIdentifier() . '|' . $current->getUniqueId()) ?>
     <input type="hidden" name="ids[]" value="<?=$this->escapeHtmlAttr($current->getSourceIdentifier() . '|' . $current->getUniqueId())?>" />
   <? endforeach; ?>
   <div class="form-group">
-    <label class="col-sm-3 control-label"><?=$this->transEsc('Title')?></label>
-    <div class="col-sm-9">
+    <label class="control-label"><?=$this->transEsc('Title')?>:</label>
     <? if(count($this->records) > 1): ?>
       <button type="button" class="btn btn-default hidden" data-toggle="collapse" data-target="#itemhide">
         <?=count($this->records).' '.$this->transEsc('items') ?>
@@ -33,38 +32,31 @@
     <? else: ?>
       <p class="form-control-static"><?=$this->records[0]->getBreadcrumb() ?></p>
     <? endif; ?>
-    </div>
   </div>
 
   <div class="form-group">
-    <label class="col-sm-3 control-label" for="save_list"><?=$this->transEsc('Choose a List') ?></label>
-    <div class="col-sm-9">
-      <select id="save_list" name="list" class="form-control">
-        <? if (count($this->lists) > 0): ?>
-          <? foreach ($this->lists as $list): ?>
-            <option value="<?=$list['id'] ?>"<? if ($list['id']==$this->userList()->lastUsed()): ?> selected="selected"<? endif; ?>><?=$this->escapeHtml($list['title'])?></option>
-          <? endforeach; ?>
-        <? else: ?>
-          <option value=""><?=$this->transEsc('My Favorites') ?></option>
-        <? endif; ?>
-      </select>
-      <a class="btn btn-link" id="make-list"  href="<?=$this->url('editList', array('id' => 'NEW')) . '?' . implode('&amp;', $idParams) ?>"><?=$this->transEsc('or create a new list'); ?></a>
-    </div>
+    <label class="control-label" for="save_list"><?=$this->transEsc('Choose a List') ?></label>
+    <select id="save_list" name="list" class="form-control">
+      <? if (count($this->lists) > 0): ?>
+        <? foreach ($this->lists as $list): ?>
+          <option value="<?=$list['id'] ?>"<? if ($list['id']==$this->userList()->lastUsed()): ?> selected="selected"<? endif; ?>><?=$this->escapeHtml($list['title'])?></option>
+        <? endforeach; ?>
+      <? else: ?>
+        <option value=""><?=$this->transEsc('My Favorites') ?></option>
+      <? endif; ?>
+    </select>
+    <a class="btn btn-link" id="make-list"  href="<?=$this->url('editList', ['id' => 'NEW']) . '?' . implode('&amp;', $idParams) ?>"><?=$this->transEsc('or create a new list'); ?></a>
   </div>
 
   <? if ($this->usertags()->getMode() !== 'disabled'): ?>
     <div class="form-group">
-      <label class="col-sm-3 control-label" for="add_mytags"><?=$this->transEsc('Add Tags') ?></label>
-      <div class="col-sm-9">
-        <input id="add_mytags" type="text" name="mytags" value="" class="form-control"/>
-        <span class="help-block"><?=$this->transEsc("add_tag_note") ?></span>
-      </div>
+      <label class="control-label" for="add_mytags"><?=$this->transEsc('Add Tags') ?></label>
+      <input id="add_mytags" type="text" name="mytags" value="" class="form-control"/>
+      <span class="help-block"><?=$this->transEsc("add_tag_note") ?></span>
     </div>
   <? endif; ?>
   <div class="form-group">
-    <div class="col-sm-9 col-sm-offset-3">
-      <input class="btn btn-default" type="submit" name="submit" value="<?=$this->transEsc('Save') ?>"/>
-    </div>
+    <input class="btn btn-primary" type="submit" name="submit" value="<?=$this->transEsc('Save') ?>"/>
   </div>
 </form>
 
@@ -74,4 +66,4 @@
   $('#itemhide').removeClass('in');
 JS;
 ?>
-<?=$this->inlineScript(\Zend\View\Helper\HeadScript::SCRIPT, $script, 'SET') ?>
\ No newline at end of file
+<?=$this->inlineScript(\Zend\View\Helper\HeadScript::SCRIPT, $script, 'SET') ?>
diff --git a/themes/bootstrap3/templates/channels/channelList.phtml b/themes/bootstrap3/templates/channels/channelList.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..b2e9f6008073325e497f8b84a9edf0b320cfce43
--- /dev/null
+++ b/themes/bootstrap3/templates/channels/channelList.phtml
@@ -0,0 +1,66 @@
+<? $this->headLink()->appendStylesheet('lib/channel-slider.css'); ?>
+<? $this->headScript()->appendFile('lib/channel-slider.js'); ?>
+<? $this->headScript()->appendFile('channels.js'); ?>
+<? $this->headScript()->appendFile('vendor/jquery.dotdotdot.min.js'); ?>
+<?
+  $this->jsTranslations()->addStrings([
+    'channel_expand' => 'channel_expand',
+    'channel_search' => 'channel_search',
+    'nohit_heading' => 'nohit_heading',
+    'View Record' => 'View Record',
+  ]);
+?>
+
+<? if (empty($token)): ?>
+  <form action="<?=$this->url('channels-search')?>" class="form-inline">
+    <?=$this->transEsc('channel_searchbox_label')?>
+    <input type="text" name="lookfor" class="form-control" value="<?=$this->escapeHtmlAttr($this->lookfor) ?>"/>
+    <input type="submit" value="<?=$this->escapeHtmlAttr($this->translate('Submit'))?>" class="btn btn-default" />
+  </form>
+<? endif; ?>
+
+<? $insideButton = false; ?>
+<? $channelLinkData = []; ?>
+<? foreach ($channels as $channel): ?>
+  <?
+    $groupId = isset($channel['groupId'])
+      ? $channel['groupId']
+      : $channel['providerId'];
+  ?>
+  <? $channelID = 'channel-' . md5(serialize($channel)); ?>
+  <? if (isset($channel['contents'])): ?>
+    <? if ($insideButton): ?>
+        </ul>
+      </div>
+      <? $insideButton = false; ?>
+    <? endif; ?>
+    <div class="channel-title">
+      <h2><?=$this->escapeHtml($channel['title'])?>
+      <? if (!empty($channel['links'])): ?>
+        <? $channelLinkData[$channelID] = json_encode($channel['links']); ?>
+      <? endif; ?>
+      </h2>
+    </div>
+    <div id="<?=$channelID ?>" class="channel" data-group="<?=$groupId ?>" data-link-json='<?=json_encode($channel['links']) ?>'>
+      <!-- Wrapper for slides -->
+      <? foreach ($channel['contents'] as $item): ?>
+        <a href="<?=$this->recordLink()->getUrl("{$item['source']}|{$item['id']}")?>" class="channel-record slide" data-record-id="<?=$this->escapeHtmlAttr($item['id']) ?>" data-record-source="<?=$item['source'] ?>">
+          <div class="thumb"><img src="<?=$this->escapeHtmlAttr($item['thumbnail'] ? $item['thumbnail'] : $this->url('cover-unavailable'))?>"/></div>
+          <?=$this->escapeHtml($item['title'])?>
+        </a>
+      <? endforeach; ?>
+    </div>
+  <? elseif (isset($channel['token'])): ?>
+    <? if (!$insideButton): ?>
+      <div class="channel-add-menu btn-group hidden" data-group="<?=$groupId ?>">
+        <button type="button" class="add-btn btn btn-default"><?=$this->transEsc('channel_add_more') ?></button>
+        <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+          <span class="caret"></span>
+          <span class="sr-only">Toggle Dropdown</span>
+        </button>
+        <ul class="dropdown-menu">
+      <? $insideButton = true; ?>
+    <? endif; ?>
+    <li><a href="<?=current(explode('?', $this->serverUrl(true)))?>?<?=empty($queryParams) ? '' : $this->escapeHtmlAttr($queryParams . '&')?>channelProvider=<?=urlencode($channel['providerId']) ?>&amp;channelToken=<?=urlencode($channel['token']) ?>&amp;layout=lightbox" data-token="<?=$channel['token'] ?>"><?=$this->escapeHtml($channel['title'])?></a></li>
+  <? endif; ?>
+<? endforeach; ?>
diff --git a/themes/bootstrap3/templates/channels/home.phtml b/themes/bootstrap3/templates/channels/home.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..67eff2710ce43f166dde4189456297de78512a08
--- /dev/null
+++ b/themes/bootstrap3/templates/channels/home.phtml
@@ -0,0 +1,8 @@
+<?
+    // Set up page title:
+    $this->headTitle($this->translate('Channels'));
+
+    // Set up breadcrumbs:
+    $this->layout()->breadcrumbs = '<li class="active">' . $this->transEsc('Channels') . '</li>';
+?>
+<?=$this->render('channels/channelList.phtml')?>
diff --git a/themes/bootstrap3/templates/channels/record.phtml b/themes/bootstrap3/templates/channels/record.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..c3239862c5733f8533bea57e49e14a45a0143b22
--- /dev/null
+++ b/themes/bootstrap3/templates/channels/record.phtml
@@ -0,0 +1,11 @@
+<?
+    // Set up page title:
+    $this->headTitle($this->translate('Channels') . ' - ' . $this->driver->getBreadcrumb());
+
+    // Set up breadcrumbs:
+    $this->layout()->breadcrumbs = '<li><a href="' . $this->url('channels-home') . '">' . $this->transEsc('Channels') . '</a></li> <li class="active">' . $this->escapeHtml($this->driver->getBreadcrumb()) . '</li>';
+
+    // Set up query parameters for channel list:
+    $this->queryParams = 'id=' . urlencode($driver->getUniqueId()) . '&source=' . urlencode($driver->getSourceIdentifier());
+?>
+<?=$this->render('channels/channelList.phtml')?>
diff --git a/themes/bootstrap3/templates/channels/search.phtml b/themes/bootstrap3/templates/channels/search.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..b57213cd070ffcf625b5c2ff18984d10e981b91f
--- /dev/null
+++ b/themes/bootstrap3/templates/channels/search.phtml
@@ -0,0 +1,13 @@
+<?
+    $lookfor = $this->results->getUrlQuery()->isQuerySuppressed() ? '' : $this->results->getParams()->getDisplayQuery();
+
+    // Set up page title:
+    $this->headTitle($this->translate('Channels') . (empty($lookfor) ? '' : " - {$lookfor}"));
+
+    // Set up breadcrumbs:
+    $this->layout()->breadcrumbs = '<li><a href="' . $this->url('channels-home') . '">' . $this->transEsc('Channels') . '</a></li> <li class="active">' . $this->escapeHtml($lookfor) . '</li>';
+
+    // Set up query parameters for channel list:
+    $this->queryParams = ltrim($this->results->getUrlQuery()->getParams(false), '?');
+?>
+<?=$this->render('channels/channelList.phtml')?>
diff --git a/themes/bootstrap3/templates/collection/view.phtml b/themes/bootstrap3/templates/collection/view.phtml
index 08b328f6ff679b60ca91fe9a6cdd901506b3c866..ac0f1fad772ca7ac3a30fdf312e8c3e979e25503 100644
--- a/themes/bootstrap3/templates/collection/view.phtml
+++ b/themes/bootstrap3/templates/collection/view.phtml
@@ -41,7 +41,10 @@
       <? endif; ?>
       <li class="disabled"><a href="#">&laquo; <?=$this->transEsc('Prev')?></a></li>
     <? endif; ?>
-    #<?=$this->localizedNumber($this->scrollData['currentPosition']) . ' ' . $this->transEsc('of') . ' ' . $this->localizedNumber($this->scrollData['resultTotal']) . ' ' . $this->transEsc('results') ?>
+    <?=$this->transEsc('of_num_results', [
+      '%%position%%' => $this->localizedNumber($this->scrollData['currentPosition']),
+      '%%total%%' => $this->localizedNumber($this->scrollData['resultTotal'])
+    ]) ?>
     <? if ($this->scrollData['nextRecord']): ?>
       <li>
         <a href="<?=$this->recordLink()->getUrl($this->scrollData['nextRecord'])?>" title="<?=$this->transEsc('Next Search Result')?>" rel="nofollow"><?=$this->transEsc('Next')?> &raquo;</a>
@@ -62,8 +65,8 @@
 
 <?=$this->record($this->driver)->getToolbar()?>
 
-<div class="record row">
-  <div class="<?=$tree ? 'col-sm-12' : $this->layoutClass('mainbody') ?>">
+<div class="record">
+  <div<? if (!$tree): /* in tree mode, do not constrain width with a class */ ?> class="<?=$this->layoutClass('mainbody') ?>"<? endif; ?>>
     <input type="hidden" value="<?=$this->escapeHtmlAttr($this->driver->getUniqueId())?>" class="hiddenId" id="record_id" />
     <input type="hidden" value="<?=$this->escapeHtmlAttr($this->driver->getSourceIdentifier())?>" class="hiddenSource" />
     <?=$this->flashmessages()?>
@@ -76,7 +79,7 @@
           <? foreach ($this->tabs as $tab => $obj): ?>
             <? // add current tab to breadcrumbs if applicable:
               $desc = $obj->getDescription();
-              $tab_classes = array();
+              $tab_classes = [];
               if (0 === strcasecmp($this->activeTab, $tab)) {
                 if (!$this->loadInitialTabWithAjax || !$obj->supportsAjax()) {
                   $tab_classes[] = 'active';
@@ -107,7 +110,7 @@
     <?=$this->driver->supportsCoinsOpenURL()?'<span class="Z3988" title="'.$this->escapeHtmlAttr($this->driver->getCoinsOpenURL()).'"></span>':''?>
   </div>
 
-  <? if (isset($activeTabObj) && is_callable(array($activeTabObj, 'getSideRecommendations'))): ?>
+  <? if (isset($activeTabObj) && is_callable([$activeTabObj, 'getSideRecommendations'])): ?>
     <div class="<?=$this->layoutClass('sidebar')?>">
       <? foreach ($activeTabObj->getSideRecommendations() as $current): ?>
         <?=$this->recommend($current)?>
diff --git a/themes/bootstrap3/templates/collections/bytitle.phtml b/themes/bootstrap3/templates/collections/bytitle.phtml
index aa49a5b70f80f2042f9904fc5c234a7ef24e703c..83d144557745bd2253fc670bb7cffe2ab05b9a76 100644
--- a/themes/bootstrap3/templates/collections/bytitle.phtml
+++ b/themes/bootstrap3/templates/collections/bytitle.phtml
@@ -11,7 +11,7 @@
         <div id="disambiguationItemsDiv">
           <? foreach ($collections as $i => $collection): ?>
            <div class="disambiguationItem <?=$i % 2 ? 'alt ' : ''?>record<?=$i?>">
-             <a href="<?=$this->url('collection', array('id' => $collection->getUniqueId()))?>"><?=$this->escapeHtml($collection->getTitle())?></a>
+             <a href="<?=$this->url('collection', ['id' => $collection->getUniqueId()])?>"><?=$this->escapeHtml($collection->getTitle())?></a>
              <p><?=$this->escapeHtml(implode(' ', $collection->getSummary()))?></p>
            </div>
           <? endforeach; ?>
diff --git a/themes/bootstrap3/templates/collections/home.phtml b/themes/bootstrap3/templates/collections/home.phtml
index f84452b719d71920e24c33d90bb2493e0b510235..059504c236ac796f8b32d541b11efeb97f10b9da 100644
--- a/themes/bootstrap3/templates/collections/home.phtml
+++ b/themes/bootstrap3/templates/collections/home.phtml
@@ -1,9 +1,9 @@
 <?
   $this->headTitle($this->translate('Collection Browse'));
   $this->layout()->breadcrumbs = '<a href="' . $this->url('collections-home') . '">' . $this->transEsc('Collections') . '</a>';
-  $filterList = array();
+  $filterList = [];
   $filterString = '';
-  foreach (isset($filters['Other']) ? $filters['Other'] : array() as $filter) {
+  foreach (isset($filters['Other']) ? $filters['Other'] : [] as $filter) {
     $filter['urlPart'] = $filter['field'] . ':' . $filter['value'];
     $filterList[] = $filter;
     $filterString .= '&' . urlencode('filter[]') .  '=' . urlencode($filter['urlPart']);
@@ -25,7 +25,7 @@
         <li class="disabled"><a href="#"><?=$this->transEsc('Next')?> &raquo;</a></li>
       <? endif; ?>
       <input type="submit" class="btn btn-default" value="<?=$this->transEsc('Jump to')?>" />
-      <input type="text" name="from" value="<?=$this->escapeHtmlAttr($from)?>" />
+      <input type="text" name="from" value="<?=$this->escapeHtmlAttr($from)?>" class="form-control" />
     </ul>
   </form>
 <? $pageLinks = ob_get_contents(); ?>
@@ -62,4 +62,4 @@
 <div class="clearfix">
   <?=$this->render('collections/list.phtml')?>
 </div><br/>
-<?=$pageLinks ?>
\ No newline at end of file
+<?=$pageLinks ?>
diff --git a/themes/bootstrap3/templates/collections/list.phtml b/themes/bootstrap3/templates/collections/list.phtml
index cc5fc011ae0d6f2a7bd44e6c33ae827900417afa..98923184192daba07008a050c126ef2f772c52dc 100644
--- a/themes/bootstrap3/templates/collections/list.phtml
+++ b/themes/bootstrap3/templates/collections/list.phtml
@@ -1,6 +1,6 @@
 <div class="list-group">
   <? foreach ($result as $i => $item): ?>
-    <a class="list-group-item" href="<?=$this->url('collection', array('id' => $item['value']))?>">
+    <a class="list-group-item" href="<?=$this->url('collection', ['id' => $item['value']])?>">
       <strong><?=$this->escapeHtml($item['displayText'])?></strong>
       <span class="badge">
         <?=$item['count']?> <?=$this->transEsc('items')?>
@@ -8,4 +8,4 @@
       </span>
     </a>
   <? endforeach; ?>
-</div>
\ No newline at end of file
+</div>
diff --git a/themes/bootstrap3/templates/combined/home.phtml b/themes/bootstrap3/templates/combined/home.phtml
index d13d4348c1e39e2222b5f16ce7d65ecd7816ef92..bc5b700660ea8e7baee8cc01de0600b0b4611521 100644
--- a/themes/bootstrap3/templates/combined/home.phtml
+++ b/themes/bootstrap3/templates/combined/home.phtml
@@ -1 +1 @@
-<?=$this->render('search/home.phtml');?>
\ No newline at end of file
+<?=$this->render('search/home.phtml');?>
diff --git a/themes/bootstrap3/templates/combined/results-list.phtml b/themes/bootstrap3/templates/combined/results-list.phtml
index 5c8fe93ca8986066109068f25e041ee56bcb9aeb..2a630401458db8d43d1a58461d522485131ce524 100644
--- a/themes/bootstrap3/templates/combined/results-list.phtml
+++ b/themes/bootstrap3/templates/combined/results-list.phtml
@@ -2,7 +2,7 @@
   $view = $currentSearch['view'];
   $results = $view->results;
   $params = $results->getParams();
-  $lookfor = $params->getDisplayQuery();
+  $lookfor = $results->getUrlQuery()->isQuerySuppressed() ? '' : $params->getDisplayQuery();
   $recordTotal = $results->getResultTotal();
 
   // More link should use default limit, not custom limit:
@@ -28,19 +28,9 @@
       <? foreach (($top = $results->getRecommendations('top')) as $current): ?>
         <?=$this->recommend($current)?>
       <? endforeach; ?>
-      <?=$this->transEsc("Showing")?>
-      <strong><?=$this->localizedNumber($results->getStartRecord())?></strong> - <strong><?=$this->localizedNumber($results->getEndRecord())?></strong>
-      <? if (!isset($view->skipTotalCount)): ?>
-        <?=$this->transEsc('of')?> <strong><?=$this->localizedNumber($recordTotal)?></strong>
-      <? endif; ?>
-      <? if (isset($view->overrideSearchHeading)): ?>
-        <?=$view->overrideSearchHeading?>
-      <? elseif ($params->getSearchType() == 'basic'): ?>
-        <?=$this->transEsc('for search')?>: <strong>'<?=$this->escapeHtml($lookfor)?>'</strong>,
-      <? endif; ?>
-      <? if ($qtime = $results->getQuerySpeed()): ?>
-        <?=$this->transEsc('query time')?>: <?=$this->localizedNumber($qtime, 2).$this->transEsc('seconds_abbrev')?>
-      <? endif; ?>
+      <?=$this->context()->renderInContext('search/controls/showing.phtml',
+                                          ['lookfor' => $lookfor, 'recordTotal' => $recordTotal,
+                                           'params' => $params, 'results' => $results] ) ?>
     <? else: ?>
       <h3><?=$this->transEsc('nohit_heading')?></h3>
     <? endif; ?>
@@ -53,7 +43,7 @@
     <? if (isset($view->overrideEmptyMessage)): ?>
       <?=$view->overrideEmptyMessage?>
     <? else: ?>
-      <?=$this->transEsc('nohit_prefix')?> - <strong><?=$this->escapeHtml($lookfor)?></strong> - <?=$this->transEsc('nohit_suffix')?>
+      <?=$this->translate('nohit_lookfor_html', ['%%lookfor%%' => $this->escapeHtml($lookfor)]) ?>
     <? endif; ?>
   </p>
   <? if (isset($view->parseError)): ?>
@@ -71,12 +61,11 @@
   <?
     $viewType = in_array('list', array_keys($params->getViewList()))
       ? 'list' : $params->getView();
-    $viewParams = array(
+    $viewParams = [
       'results' => $results,
       'params' => $params,
-      'showCartControls' => $this->showCartControls,
-      'showBulkOptions' => $this->showBulkOptions
-    );
+      'showCheckboxes' => $this->showCartControls || $this->showBulkOptions
+    ];
   ?>
   <?=$this->render('search/list-' . $viewType . '.phtml', $viewParams)?>
   <? if (isset($currentSearch['more_link']) && $currentSearch['more_link']): ?>
diff --git a/themes/bootstrap3/templates/combined/results.phtml b/themes/bootstrap3/templates/combined/results.phtml
index 93885ef57abfe3e57f4c335526de7a0f6414fb6c..35b484a7449036d2d25223a2d5cec26a0819274e 100644
--- a/themes/bootstrap3/templates/combined/results.phtml
+++ b/themes/bootstrap3/templates/combined/results.phtml
@@ -10,7 +10,7 @@
   // Set up search box:
   $this->layout()->searchbox = $this->context($this)->renderInContext(
     'search/searchbox.phtml',
-    array(
+    [
       'lookfor' => $lookfor,
       'searchIndex' => $this->params->getSearchHandler(),
       'searchType' => $this->params->getSearchType(),
@@ -20,7 +20,7 @@
       'filterList' => $this->params->getFilters(),
       'hasDefaultsApplied' => $this->params->hasDefaultsApplied(),
       'selectedShards' => $this->params->getSelectedShards()
-    )
+    ]
   );
 
   // Create shortcut to combined results (since $this->results may get overwritten in processing below):
@@ -38,6 +38,8 @@
   $this->showCartControls = $this->supportsCart && $this->cart()->isActive();
   // Enable bulk options if appropriate:
   $this->showBulkOptions = $this->supportsCart && $this->showBulkOptions;
+  // Enable bulk options if appropriate:
+  $this->showCheckboxes = $this->showCartControls || $this->showBulkOptions;
 
   // Load Javascript dependencies into header:
   $this->headScript()->appendFile("check_item_statuses.js");
@@ -47,7 +49,7 @@
   $this->headLink()->appendStylesheet('combined-search.css');
 ?>
 <?=$this->flashmessages()?>
-<form class="form-inline" method="post" name="bulkActionForm" action="<?=$this->url('cart-searchresultsbulk')?>">
+<form id="search-cart-form" class="form-inline" method="post" name="bulkActionForm" action="<?=$this->url('cart-searchresultsbulk')?>">
   <? $recs = $combinedResults->getRecommendations('top'); if (!empty($recs)): ?>
     <div>
       <? foreach ($recs as $current): ?>
@@ -55,22 +57,23 @@
       <? endforeach; ?>
     </div>
   <? endif; ?>
-  <?=$this->context($this)->renderInContext('search/bulk-action-buttons.phtml', array('idPrefix' => ''))?>
+  <?=$this->context($this)->renderInContext('search/bulk-action-buttons.phtml', ['idPrefix' => ''])?>
   <?
-    $viewParams = array(
+    $viewParams = [
       'searchClassId' => $searchClassId,
       'combinedResults' => $this->combinedResults,
       'supportsCartOptions' => $this->supportsCartOptions,
       'showCartControls' => $this->showCartControls,
       'showBulkOptions' => $this->showBulkOptions
-    );
+    ];
   ?>
-  <?=$this->context($this)->renderInContext('combined/stack-'.$placement.'.phtml', $viewParams)?>
-  <? $recs = $combinedResults->getRecommendations('bottom'); if (!empty($recs)): ?>
+  <?=$this->context($this)->renderInContext('combined/stack-' . $placement . '.phtml', $viewParams); ?>
+  <? $recs = $combinedResults->getRecommendations('bottom'); ?>
+  <? if (!empty($recs)): ?>
     <div>
       <? foreach ($recs as $current): ?>
         <?=$this->recommend($current)?>
       <? endforeach; ?>
     </div>
   <? endif; ?>
-</form>
\ No newline at end of file
+</form>
diff --git a/themes/bootstrap3/templates/combined/stack-distributed.phtml b/themes/bootstrap3/templates/combined/stack-distributed.phtml
index bfd7281646e5c6338efdb687cabee2c5eb7c15cb..82c985d349ba8adc0f8f4c0567699869376c2803 100644
--- a/themes/bootstrap3/templates/combined/stack-distributed.phtml
+++ b/themes/bootstrap3/templates/combined/stack-distributed.phtml
@@ -1,32 +1,45 @@
-<div class="row">
-  <? $span = floor(12/$columns); ?>
-  <? $sectionCount = count($this->combinedResults); ?>
-  <? $keys = array(); ?>
-  <? $searches = array(); ?>
+<div class="combined-search-container">
+  <? $columnedParams = []; ?>
+  <? $columnIndex = 0; ?>
   <? foreach ($this->combinedResults as $searchClassId => $currentSearch): ?>
-    <? $keys[] = $searchClassId; ?>
-    <? $searches[] = $currentSearch; ?>
+    <?
+      if (
+        (!isset($currentSearch['ajax']) || !$currentSearch['ajax'])                    // AJAX column
+        && (isset($currentSearch['hide_if_empty']) && $currentSearch['hide_if_empty']) // set to hide when empty
+        && $currentSearch['view']->results->getResultTotal() == 0                      // and empty
+      ) {
+        continue;
+      }
+      $colParams = [
+        'searchClassId' => $searchClassId,
+        'currentSearch' => $currentSearch,
+        // Enable cart if appropriate:
+        'showCartControls' => $this->supportsCartOptions[$columnIndex] && $this->showCartControls,
+        // Enable bulk options if appropriate:
+        'showBulkOptions' => $this->supportsCartOptions[$columnIndex] && $this->showBulkOptions,
+        // Other params
+        'domId' => $currentSearch['domId']
+      ];
+      if (isset($currentSearch['ajax'])) {
+        $colParams['ajax'] = $currentSearch['ajax'];
+      }
+      // Distribute
+      $col = $columnIndex % $columns;
+      if (!isset($columnedParams[$col])) {
+        $columnedParams[$col] = [];
+      }
+      $columnedParams[$col][] = $colParams;
+      $columnIndex ++;
+    ?>
   <? endforeach; ?>
-  <? for ($column=0;$column<$columns;$column++): ?>
-    <? $columnIndex = $column; ?>
-    <div class="col-sm-<?=$span ?> combined-list">
-      <? while ($columnIndex < $sectionCount): ?>
-        <? $searchClassId = $keys[$columnIndex]; ?>
-        <? $currentSearch = $searches[$columnIndex]; ?>
-        <? if ((!isset($currentSearch['ajax']) || !$currentSearch['ajax']) && isset($currentSearch['hide_if_empty']) && $currentSearch['hide_if_empty'] && $currentSearch['view']->results->getResultTotal() == 0) { $columnIndex += $columns; continue; } ?>
-          <?
-            $viewParams = array('searchClassId' => $searchClassId, 'currentSearch' => $currentSearch);
-            // Enable cart if appropriate:
-            $viewParams['showCartControls'] = $this->supportsCartOptions[$columnIndex] && $this->showCartControls;
-            // Enable bulk options if appropriate:
-            $viewParams['showBulkOptions'] = $this->supportsCartOptions[$columnIndex] && $this->showBulkOptions;
-          ?>
-          <div id="<?=$this->escapeHtmlAttr($currentSearch['domId'])?>">
-            <? $templateSuffix = (isset($currentSearch['ajax']) && $currentSearch['ajax']) ? 'ajax' : 'list'; ?>
-            <?=$this->render('combined/results-' . $templateSuffix . '.phtml', $viewParams)?>
-          </div>
-        <? $columnIndex += $columns ?>
-      <? endwhile; ?>
+  <? foreach ($columnedParams as $currColumn): ?>
+    <div class="combined-column">
+      <? foreach ($currColumn as $colParams): ?>
+        <div id="<?=$this->escapeHtmlAttr($colParams['domId'])?>" class="combined-list">
+          <? $templateSuffix = (isset($colParams['ajax']) && $colParams['ajax']) ? 'ajax' : 'list'; ?>
+          <?=$this->render('combined/results-' . $templateSuffix . '.phtml', $colParams)?>
+        </div>
+      <? endforeach; ?>
     </div>
-  <? endfor; ?>
-</div>
\ No newline at end of file
+  <? endforeach; ?>
+</div>
diff --git a/themes/bootstrap3/templates/combined/stack-left.phtml b/themes/bootstrap3/templates/combined/stack-left.phtml
index b75aa6bc471dcf2fe3c98422e042da496a227a31..0df1873f50f65b99a45574343c80a4890138f5dd 100644
--- a/themes/bootstrap3/templates/combined/stack-left.phtml
+++ b/themes/bootstrap3/templates/combined/stack-left.phtml
@@ -1,26 +1,50 @@
-<div class="row">
+<div class="combined-search-container">
   <? $columnIndex = 0; ?>
-  <? $span = floor(12/$columns); ?>
-  <? $sectionCount = count($this->combinedResults); ?>
-  <? foreach ($this->combinedResults as $searchClassId => $currentSearch): ?>
-    <? if ((!isset($currentSearch['ajax']) || !$currentSearch['ajax']) && isset($currentSearch['hide_if_empty']) && $currentSearch['hide_if_empty'] && $currentSearch['view']->results->getResultTotal() == 0) { continue; } ?>
-    <? if ($columnIndex < $columns): ?>
-      <div class="col-sm-<?=$span ?><? if($columnIndex == $columns-1): ?> col-sm-pull-<?=$span*($columns-1) ?><? else: ?> col-sm-push-<?=$span ?><? endif; ?> combined-list">
-    <? endif; ?>
-    <?
-      $viewParams = array('searchClassId' => $searchClassId, 'currentSearch' => $currentSearch);
-      // Enable cart if appropriate:
-      $viewParams['showCartControls'] = $this->supportsCartOptions[$columnIndex] && $this->showCartControls;
-      // Enable bulk options if appropriate:
-      $viewParams['showBulkOptions'] = $this->supportsCartOptions[$columnIndex] && $this->showBulkOptions;
-    ?>
-    <div id="<?=$this->escapeHtmlAttr($currentSearch['domId'])?>">
-      <? $templateSuffix = (isset($currentSearch['ajax']) && $currentSearch['ajax']) ? 'ajax' : 'list'; ?>
-      <?=$this->render('combined/results-' . $templateSuffix . '.phtml', $viewParams)?>
-    </div>
-    <? ++$columnIndex ?>
-    <? if($columnIndex < $columns || $columnIndex == $sectionCount): ?>
+  <? $rightColumns = []; ?>
+  <div class="combined-column">
+    <? foreach ($this->combinedResults as $searchClassId => $currentSearch): ?>
+      <?
+        $viewParams = [
+          'searchClassId' => $searchClassId,
+          'currentSearch' => $currentSearch,
+          // Enable cart if appropriate:
+          'showCartControls' => $this->supportsCartOptions[$columnIndex] && $this->showCartControls,
+          // Enable bulk options if appropriate:
+          'showBulkOptions' => $this->supportsCartOptions[$columnIndex] && $this->showBulkOptions
+        ];
+      ?>
+      <?
+        if (
+          (!isset($currentSearch['ajax']) || !$currentSearch['ajax'])                    // AJAX column
+          && (isset($currentSearch['hide_if_empty']) && $currentSearch['hide_if_empty']) // set to hide when empty
+          && $currentSearch['view']->results->getResultTotal() == 0                      // and empty
+        ) {
+          continue;
+        }
+      ?>
+      <? $columnIndex ++; ?>
+      <?
+        if ($columnIndex > 0 && $columnIndex < $columns) {
+          $viewParams['domId'] = $currentSearch['domId'];
+          if (isset($currentSearch['ajax'])) {
+            $viewParams['ajax'] = $currentSearch['ajax'];
+          }
+          $rightColumns[] = $viewParams;
+          continue;
+        }
+      ?>
+      <div id="<?=$this->escapeHtmlAttr($currentSearch['domId'])?>" class="combined-list">
+        <? $templateSuffix = (isset($currentSearch['ajax']) && $currentSearch['ajax']) ? 'ajax' : 'list'; ?>
+        <?=$this->render('combined/results-' . $templateSuffix . '.phtml', $viewParams)?>
+      </div>
+    <? endforeach; ?>
+  </div>
+  <? foreach ($rightColumns as $colParams): ?>
+    <div class="combined-column">
+      <div id="<?=$this->escapeHtmlAttr($colParams['domId'])?>" class="combined-list">
+        <? $templateSuffix = (isset($colParams['ajax']) && $colParams['ajax']) ? 'ajax' : 'list'; ?>
+        <?=$this->render('combined/results-' . $templateSuffix . '.phtml', $colParams)?>
       </div>
-    <? endif; ?>
+    </div>
   <? endforeach; ?>
-</div>
\ No newline at end of file
+</div>
diff --git a/themes/bootstrap3/templates/combined/stack-right.phtml b/themes/bootstrap3/templates/combined/stack-right.phtml
index bd6126dc369716963530e4cc2134e19800667da4..dfca691f257076fd707e21c34981e8b9c4f75f90 100644
--- a/themes/bootstrap3/templates/combined/stack-right.phtml
+++ b/themes/bootstrap3/templates/combined/stack-right.phtml
@@ -1,26 +1,35 @@
-<div class="row">
+<div class="combined-search-container">
   <? $columnIndex = 0; ?>
-  <? $span = floor(12/$columns); ?>
-  <? $sectionCount = count($this->combinedResults); ?>
-  <? foreach ($this->combinedResults as $searchClassId => $currentSearch): ?>
-    <? if ((!isset($currentSearch['ajax']) || !$currentSearch['ajax']) && isset($currentSearch['hide_if_empty']) && $currentSearch['hide_if_empty'] && $currentSearch['view']->results->getResultTotal() == 0) { continue; } ?>
-    <? if ($columnIndex < $columns): ?>
-      <div class="col-sm-<?=$span ?> combined-list">
-    <? endif; ?>
-    <?
-      $viewParams = array('searchClassId' => $searchClassId, 'currentSearch' => $currentSearch);
-      // Enable cart if appropriate:
-      $viewParams['showCartControls'] = $this->supportsCartOptions[$columnIndex] && $this->showCartControls;
-      // Enable bulk options if appropriate:
-      $viewParams['showBulkOptions'] = $this->supportsCartOptions[$columnIndex] && $this->showBulkOptions;
-    ?>
-    <div id="<?=$this->escapeHtmlAttr($currentSearch['domId'])?>">
-      <? $templateSuffix = (isset($currentSearch['ajax']) && $currentSearch['ajax']) ? 'ajax' : 'list'; ?>
-      <?=$this->render('combined/results-' . $templateSuffix . '.phtml', $viewParams)?>
-    </div>
-    <? ++$columnIndex ?>
-    <? if($columnIndex < $columns || $columnIndex == $sectionCount): ?>
+  <div class="combined-column">
+    <? foreach ($this->combinedResults as $searchClassId => $currentSearch): ?>
+      <?
+        $viewParams = [
+          'searchClassId' => $searchClassId,
+          'currentSearch' => $currentSearch,
+          // Enable cart if appropriate:
+          'showCartControls' => $this->supportsCartOptions[$columnIndex] && $this->showCartControls,
+          // Enable bulk options if appropriate:
+          'showBulkOptions' => $this->supportsCartOptions[$columnIndex] && $this->showBulkOptions
+        ];
+      ?>
+      <?
+        if (
+          (!isset($currentSearch['ajax']) || !$currentSearch['ajax'])                    // AJAX column
+          && (isset($currentSearch['hide_if_empty']) && $currentSearch['hide_if_empty']) // set to hide when empty
+          && $currentSearch['view']->results->getResultTotal() == 0                      // and empty
+        ) {
+          continue;
+        }
+      ?>
+      <div id="<?=$this->escapeHtmlAttr($currentSearch['domId'])?>" class="combined-list">
+        <? $templateSuffix = (isset($currentSearch['ajax']) && $currentSearch['ajax']) ? 'ajax' : 'list'; ?>
+        <?=$this->render('combined/results-' . $templateSuffix . '.phtml', $viewParams)?>
       </div>
-    <? endif; ?>
-  <? endforeach; ?>
-</div>
\ No newline at end of file
+      <? $columnIndex ++; ?>
+      <? if ($columnIndex < $columns): ?>
+    </div>
+    <div class="combined-column">
+      <? endif; ?>
+    <? endforeach; ?>
+  </div>
+</div>
diff --git a/themes/bootstrap3/templates/content/asklibrary.phtml b/themes/bootstrap3/templates/content/asklibrary.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..b8e493b62584820ad0285d992ec92e58b0e721d1
--- /dev/null
+++ b/themes/bootstrap3/templates/content/asklibrary.phtml
@@ -0,0 +1,8 @@
+<? $this->headTitle($this->translate('Ask a Librarian')); ?>
+
+<h1><?=$this->transEsc('Ask a Librarian') ?></h1>
+
+<p>
+  This is the default page displayed if a language-specific page in user's selected
+  language or site's default language is not found.
+</p>
diff --git a/themes/bootstrap3/templates/content/asklibrary_en.phtml b/themes/bootstrap3/templates/content/asklibrary_en.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..6a3d03efdbb184f5a3179f9134f4e6b42e752907
--- /dev/null
+++ b/themes/bootstrap3/templates/content/asklibrary_en.phtml
@@ -0,0 +1,7 @@
+<? $this->headTitle($this->translate('Ask a Librarian')); ?>
+
+<h1><?=$this->transEsc('Ask a Librarian') ?></h1>
+
+<p>
+  This is the English "Ask a Librarian" page.
+</p>
diff --git a/themes/bootstrap3/templates/content/content.phtml b/themes/bootstrap3/templates/content/content.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..af1e589e56e745cb9e6e366e80ee500a8c4acffc
--- /dev/null
+++ b/themes/bootstrap3/templates/content/content.phtml
@@ -0,0 +1 @@
+<?=$this->partial("content/$page.phtml", []) ?>
diff --git a/themes/bootstrap3/templates/content/faq.phtml b/themes/bootstrap3/templates/content/faq.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..60bd0e069c58994a55478b6af73f6b5bf5be2f46
--- /dev/null
+++ b/themes/bootstrap3/templates/content/faq.phtml
@@ -0,0 +1,14 @@
+<? $this->headTitle($this->translate('FAQs')); ?>
+
+<h1><?=$this->transEsc('FAQs') ?></h1>
+
+<? if ($this->auth()->getManager()->supportsRecovery()): ?>
+  <p>
+    Q: How do I reset my password?<br/>
+    A: Go to the login screen and click the "Forgot password" link. Enter either your user name or email address, and you will get an email containing a link to reset your password.
+  </p>
+<? endif; ?>
+<p>
+  Q: Why does the service use cookies?<br/>
+  A: Cookies are used to manage sessions, which include selected language, last search, book bag contents, any login information, etc.
+</p>
diff --git a/themes/bootstrap3/templates/devtools/home.phtml b/themes/bootstrap3/templates/devtools/home.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..81e7038fe271a850f0b4e662eba92eec4704006a
--- /dev/null
+++ b/themes/bootstrap3/templates/devtools/home.phtml
@@ -0,0 +1,10 @@
+<?
+    $this->headTitle('Development Tools');
+?>
+
+<h2>Development Tools</h2>
+
+<ul>
+  <li><a href="<?=$this->url('devtools-deminify')?>">Deminifier</a> - Examine minified search data copied from the search database table.</li>
+  <li><a href="<?=$this->url('devtools-language')?>">Language Details</a> - Summarize status of translations in language files.</li>
+</ul>
diff --git a/themes/bootstrap3/templates/devtools/language.phtml b/themes/bootstrap3/templates/devtools/language.phtml
index 5808ed9bf5445b419ed37b6458f9c6683713b921..78feea645e411d14dde2d93aa00f203e7771e250 100644
--- a/themes/bootstrap3/templates/devtools/language.phtml
+++ b/themes/bootstrap3/templates/devtools/language.phtml
@@ -9,48 +9,46 @@
 <table class="table table-striped">
   <tr><th>Language</th><th>Missing Lines</th><th>Extra Lines</th><th>Percent Translated</th><th>Extra Help Files</th></tr>
   <? foreach ($details as $langCode => $diffs): ?>
+    <?
+      $extraCount = count($diffs['notInL1']);
+      $missingCount = count($diffs['notInL2']);
+    ?>
     <tr>
       <td><?=$this->escapeHtml($langCode . ' (' . $diffs['name'] . ')')?></td>
-      <td><?=count($diffs['notInL2'])?></td>
-      <td><?=count($diffs['notInL1'])?></td>
+      <td><?=$missingCount ?><? if($missingCount > 0): ?> (<a href="#" onclick="diffManager.showMissing('<?=$langCode ?>')"><?=$this->transEsc('show') ?></a>)<? endif; ?></td>
+      <td><?=$extraCount ?><? if($extraCount > 0): ?> (<a href="#" onclick="diffManager.showExtra('<?=$langCode ?>')"><?=$this->transEsc('show') ?></a>)<? endif; ?></td>
       <td><?=$this->escapeHtml($diffs['l2Percent'])?></td>
       <td><?=count($diffs['helpFiles'])?></td>
     </tr>
   <? endforeach; ?>
 </table>
-<div class="accordion" id="accordion">
-  <? foreach ($details as $langCode => $diffs): ?>
-    <? if (count($diffs['notInL1']) > 0): ?>
-      <div class="accordion-group">
-        <div class="accordion-heading">
-          <a class="accordion-toggle" data-toggle="collapse" data-parent="#accordion" href="#extra_<?=$langCode ?>">
-            Extra Lines In <?=$this->escapeHtml($diffs['name'])?> (<?=$this->escapeHtml($langCode)?>.ini)
-          </a>
-        </div>
-        <div id="extra_<?=$langCode ?>" class="accordion-body collapse">
-          <div class="accordion-inner">
-          <? foreach ($diffs['notInL1'] as $key): ?>
-            <?=$this->escapeHtml($key)?> = "<?=$this->escapeHtml($diffs['object'][$key])?>"<br />
-          <? endforeach; ?>
-          </div>
-        </div>
-      </div>
-    <? endif; ?>
-    <? if (count($diffs['notInL2']) > 0): ?>
-      <div class="accordion-group">
-        <div class="accordion-heading">
-          <a class="accordion-toggle" data-toggle="collapse" data-parent="#accordion" href="#missing_<?=$langCode ?>">
-            Missing From <?=$this->escapeHtml($diffs['name'])?> (<?=$this->escapeHtml($langCode)?>.ini)
-            <span class="pull-right flip"></span>
-          </a>
-        </div>
-        <div id="missing_<?=$langCode ?>" class="accordion-body collapse">
-          <div class="accordion-inner">
-            <textarea class="form-control" rows="15"><? foreach ($diffs['notInL2'] as $key): ?><?=$this->escapeHtml($key)?> = "<?=$this->escapeHtml($main[$key])?>"
-<? endforeach; ?></textarea>
-          </div>
-        </div>
-      </div>
-    <? endif; ?>
-  <? endforeach; ?>
-</div>
\ No newline at end of file
+<?
+  $json = json_encode($details);
+  $script = <<<JS
+  function createDiffManager() {
+    var details = {$json};
+    function makeRow(opArray, lang) {
+      var arr = [];
+      for (var i = 0; i < opArray.length; i++) {
+        console.log(details[lang].object[opArray[i]] || details.en.object[opArray[i]]);
+        arr.push(opArray[i] + ' = "' + (details[lang].object[opArray[i]] || details.en.object[opArray[i]]) + '"');
+      }
+      return '<textarea class="translation-output form-control" rows="' + Math.min(arr.length + 1, 25)+ '" onClick="this.select()">' + arr.join('\\n') + '</textarea>';
+    }
+    function showExtra(lang) {
+      VuFind.lightbox.render('<h2>Extra Lines</h2>'+makeRow(details[lang].notInL1, lang));
+      return false;
+    }
+    function showMissing(lang) {
+      VuFind.lightbox.render('<h2>Missing Lines</h2>'+makeRow(details[lang].notInL2, lang));
+      return false;
+    }
+    return {
+      showExtra: showExtra,
+      showMissing: showMissing
+    }
+  }
+  var diffManager = createDiffManager();
+JS;
+?>
+<?=$this->inlineScript(\Zend\View\Helper\HeadScript::SCRIPT, $script, 'SET') ?>
diff --git a/themes/bootstrap3/templates/eds/advanced.phtml b/themes/bootstrap3/templates/eds/advanced.phtml
index 32be6c84edf7ce77165bc931e9cdafe0eee6427d..7811a785914b2c2a7dc12fbd2fe76139c88fc698 100644
--- a/themes/bootstrap3/templates/eds/advanced.phtml
+++ b/themes/bootstrap3/templates/eds/advanced.phtml
@@ -7,44 +7,31 @@
   ob_start();
 ?>
 <div id="new_group_template">
-  <div class="group well clearfix">
+  <div class="adv-group eds-adv">
     <input type="hidden" name="join" value="AND"/>
     <input type="hidden" name="bool0[]" value="AND"/>
-    <? for ($search=0;$search<3;$search++): ?>
-      <? if ($search == 0): ?>
+    <label class="adv-group-label"><?=$this->transEsc("adv_search_label")?>:</label>
+    <? for ($search = 0; $search < 3; $search++): ?>
+      <? if ($search === 0): ?>
         <div id="new_search_template">
       <? endif; ?>
-      <div class="search row">
-        <div class="col-sm-3">
-          <input type="hidden" value="AND" class="first-op"/>
-          <label class="help-block<? if ($search > 0): ?> hidden<?endif;?>"><?=$this->transEsc("adv_search_label")?>:</label>
-          <select id="search_op0_<?=$search ?>" name="op0[]" class="op col-sm-9 form-control<? if ($search == 0): ?> hidden<?endif;?>">
-            <option value="AND"><?=$this->transEsc("AND")?></option>
-            <option value="OR"><?=$this->transEsc("OR")?></option>
-            <option value="NOT"><?=$this->transEsc("NOT")?></option>
-          </select>
-        </div>
-        <div class="col-sm-9">
-          <div class="row">
-            <div class="col-sm-6">
-              <input id="search_lookfor0_<?=$search ?>" name="lookfor0[]" class="form-control" type="text" value=""/>
-            </div>
-            <span class="col-sm-1 help-block hidden-xs"><?=$this->transEsc("in")?></span>
-            <div class="col-sm-4 middle">
-              <select id="search_type0_<?=$search ?>" name="type0[]" class="type form-control">
-                <? foreach ($this->options->getAdvancedHandlers() as $searchVal => $searchDesc): ?>
-                  <option value="<?=$this->escapeHtml($searchVal)?>"><?=$this->transEsc($searchDesc)?></option>
-                <? endforeach; ?>
-              </select>
-            </div>
-            <div class="close">
-              <a href="#" class="help-block">&times;</a>
-            </div>
-          </div>
-        </div>
-        <br class="hidden-lg"/>
+      <div class="adv-search">
+        <? if ($search === 0): ?><input type="hidden" value="AND" class="first-op"/><? endif; ?>
+        <select id="search_op0_<?=$search ?>" name="op0[]" class="adv-term-op form-control">
+          <option value="AND"><?=$this->transEsc("AND")?></option>
+          <option value="OR"><?=$this->transEsc("OR")?></option>
+          <option value="NOT"><?=$this->transEsc("NOT")?></option>
+        </select>
+        <input id="search_lookfor0_<?=$search ?>" name="lookfor0[]" class="adv-term-input form-control" type="text" value=""/>
+        <span class="help-block hidden-xs"><?=$this->transEsc("in")?></span>
+        <select id="search_type0_<?=$search ?>" name="type0[]" class="adv-term-type form-control">
+          <? foreach ($this->options->getAdvancedHandlers() as $searchVal => $searchDesc): ?>
+            <option value="<?=$this->escapeHtml($searchVal)?>"><?=$this->transEsc($searchDesc)?></option>
+          <? endforeach; ?>
+        </select>
+        <a class="adv-term-remove">&times;</a>
       </div>
-      <? if ($search == 0): ?>
+      <? if ($search === 0): ?>
         </div>
       <? endif; ?>
     <? endfor; ?>
@@ -56,4 +43,4 @@
   ob_end_clean();
 
   echo $this->render('search/advanced/layout.phtml');
-?>
\ No newline at end of file
+?>
diff --git a/themes/bootstrap3/templates/eds/home.phtml b/themes/bootstrap3/templates/eds/home.phtml
index d7a41e70131abc1ccb759a55a3c5e2309c51bfa4..ff9936df1db6d7be50278f25029832ddf1c5817d 100644
--- a/themes/bootstrap3/templates/eds/home.phtml
+++ b/themes/bootstrap3/templates/eds/home.phtml
@@ -1,3 +1,3 @@
 <?
   echo $this->render('search/home.phtml');
-?>
\ No newline at end of file
+?>
diff --git a/themes/bootstrap3/templates/eds/search.phtml b/themes/bootstrap3/templates/eds/search.phtml
index 6894a00ae29465b308925f7ba56bffa50a0a8989..3f3e56e0a72946e6d0048b2f117c8ffd4ee382bc 100644
--- a/themes/bootstrap3/templates/eds/search.phtml
+++ b/themes/bootstrap3/templates/eds/search.phtml
@@ -3,4 +3,4 @@
   $this->overrideSideFacetCaption = 'Refine Results';
   $this->paginationOptions = ['disableFirst' => true, 'disableLast' => true];
   echo $this->render('search/results.phtml');
-?>
\ No newline at end of file
+?>
diff --git a/themes/bootstrap3/templates/eit/home.phtml b/themes/bootstrap3/templates/eit/home.phtml
index d13d4348c1e39e2222b5f16ce7d65ecd7816ef92..bc5b700660ea8e7baee8cc01de0600b0b4611521 100644
--- a/themes/bootstrap3/templates/eit/home.phtml
+++ b/themes/bootstrap3/templates/eit/home.phtml
@@ -1 +1 @@
-<?=$this->render('search/home.phtml');?>
\ No newline at end of file
+<?=$this->render('search/home.phtml');?>
diff --git a/themes/bootstrap3/templates/eit/search.phtml b/themes/bootstrap3/templates/eit/search.phtml
index c1797c1cd4a1ebb2ccad84718b1e225e51cac6a8..a0c6dd4bbf5077e0b43b335e98733b44bba7b4e6 100644
--- a/themes/bootstrap3/templates/eit/search.phtml
+++ b/themes/bootstrap3/templates/eit/search.phtml
@@ -1,4 +1,4 @@
 <?
     // Load standard settings from the default search results screen:
     echo $this->render('search/results.phtml');
-?>
\ No newline at end of file
+?>
diff --git a/themes/bootstrap3/templates/error/index.phtml b/themes/bootstrap3/templates/error/index.phtml
index 19a86243a3f2dcd8fd961a4b69acff19a3f948b7..36ac5fb44d0e4bce00d6a74daa3be83fa7f8071b 100644
--- a/themes/bootstrap3/templates/error/index.phtml
+++ b/themes/bootstrap3/templates/error/index.phtml
@@ -16,10 +16,10 @@
 </div>
 
 <? if ($this->showInstallLink): ?>
-  <h2><a href="<?=$this->url('install-home')?>"><?=$this->transEsc('auto_configure_title', array(), 'Auto Configure')?></a></h2>
-  <?=$this->transEsc('auto_configure_description', array(), 'If this is a new installation, you may be able to fix the error using VuFind\'s Auto Configure tool.')?>
+  <h2><a href="<?=$this->url('install-home')?>"><?=$this->transEsc('auto_configure_title', [], 'Auto Configure')?></a></h2>
+  <?=$this->transEsc('auto_configure_description', [], 'If this is a new installation, you may be able to fix the error using VuFind\'s Auto Configure tool.')?>
   <h2><a href="<?=$this->url('upgrade-home')?>"><?=$this->transEsc('Upgrade VuFind')?></a></h2>
-  <?=$this->transEsc('upgrade_description', array(), 'If you are upgrading a previous VuFind version, you can load your old settings with this tool.')?>
+  <?=$this->transEsc('upgrade_description', [], 'If you are upgrading a previous VuFind version, you can load your old settings with this tool.')?>
 <? endif; ?>
 
 <? if (isset($this->display_exceptions) && $this->display_exceptions): ?>
diff --git a/themes/bootstrap3/templates/error/unavailable.phtml b/themes/bootstrap3/templates/error/unavailable.phtml
index 4cac53eb415955956d1f4116b156a194cb3274c4..9ebaa42658ffb4cf15b59ba942df27847db0006d 100644
--- a/themes/bootstrap3/templates/error/unavailable.phtml
+++ b/themes/bootstrap3/templates/error/unavailable.phtml
@@ -7,7 +7,7 @@
 
   $this->layout()->breadcrumbs = '<li class="active">Error</li>';
 ?>
-<div class="alert alert-danger">
+<div class="alert alert-warning">
   <h2><?=$this->transEsc('System Unavailable')?></h2>
   <p>
     <?=$this->transEsc('The system is currently unavailable due to system maintenance')?>.
diff --git a/themes/bootstrap3/templates/externalauth/ezproxylogin.phtml b/themes/bootstrap3/templates/externalauth/ezproxylogin.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..1bef7b8f1ac4aeca7c07c2693798b60e3559d89e
--- /dev/null
+++ b/themes/bootstrap3/templates/externalauth/ezproxylogin.phtml
@@ -0,0 +1,16 @@
+<?
+    // Set page title
+    $this->headTitle($this->translate('external_auth_heading'));
+?>
+
+<div class="external-content-access">
+  <?=$this->flashmessages()?>
+  <? if ($this->unauthorized): ?>
+    <div class="unauthorized-description">
+      <p><?=$this->transEsc('external_auth_unauthorized_desc'); ?></p>
+    </div>
+    <div>
+      <a href="<?=$this->url('myresearch-logout')?>" class="logout btn btn-primary" title="<?=$this->transEsc("Log Out")?>"><strong><?=$this->transEsc("Log Out")?></strong></a>
+    </div>
+  <? endif; ?>
+</div>
diff --git a/themes/bootstrap3/templates/feedback/form.phtml b/themes/bootstrap3/templates/feedback/form.phtml
index 296f0820a669a8e3858a275514770e66676b8717..c2e9cc573e2251da8e40a5922e46ff31a4ca5c13 100644
--- a/themes/bootstrap3/templates/feedback/form.phtml
+++ b/themes/bootstrap3/templates/feedback/form.phtml
@@ -1,28 +1,20 @@
 <h2><?=$this->transEsc("Send us your feedback!")?></h2>
 <?=$this->flashmessages() ?>
-<form class="form-horizontal" name="feedback" method="post" action="<?=$this->url('feedback-email')?>">
+<form class="form-feedback" name="feedback" method="post" action="<?=$this->url('feedback-email')?>">
   <div class="form-group">
-    <label class="col-sm-3 control-label" for="name"><?=$this->transEsc("feedback_name")?></label>
-    <div class="col-sm-9">
-      <input type="text" id="name" name="name" value="<?=$this->escapeHtmlAttr(isset($name) ? $name : '')?>" class="form-control"/>
-    </div>
+    <label class="control-label" for="name"><?=$this->transEsc("feedback_name")?></label>
+    <input type="text" id="name" name="name" value="<?=$this->escapeHtmlAttr(isset($name) ? $name : '')?>" class="form-control"/>
   </div>
   <div class="form-group">
-    <label class="col-sm-3 control-label" for="email"><?=$this->transEsc("Email")?></label>
-    <div class="col-sm-9">
-      <input type="email" id="email" name="email" value="<?=$this->escapeHtmlAttr(isset($email) ? $email : '')?>" class="form-control" required/>
-    </div>
+    <label class="control-label" for="email"><?=$this->transEsc("Email")?></label>
+    <input type="email" id="email" name="email" value="<?=$this->escapeHtmlAttr(isset($email) ? $email : '')?>" class="form-control" required/>
   </div>
   <div class="form-group">
-    <label class="col-sm-3 control-label" for="comments"><?=$this->transEsc("Comments")?></label>
-    <div class="col-sm-9">
-      <textarea id="comments" name="comments" class="form-control" required><?=$this->escapeHtml(isset($comments) ? $comments : '')?></textarea>
-    </div>
+    <label class="control-label" for="comments"><?=$this->transEsc("Comments")?></label>
+    <textarea id="comments" name="comments" class="form-control" required><?=$this->escapeHtml(isset($comments) ? $comments : '')?></textarea>
   </div>
   <?=$this->recaptcha()->html($this->useRecaptcha) ?>
   <div class="form-group">
-    <div class="col-sm-9 col-sm-offset-3">
-      <input type="submit" name="submit" class="btn btn-primary" value="<?=$this->transEsc("Send")?>" />
-    </div>
+    <input type="submit" name="submit" class="btn btn-primary" value="<?=$this->transEsc("Send")?>" />
   </div>
 </form>
diff --git a/themes/bootstrap3/templates/footer.phtml b/themes/bootstrap3/templates/footer.phtml
index abdcdeeae069685e051fb6c3ee113dcb9a97c29e..dcd04d06b06b1a393ed54657989101021b9437a0 100644
--- a/themes/bootstrap3/templates/footer.phtml
+++ b/themes/bootstrap3/templates/footer.phtml
@@ -1,27 +1,32 @@
-<hr/>
-<div class="row">
-  <div class="col-sm-4">
-    <p><strong><?=$this->transEsc('Search Options')?></strong></p>
-    <ul>
-      <li><a href="<?=$this->url('search-history')?>"><?=$this->transEsc('Search History')?></a></li>
-      <li><a href="<?=$this->url('search-advanced')?>"><?=$this->transEsc('Advanced Search')?></a></li>
-    </ul>
+<footer class="hidden-print">
+  <div class="footer-container">
+    <div class="footer-column">
+      <p><strong><?=$this->transEsc('Search Options')?></strong></p>
+      <ul>
+        <li><a href="<?=$this->url('search-history')?>"><?=$this->transEsc('Search History')?></a></li>
+        <li><a href="<?=$this->url('search-advanced')?>"><?=$this->transEsc('Advanced Search')?></a></li>
+      </ul>
+    </div>
+    <div class="footer-column">
+      <p><strong><?=$this->transEsc('Find More')?></strong></p>
+      <ul>
+        <li><a href="<?=$this->url('browse-home')?>"><?=$this->transEsc('Browse the Catalog')?></a></li>
+        <li><a href="<?=$this->url('alphabrowse-home')?>"><?=$this->transEsc('Browse Alphabetically')?></a></li>
+        <li><a href="<?=$this->url('channels-home')?>"><?=$this->transEsc('channel_explore')?></a></li>
+        <li><a href="<?=$this->url('search-reserves')?>"><?=$this->transEsc('Course Reserves')?></a></li>
+        <li><a href="<?=$this->url('search-newitem')?>"><?=$this->transEsc('New Items')?></a></li>
+      </ul>
+    </div>
+    <div class="footer-column">
+      <p><strong><?=$this->transEsc('Need Help?')?></strong></p>
+      <ul>
+        <li><a href="<?=$this->url('help-home')?>?topic=search&amp;_=<?=time() ?>" data-lightbox class="help-link"><?=$this->transEsc('Search Tips')?></a></li>
+        <li><a href="<?=$this->url('content-page', ['page' => 'asklibrary']) ?>"><?=$this->transEsc('Ask a Librarian')?></a></li>
+        <li><a href="<?=$this->url('content-page', ['page' => 'faq']) ?>"><?=$this->transEsc('FAQs')?></a></li>
+      </ul>
+    </div>
   </div>
-  <div class="col-sm-4">
-    <p><strong><?=$this->transEsc('Find More')?></strong></p>
-    <ul>
-      <li><a href="<?=$this->url('browse-home')?>"><?=$this->transEsc('Browse the Catalog')?></a></li>
-      <li><a href="<?=$this->url('alphabrowse-home')?>"><?=$this->transEsc('Browse Alphabetically')?></a></li>
-      <li><a href="<?=$this->url('search-reserves')?>"><?=$this->transEsc('Course Reserves')?></a></li>
-      <li><a href="<?=$this->url('search-newitem')?>"><?=$this->transEsc('New Items')?></a></li>
-    </ul>
+  <div class="poweredby">
+    <?=$this->layout()->poweredBy ?>
   </div>
-  <div class="col-sm-4">
-    <p><strong><?=$this->transEsc('Need Help?')?></strong></p>
-    <ul>
-      <li><a href="<?=$this->url('help-home')?>?topic=search&amp;_=<?=time() ?>" data-lightbox class="help-link"><?=$this->transEsc('Search Tips')?></a></li>
-      <li><a href="#"><?=$this->transEsc('Ask a Librarian')?></a></li>
-      <li><a href="#"><?=$this->transEsc('FAQs')?></a></li>
-    </ul>
-  </div>
-</div>
+</footer>
diff --git a/themes/bootstrap3/templates/header.phtml b/themes/bootstrap3/templates/header.phtml
index bdf98502dab6c0192a1641ee5a41aa18af618f74..457b6b07bad04fb98f94485336c21d10643cd1a8 100644
--- a/themes/bootstrap3/templates/header.phtml
+++ b/themes/bootstrap3/templates/header.phtml
@@ -1,77 +1,81 @@
 <? $account = $this->auth()->getManager(); ?>
-<div class="navbar-header">
-  <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#header-collapse">
-    <span class="sr-only">Toggle navigation</span>
-    <i class="fa fa-bars" aria-hidden="true"></i>
-  </button>
-  <a class="navbar-brand lang-<?=$this->layout()->userLang ?>" href="<?=$this->url('home')?>">VuFind</a>
-</div>
-<? if ($this->layout()->searchbox !== false): ?>
-  <section class="visible-lg">
-    <?=$this->layout()->searchbox ?>
-  </section>
-<? endif; ?>
-<? if (!isset($this->layout()->renderingError)): ?>
-  <div class="collapse navbar-collapse" id="header-collapse">
-    <nav>
-      <ul role="navigation" class="nav navbar-nav navbar-right flip">
-        <? if ($this->feedback()->tabEnabled()): ?>
-          <li>
-            <a id="feedbackLink" data-lightbox href="<?=$this->url('feedback-home') ?>"><i class="fa fa-envelope" aria-hidden="true"></i> <?=$this->transEsc("Feedback")?></a>
-          </li>
-        <? endif; ?>
-        <? $cart = $this->cart(); if ($cart->isActive()): ?>
-          <li id="cartSummary">
-            <a id="cartItems" data-lightbox title="<?=$this->transEsc('View Book Bag')?>" href="<?=$this->url('cart-home')?>">
-              <i class="fa fa-suitcase" aria-hidden="true"></i> <strong><?=count($cart->getItems())?></strong> <?=$this->transEsc('items')?>
-              <span class="full<?=!$cart->isFull() ? ' hidden' : '' ?>">(<?=$this->transEsc('bookbag_full') ?>)</span>
-            </a>
-          </li>
-        <? endif; ?>
-        <? if (is_object($account) && $account->loginEnabled()): // hide login/logout if unavailable ?>
-          <li class="logoutOptions<? if(!$account->isLoggedIn()): ?> hidden<? endif ?>">
-            <a href="<?=$this->url('myresearch-home', array(), array('query' => array('redirect' => 0)))?>"><i class="fa fa-home" aria-hidden="true"></i> <?=$this->transEsc("Your Account")?></a>
-          </li>
-          <li class="logoutOptions<? if(!$account->isLoggedIn()): ?> hidden<? endif ?>">
-            <a href="<?=$this->url('myresearch-logout')?>" class="logout"><i class="fa fa-sign-out" aria-hidden="true"></i> <?=$this->transEsc("Log Out")?></a>
-          </li>
-          <li id="loginOptions"<? if($account->isLoggedIn()): ?> class="hidden"<? endif ?>>
-            <? if ($account->getSessionInitiator($this->serverUrl($this->url('myresearch-home')))): ?>
-              <a href="<?=$this->url('myresearch-userlogin')?>"><i class="fa fa-sign-in" aria-hidden="true"></i> <?=$this->transEsc("Institutional Login")?></a>
-            <? else: ?>
-              <a href="<?=$this->url('myresearch-userlogin')?>" data-lightbox><i class="fa fa-sign-in" aria-hidden="true"></i> <?=$this->transEsc("Login")?></a>
-            <? endif; ?>
-          </li>
-        <? endif; ?>
+<div class="banner container navbar">
+  <div class="navbar-header">
+    <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#header-collapse">
+      <span class="sr-only">Toggle navigation</span>
+      <i class="fa fa-bars" aria-hidden="true"></i>
+    </button>
+    <a class="navbar-brand lang-<?=$this->layout()->userLang ?>" href="<?=$this->url('home')?>">VuFind</a>
+  </div>
+  <? if (!isset($this->layout()->renderingError)): ?>
+    <div class="collapse navbar-collapse" id="header-collapse">
+      <nav>
+        <ul role="navigation" class="nav navbar-nav navbar-right flip">
+          <? if ($this->feedback()->tabEnabled()): ?>
+            <li>
+              <a id="feedbackLink" data-lightbox href="<?=$this->url('feedback-home') ?>"><i class="fa fa-envelope" aria-hidden="true"></i> <?=$this->transEsc("Feedback")?></a>
+            </li>
+          <? endif; ?>
+          <? $cart = $this->cart(); if ($cart->isActive()): ?>
+            <li id="cartSummary">
+              <a id="cartItems" data-lightbox title="<?=$this->transEsc('View Book Bag')?>" href="<?=$this->url('cart-home')?>">
+                <i class="fa fa-suitcase" aria-hidden="true"></i> <strong><?=count($cart->getItems())?></strong> <?=$this->transEsc('items')?>
+                <span class="full<?=!$cart->isFull() ? ' hidden' : '' ?>">(<?=$this->transEsc('bookbag_full') ?>)</span>
+              </a>
+            </li>
+          <? endif; ?>
+          <? if (is_object($account) && $account->loginEnabled()): // hide login/logout if unavailable ?>
+            <li class="logoutOptions<? if(!$account->isLoggedIn()): ?> hidden<? endif ?>">
+              <a href="<?=$this->url('myresearch-home', array(), array('query' => array('redirect' => 0)))?>"><i class="fa fa-home" aria-hidden="true"></i> <?=$this->transEsc("Your Account")?></a>
+            </li>
+            <li class="logoutOptions<? if(!$account->isLoggedIn()): ?> hidden<? endif ?>">
+              <a href="<?=$this->url('myresearch-logout')?>" class="logout"><i class="fa fa-sign-out" aria-hidden="true"></i> <?=$this->transEsc("Log Out")?></a>
+            </li>
+            <li id="loginOptions"<? if($account->isLoggedIn()): ?> class="hidden"<? endif ?>>
+              <? if ($account->getSessionInitiator($this->serverUrl($this->url('myresearch-home')))): ?>
+                <a href="<?=$this->url('myresearch-userlogin')?>"><i class="fa fa-sign-in" aria-hidden="true"></i> <?=$this->transEsc("Institutional Login")?></a>
+              <? else: ?>
+                <a href="<?=$this->url('myresearch-userlogin')?>" data-lightbox><i class="fa fa-sign-in" aria-hidden="true"></i> <?=$this->transEsc("Login")?></a>
+              <? endif; ?>
+            </li>
+          <? endif; ?>
 
-        <? if (isset($this->layout()->themeOptions) && count($this->layout()->themeOptions) > 1): ?>
-          <li class="theme dropdown">
-            <form method="post" name="themeForm" id="themeForm">
-              <input type="hidden" name="ui"/>
-            </form>
-            <a href="#" class="dropdown-toggle" data-toggle="dropdown"><?=$this->transEsc("Theme")?> <b class="caret"></b></a>
-            <ul class="dropdown-menu">
-              <? foreach ($this->layout()->themeOptions as $current): ?>
-                <li<?=$current['selected'] ? ' class="active"' : ''?>><a href="#" onClick="document.themeForm.ui.value='<?=$this->escapeHtmlAttr($current['name'])?>';document.themeForm.submit()"><?=$this->transEsc($current['desc'])?></a></li>
-              <? endforeach; ?>
-            </ul>
-          </li>
-        <? endif; ?>
+          <? if (isset($this->layout()->themeOptions) && count($this->layout()->themeOptions) > 1): ?>
+            <li class="theme dropdown">
+              <form method="post" name="themeForm" id="themeForm">
+                <input type="hidden" name="ui"/>
+              </form>
+              <a href="#" class="dropdown-toggle" data-toggle="dropdown"><?=$this->transEsc("Theme")?> <b class="caret"></b></a>
+              <ul class="dropdown-menu">
+                <? foreach ($this->layout()->themeOptions as $current): ?>
+                  <li<?=$current['selected'] ? ' class="active"' : ''?>><a href="#" onClick="document.themeForm.ui.value='<?=$this->escapeHtmlAttr($current['name'])?>';document.themeForm.submit()"><?=$this->transEsc($current['desc'])?></a></li>
+                <? endforeach; ?>
+              </ul>
+            </li>
+          <? endif; ?>
 
-        <? if (isset($this->layout()->allLangs) && count($this->layout()->allLangs) > 1): ?>
-          <li class="language dropdown">
-            <form method="post" name="langForm" id="langForm">
-              <input type="hidden" name="mylang"/>
-            </form>
-            <a href="#" class="dropdown-toggle" data-toggle="dropdown"><?=$this->transEsc("Language")?> <b class="caret"></b></a>
-            <ul class="dropdown-menu">
-              <? foreach ($this->layout()->allLangs as $langCode => $langName): ?>
-                <li<?=$this->layout()->userLang == $langCode ? ' class="active"' : ''?>><a href="#" onClick="document.langForm.mylang.value='<?=$langCode?>';document.langForm.submit()"><?=$this->displayLanguageOption($langName)?></a></li>
-              <? endforeach; ?>
-            </ul>
-          </li>
-        <? endif; ?>
-      </ul>
+          <? if (isset($this->layout()->allLangs) && count($this->layout()->allLangs) > 1): ?>
+            <li class="language dropdown">
+              <form method="post" name="langForm" id="langForm">
+                <input type="hidden" name="mylang"/>
+              </form>
+              <a href="#" class="dropdown-toggle" data-toggle="dropdown"><?=$this->transEsc("Language")?> <b class="caret"></b></a>
+              <ul class="dropdown-menu">
+                <? foreach ($this->layout()->allLangs as $langCode => $langName): ?>
+                  <li<?=$this->layout()->userLang == $langCode ? ' class="active"' : ''?>><a href="#" onClick="document.langForm.mylang.value='<?=$langCode?>';document.langForm.submit()"><?=$this->displayLanguageOption($langName)?></a></li>
+                <? endforeach; ?>
+              </ul>
+            </li>
+          <? endif; ?>
+        </ul>
+      </nav>
+    </div>
+  <? endif; ?>
+</div>
+<? if ($this->layout()->searchbox !== false): ?>
+  <div class="search container navbar">
+    <nav class="nav searchbox hidden-print">
+      <?=$this->layout()->searchbox ?>
     </nav>
   </div>
 <? endif; ?>
diff --git a/themes/bootstrap3/templates/help/home.phtml b/themes/bootstrap3/templates/help/home.phtml
index 92b678d6963b369c69619b2428df4a32256e9a5c..82e08b7db1fb8342afbef3e9cc76c25a1aeefe18 100644
--- a/themes/bootstrap3/templates/help/home.phtml
+++ b/themes/bootstrap3/templates/help/home.phtml
@@ -6,4 +6,4 @@
   <?=$help?>
 <? else: ?>
   <p class="alert alert-danger"><?=$this->transEsc('help_page_missing')?></p>
-<? endif; ?>
\ No newline at end of file
+<? endif; ?>
diff --git a/themes/bootstrap3/templates/install/disabled.phtml b/themes/bootstrap3/templates/install/disabled.phtml
index db02a66496c1fe4b365a08762f8e487bdde97373..6da3c47c0a0b9b5d1c8ded29f76cc6d1f7e64d73 100644
--- a/themes/bootstrap3/templates/install/disabled.phtml
+++ b/themes/bootstrap3/templates/install/disabled.phtml
@@ -7,4 +7,4 @@
 ?>
 <h2><?=$this->transEsc('auto_configure_title')?></h2>
 
-<p><?=$this->transEsc('auto_configure_disabled')?></p>
\ No newline at end of file
+<p><?=$this->transEsc('auto_configure_disabled')?></p>
diff --git a/themes/bootstrap3/templates/install/done.phtml b/themes/bootstrap3/templates/install/done.phtml
index 17d72d134205338c03b65cb5c53b86851dd1054c..f1a18df64804499c7ea5c371851928acad7a5c2c 100644
--- a/themes/bootstrap3/templates/install/done.phtml
+++ b/themes/bootstrap3/templates/install/done.phtml
@@ -11,4 +11,4 @@
 
 <p>If you are concerned about security, you may want to change the permissions on
 the <strong><?=$this->escapeHtml($this->configDir)?></strong> directory to prevent the
-web server from writing changes to configurations in the future.</p>
\ No newline at end of file
+web server from writing changes to configurations in the future.</p>
diff --git a/themes/bootstrap3/templates/install/fixdatabase.phtml b/themes/bootstrap3/templates/install/fixdatabase.phtml
index dbbb5508cfe24d7e4b47a0ec50878b62e9384d79..deef34c38144907c81e67dabd4c9c4b350571fa7 100644
--- a/themes/bootstrap3/templates/install/fixdatabase.phtml
+++ b/themes/bootstrap3/templates/install/fixdatabase.phtml
@@ -11,73 +11,50 @@
 
 <p>To create a new database for VuFind, please fill in this form:</p>
 
-<form class="form-horizontal" method="post">
+<form class="form-fix-database" method="post">
   <div class="form-group">
-    <label class="col-sm-3 control-label" for="dbname">Select database type:</label>
-    <div class="col-sm-9">
-      <select name="driver" class="form-control">
-        <option value="mysql">MySQL</option>
-        <option <? if ($driver == 'pgsql'): ?>selected="selected" <? endif; ?>value="pgsql">PostgreSQL</option>
-      </select>
-    </div>
+    <label class="control-label" for="dbname">Select database type:</label>
+    <select name="driver" class="form-control">
+      <option value="mysql">MySQL</option>
+      <option <? if ($driver == 'pgsql'): ?>selected="selected" <? endif; ?>value="pgsql">PostgreSQL</option>
+    </select>
   </div>
   <div class="form-group">
-    <label class="col-sm-3 control-label" for="dbname">New database name:</label>
-    <div class="col-sm-9">
-      <input type="text" name="dbname" value="<?=$this->escapeHtmlAttr($this->dbname)?>" class="form-control"/>
-    </div>
+    <label class="control-label" for="dbname">New database name:</label>
+    <input type="text" name="dbname" value="<?=$this->escapeHtmlAttr($this->dbname)?>" class="form-control"/>
   </div>
   <div class="form-group">
-    <label class="col-sm-3 control-label" for="dbuser">New database user:</label>
-    <div class="col-sm-9">
-      <input type="text" name="dbuser" value="<?=$this->escapeHtmlAttr($this->dbuser)?>" class="form-control"/>
-    </div>
+    <label class="control-label" for="dbuser">New database user:</label>
+    <input type="text" name="dbuser" value="<?=$this->escapeHtmlAttr($this->dbuser)?>" class="form-control"/>
   </div>
   <div class="form-group">
-    <label class="col-sm-3 control-label" for="dbpass">New user password:</label>
-    <div class="col-sm-9">
-      <input type="password" name="dbpass" value="" class="form-control"/>
-    </div>
+    <label class="control-label" for="dbpass">New user password:</label>
+    <input type="password" name="dbpass" value="" class="form-control"/>
   </div>
   <div class="form-group">
-    <label class="col-sm-3 control-label" for="dbpassconfirm">Confirm new user password:</label>
-    <div class="col-sm-9">
-      <input type="password" name="dbpassconfirm" value="" class="form-control"/>
-    </div>
+    <label class="control-label" for="dbpassconfirm">Confirm new user password:</label>
+    <input type="password" name="dbpassconfirm" value="" class="form-control"/>
   </div>
   <div class="form-group">
-    <label class="col-sm-3 control-label" for="dbhost">MySQL Host:</label>
-    <div class="col-sm-9">
-      <input type="text" name="dbhost" value="<?=$this->escapeHtmlAttr($this->dbhost)?>" class="form-control"/>
-    </div>
+    <label class="control-label" for="dbhost">MySQL Host:</label>
+    <input type="text" name="dbhost" value="<?=$this->escapeHtmlAttr($this->dbhost)?>" class="form-control"/>
   </div>
   <div class="form-group">
-    <label class="col-sm-3 control-label" for="vufindhost">VuFind IP/Host (if different from SQL Host):</label>
-    <div class="col-sm-9">
-      <input type="text" name="vufindhost" value="<?=$this->escapeHtmlAttr($this->vufindhost)?>"/>
-    </div>
+    <label class="control-label" for="vufindhost">VuFind IP/Host (if different from SQL Host):</label>
+    <input type="text" name="vufindhost" value="<?=$this->escapeHtmlAttr($this->vufindhost)?>" class="form-control"/>
   </div>
   <div class="form-group">
-    <label class="col-sm-3 control-label" for="dbrootuser">MySQL Root User:</label>
-    <div class="col-sm-9">
-      <input type="text" name="dbrootuser" value="<?=$this->escapeHtmlAttr($this->dbrootuser)?>" class="form-control"/>
-    </div>
+    <label class="control-label" for="dbrootuser">MySQL Root User:</label>
+    <input type="text" name="dbrootuser" value="<?=$this->escapeHtmlAttr($this->dbrootuser)?>" class="form-control"/>
   </div>
   <div class="form-group">
-    <label class="col-sm-3 control-label" for="dbrootpass">MySQL Root Password:</label>
-    <div class="col-sm-9">
-      <input type="password" name="dbrootpass" value="" class="form-control"/>
-    </div>
+    <label class="control-label" for="dbrootpass">MySQL Root Password:</label>
+    <input type="password" name="dbrootpass" value="" class="form-control"/>
   </div>
   <div class="form-group">
-    <div class="col-sm-9 col-sm-offset-3">
-      <input class="btn btn-primary" type="submit" name="submit" value="<?=$this->transEsc('Submit') ?>" />
-    </div>
+    <input class="btn btn-primary" type="submit" name="submit" value="<?=$this->transEsc('Submit') ?>" />
   </div>
   <div class="form-group">
-    <label class="col-sm-3 control-label" for="printsql">If you don't have the credentials or you wish to print the SQL out :</label>
-    <div class="col-sm-9">
-      <p class="form-control-static">Click here to <input class="btn btn-default" type="submit" name="printsql" value="Skip"/> credentials.</p>
-    </div>
+    <p class="form-control-static">If you don't have the credentials or you wish to print the SQL out, click here to <input class="btn btn-default" type="submit" name="printsql" value="Skip"/> credentials.</p>
   </div>
-</form>
\ No newline at end of file
+</form>
diff --git a/themes/bootstrap3/templates/install/fixdependencies.phtml b/themes/bootstrap3/templates/install/fixdependencies.phtml
index 5d5160af5cbe26feda2396f6e1a388a4e076c35f..c2872601b358f870ecd570ef8edf1e34a89fe43f 100644
--- a/themes/bootstrap3/templates/install/fixdependencies.phtml
+++ b/themes/bootstrap3/templates/install/fixdependencies.phtml
@@ -9,4 +9,4 @@
 
 <?=$this->flashmessages()?>
 
-<? if ($this->problems == 0): ?><p><?=$this->transEsc('No dependency problems found') ?>.</p><? endif; ?>
\ No newline at end of file
+<? if ($this->problems == 0): ?><p><?=$this->transEsc('No dependency problems found') ?>.</p><? endif; ?>
diff --git a/themes/bootstrap3/templates/install/fixils.phtml b/themes/bootstrap3/templates/install/fixils.phtml
index cd80be07894be849857f40b4431be229f43a5e7a..d76829301d75f0f9ad32f9b959ed27965254e2ca 100644
--- a/themes/bootstrap3/templates/install/fixils.phtml
+++ b/themes/bootstrap3/templates/install/fixils.phtml
@@ -12,21 +12,17 @@
   in order to demonstrate the capabilities of the system.  If you want real patron and status information to display,
   you should change your configuration to communicate with a real ILS.</p>
 
-  <form method="post" class="form-horizontal" role="form">
+  <form method="post" class="form-fix-ils" role="form">
     <div class="form-group">
-      <label for="driver" class="col-sm-2 control-label">Pick a driver:</label>
-      <div class="col-sm-10">
-        <select id="driver" name="driver" class="form-control">
-          <? foreach ($this->drivers as $driver): ?>
-            <option value="<?=$this->escapeHtmlAttr($driver)?>"><?=$this->escapeHtml($driver)?></option>
-          <? endforeach; ?>
-        </select>
-      </div>
+      <label for="driver" class="control-label">Pick a driver:</label>
+      <select id="driver" name="driver" class="form-control">
+        <? foreach ($this->drivers as $driver): ?>
+          <option value="<?=$this->escapeHtmlAttr($driver)?>"><?=$this->escapeHtml($driver)?></option>
+        <? endforeach; ?>
+      </select>
     </div>
     <div class="form-group">
-      <div class="col-sm-10 col-sm-offset-2">
-        <input type="submit" class="btn btn-primary"/>
-      </div>
+      <input type="submit" class="btn btn-primary"/>
     </div>
   </form>
 
@@ -36,4 +32,4 @@
   <p>VuFind is having trouble communicating with your Integrated Library System (ILS).  Check your configuration.
   You may need to edit the file at <strong><?=$this->escapeHtml($this->configPath)?></strong> and fill in some
   connection details.</p>
-<? endif; ?>
\ No newline at end of file
+<? endif; ?>
diff --git a/themes/bootstrap3/templates/install/fixsecurity.phtml b/themes/bootstrap3/templates/install/fixsecurity.phtml
index 117ad5785cef7652c4fd3a68b648d40c218b886d..5d5042d401c9f53326c934bc18c166f2151369d2 100644
--- a/themes/bootstrap3/templates/install/fixsecurity.phtml
+++ b/themes/bootstrap3/templates/install/fixsecurity.phtml
@@ -19,7 +19,7 @@
   </p>
   <p><i>Do you still wish to proceed with enabling enhanced security in the database?</i></p>
   <form method="post" action="<?=$this->url('install-fixsecurity')?>">
-    <input type="submit" name="fix-user-table" value="Yes" class="btn btn-default"/>
+    <input type="submit" name="fix-user-table" value="Yes" class="btn btn-primary"/>
     <input type="submit" name="fix-user-table" value="No" class="btn btn-default"/>
   </form>
 <? else: ?>
diff --git a/themes/bootstrap3/templates/install/fixsolr.phtml b/themes/bootstrap3/templates/install/fixsolr.phtml
index 9069b80f53612985d78aa77ae6268f51454b143b..2a9121c78d13cf256540543208b4a2e41c8a71af 100644
--- a/themes/bootstrap3/templates/install/fixsolr.phtml
+++ b/themes/bootstrap3/templates/install/fixsolr.phtml
@@ -15,4 +15,4 @@
   <li>Did you start the Solr server?  See <a href="https://vufind.org/wiki/administration:starting_and_stopping_solr">Starting and Stopping Solr</a> in the documentation.</li>
   <li>Have you checked the Solr admin panel for errors?  You may be able to find it <a href="<?=$this->escapeHtmlAttr($this->userUrl)?>">here</a>.</li>
   <li>Are you using non-default Solr settings?  If your Solr URL is not <strong><?=$this->escapeHtml($this->rawUrl)?></strong> or your core name is not <strong><?=$this->escapeHtml($this->core)?></strong>, you will need to customize the [Index] section of <?=$this->escapeHtml($this->configFile)?>.</li>
-</ol>
\ No newline at end of file
+</ol>
diff --git a/themes/bootstrap3/templates/install/fixsslcerts.phtml b/themes/bootstrap3/templates/install/fixsslcerts.phtml
index 0408c875e324e65327e7b1d7f0db1ad9b5a8fb35..043c60bcc2d56489873ebe11bb960a3449bf4b44 100644
--- a/themes/bootstrap3/templates/install/fixsslcerts.phtml
+++ b/themes/bootstrap3/templates/install/fixsslcerts.phtml
@@ -14,4 +14,4 @@
 <ol>
   <li>Try setting the sslcapath or sslcafile setting in the [Http] section of your config.ini file to point to your local certificate store.</li>
   <li>If you wish to disable certificate checking, you can set sslverifypeer to false in the [Http] section of config.ini. This is <b>insecure</b> and <b>not recommended</b> but may be useful for initial testing purposes.</li>
-</ol>
\ No newline at end of file
+</ol>
diff --git a/themes/bootstrap3/templates/install/home.phtml b/themes/bootstrap3/templates/install/home.phtml
index f8398674f1acb4f3f832077f2a99543061f141b6..920c45cfbb9d1e4c805b8cd7b6ac75552408ecc1 100644
--- a/themes/bootstrap3/templates/install/home.phtml
+++ b/themes/bootstrap3/templates/install/home.phtml
@@ -14,4 +14,4 @@
 
 <? if ($errors == 0): ?>
   <p>No problems were found.  You may wish to <a href="<?=$this->url('install-done')?>">Disable Auto Configuration</a> at this time.</p>
-<? endif; ?>
\ No newline at end of file
+<? endif; ?>
diff --git a/themes/bootstrap3/templates/install/showsql.phtml b/themes/bootstrap3/templates/install/showsql.phtml
index 08636c86334fe63d3caf6caf413287d9e0d10dbf..54bdc9089452ef829275f106060a401e842b81c9 100644
--- a/themes/bootstrap3/templates/install/showsql.phtml
+++ b/themes/bootstrap3/templates/install/showsql.phtml
@@ -20,4 +20,4 @@
 
 <form method="post" action="<?=$this->url('install-showsql')?>">
     <input type="submit" name="continue" value="Next" class="btn btn-primary"/>
-</form>
\ No newline at end of file
+</form>
diff --git a/themes/bootstrap3/templates/layout/layout.phtml b/themes/bootstrap3/templates/layout/layout.phtml
index acb94aa761405b30a51c40de71b6c9fcd5968f8d..622c5e5d976696e95a2a6b131831097e88786bd5 100644
--- a/themes/bootstrap3/templates/layout/layout.phtml
+++ b/themes/bootstrap3/templates/layout/layout.phtml
@@ -10,12 +10,12 @@
     <?
       // Set up OpenSearch link:
       $this->headLink(
-        array(
+        [
           'href' => $this->url('search-opensearch') . '?method=describe',
           'type' => 'application/opensearchdescription+xml',
           'title' => $this->transEsc('Library Catalog Search'),
           'rel' => 'search'
-        )
+        ]
       );
     ?>
     <!-- RTL styling -->
@@ -28,7 +28,7 @@
       if (!isset($this->renderingError)) {
         // Add translation strings
         $this->jsTranslations()->addStrings(
-          array(
+          [
             'add_tag_success' => 'add_tag_success',
             'bulk_email_success' => 'bulk_email_success',
             'bulk_noitems_advice' => 'bulk_noitems_advice',
@@ -50,11 +50,11 @@
                 'number_thousands_separator', null, ','
             ],
             'sms_success' => 'sms_success'
-          )
+          ]
         );
         // Add libphonenumber.js strings
         $this->jsTranslations()->addStrings(
-          array(
+          [
             "Phone number invalid" => 'libphonenumber_invalid',
             "Invalid country calling code" => 'libphonenumber_invalidcountry',
             "Invalid region code" => 'libphonenumber_invalidregion',
@@ -62,7 +62,7 @@
             "The string supplied is too long to be a phone number" => 'libphonenumber_toolong',
             "The string supplied is too short to be a phone number" => 'libphonenumber_tooshort',
             "Phone number too short after IDD" => 'libphonenumber_tooshortidd'
-          )
+          ]
         );
         // Deal with cart stuff:
         $cart = $this->cart();
@@ -82,7 +82,7 @@
             );
           }
           $this->jsTranslations()->addStrings(
-            array(
+            [
               'addBookBag' => 'Add to Book Bag',
               'bookbagFull' => 'bookbag_full_msg',
               'bookbagMax' => $cart->getMaxSize(),
@@ -93,7 +93,7 @@
               'itemsInBag' => 'items_already_in_bookbag',
               'removeBookBag' => 'Remove from Book Bag',
               'viewBookBag' => 'View Book Bag'
-            )
+            ]
           );
         }
         $this->headScript()->appendScript(
@@ -121,7 +121,7 @@ JS;
     ?>
     <?=$this->headScript()?>
   </head>
-  <body class="<?=$this->layoutClass('offcanvas-row')?><? if ($this->layout()->rtl): ?> rtl<? endif; ?>">
+  <body class="template-dir-<?=$this->templateDir?> template-name-<?=$this->templateName?> <?=$this->layoutClass('offcanvas-row')?><? if ($this->layout()->rtl): ?> rtl<? endif; ?>">
     <? // Set up the search box -- there are three possible cases:
       // 1. No search box was set; we should default to the normal box
       // 2. It was set to false; we should display nothing
@@ -133,17 +133,14 @@ JS;
       }
     ?>
     <header class="hidden-print">
-      <div class="container navbar">
-        <? if (isset($this->layout()->srmessage)): // message for benefit of screen-reader users ?>
-          <span class="sr-only"><?=$this->layout()->srmessage ?></span>
-        <? endif; ?>
-        <a class="sr-only" href="#content"><?=$this->transEsc('Skip to content') ?></a>
-        <?=$this->render('header.phtml')?>
-      </div>
+      <? if (isset($this->layout()->srmessage)): // message for benefit of screen-reader users ?>
+        <span class="sr-only"><?=$this->layout()->srmessage ?></span>
+      <? endif; ?>
+      <a class="sr-only" href="#content"><?=$this->transEsc('Skip to content') ?></a>
+      <?=$this->render('header.phtml')?>
+    </header>
+    <nav class="breadcrumbs">
       <div class="container">
-        <nav class="nav searchbox hidden-lg hidden-print">
-          <?=$this->layout()->searchbox ?>
-        </nav>
         <? if((!isset($this->layout()->showBreadcrumbs) || $this->layout()->showBreadcrumbs == true)
           && !empty($this->layout()->breadcrumbs)
           && $this->layout()->breadcrumbs !== false
@@ -151,16 +148,16 @@ JS;
           <ul class="breadcrumb hidden-print">
             <? if(is_array($this->layout()->breadcrumbs)): ?>
               <? if(count($this->layout()->breadcrumbs) > 1): ?>
-                <?=$this->render('breadcrumbs/multi.phtml', array(
+                <?=$this->render('breadcrumbs/multi.phtml', [
                     'parents' => $this->layout()->breadcrumbs,
                     'title'   => $this->layout()->title,
                     'from'    => $this->layout()->from
-                  )) ?>
+                  ]) ?>
               <? else: ?>
-                <?=$this->render('breadcrumbs/default.phtml', array(
+                <?=$this->render('breadcrumbs/default.phtml', [
                     'parents' => $this->layout()->breadcrumbs,
                     'title'   => $this->layout()->title
-                  )) ?>
+                  ]) ?>
               <? endif; ?>
             <? else: ?>
               <?=$this->layout()->breadcrumbs ?>
@@ -168,18 +165,13 @@ JS;
           </ul>
         <? endif; ?>
       </div>
-    </header>
-    <div role="main" class="main template-dir-<?=$this->templateDir?> template-name-<?=$this->templateName?>">
+    </nav>
+    <div role="main" class="main">
       <div id="content" class="container">
         <?=$this->layout()->content ?>
       </div>
     </div>
-    <footer class="hidden-print">
-      <div class="container">
-        <?=$this->render('footer.phtml')?>
-        <?=$this->layout()->poweredBy ?>
-      </div>
-    </footer>
+    <?=$this->render('footer.phtml')?>
     <!-- MODAL IN CASE WE NEED ONE -->
     <div id="modal" class="modal fade hidden-print" tabindex="-1" role="dialog" aria-labelledby="modalTitle" aria-hidden="true">
       <div class="modal-dialog">
diff --git a/themes/bootstrap3/templates/libguides/home.phtml b/themes/bootstrap3/templates/libguides/home.phtml
index d13d4348c1e39e2222b5f16ce7d65ecd7816ef92..bc5b700660ea8e7baee8cc01de0600b0b4611521 100644
--- a/themes/bootstrap3/templates/libguides/home.phtml
+++ b/themes/bootstrap3/templates/libguides/home.phtml
@@ -1 +1 @@
-<?=$this->render('search/home.phtml');?>
\ No newline at end of file
+<?=$this->render('search/home.phtml');?>
diff --git a/themes/bootstrap3/templates/libguides/results.phtml b/themes/bootstrap3/templates/libguides/results.phtml
index c1797c1cd4a1ebb2ccad84718b1e225e51cac6a8..a0c6dd4bbf5077e0b43b335e98733b44bba7b4e6 100644
--- a/themes/bootstrap3/templates/libguides/results.phtml
+++ b/themes/bootstrap3/templates/libguides/results.phtml
@@ -1,4 +1,4 @@
 <?
     // Load standard settings from the default search results screen:
     echo $this->render('search/results.phtml');
-?>
\ No newline at end of file
+?>
diff --git a/themes/bootstrap3/templates/librarycards/editcard.phtml b/themes/bootstrap3/templates/librarycards/editcard.phtml
index beb61aa23e65bd30eaa2b92caf67a1cfcbac55d2..9c2be42a724ad9876f5b657d5134c56c6e406201 100644
--- a/themes/bootstrap3/templates/librarycards/editcard.phtml
+++ b/themes/bootstrap3/templates/librarycards/editcard.phtml
@@ -13,41 +13,31 @@
 
 <h2><?=$this->transEsc($pageTitle); ?></h2>
 
-<form class="form-horizontal edit-card-form" method="post" name="<?=empty($this->card->id) ? 'newCardForm' : 'editCardForm'?>">
+<form class="form-edit-card" method="post" name="<?=empty($this->card->id) ? 'newCardForm' : 'editCardForm'?>">
   <input type="hidden" name="id" value="<?=empty($this->card->id) ? 'NEW' : $this->card->id ?>"/>
   <div class="form-group">
-    <label class="col-sm-3 control-label" for="card_name"><?=$this->transEsc('Library Card Name'); ?>:</label>
-    <div class="col-sm-9">
-      <input id="card_name" class="form-control" type="text" name="card_name" value="<?=$this->escapeHtmlAttr($this->cardName)?>"/>
-    </div>
+    <label class="control-label" for="card_name"><?=$this->transEsc('Library Card Name'); ?>:</label>
+    <input id="card_name" class="form-control" type="text" name="card_name" value="<?=$this->escapeHtmlAttr($this->cardName)?>"/>
   </div>
   <? if ($this->targets !== null): ?>
   <div class="form-group">
-    <label class="col-sm-3 control-label" for="login_target"><?=$this->transEsc('login_target')?>:</label>
-    <div class="col-sm-9">
-      <select id="login_target" name="target" class="form-control">
+    <label class="control-label" for="login_target"><?=$this->transEsc('login_target')?>:</label>
+    <select id="login_target" name="target" class="form-control">
       <? foreach ($this->targets as $target): ?>
         <option value="<?=$this->escapeHtmlAttr($target)?>"<?=($target == $this->target ? ' selected="selected"' : '')?>><?=$this->transEsc("source_$target", null, $target)?></option>
       <? endforeach; ?>
-      </select>
-    </div>
+    </select>
   </div>
   <? endif; ?>
   <div class="form-group">
-    <label class="col-sm-3 control-label" for="login_username"><?=$this->transEsc('Username')?>:</label>
-    <div class="col-sm-9">
-      <input id="login_username" type="text" name="username" value="<?=$this->escapeHtmlAttr($this->username)?>" class="form-control"/>
-    </div>
+    <label class="control-label" for="login_username"><?=$this->transEsc('Username')?>:</label>
+    <input id="login_username" type="text" name="username" value="<?=$this->escapeHtmlAttr($this->username)?>" class="form-control"/>
   </div>
   <div class="form-group">
-    <label class="col-sm-3 control-label" for="login_password"><?=$this->transEsc('Password')?>:</label>
-    <div class="col-sm-9">
-      <input id="login_password" type="password" name="password" value="<?=$this->escapeHtmlAttr($this->password)?>" class="form-control"/>
-    </div>
+    <label class="control-label" for="login_password"><?=$this->transEsc('Password')?>:</label>
+    <input id="login_password" type="password" name="password" value="<?=$this->escapeHtmlAttr($this->password)?>" class="form-control"/>
   </div>
   <div class="form-group">
-    <div class="col-sm-9 col-sm-offset-3">
-      <input class="btn btn-primary" type="submit" name="submit" value="<?=$this->transEsc('Save') ?>"/>
-    </div>
+    <input class="btn btn-primary" type="submit" name="submit" value="<?=$this->transEsc('Save') ?>"/>
   </div>
 </form>
diff --git a/themes/bootstrap3/templates/librarycards/home.phtml b/themes/bootstrap3/templates/librarycards/home.phtml
index 3d5eb9a978cf7f8f47081f7df3d48645b915215a..b3cbd230362f70352b985ba8f898423e7a9d8fa2 100644
--- a/themes/bootstrap3/templates/librarycards/home.phtml
+++ b/themes/bootstrap3/templates/librarycards/home.phtml
@@ -5,59 +5,56 @@
     // Set up breadcrumbs:
     $this->layout()->breadcrumbs = '<li><a href="' . $this->url('myresearch-home') . '">' . $this->transEsc('Your Account') . '</a></li> <li class="active">' . $this->transEsc('Library Cards') . '</li>';
 ?>
-<div class="row">
-  <div class="<?=$this->layoutClass('mainbody')?>">
+<div class="<?=$this->layoutClass('mainbody')?>">
 
-    <?=$this->flashmessages()?>
+  <?=$this->flashmessages()?>
 
-    <h2><?=$this->transEsc('Library Cards')?></h2>
-    <? if ($this->libraryCards->count() == 0): ?>
-      <div><?=$this->transEsc('You do not have any library cards')?></div>
-    <? else: ?>
-      <table class="table table-striped" summary="<?=$this->transEsc('Library Cards')?>">
+  <h2><?=$this->transEsc('Library Cards')?></h2>
+  <? if ($this->libraryCards->count() == 0): ?>
+    <div><?=$this->transEsc('You do not have any library cards')?></div>
+  <? else: ?>
+    <table class="table table-striped" summary="<?=$this->transEsc('Library Cards')?>">
+    <tr>
+      <th><?=$this->transEsc('Library Card Name')?></th>
+      <? if ($this->multipleTargets): ?>
+      <th><?=$this->transEsc('login_target')?></th>
+      <? endif; ?>
+      <th><?=$this->transEsc('Username')?></th>
+      <th>&nbsp;</th>
+    </tr>
+    <? foreach ($this->libraryCards as $record): ?>
       <tr>
-        <th><?=$this->transEsc('Library Card Name')?></th>
-        <? if ($this->multipleTargets): ?>
-        <th><?=$this->transEsc('login_target')?></th>
+        <td><?=$this->escapeHtml($record['card_name'])?></td>
+        <? $username = $record['cat_username']; if ($this->multipleTargets): ?>
+          <? $target = ''; ?>
+          <? if (strstr($username, '.')): ?>
+            <? list($target, $username) = explode('.', $username, 2); ?>
+          <? endif; ?>
+          <td><?=$target ? $this->transEsc("source_$target", null, $target) : '&nbsp;' ?></td>
         <? endif; ?>
-        <th><?=$this->transEsc('Username')?></th>
-        <th>&nbsp;</th>
+        <td><?=$this->escapeHtml($username)?></td>
+        <td>
+          <div class="btn-group">
+            <a class="btn btn-link" href="<?=$this->url('editLibraryCard') . $this->escapeHtmlAttr($record['id']) ?>" title="<?=$this->transEsc('Edit Library Card')?>"><i class="fa fa-edit" aria-hidden="true"></i> <?=$this->transEsc('Edit')?></a>
+            <a class="btn btn-link dropdown-toggle" data-toggle="dropdown" href="<?=$this->url('librarycards-deletecard') ?>?cardID=<?=urlencode($record['id'])?>">
+              <i class="fa fa-trash-o" aria-hidden="true"></i> <?=$this->transEsc('Delete')?>
+            </a>
+            <ul class="dropdown-menu">
+              <li><a href="<?=$this->url('librarycards-deletecard') ?>?cardID=<?=urlencode($record['id'])?>&amp;confirm=1"><?=$this->transEsc('confirm_dialog_yes') ?></a></li>
+              <li><a href="#"><?=$this->transEsc('confirm_dialog_no')?></a></li>
+            </ul>
+          </div>
+        </td>
       </tr>
-      <? foreach ($this->libraryCards as $record): ?>
-        <tr>
-          <td><?=$this->escapeHtml($record['card_name'])?></td>
-          <? $username = $record['cat_username']; if ($this->multipleTargets): ?>
-            <? $target = ''; ?>
-            <? if (strstr($username, '.')): ?>
-              <? list($target, $username) = explode('.', $username, 2); ?>
-            <? endif; ?>
-            <td><?=$target ? $this->transEsc("source_$target", null, $target) : '&nbsp;' ?></td>
-          <? endif; ?>
-          <td><?=$this->escapeHtml($username)?></td>
-          <td>
-            <div class="btn-group">
-              <a class="btn btn-link" href="<?=$this->url('editLibraryCard') . $this->escapeHtmlAttr($record['id']) ?>" title="<?=$this->transEsc('Edit Library Card')?>"><i class="fa fa-edit" aria-hidden="true"></i> <?=$this->transEsc('Edit')?></a>
-              <a class="btn btn-link dropdown-toggle" data-toggle="dropdown" href="<?=$this->url('librarycards-deletecard') ?>?cardID=<?=urlencode($record['id'])?>">
-                <i class="fa fa-trash-o" aria-hidden="true"></i> <?=$this->transEsc('Delete')?>
-              </a>
-              <ul class="dropdown-menu">
-                <li><a href="<?=$this->url('librarycards-deletecard') ?>?cardID=<?=urlencode($record['id'])?>&amp;confirm=1"><?=$this->transEsc('confirm_dialog_yes') ?></a></li>
-                <li><a href="#"><?=$this->transEsc('confirm_dialog_no')?></a></li>
-              </ul>
-            </div>
-          </td>
-        </tr>
-      <? endforeach; ?>
-      </table>
-    <? endif; ?>
+    <? endforeach; ?>
+    </table>
+  <? endif; ?>
 
-    <div class="btn-group">
-      <a href="<?=$this->url('editLibraryCard') ?>NEW" class="btn btn-link"><i class="fa fa-edit" aria-hidden="true"></i> <?=$this->transEsc('Add a Library Card')?></a>
-    </div>
-  </div>
-
-  <div class="<?=$this->layoutClass('sidebar')?>">
-    <?=$this->context($this)->renderInContext("myresearch/menu.phtml", array('active' => 'librarycards'))?>
+  <div class="btn-group">
+    <a href="<?=$this->url('editLibraryCard') ?>NEW" class="btn btn-link"><i class="fa fa-edit" aria-hidden="true"></i> <?=$this->transEsc('Add a Library Card')?></a>
   </div>
+</div>
 
+<div class="<?=$this->layoutClass('sidebar')?>">
+  <?=$this->context($this)->renderInContext("myresearch/menu.phtml", ['active' => 'librarycards'])?>
 </div>
diff --git a/themes/bootstrap3/templates/myresearch/account.phtml b/themes/bootstrap3/templates/myresearch/account.phtml
index aebfcbd6a1a80622f49da20432ae1df4c5308d42..ac81a11f783bfeac09a82e964cbc3a35e729a47f 100644
--- a/themes/bootstrap3/templates/myresearch/account.phtml
+++ b/themes/bootstrap3/templates/myresearch/account.phtml
@@ -8,15 +8,11 @@
 <h2><?=$this->transEsc('User Account')?></h2>
 <?=$this->flashmessages()?>
 
-<form method="post" name="accountForm" id="accountForm" class="form-horizontal" data-toggle="validator" role="form">
+<form method="post" name="accountForm" id="accountForm" class="form-user-create" data-toggle="validator" role="form">
   <?=$this->auth()->getCreateFields()?>
   <?=$this->recaptcha()->html($this->useRecaptcha) ?>
   <div class="form-group">
-    <div class="col-sm-3">
-      <a class="back-to-login btn btn-link" href="<?=$this->url('myresearch-userlogin') ?>"><i class="fa fa-chevron-left" aria-hidden="true"></i> <?=$this->transEsc('Back')?></a>
-    </div>
-    <div class="col-sm-9">
-      <input class="btn btn-primary" type="submit" name="submit" value="<?=$this->transEsc('Submit')?>"/>
-    </div>
+    <a class="back-to-login btn btn-link" href="<?=$this->url('myresearch-userlogin') ?>"><i class="fa fa-chevron-left" aria-hidden="true"></i> <?=$this->transEsc('Back')?></a>
+    <input class="btn btn-primary" type="submit" name="submit" value="<?=$this->transEsc('Submit')?>"/>
   </div>
 </form>
diff --git a/themes/bootstrap3/templates/myresearch/bulk-action-buttons.phtml b/themes/bootstrap3/templates/myresearch/bulk-action-buttons.phtml
index 5adb7b86aae6e54782acac4a0f5a2a5ccf3b4468..26a447a4cc6491acc24dc6b363867da3a15c5942 100644
--- a/themes/bootstrap3/templates/myresearch/bulk-action-buttons.phtml
+++ b/themes/bootstrap3/templates/myresearch/bulk-action-buttons.phtml
@@ -3,22 +3,22 @@
   <input type="hidden" name="listName" value="<?=$this->escapeHtmlAttr($list->title)?>" />
 <? endif; ?>
 <? $user = $this->auth()->isLoggedIn(); ?>
-<div class="checkbox">
-  <label>
-    <input type="checkbox" name="selectAll" class="checkbox-select-all"/>
-    <?=$this->transEsc('select_page')?> | <?=$this->transEsc('with_selected')?>:
-  </label>
+<div class="bulkActionButtons">
+  <div class="bulk-checkbox">
+    <input type="checkbox" name="selectAll" class="checkbox-select-all" id="myresearchCheckAll"/>
+    <label for="myresearchCheckAll"><?=$this->transEsc('select_page')?> | <?=$this->transEsc('with_selected')?>:</label>
+  </div>
+  <div class="btn-group">
+    <input class="btn btn-default" type="submit" name="email" value="<?=$this->transEsc('Email')?>" title="<?=$this->transEsc('email_selected')?>"/>
+    <? if ((!is_null($this->list) && $this->list->editAllowed($user)) || is_null($this->list) && $user): ?>
+      <input class="btn btn-default" id="<?=$this->idPrefix?>delete_list_items_<?=!is_null($this->list) ? $this->escapeHtmlAttr($this->list->id) : ''?>" type="submit" name="delete" value="<?=$this->transEsc('Delete')?>" title="<?=$this->transEsc('delete_selected')?>"/>
+    <? endif; ?>
+    <? $exportOptions = $this->export()->getActiveFormats('bulk'); if (count($exportOptions) > 0): ?>
+      <input class="btn btn-default" type="submit" name="export" value="<?=$this->transEsc('Export')?>" title="<?=$this->transEsc('export_selected')?>"/>
+    <? endif; ?>
+    <input class="btn btn-default" type="submit" name="print" value="<?=$this->transEsc('Print')?>" title="<?=$this->transEsc('print_selected')?>" data-lightbox-ignore/>
+    <? if ($this->cart()->isActive()): ?>
+      <input class="btn btn-default" id="<?=$this->idPrefix?>updateCart" type="submit" name="add" value="<?=$this->transEsc('Add to Book Bag')?>"/>
+    <? endif; ?>
+  </div>
 </div>
-<div class="btn-group">
-  <input class="btn btn-default" type="submit" name="email" value="<?=$this->transEsc('Email')?>" title="<?=$this->transEsc('email_selected')?>"/>
-  <? if ((!is_null($this->list) && $this->list->editAllowed($user)) || is_null($this->list) && $user): ?>
-    <input class="btn btn-default" id="<?=$this->idPrefix?>delete_list_items_<?=!is_null($this->list) ? $this->escapeHtmlAttr($this->list->id) : ''?>" type="submit" name="delete" value="<?=$this->transEsc('Delete')?>" title="<?=$this->transEsc('delete_selected')?>"/>
-  <? endif; ?>
-  <? $exportOptions = $this->export()->getActiveFormats('bulk'); if (count($exportOptions) > 0): ?>
-    <input class="btn btn-default" type="submit" name="export" value="<?=$this->transEsc('Export')?>" title="<?=$this->transEsc('export_selected')?>"/>
-  <? endif; ?>
-  <input class="btn btn-default" type="submit" name="print" value="<?=$this->transEsc('Print')?>" title="<?=$this->transEsc('print_selected')?>" data-lightbox-ignore/>
-  <? if ($this->cart()->isActive()): ?>
-    <input class="btn btn-default" id="<?=$this->idPrefix?>updateCart" type="submit" name="add" value="<?=$this->transEsc('Add to Book Bag')?>"/>
-  <? endif; ?>
-</div>
\ No newline at end of file
diff --git a/themes/bootstrap3/templates/myresearch/cataloglogin.phtml b/themes/bootstrap3/templates/myresearch/cataloglogin.phtml
index 7dfc11a0b36158399251e3a60e6e034f9eebe637..eed7393889c674adeff58e4fddec8f351cfd971f 100644
--- a/themes/bootstrap3/templates/myresearch/cataloglogin.phtml
+++ b/themes/bootstrap3/templates/myresearch/cataloglogin.phtml
@@ -14,35 +14,27 @@
   <h3><?=$this->transEsc('Library Catalog Profile')?></h3>
   <?=$this->flashmessages()?>
   <p><?=$this->transEsc('cat_establish_account')?></p>
-  <form method="post" action="<?=$this->serverUrl(true)?>" class="form-horizontal">
+  <form method="post" action="<?=$this->serverUrl(true)?>" class="form-catalog-login">
     <? if ($this->targets !== null): ?>
-    <div class="form-group">
-      <label class="col-sm-2 control-label" for="login_target"><?=$this->transEsc('login_target')?>:</label>
-      <div class="col-sm-10">
+      <div class="form-group">
+        <label class="control-label" for="login_target"><?=$this->transEsc('login_target')?>:</label>
         <select id="login_target" name="target" class="form-control">
-        <? foreach ($this->targets as $target): ?>
-          <option value="<?=$this->escapeHtmlAttr($target)?>"><?=$this->transEsc("source_$target", null, $target)?></option>
-        <? endforeach; ?>
+          <? foreach ($this->targets as $target): ?>
+            <option value="<?=$this->escapeHtmlAttr($target)?>"><?=$this->transEsc("source_$target", null, $target)?></option>
+          <? endforeach; ?>
         </select>
       </div>
-    </div>
     <? endif; ?>
     <div class="form-group">
-      <label class="col-sm-2 control-label" for="profile_cat_username"><?=$this->transEsc('Library Catalog Username')?>:</label>
-      <div class="col-sm-10">
-        <input id="profile_cat_username" type="text" name="cat_username" value="" class="form-control"/>
-      </div>
+      <label class="control-label" for="profile_cat_username"><?=$this->transEsc('Library Catalog Username')?>:</label>
+      <input id="profile_cat_username" type="text" name="cat_username" value="" class="form-control"/>
     </div>
     <div class="form-group">
-      <label class="col-sm-2 control-label" for="profile_cat_password"><?=$this->transEsc('Library Catalog Password')?>:</label>
-      <div class="col-sm-10">
-        <input id="profile_cat_password" type="password" name="cat_password" value="" class="form-control"/>
-      </div>
+      <label class="control-label" for="profile_cat_password"><?=$this->transEsc('Library Catalog Password')?>:</label>
+      <input id="profile_cat_password" type="password" name="cat_password" value="" class="form-control"/>
     </div>
     <div class="form-group">
-      <div class="col-sm-offset-2 col-sm-10">
-        <input class="btn btn-primary" type="submit" name="processLogin" value="<?=$this->transEsc('Login')?>">
-      </div>
+      <input class="btn btn-primary" type="submit" name="processLogin" value="<?=$this->transEsc('Login')?>">
     </div>
   </form>
 <? endif; ?>
diff --git a/themes/bootstrap3/templates/myresearch/checkedout.phtml b/themes/bootstrap3/templates/myresearch/checkedout.phtml
index 0faacfc2aaaeda01dcc4681973dbcdec11948e96..3ff144feab0140452a0721d55a55f6b1d7ea6bb2 100644
--- a/themes/bootstrap3/templates/myresearch/checkedout.phtml
+++ b/themes/bootstrap3/templates/myresearch/checkedout.phtml
@@ -1,86 +1,97 @@
 <?
-    // Set up page title:
-    $this->headTitle($this->translate('Checked Out Items'));
+  // Set up page title:
+  $this->headTitle($this->translate('Checked Out Items'));
 
-    // Set up breadcrumbs:
-    $this->layout()->breadcrumbs = '<li><a href="' . $this->url('myresearch-home') . '">' . $this->transEsc('Your Account') . '</a></li> <li class="active">' . $this->transEsc('Checked Out Items') . '</li>';
+  // Set up breadcrumbs:
+  $this->layout()->breadcrumbs = '<li><a href="' . $this->url('myresearch-home') . '">' . $this->transEsc('Your Account') . '</a></li> <li class="active">' . $this->transEsc('Checked Out Items') . '</li>';
 ?>
 
-<div class="row">
-  <div class="<?=$this->layoutClass('mainbody')?>">
-    <h2><?=$this->transEsc('Your Checked Out Items')?></h2>
-    <?=$this->flashmessages()?>
-
-    <?=$this->context($this)->renderInContext('librarycards/selectcard.phtml', array('user' => $this->auth()->isLoggedIn())); ?>
-
-    <? if (!empty($this->transactions)): ?>
-      <? if ($this->renewForm): ?>
-      <form name="renewals" method="post" id="renewals">
-        <div class="toolbar">
-          <div class="checkbox">
-            <label>
-              <input type="checkbox" name="selectAll" class="checkbox-select-all"/>
-              <?=$this->transEsc('select_page')?> |
-            </label>
-            <input type="submit" class="btn btn-default" id="renewSelected" name="renewSelected" value="<?=$this->transEsc("renew_selected")?>" />
-            <input type="submit" class="btn btn-default" id="renewAll" name="renewAll" value="<?=$this->transEsc('renew_all')?>" />
-          </div>
+<div class="<?=$this->layoutClass('mainbody')?>">
+  <h2><?=$this->transEsc('Your Checked Out Items')?></h2>
+  <?=$this->flashmessages()?>
+
+  <?=$this->context($this)->renderInContext('librarycards/selectcard.phtml', ['user' => $this->auth()->isLoggedIn()]); ?>
+
+  <? if (!empty($this->transactions)): ?>
+    <? if ($this->renewForm): ?>
+    <form name="renewals" method="post" id="renewals">
+      <div class="toolbar">
+        <div class="checkbox">
+          <label>
+            <input type="checkbox" name="selectAll" class="checkbox-select-all"/>
+            <?=$this->transEsc('select_page')?>
+          </label>
+          <input type="submit" class="btn btn-default" id="renewSelected" name="renewSelected" value="<?=$this->transEsc("renew_selected")?>" />
+          <input type="submit" class="btn btn-default" id="renewAll" name="renewAll" value="<?=$this->transEsc('renew_all')?>" />
         </div>
-      <? endif; ?>
+      </div>
+    <? endif; ?>
 
-      <? if ($paginator): ?>
-        <?=$this->transEsc("Showing")?>
-        <? $start = $paginator->getAbsoluteItemNumber(1);
-           $end = $paginator->getAbsoluteItemNumber($paginator->getItemCountPerPage());
-           $total = $paginator->getTotalItemCount();
-        ?>
-        <strong><?=$this->localizedNumber($start)?></strong> - <strong><?=$this->localizedNumber($end > $total ? $total : $end)?></strong>
-        <?=$this->transEsc('of')?> <strong><?=$this->localizedNumber($total)?></strong>
-      <? endif; ?>
+    <? if ($paginator): ?>
+      <?
+        $end = min(
+          $paginator->getAbsoluteItemNumber($paginator->getItemCountPerPage()),
+          $paginator->getTotalItemCount()
+        );
+        $transParams = [
+          '%%start%%' => $this->localizedNumber($paginator->getAbsoluteItemNumber(1)),
+          '%%end%%'   => $this->localizedNumber($end),
+          '%%total%%' => $this->localizedNumber($paginator->getTotalItemCount())
+        ];
+      ?>
+      <?=$this->translate('showing_items_of_html', $transParams); ?>
+    <? endif; ?>
 
-      <? foreach ($hiddenTransactions as $ilsDetails): ?>
-        <? if (isset($this->renewResult[$ilsDetails['item_id']])): ?>
-          <? $renewDetails = $this->renewResult[$ilsDetails['item_id']]; ?>
-          <? $prefix = isset($ilsDetails['title']) ? $ilsDetails['title'] : $ilsDetails['item_id']; ?>
-          <? if (isset($renewDetails['success']) && $renewDetails['success']): ?>
-            <div class="alert alert-success"><?=$this->escapeHtml($prefix . ': ') . $this->transEsc('renew_success')?></div>
-          <? else: ?>
-            <div class="alert alert-danger"><?=$this->escapeHtml($prefix . ': ') . $this->transEsc('renew_fail')?><? if (isset($renewDetails['sysMessage'])): ?>: <?=$this->escapeHtml($renewDetails['sysMessage'])?><? endif; ?></div>
-          <? endif; ?>
-        <? endif; ?>
-        <? if (isset($ilsDetails['renewable']) && $ilsDetails['renewable'] && isset($ilsDetails['renew_details'])): ?>
-          <? $safeId = preg_replace('/[^a-zA-Z0-9]/', '', $ilsDetails['renew_details']); ?>
-          <input class="pull-left flip" type="hidden" name="renewAllIDS[]" value="<?=$this->escapeHtmlAttr($ilsDetails['renew_details'])?>" />
+    <? foreach ($hiddenTransactions as $ilsDetails): ?>
+      <? if (isset($this->renewResult[$ilsDetails['item_id']])): ?>
+        <? $renewDetails = $this->renewResult[$ilsDetails['item_id']]; ?>
+        <? $prefix = isset($ilsDetails['title']) ? $ilsDetails['title'] : $ilsDetails['item_id']; ?>
+        <? if (isset($renewDetails['success']) && $renewDetails['success']): ?>
+          <div class="alert alert-success"><?=$this->escapeHtml($prefix . ': ') . $this->transEsc('renew_success')?></div>
+        <? else: ?>
+          <div class="alert alert-danger"><?=$this->escapeHtml($prefix . ': ') . $this->transEsc('renew_fail')?><? if (isset($renewDetails['sysMessage'])): ?>: <?=$this->escapeHtml($renewDetails['sysMessage'])?><? endif; ?></div>
         <? endif; ?>
-      <? endforeach; ?>
-
-      <? $i = 0; foreach ($this->transactions as $resource): ?>
-        <hr/>
-        <? $ilsDetails = $resource->getExtraDetail('ils_details'); ?>
-        <div id="record<?=$this->escapeHtmlAttr($resource->getUniqueId())?>" class="row result">
-          <? if ($this->renewForm): ?>
-            <? if (isset($ilsDetails['renewable']) && $ilsDetails['renewable'] && isset($ilsDetails['renew_details'])): ?>
-              <? $safeId = preg_replace('/[^a-zA-Z0-9]/', '', $ilsDetails['renew_details']); ?>
-              <div class="col-xs-1">
+      <? endif; ?>
+      <? if (isset($ilsDetails['renewable']) && $ilsDetails['renewable'] && isset($ilsDetails['renew_details'])): ?>
+        <? $safeId = preg_replace('/[^a-zA-Z0-9]/', '', $ilsDetails['renew_details']); ?>
+        <input class="pull-left flip" type="hidden" name="renewAllIDS[]" value="<?=$this->escapeHtmlAttr($ilsDetails['renew_details'])?>" />
+      <? endif; ?>
+    <? endforeach; ?>
+
+    <? $i = 0; foreach ($this->transactions as $resource): ?>
+      <? $ilsDetails = $resource->getExtraDetail('ils_details'); ?>
+      <div id="record<?=$this->escapeHtmlAttr($resource->getUniqueId())?>" class="result">
+        <? if ($this->renewForm): ?>
+          <? if (isset($ilsDetails['renewable']) && $ilsDetails['renewable'] && isset($ilsDetails['renew_details'])): ?>
+            <? $safeId = preg_replace('/[^a-zA-Z0-9]/', '', $ilsDetails['renew_details']); ?>
+            <div class="checkbox">
+              <label>
                 <input class="checkbox-select-item" type="checkbox" name="renewSelectedIDS[]" value="<?=$this->escapeHtmlAttr($ilsDetails['renew_details'])?>" id="checkbox_<?=$safeId?>" />
-                <input type="hidden" name="selectAllIDS[]" value="<?=$this->escapeHtmlAttr($ilsDetails['renew_details'])?>" />
-                <input type="hidden" name="renewAllIDS[]" value="<?=$this->escapeHtmlAttr($ilsDetails['renew_details'])?>" />
-              </div>
-            <? endif; ?>
+              </label>
+              <input type="hidden" name="selectAllIDS[]" value="<?=$this->escapeHtmlAttr($ilsDetails['renew_details'])?>" />
+              <input type="hidden" name="renewAllIDS[]" value="<?=$this->escapeHtmlAttr($ilsDetails['renew_details'])?>" />
+            </div>
           <? endif; ?>
+        <? endif; ?>
 
-          <? $cover = $this->record($resource)->getCover('checkedout', 'small'); ?>
-          <? if ($cover): ?>
-            <div class="col-sm-2 col-xs-11 text-center">
-            <? /* Display thumbnail if appropriate: */ ?>
-              <?=$cover?>
+        <?
+          $coverDetails = $this->record($resource)->getCoverDetails('checkedout', 'small', $this->recordLink()->getUrl($resource));
+          $cover = $coverDetails['html'];
+          $thumbnail = false;
+          $thumbnailAlignment = $this->record($resource)->getThumbnailAlignment('account');
+          if ($cover):
+            ob_start(); ?>
+            <div class="media-<?=$thumbnailAlignment ?> <?=$this->escapeHtmlAttr($coverDetails['size'])?>">
+              <?=$cover ?>
             </div>
-
-            <div class="col-sm-6 col-xs-12">
-         <? else: ?>
-            <div class="col-sm-9">
-         <? endif; ?>
-
+            <? $thumbnail = ob_get_contents(); ?>
+          <? ob_end_clean(); ?>
+        <? endif; ?>
+        <div class="media">
+          <? if ($thumbnail && $thumbnailAlignment == 'left'): ?>
+            <?=$thumbnail ?>
+          <? endif ?>
+          <div class="media-body">
             <?
               // If this is a non-missing Solr record, we should display a link:
               if (is_a($resource, 'VuFind\\RecordDriver\\SolrDefault') && !is_a($resource, 'VuFind\\RecordDriver\\Missing')) {
@@ -115,12 +126,12 @@
             <? endif; ?>
 
             <? if (!empty($ilsDetails['institution_name']) && (empty($ilsDetails['borrowingLocation']) || $ilsDetails['institution_name'] != $ilsDetails['borrowingLocation'])): ?>
-              <strong><?=$this->transEsc('location_' . $ilsDetails['institution_name'], array(), $ilsDetails['institution_name'])?></strong>
+              <strong><?=$this->transEsc('location_' . $ilsDetails['institution_name'], [], $ilsDetails['institution_name'])?></strong>
               <br />
             <? endif; ?>
 
             <? if (!empty($ilsDetails['borrowingLocation'])): ?>
-              <strong><?=$this->transEsc('Borrowing Location')?>:</strong> <?=$this->transEsc('location_' . $ilsDetails['borrowingLocation'], array(), $ilsDetails['borrowingLocation'])?>
+              <strong><?=$this->transEsc('Borrowing Location')?>:</strong> <?=$this->transEsc('location_' . $ilsDetails['borrowingLocation'], [], $ilsDetails['borrowingLocation'])?>
               <br />
             <? endif; ?>
 
@@ -162,16 +173,19 @@
               <a href="<?=$this->escapeHtmlAttr($ilsDetails['renew_link'])?>"><?=$this->transEsc('renew_item')?></a>
             <? endif; ?>
           </div>
+          <? if ($thumbnail && $thumbnailAlignment == 'right'): ?>
+            <?=$thumbnail ?>
+          <? endif ?>
         </div>
-      <? endforeach; ?>
-      <? if ($this->renewForm): ?></form><? endif; ?>
-      <?=$paginator ? $this->paginationControl($paginator, 'Sliding', 'Helpers/pagination.phtml') : ''?>
-    <? else: ?>
-      <?=$this->transEsc('You do not have any items checked out')?>.
-    <? endif; ?>
-  </div>
+      </div>
+    <? endforeach; ?>
+    <? if ($this->renewForm): ?></form><? endif; ?>
+    <?=$paginator ? $this->paginationControl($paginator, 'Sliding', 'Helpers/pagination.phtml') : ''?>
+  <? else: ?>
+    <?=$this->transEsc('You do not have any items checked out')?>.
+  <? endif; ?>
+</div>
 
-  <div class="<?=$this->layoutClass('sidebar')?>">
-    <?=$this->context($this)->renderInContext("myresearch/menu.phtml", array('active' => 'checkedout'))?>
-  </div>
+<div class="<?=$this->layoutClass('sidebar')?>">
+  <?=$this->context($this)->renderInContext("myresearch/menu.phtml", ['active' => 'checkedout'])?>
 </div>
diff --git a/themes/bootstrap3/templates/myresearch/delete.phtml b/themes/bootstrap3/templates/myresearch/delete.phtml
index 6c138d756207ea36fa2e53f111e8fb4bf7ac43de..5829c92163ffab74bd47fe5848025d56172bdbcd 100644
--- a/themes/bootstrap3/templates/myresearch/delete.phtml
+++ b/themes/bootstrap3/templates/myresearch/delete.phtml
@@ -1,5 +1,5 @@
 <h2><?=$this->transEsc('delete_selected_favorites')?></h2>
- <form action="<?=$this->url('myresearch-delete')?>" method="post" name="bulkDelete" data-lightbox-onclose="VuFind.refreshPage();">
+ <form action="<?=$this->url('myresearch-delete')?>" method="post" name="bulkDelete" data-lightbox-onclose="VuFind.refreshPage">
   <div id="popupMessages"><?=$this->flashmessages()?></div>
   <div id="popupDetails">
     <? if (!$this->list): ?>
@@ -19,4 +19,4 @@
     <? endforeach; ?>
       <input type="hidden" name="listID" value="<?=$this->list?$this->escapeHtmlAttr($this->list->id):''?>" />
   </div>
-</form>
\ No newline at end of file
+</form>
diff --git a/themes/bootstrap3/templates/myresearch/edit.phtml b/themes/bootstrap3/templates/myresearch/edit.phtml
index 3ec402b3c166f48e56833f7dd05355a876d43140..24c42c84d58e7cc70104ed4ceaa02844c72e341a 100644
--- a/themes/bootstrap3/templates/myresearch/edit.phtml
+++ b/themes/bootstrap3/templates/myresearch/edit.phtml
@@ -4,14 +4,11 @@
 
   // Set up breadcrumbs:
   $this->layout()->breadcrumbs = '<li><a href="' . $this->url('myresearch-home') . '">' . $this->transEsc('Your Account') . '</a></li> <li class="active">' . $this->transEsc('Edit') . '</li>';
-
-  // Load Javascript dependencies into header:
-  $this->headScript()->appendFile("bulk_actions.js");
 ?>
 <div class="record">
   <h2><?=$this->escapeHtml($this->driver->getBreadcrumb())?></h2>
 
-  <form class="form-horizontal" method="post" name="editForm">
+  <form class="form-list-edit" method="post" name="editForm">
   <? if (empty($this->savedData)): ?>
     <p class="alert alert-info">
       <? if (isset($listFilter)): ?>
@@ -21,51 +18,43 @@
       <? endif; ?>
     </p>
   <? else: ?>
-    <? foreach ($this->savedData as $i=>$current): ?>
-      <fieldset>
-        <legend>
-          <a href="<?=$this->url('userList', array('id' => $current['listId'])) ?>?delete=<?=urlencode($this->driver->getUniqueId())?>&amp;source=<?=urlencode($this->driver->getSourceIdentifier())?>" id="<?=$this->escapeHtmlAttr($this->driver->getUniqueId())?>delete<?=$current['listId'] ?>" title="<?=$this->transEsc('confirm_delete')?>" class="close">&times;</a> <?=$this->transEsc('List') ?>: <?=$this->escapeHtml($current['listTitle'])?>
-        </legend>
-        <input type="hidden" name="lists[]" value="<?=$current['listId'] ?>"/>
-        <? if ($this->usertags()->getMode() !== 'disabled'): ?>
-          <div class="form-group">
-            <label class="col-sm-2 control-label" for="edit_tags<?=$current['listId'] ?>"><?=$this->transEsc('Tags') ?>:</label>
-            <div class="col-sm-10">
+    <div class="list-edit-container">
+      <? foreach ($this->savedData as $i=>$current): ?>
+        <fieldset class="list-edit-group">
+          <h3><?=$this->transEsc('List') ?>: <?=$this->escapeHtml($current['listTitle'])?></h3>
+          <input type="hidden" name="lists[]" value="<?=$current['listId'] ?>"/>
+          <? if ($this->usertags()->getMode() !== 'disabled'): ?>
+            <div class="form-group">
+              <label class="control-label" for="edit_tags<?=$current['listId'] ?>"><?=$this->transEsc('Tags') ?>:</label>
               <input type="text" name="tags<?=$current['listId'] ?>" id="edit_tags<?=$current['listId'] ?>" class="form-control" value="<?=$this->escapeHtmlAttr($current['tags'])?>"/>
               <span class="help-block"><?=$this->transEsc("add_tag_note") ?></span>
             </div>
-          </div>
-        <? endif; ?>
-        <div class="form-group">
-          <label class="col-sm-2 control-label" for="edit_notes<?=$current['listId'] ?>"><?=$this->transEsc('Notes') ?>:</label>
-          <div class="col-sm-10">
+          <? endif; ?>
+          <div class="form-group">
+            <label class="control-label" for="edit_notes<?=$current['listId'] ?>"><?=$this->transEsc('Notes') ?>:</label>
             <textarea class="form-control" id="edit_notes<?=$current['listId'] ?>" name="notes<?=$current['listId'] ?>" rows="3"><?=$this->escapeHtml($current['notes'])?></textarea>
           </div>
-        </div>
-      </fieldset>
-      <? if($i < count($this->savedData)-1): ?>
-        <hr/>
-      <? endif; ?>
-    <? endforeach; ?>
+          <a href="<?=$this->url('userList', ['id' => $current['listId']]) ?>?delete=<?=urlencode($this->driver->getUniqueId())?>&amp;source=<?=urlencode($this->driver->getSourceIdentifier())?>" id="<?=$this->escapeHtmlAttr($this->driver->getUniqueId())?>delete<?=$current['listId'] ?>" data-lightbox>
+            <i class="fa fa-trash"></i> <?=$this->transEsc('delete') /* TODO: replace with better string */ ?>
+          </a>
+        </fieldset>
+      <? endforeach; ?>
+    </div>
   <? endif; ?>
   <? if (count($this->lists) > 0): ?>
-    <hr />
+    <hr/>
     <div class="form-group">
-      <div class="col-sm-10 col-sm-offset-2">
-        <select name="addToList" class="form-control">
-          <option value="-1">- <?=$this->transEsc('Add to another list')?> -</option>
-          <? foreach ($this->lists as $listID=>$listTitle): ?>
-            <option value="<?=$listID ?>"><?=$this->escapeHtml($listTitle) ?></option>
-          <? endforeach; ?>
-        </select>
-      </div>
+      <select name="addToList" class="form-control">
+        <option value="-1">- <?=$this->transEsc('Add to another list')?> -</option>
+        <? foreach ($this->lists as $listID=>$listTitle): ?>
+          <option value="<?=$listID ?>"><?=$this->escapeHtml($listTitle) ?></option>
+        <? endforeach; ?>
+      </select>
     </div>
   <? endif; ?>
   <? if (!empty($this->savedData) || count($this->lists) > 0): ?>
     <div class="form-group">
-      <div class="col-sm-10 col-sm-offset-2">
-        <input class="btn btn-primary" type="submit" name="submit" value="<?=$this->transEsc('Save') ?>"/>
-      </div>
+      <input class="btn btn-primary" type="submit" name="submit" value="<?=$this->transEsc('Save') ?>"/>
     </div>
   <? endif; ?>
   </form>
diff --git a/themes/bootstrap3/templates/myresearch/editlist.phtml b/themes/bootstrap3/templates/myresearch/editlist.phtml
index 65c5c4c3e80f5d290c158938c553c39f1b4c8670..df9daf9b89fab281428b3edafae31a7a84ff1386 100644
--- a/themes/bootstrap3/templates/myresearch/editlist.phtml
+++ b/themes/bootstrap3/templates/myresearch/editlist.phtml
@@ -12,19 +12,15 @@
 
 <h2><?=$this->transEsc($pageTitle); ?></h2>
 
-<form class="form-horizontal edit-list-form" method="post" name="<?=empty($this->list->id) ? 'newList' : 'editListForm'?>">
+<form class="form-edit-list" method="post" name="<?=empty($this->list->id) ? 'newList' : 'editListForm'?>">
   <input type="hidden" name="id" value="<?=empty($this->list->id) ? 'NEW' : $this->list->id ?>"/>
   <div class="form-group">
-    <label class="col-sm-3 control-label" for="list_title"><?=$this->transEsc('List'); ?>:</label>
-    <div class="col-sm-9">
-      <input id="list_title" class="form-control" type="text" name="title" value="<?=isset($this->list['title']) ? $this->escapeHtml($this->list['title']) : ''?>"/>
-    </div>
+    <label class="control-label" for="list_title"><?=$this->transEsc('List'); ?>:</label>
+    <input id="list_title" class="form-control" type="text" name="title" value="<?=isset($this->list['title']) ? $this->escapeHtml($this->list['title']) : ''?>"/>
   </div>
   <div class="form-group">
-    <label class="col-sm-3 control-label" for="list_desc"><?=$this->transEsc('Description') ?></label>
-    <div class="col-sm-9">
-      <textarea id="list_desc" class="form-control" name="desc" rows="3"><?=isset($this->list['description']) ? $this->escapeHtml($this->list['description']) : ''?></textarea>
-    </div>
+    <label class="control-label" for="list_desc"><?=$this->transEsc('Description') ?></label>
+    <textarea id="list_desc" class="form-control" name="desc" rows="3"><?=isset($this->list['description']) ? $this->escapeHtml($this->list['description']) : ''?></textarea>
   </div>
   <? if ($this->userlist()->getMode() === 'public_only'): ?>
     <input type="hidden" name="public" value="1" />
@@ -32,24 +28,20 @@
     <input type="hidden" name="public" value="0" />
   <? else: ?>
     <div class="form-group">
-      <label class="col-sm-3 control-label"><?=$this->transEsc('Access') ?></label>
-      <div class="col-sm-9">
-        <div class="radio inline">
-          <label>
-            <input id="list_public_1" type="radio" name="public" value="1"<? if ($this->list->isPublic()): ?> checked="checked"<? endif; ?>/> <?=$this->transEsc('Public') ?>
-          </label>
-        </div>
-        <div class="radio inline">
-          <label>
-            <input id="list_public_0" type="radio" name="public" value="0"<? if (!$this->list->isPublic()): ?> checked="checked"<? endif; ?>/> <?=$this->transEsc('Private') ?>
-          </label>
-        </div>
+      <label class="control-label"><?=$this->transEsc('Access') ?></label>
+      <div class="radio inline">
+        <label>
+          <input id="list_public_1" type="radio" name="public" value="1"<? if ($this->list->isPublic()): ?> checked="checked"<? endif; ?>/> <?=$this->transEsc('Public') ?>
+        </label>
+      </div>
+      <div class="radio inline">
+        <label>
+          <input id="list_public_0" type="radio" name="public" value="0"<? if (!$this->list->isPublic()): ?> checked="checked"<? endif; ?>/> <?=$this->transEsc('Private') ?>
+        </label>
       </div>
     </div>
   <? endif; ?>
   <div class="form-group">
-    <div class="col-sm-9 col-sm-offset-3">
-      <input class="btn btn-primary" type="submit" name="submit" value="<?=$this->transEsc('Save') ?>"/>
-    </div>
+    <input class="btn btn-primary" type="submit" name="submit" value="<?=$this->transEsc('Save') ?>"/>
   </div>
 </form>
diff --git a/themes/bootstrap3/templates/myresearch/fines.phtml b/themes/bootstrap3/templates/myresearch/fines.phtml
index fc40cfd3353e165deb646b3bc17d7895f6a1f12d..e42726f1b52ffe38d07ca4dd8a9261d6cd648845 100644
--- a/themes/bootstrap3/templates/myresearch/fines.phtml
+++ b/themes/bootstrap3/templates/myresearch/fines.phtml
@@ -9,7 +9,7 @@
   <h2><?=$this->transEsc('Your Fines')?></h2>
   <?=$this->flashmessages()?>
 
-  <?=$this->context($this)->renderInContext('librarycards/selectcard.phtml', array('user' => $this->auth()->isLoggedIn())); ?>
+  <?=$this->context($this)->renderInContext('librarycards/selectcard.phtml', ['user' => $this->auth()->isLoggedIn()]); ?>
 
   <? if (empty($this->fines)): ?>
     <?=$this->transEsc('You do not have any fines')?>
@@ -49,5 +49,5 @@
 </div>
 
 <div class="<?=$this->layoutClass('sidebar')?>">
-  <?=$this->context($this)->renderInContext("myresearch/menu.phtml", array('active' => 'fines'))?>
-</div>
\ No newline at end of file
+  <?=$this->context($this)->renderInContext("myresearch/menu.phtml", ['active' => 'fines'])?>
+</div>
diff --git a/themes/bootstrap3/templates/myresearch/holds.phtml b/themes/bootstrap3/templates/myresearch/holds.phtml
index 7f0e5e95b8450eef11f4d7cb1b5ef35456269422..8d398115075fdf263253ead841b602797c8a67e4 100644
--- a/themes/bootstrap3/templates/myresearch/holds.phtml
+++ b/themes/bootstrap3/templates/myresearch/holds.phtml
@@ -1,68 +1,74 @@
 <?
-    // Set up page title:
-    $this->headTitle($this->translate('My Holds'));
+  // Set up page title:
+  $this->headTitle($this->translate('My Holds'));
 
-    // Set up breadcrumbs:
-    $this->layout()->breadcrumbs = '<li><a href="' . $this->url('myresearch-home') . '">' . $this->transEsc('Your Account') . '</a></li> <li class="active">' . $this->transEsc('My Holds') . '</li>';
+  // Set up breadcrumbs:
+  $this->layout()->breadcrumbs = '<li><a href="' . $this->url('myresearch-home') . '">' . $this->transEsc('Your Account') . '</a></li> <li class="active">' . $this->transEsc('My Holds') . '</li>';
 ?>
 
-<div class="row">
-  <div class="<?=$this->layoutClass('mainbody')?>">
-    <h2><?=$this->transEsc('Your Holds and Recalls') ?></h2>
-
-    <?=$this->flashmessages()?>
-
-    <?=$this->context($this)->renderInContext('librarycards/selectcard.phtml', array('user' => $this->auth()->isLoggedIn())); ?>
-
-    <? if (!empty($this->recordList)): ?>
-      <? if ($this->cancelForm): ?>
-        <form name="cancelForm" class="inline" method="post" id="cancelHold">
-          <input type="hidden" id="submitType" name="cancelSelected" value="1"/>
-          <input type="hidden" id="cancelConfirm" name="confirm" value="0"/>
-          <div class="btn-group">
-            <input id="cancelSelected" name="cancelSelected" type="submit" value="<?=$this->transEsc("hold_cancel_selected") ?>" class="btn btn-default dropdown-toggle" data-toggle="dropdown"/>
-            <ul class="dropdown-menu">
-              <li class="disabled"><a><?=$this->transEsc("confirm_hold_cancel_selected_text") ?></a></li>
-              <li><a href="#" onClick="$('#cancelConfirm').val(1);$('#submitType').attr('name','cancelSelected');$(this).parents('form').submit(); return false;"><?=$this->transEsc('confirm_dialog_yes') ?></a></li>
-              <li><a href="#" onClick="return false;"><?=$this->transEsc('confirm_dialog_no')?></a></li>
-            </ul>
-          </div>
-          <div class="btn-group">
-            <input id="cancelAll" name="cancelAll" type="submit" value="<?=$this->transEsc("hold_cancel_all") ?>" class="btn btn-default dropdown-toggle" data-toggle="dropdown"/>
-            <ul class="dropdown-menu">
-              <li class="disabled"><a><?=$this->transEsc("confirm_hold_cancel_all_text") ?></a></li>
-              <li><a href="#" onClick="$('#cancelConfirm').val(1);$('#submitType').attr('name','cancelAll');$(this).parents('form').submit(); return false;"><?=$this->transEsc('confirm_dialog_yes') ?></a></li>
-              <li><a href="#" onClick="return false;"><?=$this->transEsc('confirm_dialog_no')?></a></li>
-            </ul>
-          </div>
-      <? endif; ?>
+<div class="<?=$this->layoutClass('mainbody')?>">
+  <h2><?=$this->transEsc('Your Holds and Recalls') ?></h2>
+
+  <?=$this->flashmessages()?>
+
+  <?=$this->context($this)->renderInContext('librarycards/selectcard.phtml', ['user' => $this->auth()->isLoggedIn()]); ?>
+
+  <? if (!empty($this->recordList)): ?>
+    <? if ($this->cancelForm): ?>
+      <form name="cancelForm" class="inline" method="post" id="cancelHold">
+        <input type="hidden" id="submitType" name="cancelSelected" value="1"/>
+        <input type="hidden" id="cancelConfirm" name="confirm" value="0"/>
+        <div class="btn-group">
+          <input id="cancelSelected" name="cancelSelected" type="submit" value="<?=$this->transEsc("hold_cancel_selected") ?>" class="btn btn-default dropdown-toggle" data-toggle="dropdown"/>
+          <ul class="dropdown-menu">
+            <li class="disabled"><a><?=$this->transEsc("confirm_hold_cancel_selected_text") ?></a></li>
+            <li><a href="#" onClick="$('#cancelConfirm').val(1);$('#submitType').attr('name','cancelSelected');$(this).parents('form').submit(); return false;"><?=$this->transEsc('confirm_dialog_yes') ?></a></li>
+            <li><a href="#" onClick="return false;"><?=$this->transEsc('confirm_dialog_no')?></a></li>
+          </ul>
+        </div>
+        <div class="btn-group">
+          <input id="cancelAll" name="cancelAll" type="submit" value="<?=$this->transEsc("hold_cancel_all") ?>" class="btn btn-default dropdown-toggle" data-toggle="dropdown"/>
+          <ul class="dropdown-menu">
+            <li class="disabled"><a><?=$this->transEsc("confirm_hold_cancel_all_text") ?></a></li>
+            <li><a href="#" onClick="$('#cancelConfirm').val(1);$('#submitType').attr('name','cancelAll');$(this).parents('form').submit(); return false;"><?=$this->transEsc('confirm_dialog_yes') ?></a></li>
+            <li><a href="#" onClick="return false;"><?=$this->transEsc('confirm_dialog_no')?></a></li>
+          </ul>
+        </div>
+    <? endif; ?>
 
-      <? $iteration = 0; ?>
-      <? foreach ($this->recordList as $resource): ?>
-        <hr/>
-        <? $iteration++; ?>
-        <? $ilsDetails = $resource->getExtraDetail('ils_details'); ?>
-        <div id="record<?=$this->escapeHtmlAttr($resource->getUniqueId()) ?>" class="row result">
-          <? if ($this->cancelForm && isset($ilsDetails['cancel_details'])): ?>
-            <? $safeId = preg_replace('/[^a-zA-Z0-9]/', '', $resource->getUniqueId()); ?>
-            <input type="hidden" name="cancelAllIDS[]" value="<?=$this->escapeHtmlAttr($ilsDetails['cancel_details']) ?>" />
-            <div class="col-xs-1">
+    <? $iteration = 0; ?>
+    <? foreach ($this->recordList as $resource): ?>
+      <? $iteration++; ?>
+      <? $ilsDetails = $resource->getExtraDetail('ils_details'); ?>
+      <div id="record<?=$this->escapeHtmlAttr($resource->getUniqueId()) ?>" class="result">
+        <? if ($this->cancelForm && isset($ilsDetails['cancel_details'])): ?>
+          <? $safeId = preg_replace('/[^a-zA-Z0-9]/', '', $resource->getUniqueId()); ?>
+          <input type="hidden" name="cancelAllIDS[]" value="<?=$this->escapeHtmlAttr($ilsDetails['cancel_details']) ?>" />
+          <div class="checkbox">
+            <label>
               <input type="checkbox" name="cancelSelectedIDS[]" value="<?=$this->escapeHtmlAttr($ilsDetails['cancel_details']) ?>" id="checkbox_<?=$safeId?>" />
+            </label>
+          </div>
+        <? endif; ?>
+
+        <?
+          $coverDetails = $this->record($resource)->getCoverDetails('holds', 'small', $this->recordLink()->getUrl($resource));
+          $cover = $coverDetails['html'];
+          $thumbnail = false;
+          $thumbnailAlignment = $this->record($resource)->getThumbnailAlignment('account');
+          if ($cover):
+            ob_start(); ?>
+            <div class="media-<?=$thumbnailAlignment ?> <?=$this->escapeHtmlAttr($coverDetails['size'])?>">
+              <?=$cover ?>
             </div>
-          <? endif; ?>
-          <? $cover = $this->record($resource)->getCover('holds', 'small'); ?>
-          <? if ($cover): ?>
-            <div class="col-sm-2 col-xs-11 text-center">
-            <? /* Display thumbnail if appropriate: */ ?>
-            <? if($cover): ?>
-              <?=$cover?>
-            <? endif; ?>
-            </div>
-
-            <div class="col-sm-6 col-xs-12">
-         <? else: ?>
-            <div class="col-sm-9 col-xs-11">
-         <? endif; ?>
+            <? $thumbnail = ob_get_contents(); ?>
+          <? ob_end_clean(); ?>
+        <? endif; ?>
+        <div class="media">
+          <? if ($thumbnail && $thumbnailAlignment == 'left'): ?>
+            <?=$thumbnail ?>
+          <? endif ?>
+          <div class="media-body">
             <?
               // If this is a non-missing Solr record, we should display a link:
               if (is_a($resource, 'VuFind\\RecordDriver\\SolrDefault') && !is_a($resource, 'VuFind\\RecordDriver\\Missing')) {
@@ -72,7 +78,7 @@
                   . '" class="title">' . $title . '</a>';
               } else if (isset($ilsDetails['title']) && !empty($ilsDetails['title'])){
                 // If the record is not available in Solr, perhaps the ILS driver sent us a title we can show...
-                echo $this->escapeHtml($ilsDetails['title']);
+                echo '<span class="title">' . $this->escapeHtml($ilsDetails['title']) . '</span>';
               } else {
                 // Last resort -- indicate that no title could be found.
                 echo $this->transEsc('Title not available');
@@ -145,24 +151,26 @@
             <? if (isset($ilsDetails['available']) && $ilsDetails['available'] == true): ?>
               <div class="text-success"><?=$this->transEsc("hold_available") ?></div>
             <? elseif (isset($ilsDetails['in_transit']) && $ilsDetails['in_transit']): ?>
-              <div class="text-success"><?=$this->transEsc('request_in_transit') . (is_string($ilsDetails['in_transit']) ? ': ' . $this->transEsc('institution_' . $ilsDetails['in_transit'], array(), $ilsDetails['in_transit']) : '') ?></div>
+              <div class="text-success"><?=$this->transEsc('request_in_transit') . (is_string($ilsDetails['in_transit']) ? ': ' . $this->transEsc('institution_' . $ilsDetails['in_transit'], [], $ilsDetails['in_transit']) : '') ?></div>
             <? elseif (isset($ilsDetails['position'])): ?>
               <p><strong><?=$this->transEsc("hold_queue_position") ?>:</strong> <?=$this->escapeHtml($ilsDetails['position']) ?></p>
             <? endif; ?>
             <? if (isset($ilsDetails['cancel_link'])): ?>
               <p><a href="<?=$this->escapeHtmlAttr($ilsDetails['cancel_link']) ?>"><?=$this->transEsc("hold_cancel") ?></a></p>
             <? endif; ?>
-
           </div>
+          <? if ($thumbnail && $thumbnailAlignment == 'right'): ?>
+            <?=$thumbnail ?>
+          <? endif ?>
         </div>
-      <? endforeach; ?>
-      <? if ($this->cancelForm): ?></form><? endif; ?>
-    <? else: ?>
-      <?=$this->transEsc('You do not have any holds or recalls placed') ?>.
-    <? endif; ?>
-  </div>
+      </div>
+    <? endforeach; ?>
+    <? if ($this->cancelForm): ?></form><? endif; ?>
+  <? else: ?>
+    <?=$this->transEsc('You do not have any holds or recalls placed') ?>.
+  <? endif; ?>
+</div>
 
-  <div class="<?=$this->layoutClass('sidebar')?>">
-    <?=$this->context($this)->renderInContext("myresearch/menu.phtml", array('active' => 'holds'))?>
-  </div>
+<div class="<?=$this->layoutClass('sidebar')?>">
+  <?=$this->context($this)->renderInContext("myresearch/menu.phtml", ['active' => 'holds'])?>
 </div>
diff --git a/themes/bootstrap3/templates/myresearch/illrequests.phtml b/themes/bootstrap3/templates/myresearch/illrequests.phtml
index cfb1f3fd85472dc5dc2aff4655bdbabff441304c..56ee96b4811eeb896498f0134d10b3b01f656d06 100644
--- a/themes/bootstrap3/templates/myresearch/illrequests.phtml
+++ b/themes/bootstrap3/templates/myresearch/illrequests.phtml
@@ -6,64 +6,69 @@
     $this->layout()->breadcrumbs = '<li><a href="' . $this->url('myresearch-home') . '">' . $this->transEsc('Your Account') . '</a></li>'
         . '<li class="active">' . $this->transEsc('Interlibrary Loan Requests') . '</li>';
 ?>
+<div class="<?=$this->layoutClass('mainbody')?>">
+  <h2><?=$this->transEsc('Interlibrary Loan Requests') ?></h2>
 
-<div class="row">
-  <div class="<?=$this->layoutClass('mainbody')?>">
-    <h2><?=$this->transEsc('Interlibrary Loan Requests') ?></h2>
+  <?=$this->flashmessages()?>
 
-    <?=$this->flashmessages()?>
+  <?=$this->context($this)->renderInContext('librarycards/selectcard.phtml', ['user' => $this->auth()->isLoggedIn()]); ?>
 
-    <?=$this->context($this)->renderInContext('librarycards/selectcard.phtml', array('user' => $this->auth()->isLoggedIn())); ?>
-
-    <? if (!empty($this->recordList)): ?>
-      <? if ($this->cancelForm): ?>
-        <form name="cancelForm" class="inline" method="post" id="cancelILLRequest">
-          <input type="hidden" id="submitType" name="cancelSelected" value="1"/>
-          <input type="hidden" id="cancelConfirm" name="confirm" value="0"/>
-          <div class="btn-group">
-            <input id="cancelSelected" name="cancelSelected" type="submit" value="<?=$this->transEsc("ill_request_cancel_selected") ?>" class="btn btn-default dropdown-toggle" data-toggle="dropdown"/>
-            <ul class="dropdown-menu">
-              <li class="disabled"><a><?=$this->transEsc("confirm_ill_request_cancel_selected_text") ?></a></li>
-              <li><a href="#" onClick="$('#cancelConfirm').val(1);$('#submitType').attr('name','cancelSelected');$(this).parents('form').submit(); return false;"><?=$this->transEsc('confirm_dialog_yes') ?></a></li>
-              <li><a href="#" onClick="return false;"><?=$this->transEsc('confirm_dialog_no')?></a></li>
-            </ul>
-          </div>
-          <div class="btn-group">
-            <input id="cancelAll" name="cancelAll" type="submit" value="<?=$this->transEsc("ill_request_cancel_all") ?>" class="btn btn-default dropdown-toggle" data-toggle="dropdown"/>
-            <ul class="dropdown-menu">
-              <li class="disabled"><a><?=$this->transEsc("confirm_ill_request_cancel_all_text") ?></a></li>
-              <li><a href="#" onClick="$('#cancelConfirm').val(1);$('#submitType').attr('name','cancelAll');$(this).parents('form').submit(); return false;"><?=$this->transEsc('confirm_dialog_yes') ?></a></li>
-              <li><a href="#" onClick="return false;"><?=$this->transEsc('confirm_dialog_no')?></a></li>
-            </ul>
-          </div>
-      <? endif; ?>
+  <? if (!empty($this->recordList)): ?>
+    <? if ($this->cancelForm): ?>
+      <form name="cancelForm" class="inline" method="post" id="cancelILLRequest">
+        <input type="hidden" id="submitType" name="cancelSelected" value="1"/>
+        <input type="hidden" id="cancelConfirm" name="confirm" value="0"/>
+        <div class="btn-group">
+          <input id="cancelSelected" name="cancelSelected" type="submit" value="<?=$this->transEsc("ill_request_cancel_selected") ?>" class="btn btn-default dropdown-toggle" data-toggle="dropdown"/>
+          <ul class="dropdown-menu">
+            <li class="disabled"><a><?=$this->transEsc("confirm_ill_request_cancel_selected_text") ?></a></li>
+            <li><a href="#" onClick="$('#cancelConfirm').val(1);$('#submitType').attr('name','cancelSelected');$(this).parents('form').submit(); return false;"><?=$this->transEsc('confirm_dialog_yes') ?></a></li>
+            <li><a href="#" onClick="return false;"><?=$this->transEsc('confirm_dialog_no')?></a></li>
+          </ul>
+        </div>
+        <div class="btn-group">
+          <input id="cancelAll" name="cancelAll" type="submit" value="<?=$this->transEsc("ill_request_cancel_all") ?>" class="btn btn-default dropdown-toggle" data-toggle="dropdown"/>
+          <ul class="dropdown-menu">
+            <li class="disabled"><a><?=$this->transEsc("confirm_ill_request_cancel_all_text") ?></a></li>
+            <li><a href="#" onClick="$('#cancelConfirm').val(1);$('#submitType').attr('name','cancelAll');$(this).parents('form').submit(); return false;"><?=$this->transEsc('confirm_dialog_yes') ?></a></li>
+            <li><a href="#" onClick="return false;"><?=$this->transEsc('confirm_dialog_no')?></a></li>
+          </ul>
+        </div>
+    <? endif; ?>
 
-      <? $iteration = 0; ?>
-      <? foreach ($this->recordList as $resource): ?>
-        <hr/>
-        <? $iteration++; ?>
-        <? $ilsDetails = $resource->getExtraDetail('ils_details'); ?>
-        <div id="record<?=$this->escapeHtmlAttr($resource->getUniqueId()) ?>" class="row result">
-          <? if ($this->cancelForm && isset($ilsDetails['cancel_details'])): ?>
-            <? $safeId = preg_replace('/[^a-zA-Z0-9]/', '', $resource->getUniqueId()); ?>
+    <? $iteration = 0; ?>
+    <? foreach ($this->recordList as $resource): ?>
+      <? $iteration++; ?>
+      <? $ilsDetails = $resource->getExtraDetail('ils_details'); ?>
+      <div id="record<?=$this->escapeHtmlAttr($resource->getUniqueId()) ?>" class="result">
+        <? if ($this->cancelForm && isset($ilsDetails['cancel_details'])): ?>
+          <? $safeId = preg_replace('/[^a-zA-Z0-9]/', '', $resource->getUniqueId()); ?>
+          <div class="checkbox">
             <input type="hidden" name="cancelAllIDS[]" value="<?=$this->escapeHtmlAttr($ilsDetails['cancel_details']) ?>" />
-            <div class="pull-left flip">
+            <label>
               <input type="checkbox" name="cancelSelectedIDS[]" value="<?=$this->escapeHtmlAttr($ilsDetails['cancel_details']) ?>" id="checkbox_<?=$safeId?>" />
-            </div>
-          <? endif; ?>
-          <? $cover = $this->record($resource)->getCover('illrequests', 'small'); ?>
-          <? if ($cover): ?>
-            <div class="col-sm-2 text-center">
-            <? /* Display thumbnail if appropriate: */ ?>
-            <? if($cover): ?>
-              <?=$cover?>
-            <? endif; ?>
-            </div>
+            </label>
+          </div>
+        <? endif; ?>
 
-            <div class="col-sm-6">
-         <? else: ?>
-            <div class="col-sm-9">
-         <? endif; ?>
+        <?
+          $coverDetails = $this->record($resource)->getCoverDetails('illrequests', 'small', $this->recordLink()->getUrl($resource));
+          $cover = $coverDetails['html'];
+          $thumbnail = false;
+          $thumbnailAlignment = $this->record($resource)->getThumbnailAlignment('account');
+          if ($cover):
+            ob_start(); ?>
+            <div class="media-<?=$thumbnailAlignment ?> <?=$this->escapeHtmlAttr($coverDetails['size'])?>">
+              <?=$cover ?>
+            </div>
+            <? $thumbnail = ob_get_contents(); ?>
+          <? ob_end_clean(); ?>
+        <? endif; ?>
+        <div class="media">
+          <? if ($thumbnail && $thumbnailAlignment == 'left'): ?>
+            <?=$thumbnail ?>
+          <? endif ?>
+          <div class="media-body">
             <?
               // If this is a non-missing Solr record, we should display a link:
               if (is_a($resource, 'VuFind\\RecordDriver\\SolrDefault') && !is_a($resource, 'VuFind\\RecordDriver\\Missing')) {
@@ -139,7 +144,7 @@
             <? endif; ?>
 
             <? if (isset($ilsDetails['in_transit']) && $ilsDetails['in_transit']): ?>
-              <div class="text-success"><?=$this->transEsc("request_in_transit") . (is_string($ilsDetails['in_transit']) ? ': ' . $this->transEsc('institution_' . $ilsDetails['in_transit'], array(), $ilsDetails['in_transit']) : '') ?></div>
+              <div class="text-success"><?=$this->transEsc("request_in_transit") . (is_string($ilsDetails['in_transit']) ? ': ' . $this->transEsc('institution_' . $ilsDetails['in_transit'], [], $ilsDetails['in_transit']) : '') ?></div>
             <? endif; ?>
             <? if (isset($ilsDetails['processed']) && $ilsDetails['processed']): ?>
               <div class="text-success"><?=$this->transEsc("ill_request_processed") . (is_string($ilsDetails['processed']) ? ': ' . $ilsDetails['processed'] : '') ?></div>
@@ -153,17 +158,19 @@
             <? if (isset($ilsDetails['cancel_link'])): ?>
               <p><a href="<?=$this->escapeHtmlAttr($ilsDetails['cancel_link']) ?>"><?=$this->transEsc("ill_request_cancel") ?></a></p>
             <? endif; ?>
-
           </div>
+          <? if ($thumbnail && $thumbnailAlignment == 'right'): ?>
+            <?=$thumbnail ?>
+          <? endif ?>
         </div>
-      <? endforeach; ?>
-      <? if ($this->cancelForm): ?></form><? endif; ?>
-    <? else: ?>
-      <?=$this->transEsc('You do not have any interlibrary loan requests placed') ?>.
-    <? endif; ?>
-  </div>
+      </div>
+    <? endforeach; ?>
+    <? if ($this->cancelForm): ?></form><? endif; ?>
+  <? else: ?>
+    <?=$this->transEsc('You do not have any interlibrary loan requests placed') ?>.
+  <? endif; ?>
+</div>
 
-  <div class="<?=$this->layoutClass('sidebar')?>">
-    <?=$this->context($this)->renderInContext("myresearch/menu.phtml", array('active' => 'ILLRequests'))?>
-  </div>
+<div class="<?=$this->layoutClass('sidebar')?>">
+  <?=$this->context($this)->renderInContext("myresearch/menu.phtml", ['active' => 'ILLRequests'])?>
 </div>
diff --git a/themes/bootstrap3/templates/myresearch/menu.phtml b/themes/bootstrap3/templates/myresearch/menu.phtml
index 33dea93d5d457efd5e45cb1f7c45edb81ab85eda..d18f946883cced1832a41d46a580f32a59e8087e 100644
--- a/themes/bootstrap3/templates/myresearch/menu.phtml
+++ b/themes/bootstrap3/templates/myresearch/menu.phtml
@@ -1,80 +1,80 @@
 <h4><?=$this->transEsc('Your Account')?></h4>
-<div class="list-group">
+<div class="myresearch-menu">
   <? if ($this->userlist()->getMode() !== 'disabled'): ?>
-    <a href="<?=$this->url('myresearch-favorites')?>" class="list-group-item<?=$this->active == 'favorites' ? ' active' : ''?>">
+    <a href="<?=$this->url('myresearch-favorites')?>"<?=$this->active == 'favorites' ? ' class="active"' : ''?>>
       <i class="fa fa-fw fa-star" aria-hidden="true"></i> <?=$this->transEsc('Favorites')?>
     </a>
   <? endif; ?>
   <? if ('ils-none' !== $this->ils()->getOfflineMode()): ?>
     <? if ($this->ils()->checkCapability('getMyTransactions')): ?>
-      <a href="<?=$this->url('myresearch-checkedout')?>" class="list-group-item<?=$this->active == 'checkedout' ? ' active' : ''?>">
+      <a href="<?=$this->url('myresearch-checkedout')?>"<?=$this->active == 'checkedout' ? ' class="active"' : ''?>">
         <i class="fa fa-fw fa-book" aria-hidden="true"></i> <?=$this->transEsc('Checked Out Items')?>
       </a>
     <? endif; ?>
     <? if ($this->ils()->checkCapability('getMyHolds')): ?>
-      <a href="<?=$this->url('myresearch-holds')?>" class="list-group-item<?=$this->active == 'holds' ? ' active' : ''?>">
+      <a href="<?=$this->url('myresearch-holds')?>"<?=$this->active == 'holds' ? ' class="active"' : ''?>">
         <i class="fa fa-fw fa-flag" aria-hidden="true"></i> <?=$this->transEsc('Holds and Recalls')?>
       </a>
     <? endif; ?>
     <? if ($this->ils()->checkFunction('StorageRetrievalRequests')): ?>
-      <a href="<?=$this->url('myresearch-storageretrievalrequests')?>" class="list-group-item<?=$this->active == 'storageRetrievalRequests' ? ' active' : ''?>">
+      <a href="<?=$this->url('myresearch-storageretrievalrequests')?>"<?=$this->active == 'storageRetrievalRequests' ? ' class="active"' : ''?>">
         <i class="fa fa-fw fa-archive" aria-hidden="true"></i> <?=$this->transEsc('Storage Retrieval Requests')?>
       </a>
     <? endif; ?>
     <? if ($this->ils()->checkFunction('ILLRequests')): ?>
-    <a href="<?=$this->url('myresearch-illrequests')?>" class="list-group-item<?=$this->active == 'ILLRequests' ? ' active' : ''?>">
+    <a href="<?=$this->url('myresearch-illrequests')?>"<?=$this->active == 'ILLRequests' ? ' class="active"' : ''?>">
       <i class="fa fa-fw fa-exchange" aria-hidden="true"></i> <?=$this->transEsc('Interlibrary Loan Requests')?>
     </a>
     <? endif; ?>
     <? if ($this->ils()->checkCapability('getMyFines')): ?>
-      <a href="<?=$this->url('myresearch-fines')?>" class="list-group-item<?=$this->active == 'fines' ? ' active' : ''?>">
+      <a href="<?=$this->url('myresearch-fines')?>"<?=$this->active == 'fines' ? ' class="active"' : ''?>">
         <i class="fa fa-fw fa-usd" aria-hidden="true"></i> <?=$this->transEsc('Fines')?>
       </a>
     <? endif; ?>
     <? if ($this->ils()->checkCapability('getMyProfile')): ?>
-      <a href="<?=$this->url('myresearch-profile')?>" class="list-group-item<?=$this->active == 'profile' ? ' active' : ''?>">
+      <a href="<?=$this->url('myresearch-profile')?>"<?=$this->active == 'profile' ? ' class="active"' : ''?>">
         <i class="fa fa-fw fa-user" aria-hidden="true"></i> <?=$this->transEsc('Profile')?>
       </a>
     <? endif; ?>
     <? $user = $this->auth()->isLoggedIn(); if ($user && $user->libraryCardsEnabled()): ?>
-      <a href="<?=$this->url('librarycards-home')?>" class="list-group-item<?=$this->active == 'librarycards' ? ' active' : ''?>">
+      <a href="<?=$this->url('librarycards-home')?>"<?=$this->active == 'librarycards' ? ' class="active"' : ''?>">
         <i class="fa fa-fw fa-barcode" aria-hidden="true"></i> <?=$this->transEsc('Library Cards')?>
       </a>
     <? endif; ?>
   <? endif; ?>
   <? if ($this->accountCapabilities()->getSavedSearchSetting() === 'enabled'): ?>
-    <a href="<?=$this->url('search-history')?>?require_login" class="list-group-item<?=$this->active == 'history' ? ' active' : ''?>">
+    <a href="<?=$this->url('search-history')?>?require_login"<?=$this->active == 'history' ? ' class="active"' : ''?>">
       <i class="fa fa-fw fa-search" aria-hidden="true"></i> <?=$this->transEsc('history_saved_searches')?>
     </a>
   <? endif; ?>
   <? if ($user = $this->auth()->isLoggedIn()): ?>
-    <a href="<?=$this->url('myresearch-logout')?>" class="list-group-item">
+    <a href="<?=$this->url('myresearch-logout')?>">
       <i class="fa fa-fw fa-sign-out" aria-hidden="true"></i> <?=$this->transEsc("Log Out")?>
     </a>
   <? endif; ?>
 </div>
 <? if ($this->auth()->isLoggedIn() && $this->auth()->getManager()->supportsPasswordChange()): ?>
   <h4><?=$this->transEsc('Preferences')?></h4>
-  <div class="list-group">
-    <a href="<?=$this->url('myresearch-changepassword') ?>" class="list-group-item<?=$this->active == 'newpassword' ? ' active' : ''?>">
+  <div class="myresearch-menu">
+    <a href="<?=$this->url('myresearch-changepassword') ?>"<?=$this->active == 'newpassword' ? ' class="active"' : ''?>">
       <i class="fa fa-fw fa-lock" aria-hidden="true"></i> <?=$this->transEsc('Change Password') ?>
     </a>
   </div>
 <? endif; ?>
 <? if ($this->userlist()->getMode() !== 'disabled' && $user = $this->auth()->isLoggedIn()): ?>
   <h4><?=$this->transEsc('Your Lists')?></h4>
-  <div class="list-group">
-    <a href="<?=$this->url('myresearch-favorites')?>" class="list-group-item<?=$this->active == 'favorites' ? ' active' : ''?>">
+  <div class="myresearch-menu">
+    <a href="<?=$this->url('myresearch-favorites')?>"<?=$this->active == 'favorites' ? ' class="active"' : ''?>">
       <i class="fa fa-fw fa-star" aria-hidden="true"></i> <?=$this->transEsc('Your Favorites')?>
     </a>
     <? $lists = $user->getLists() ?>
     <? foreach ($lists as $list): ?>
-        <a href="<?=$this->url('userList', array('id' => $list['id']))?>" class="list-group-item<?=$this->active == 'list' . $list['id'] ? ' active' : ''?>">
-          <?=$this->escapeHtml($list['title'])?>
-          <span class="badge"><?=$list->cnt?></span>
-        </a>
+      <a href="<?=$this->url('userList', ['id' => $list['id']])?>"<?=$this->active == 'list' . $list['id'] ? ' class="active"' : ''?>">
+        <?=$this->escapeHtml($list['title'])?>
+        <span class="badge"><?=$list->cnt ?></span>
+      </a>
     <? endforeach; ?>
-    <a href="<?=$this->url('editList', array('id'=>'NEW'))?>" class="list-group-item">
+    <a href="<?=$this->url('editList', ['id'=>'NEW'])?>">
       <i class="fa fa-fw fa-plus" aria-hidden="true"></i> <?=$this->transEsc('Create a List') ?>
     </a>
   </div>
diff --git a/themes/bootstrap3/templates/myresearch/mylist.phtml b/themes/bootstrap3/templates/myresearch/mylist.phtml
index df9aae819b5691b0198f9019faf019024385f915..0c3ace56786c59de887c0aa615b78c8a4087030d 100644
--- a/themes/bootstrap3/templates/myresearch/mylist.phtml
+++ b/themes/bootstrap3/templates/myresearch/mylist.phtml
@@ -27,57 +27,61 @@
 
 <?=$this->flashmessages()?>
 
-<div class="row">
-  <div class="<?=$this->layoutClass('mainbody')?>">
-    <div class="clearfix hidden-print">
-      <h2 class="pull-left flip"><?=$list ? $this->escapeHtml($list->title) : $this->transEsc("Your Favorites")?></h2>
-      <div class="pull-right flip">
-        <? if (isset($list)): ?>
-          <? if ($list->editAllowed($account->isLoggedIn())): ?>
-            <a href="<?=$this->url('editList', array('id' => $list->id)) ?>" class="btn btn-link"><i class="fa fa-edit" aria-hidden="true"></i> <?=$this->transEsc("edit_list")?></a>
-            <div class="btn-group">
-              <a class="btn btn-link dropdown-toggle" data-toggle="dropdown" href="<?=$this->url('myresearch-deletelist') ?>?listID=<?=urlencode($list->id)?>">
-                <i class="fa fa-trash-o" aria-hidden="true"></i> <?=$this->transEsc("delete_list")?>
-              </a>
-              <ul class="dropdown-menu">
-                <li><a href="<?=$this->url('myresearch-deletelist') ?>?listID=<?=urlencode($list->id)?>&amp;confirm=1"><?=$this->transEsc('confirm_dialog_yes') ?></a></li>
-                <li><a href="#"><?=$this->transEsc('confirm_dialog_no')?></a></li>
-              </ul>
-            </div>
-          <? endif; ?>
-        <? elseif ($recordTotal > 0): ?>
-          <?=$this->transEsc("Showing")?>
-          <strong><?=$this->localizedNumber($this->results->getStartRecord())?></strong> - <strong><?=$this->localizedNumber($this->results->getEndRecord())?></strong>
-          <?=$this->transEsc('of')?> <strong><?=$this->localizedNumber($recordTotal)?></strong>
+<div class="<?=$this->layoutClass('mainbody')?>">
+  <h2><?=$list ? $this->escapeHtml($list->title) : $this->transEsc("Your Favorites")?></h2>
+  <nav class="search-header hidden-print">
+    <div class="search-stats">
+      <? if ($recordTotal > 0): ?>
+        <?
+          $transParams = [
+            '%%start%%' => $this->localizedNumber($this->results->getStartRecord()),
+            '%%end%%'   => $this->localizedNumber($this->results->getEndRecord()),
+            '%%total%%' => $this->localizedNumber($recordTotal)
+          ];
+        ?>
+        <?=$this->translate('showing_items_of_html', $transParams); ?>
+      <? endif; ?>
+    </div>
+    <div class="search-controls">
+      <? if (isset($list)): ?>
+        <? if ($list->editAllowed($account->isLoggedIn())): ?>
+          <a href="<?=$this->url('editList', ['id' => $list->id]) ?>" class="btn btn-link"><i class="fa fa-edit" aria-hidden="true"></i> <?=$this->transEsc("edit_list")?></a>
+          <div class="btn-group">
+            <a class="btn btn-link dropdown-toggle" data-toggle="dropdown" href="<?=$this->url('myresearch-deletelist') ?>?listID=<?=urlencode($list->id)?>">
+              <i class="fa fa-trash-o" aria-hidden="true"></i> <?=$this->transEsc("delete_list")?>
+            </a>
+            <ul class="dropdown-menu">
+              <li><a href="<?=$this->url('myresearch-deletelist') ?>?listID=<?=urlencode($list->id)?>&amp;confirm=1"><?=$this->transEsc('confirm_dialog_yes') ?></a></li>
+              <li><a href="#"><?=$this->transEsc('confirm_dialog_no')?></a></li>
+            </ul>
+          </div>
         <? endif; ?>
-      </div>
+      <? endif; ?>
+      <? if ($recordTotal > 0): ?>
+        <?=$this->render('search/controls/limit.phtml')?>
+        <?=$this->render('search/controls/sort.phtml')?>
+      <? endif; ?>
     </div>
+  </nav>
   <? if ($list && !empty($list->description)): ?>
     <p><?=$this->escapeHtml($list->description)?></p>
   <? endif; ?>
-    <? if ($recordTotal > 0): ?>
-      <div class="resulthead">
-        <div class="pull-right flip">
-          <?=$this->render('search/controls/limit.phtml')?>
-          <?=$this->render('search/controls/sort.phtml')?>
-        </div>
-      </div>
-      <form class="form-inline" method="post" name="bulkActionForm" action="<?=$this->url('cart-myresearchbulk')?>" data-lightbox data-lightbox-onsubmit="bulkFormHandler">
-        <?=$this->context($this)->renderInContext('myresearch/bulk-action-buttons.phtml', array('idPrefix' => '', 'list' => isset($list) ? $list : null, 'account' => $this->account))?>
-        <? foreach ($this->results->getResults() as $i=>$current): ?>
-          <?=$this->record($current)->getListEntry($list, $user)?>
-        <? endforeach; ?>
-      </form>
-      <?=$this->paginationControl($this->results->getPaginator(), 'Sliding', 'search/pagination.phtml', array('results' => $this->results))?>
-    <? else: ?>
-      <p><?=$this->transEsc('You do not have any saved resources')?></p>
-    <? endif; ?>
-  </div>
+  <? if ($recordTotal > 0): ?>
+    <form class="form-inline" method="post" name="bulkActionForm" action="<?=$this->url('cart-myresearchbulk')?>" data-lightbox data-lightbox-onsubmit="bulkFormHandler">
+      <?=$this->context($this)->renderInContext('myresearch/bulk-action-buttons.phtml', ['idPrefix' => '', 'list' => isset($list) ? $list : null, 'account' => $this->account])?>
+      <? foreach ($this->results->getResults() as $i=>$current): ?>
+        <?=$this->record($current)->getListEntry($list, $user)?>
+      <? endforeach; ?>
+    </form>
+    <?=$this->paginationControl($this->results->getPaginator(), 'Sliding', 'search/pagination.phtml', ['results' => $this->results])?>
+  <? else: ?>
+    <p><?=$this->transEsc('You do not have any saved resources')?></p>
+  <? endif; ?>
+</div>
 
-  <div class="<?=$this->layoutClass('sidebar')?>">
-    <?=$this->context($this)->renderInContext("myresearch/menu.phtml", array('active' => isset($list) ? 'list' . $list['id'] : 'favorites'))?>
-    <? foreach ($this->results->getRecommendations('side') as $current): ?>
-      <?=$this->recommend($current)?>
-    <? endforeach; ?>
-  </div>
+<div class="<?=$this->layoutClass('sidebar')?>">
+  <?=$this->context($this)->renderInContext("myresearch/menu.phtml", ['active' => isset($list) ? 'list' . $list['id'] : 'favorites'])?>
+  <? foreach ($this->results->getRecommendations('side') as $current): ?>
+    <?=$this->recommend($current)?>
+  <? endforeach; ?>
 </div>
diff --git a/themes/bootstrap3/templates/myresearch/newpassword.phtml b/themes/bootstrap3/templates/myresearch/newpassword.phtml
index 8391573200f32efa7bbaee5009be4b316f491007..efe13c906c5f563cdcc3969d416c868cf1483964 100644
--- a/themes/bootstrap3/templates/myresearch/newpassword.phtml
+++ b/themes/bootstrap3/templates/myresearch/newpassword.phtml
@@ -7,8 +7,7 @@
         . '<li class="active">' . $this->transEsc('Create New Password') . '</li>';
 ?>
 <? if ($this->auth()->isLoggedIn()): ?>
-  <div class="row">
-    <div class="<?=$this->layoutClass('mainbody')?>">
+  <div class="<?=$this->layoutClass('mainbody')?>">
 <? endif; ?>
 
 <h2><?=$this->transEsc('Create New Password') ?></h2>
@@ -19,7 +18,7 @@
 <? elseif (!isset($this->hash)): ?>
   <div class="error"><?=$this->transEsc('recovery_user_not_found') ?></div>
 <? else: ?>
-  <form id="newpassword" class="form-horizontal" action="<?=$this->url('myresearch-newpassword') ?>" method="post" data-toggle="validator" role="form">
+  <form id="newpassword" class="form-new-password" action="<?=$this->url('myresearch-newpassword') ?>" method="post" data-toggle="validator" role="form">
     <input type="hidden" value="<?=$this->escapeHtmlAttr($this->auth()->getManager()->getCsrfHash(true))?>" name="csrf"/>
     <input type="hidden" value="<?=$this->escapeHtmlAttr($this->hash) ?>" name="hash"/>
     <input type="hidden" value="<?=$this->escapeHtmlAttr($this->username) ?>" name="username"/>
@@ -27,17 +26,14 @@
     <?=$this->auth()->getNewPasswordForm() ?>
     <?=$this->recaptcha()->html($this->useRecaptcha) ?>
     <div class="form-group">
-      <div class="col-sm-9 col-sm-offset-3">
-        <input class="btn btn-primary" name="submit" type="submit" value="<?=$this->transEsc('Submit')?>" />
-      </div>
+      <input class="btn btn-primary" name="submit" type="submit" value="<?=$this->transEsc('Submit')?>" />
     </div>
   </form>
 <? endif; ?>
 
 <? if ($this->auth()->isLoggedIn()): ?>
-    </div>
-    <div class="<?=$this->layoutClass('sidebar')?>">
-      <?=$this->context($this)->renderInContext("myresearch/menu.phtml", array('active' => 'newpassword'))?>
-    </div>
+  </div>
+  <div class="<?=$this->layoutClass('sidebar')?>">
+    <?=$this->context($this)->renderInContext("myresearch/menu.phtml", ['active' => 'newpassword'])?>
   </div>
 <? endif; ?>
diff --git a/themes/bootstrap3/templates/myresearch/profile.phtml b/themes/bootstrap3/templates/myresearch/profile.phtml
index 24a25874fc6f3f278bfccbde3147b3968bd006b9..f7aac31e3bdf1676bad823c01de707a695301128 100644
--- a/themes/bootstrap3/templates/myresearch/profile.phtml
+++ b/themes/bootstrap3/templates/myresearch/profile.phtml
@@ -11,59 +11,56 @@
     // Template for use by the renderArray helper:
     $arrTemplate = '<tr><th>%%LABEL%%:</th><td> %%VALUE%%</td></tr>';
 ?>
+<div class="<?=$this->layoutClass('mainbody')?>">
+  <h2><?=$this->transEsc('Your Profile')?></h2>
+  <?=$this->flashmessages();?>
 
-<div class="row">
-  <div class="<?=$this->layoutClass('mainbody')?>">
-    <h2><?=$this->transEsc('Your Profile')?></h2>
-    <?=$this->flashmessages();?>
+  <?=$this->context($this)->renderInContext('librarycards/selectcard.phtml', ['user' => $this->auth()->isLoggedIn()]); ?>
 
-    <?=$this->context($this)->renderInContext('librarycards/selectcard.phtml', array('user' => $this->auth()->isLoggedIn())); ?>
-
-    <table class="table table-striped">
-      <?
-        echo $this->renderArray(
-          $arrTemplate, $this->profile,
-          array(
-            $this->transEsc('First Name') => 'firstname',
-            $this->transEsc('Last Name') => 'lastname'
-          )
-        );
-       ?>
-      <? if ($showHomeLibForm): ?>
-        <tr><th><?=$this->transEsc('Preferred Library')?>:</th>
-        <?
-          $selected = (isset($this->profile['home_library']) && $this->profile['home_library'] != "")
-              ? $this->profile['home_library'] : $this->defaultPickupLocation
-        ?>
-        <td>
-          <form id="profile_form" class="form-inline" method="post">
-            <select id="home_library" name="home_library" class="form-control">
-              <? foreach ($this->pickup as $lib): ?>
-                <option value="<?=$this->escapeHtmlAttr($lib['locationID'])?>"<?=($selected == $lib['locationID'])?' selected="selected"':''?>><?=$this->transEsc('location_' . $lib['locationDisplay'], null, $lib['locationDisplay'])?></option>
-              <? endforeach; ?>
-            </select>
-            <input class="btn btn-default" type="submit" value="<?=$this->transEsc('Save')?>" />
-          </form>
-        </td>
-      <? endif; ?>
+  <table class="table table-striped">
+    <?
+      echo $this->renderArray(
+        $arrTemplate, $this->profile,
+        [
+          $this->transEsc('First Name') => 'firstname',
+          $this->transEsc('Last Name') => 'lastname'
+        ]
+      );
+     ?>
+    <? if ($showHomeLibForm): ?>
+      <tr><th><?=$this->transEsc('Preferred Library')?>:</th>
       <?
-        echo $this->renderArray(
-          $arrTemplate, $this->profile,
-          array(
-            $this->transEsc('Address') . ' 1' => 'address1',
-            $this->transEsc('Address') . ' 2' => 'address2',
-            $this->transEsc('Zip') => 'zip',
-            $this->transEsc('City') => 'city',
-            $this->transEsc('Country') => 'country',
-            $this->transEsc('Phone Number') => 'phone',
-            $this->transEsc('Group') => 'group'
-          )
-        );
+        $selected = (isset($this->profile['home_library']) && $this->profile['home_library'] != "")
+            ? $this->profile['home_library'] : $this->defaultPickupLocation
       ?>
-    </table>
-  </div>
+      <td>
+        <form id="profile_form" class="form-inline" method="post">
+          <select id="home_library" name="home_library" class="form-control">
+            <? foreach ($this->pickup as $lib): ?>
+              <option value="<?=$this->escapeHtmlAttr($lib['locationID'])?>"<?=($selected == $lib['locationID'])?' selected="selected"':''?>><?=$this->transEsc('location_' . $lib['locationDisplay'], null, $lib['locationDisplay'])?></option>
+            <? endforeach; ?>
+          </select>
+          <input class="btn btn-default" type="submit" value="<?=$this->transEsc('Save')?>" />
+        </form>
+      </td>
+    <? endif; ?>
+    <?
+      echo $this->renderArray(
+        $arrTemplate, $this->profile,
+        [
+          $this->transEsc('Address') . ' 1' => 'address1',
+          $this->transEsc('Address') . ' 2' => 'address2',
+          $this->transEsc('Zip') => 'zip',
+          $this->transEsc('City') => 'city',
+          $this->transEsc('Country') => 'country',
+          $this->transEsc('Phone Number') => 'phone',
+          $this->transEsc('Group') => 'group'
+        ]
+      );
+    ?>
+  </table>
+</div>
 
-  <div class="<?=$this->layoutClass('sidebar')?>">
-    <?=$this->context($this)->renderInContext("myresearch/menu.phtml", array('active' => 'profile'))?>
-  </div>
-</div>
\ No newline at end of file
+<div class="<?=$this->layoutClass('sidebar')?>">
+  <?=$this->context($this)->renderInContext("myresearch/menu.phtml", ['active' => 'profile'])?>
+</div>
diff --git a/themes/bootstrap3/templates/myresearch/recover.phtml b/themes/bootstrap3/templates/myresearch/recover.phtml
index 225bf0642ba1cb7259771c8643f5c3ca8b3557fa..4d89d789a48ce129650dbd3288adccb4a66d99ac 100644
--- a/themes/bootstrap3/templates/myresearch/recover.phtml
+++ b/themes/bootstrap3/templates/myresearch/recover.phtml
@@ -3,7 +3,7 @@
 <? if (!$this->auth()->getManager()->supportsRecovery()): ?>
   <div class="error"><?=$this->transEsc('recovery_disabled') ?></div>
 <? else: ?>
-  <form class="form-horizontal" method="post">
+  <form class="form-password-recovery" method="post">
     <?=$this->auth()->getPasswordRecoveryForm() ?>
   </form>
-<? endif; ?>
\ No newline at end of file
+<? endif; ?>
diff --git a/themes/bootstrap3/templates/myresearch/storageretrievalrequests.phtml b/themes/bootstrap3/templates/myresearch/storageretrievalrequests.phtml
index fc8050b7e0c0c78d237f703f9c8ed0974d61a188..a64345a449b2ff4761b468e00c791dd605dcb784 100644
--- a/themes/bootstrap3/templates/myresearch/storageretrievalrequests.phtml
+++ b/themes/bootstrap3/templates/myresearch/storageretrievalrequests.phtml
@@ -5,62 +5,70 @@
   // Set up breadcrumbs:
   $this->layout()->breadcrumbs = '<li><a href="' . $this->url('myresearch-home') . '">' . $this->transEsc('Your Account') . '</a></li> <li class="active">' . $this->transEsc('Storage Retrieval Requests') . '</li>';
 ?>
-<div class="row">
-  <div class="<?=$this->layoutClass('mainbody')?>">
-    <h2><?=$this->transEsc('Storage Retrieval Requests') ?></h2>
 
-    <?=$this->flashmessages()?>
+<div class="<?=$this->layoutClass('mainbody')?>">
+  <h2><?=$this->transEsc('Storage Retrieval Requests') ?></h2>
 
-    <?=$this->context($this)->renderInContext('librarycards/selectcard.phtml', array('user' => $this->auth()->isLoggedIn())); ?>
+  <?=$this->flashmessages()?>
 
-    <? if (!empty($this->recordList)): ?>
-      <? if ($this->cancelForm): ?>
-        <form name="cancelForm" class="inline" method="post" id="cancelStorageRetrievalRequest">
-          <input type="hidden" id="submitType" name="cancelSelected" value="1"/>
-          <input type="hidden" id="cancelConfirm" name="confirm" value="0"/>
-          <div class="btn-group">
-            <input id="cancelSelected" name="cancelSelected" type="submit" value="<?=$this->transEsc("storage_retrieval_request_cancel_selected") ?>" class="btn btn-default dropdown-toggle" data-toggle="dropdown"/>
-            <ul class="dropdown-menu">
-              <li class="disabled"><a><?=$this->transEsc("confirm_storage_retrieval_request_cancel_selected_text") ?></a></li>
-              <li><a href="#" onClick="$('#cancelConfirm').val(1);$('#submitType').attr('name','cancelSelected');$(this).parents('form').submit(); return false;"><?=$this->transEsc('confirm_dialog_yes') ?></a></li>
-              <li><a href="#" onClick="return false;"><?=$this->transEsc('confirm_dialog_no')?></a></li>
-            </ul>
-          </div>
-          <div class="btn-group">
-            <input id="cancelAll" name="cancelAll" type="submit" value="<?=$this->transEsc("storage_retrieval_request_cancel_all") ?>" class="btn btn-default dropdown-toggle" data-toggle="dropdown"/>
-            <ul class="dropdown-menu">
-              <li class="disabled"><a><?=$this->transEsc("confirm_storage_retrieval_request_cancel_all_text") ?></a></li>
-              <li><a href="#" onClick="$('#cancelConfirm').val(1);$('#submitType').attr('name','cancelAll');$(this).parents('form').submit(); return false;"><?=$this->transEsc('confirm_dialog_yes') ?></a></li>
-              <li><a href="#" onClick="return false;"><?=$this->transEsc('confirm_dialog_no')?></a></li>
-            </ul>
-          </div>
-      <? endif; ?>
+  <?=$this->context($this)->renderInContext('librarycards/selectcard.phtml', ['user' => $this->auth()->isLoggedIn()]); ?>
 
-      <? $iteration = 0; ?>
-      <? foreach ($this->recordList as $resource): ?>
-        <hr/>
-        <? $iteration++; ?>
-        <? $ilsDetails = $resource->getExtraDetail('ils_details'); ?>
-        <div id="record<?=$this->escapeHtmlAttr($resource->getUniqueId()) ?>" class="row result">
-          <? if ($this->cancelForm && isset($ilsDetails['cancel_details'])): ?>
-            <? $safeId = preg_replace('/[^a-zA-Z0-9]/', '', $resource->getUniqueId()); ?>
+  <? if (!empty($this->recordList)): ?>
+    <? if ($this->cancelForm): ?>
+      <form name="cancelForm" class="inline" method="post" id="cancelStorageRetrievalRequest">
+        <input type="hidden" id="submitType" name="cancelSelected" value="1"/>
+        <input type="hidden" id="cancelConfirm" name="confirm" value="0"/>
+        <div class="btn-group">
+          <input id="cancelSelected" name="cancelSelected" type="submit" value="<?=$this->transEsc("storage_retrieval_request_cancel_selected") ?>" class="btn btn-default dropdown-toggle" data-toggle="dropdown"/>
+          <ul class="dropdown-menu">
+            <li class="disabled"><a><?=$this->transEsc("confirm_storage_retrieval_request_cancel_selected_text") ?></a></li>
+            <li><a href="#" onClick="$('#cancelConfirm').val(1);$('#submitType').attr('name','cancelSelected');$(this).parents('form').submit(); return false;"><?=$this->transEsc('confirm_dialog_yes') ?></a></li>
+            <li><a href="#" onClick="return false;"><?=$this->transEsc('confirm_dialog_no')?></a></li>
+          </ul>
+        </div>
+        <div class="btn-group">
+          <input id="cancelAll" name="cancelAll" type="submit" value="<?=$this->transEsc("storage_retrieval_request_cancel_all") ?>" class="btn btn-default dropdown-toggle" data-toggle="dropdown"/>
+          <ul class="dropdown-menu">
+            <li class="disabled"><a><?=$this->transEsc("confirm_storage_retrieval_request_cancel_all_text") ?></a></li>
+            <li><a href="#" onClick="$('#cancelConfirm').val(1);$('#submitType').attr('name','cancelAll');$(this).parents('form').submit(); return false;"><?=$this->transEsc('confirm_dialog_yes') ?></a></li>
+            <li><a href="#" onClick="return false;"><?=$this->transEsc('confirm_dialog_no')?></a></li>
+          </ul>
+        </div>
+    <? endif; ?>
+
+    <? $iteration = 0; ?>
+    <? foreach ($this->recordList as $resource): ?>
+      <? $iteration++; ?>
+      <? $ilsDetails = $resource->getExtraDetail('ils_details'); ?>
+      <div id="record<?=$this->escapeHtmlAttr($resource->getUniqueId()) ?>" class="result">
+        <? if ($this->cancelForm && isset($ilsDetails['cancel_details'])): ?>
+          <? $safeId = preg_replace('/[^a-zA-Z0-9]/', '', $resource->getUniqueId()); ?>
+          <div class="checkbox">
             <input type="hidden" name="cancelAllIDS[]" value="<?=$this->escapeHtmlAttr($ilsDetails['cancel_details']) ?>" />
-            <div class="pull-left flip">
+            <label class="pull-left flip">
               <input type="checkbox" name="cancelSelectedIDS[]" value="<?=$this->escapeHtmlAttr($ilsDetails['cancel_details']) ?>" id="checkbox_<?=$safeId?>" />
-            </div>
-          <? endif; ?>
-          <? $cover = $this->record($resource)->getCover('storageretrievalrequests', 'small'); ?>
-          <? if ($cover): ?>
-            <div class="col-sm-2 text-center">
-              <? /* Display thumbnail if appropriate: */ ?>
-              <?=$cover?>
-            </div>
-
-            <div class="col-sm-7">
-         <? else: ?>
-            <div class="col-sm-9">
-         <? endif; ?>
+            </label>
+          </div>
+        <? endif; ?>
 
+        <?
+          $coverDetails = $this->record($resource)->getCoverDetails('storageretrievalrequests', 'small', $this->recordLink()->getUrl($resource));
+          $cover = $coverDetails['html'];
+          $thumbnail = false;
+          $thumbnailAlignment = $this->record($resource)->getThumbnailAlignment('account');
+          if ($cover):
+            ob_start(); ?>
+            <div class="media-<?=$thumbnailAlignment ?> <?=$this->escapeHtmlAttr($coverDetails['size'])?>">
+              <?=$cover ?>
+            </div>
+            <? $thumbnail = ob_get_contents(); ?>
+          <? ob_end_clean(); ?>
+        <? endif; ?>
+        <div class="media">
+          <? if ($thumbnail && $thumbnailAlignment == 'left'): ?>
+            <?=$thumbnail ?>
+          <? endif ?>
+          <div class="media-body">
             <?
               // If this is a non-missing Solr record, we should display a link:
               if (is_a($resource, 'VuFind\\RecordDriver\\SolrDefault') && !is_a($resource, 'VuFind\\RecordDriver\\Missing')) {
@@ -147,17 +155,19 @@
             <? if (isset($ilsDetails['cancel_link'])): ?>
               <p><a href="<?=$this->escapeHtmlAttr($ilsDetails['cancel_link']) ?>"><?=$this->transEsc("storage_retrieval_request_cancel") ?></a></p>
             <? endif; ?>
-
           </div>
+          <? if ($thumbnail && $thumbnailAlignment == 'right'): ?>
+            <?=$thumbnail ?>
+          <? endif ?>
         </div>
-      <? endforeach; ?>
-      <? if ($this->cancelForm): ?></form><? endif; ?>
-    <? else: ?>
-      <?=$this->transEsc('You do not have any storage retrieval requests placed') ?>.
-    <? endif; ?>
-  </div>
+      </div>
+    <? endforeach; ?>
+    <? if ($this->cancelForm): ?></form><? endif; ?>
+  <? else: ?>
+    <?=$this->transEsc('You do not have any storage retrieval requests placed') ?>.
+  <? endif; ?>
+</div>
 
-  <div class="<?=$this->layoutClass('sidebar')?>">
-    <?=$this->context($this)->renderInContext("myresearch/menu.phtml", array('active' => 'storageRetrievalRequests'))?>
-  </div>
+<div class="<?=$this->layoutClass('sidebar')?>">
+  <?=$this->context($this)->renderInContext("myresearch/menu.phtml", ['active' => 'storageRetrievalRequests'])?>
 </div>
diff --git a/themes/bootstrap3/templates/oai/home.phtml b/themes/bootstrap3/templates/oai/home.phtml
index 3f56566f81f3ad6030b84c53b20d108ead663e9c..c9f5c55ba29e15bef60ecfb62c2b42c128c13ce1 100644
--- a/themes/bootstrap3/templates/oai/home.phtml
+++ b/themes/bootstrap3/templates/oai/home.phtml
@@ -3,198 +3,140 @@
   $this->layout()->breadcrumbs = $this->transEsc('OAI Server');
   $baseUrl = $this->url('oai-server');
 ?>
-<div class="row">
-  <div class="col-sm-9">
-    <h2><?=$this->transEsc('OAI Server')?></h2>
-    <p>
-      This OAI server is OAI 2.0 compliant.<br/>
-      The OAI Server URL is: <?=$this->serverUrl($baseUrl)?>
-    </p>
-    <hr/>
-    <a name="Identify"></a>
-    <h2>Identify</h2>
-    <form method="get" action="<?=$baseUrl?>">
-      <div class="row">
-        <div class="col-sm-8">
-          <p class="help-block">Returns the Identification information of this OAI Server.</p>
-          <input type="hidden" name="verb" value="Identify"/>
-          <p class="help-block">Accepts no additional parameters.</p>
-        </div>
-        <div class="col-sm-4">
-          <input class="btn btn-default" type="submit" name="submit" value="<?=$this->transEsc('Go')?>"/>
-        </div>
-      </div>
-    </form>
-    <hr/>
-    <a name="ListIdentifiers"></a>
-    <h2>ListIdentifiers</h2>
-    <form class="form-horizontal" method="get" action="<?=$baseUrl?>">
-      <div class="row">
-        <div class="col-sm-8">
-          <input type="hidden" name="verb" value="ListIdentifiers"/>
-          <p class="help-block">Returns a listing of available identifiers</p>
-          <div class="form-group">
-            <label for="ListIdentifier_from" class="col-sm-3 control-label"><?=$this->transEsc('From')?>:</label>
-            <div class="col-sm-9">
-              <input id="ListIdentifier_from" type="text" name="from" class="form-control"/>
-            </div>
-          </div>
-          <div class="form-group">
-            <label for="ListIdentifier_until" class="col-sm-3 control-label"><?=$this->transEsc('Until')?>:</label>
-            <div class="col-sm-9">
-              <input id="ListIdentifier_until" type="text" name="until" class="form-control"/>
-            </div>
-          </div>
-          <div class="form-group">
-            <label for="ListIdentifier_set" class="col-sm-3 control-label"><?=$this->transEsc('Set')?>:</label>
-            <div class="col-sm-9">
-              <input id="ListIdentifier_set" type="text" name="set" class="form-control"/>
-            </div>
-          </div>
-          <div class="form-group">
-            <label for="ListIdentifier_metadataPrefix" class="col-sm-3 control-label"><?=$this->transEsc('Metadata Prefix')?>:</label>
-            <div class="col-sm-9">
-              <input id="ListIdentifier_metadataPrefix" type="text" name="metadataPrefix" class="form-control"/>
-            </div>
-          </div>
-          <div class="form-group">
-            <label for="ListIdentifier_resumptionToken" class="col-sm-3 control-label"><?=$this->transEsc('Resumption Token')?>:</label>
-            <div class="col-sm-9">
-              <input id="ListIdentifier_resumptionToken" type="text" name="resumptionToken" class="form-control"/>
-            </div>
-          </div>
-        </div>
-        <div class="col-sm-4">
-          <input class="btn btn-default" type="submit" name="submit" value="<?=$this->transEsc('Go')?>"/>
-        </div>
-      </div>
-    </form>
-    <hr/>
-    <a name="ListMetadataFormats"></a>
-    <h2>ListMetadataFormats</h2>
-    <form class="form-horizontal" method="get" action="<?=$baseUrl?>">
-      <div class="row">
-        <div class="col-sm-8">
-            <input type="hidden" name="verb" value="ListMetadataFormats"/>
-            <p class="help-block">Returns a listing of available metadata formats.</p>
-            <div class="form-group">
-              <label for="ListMetadataFormats_identifier" class="col-sm-3 control-label"><?=$this->transEsc('Identifier')?>:</label>
-              <div class="col-sm-9">
-                <input id="ListMetadataFormats_identifier" type="text" name="identifier" class="form-control"/>
-              </div>
-            </div>
-        </div>
-        <div class="col-sm-4">
-          <input class="btn btn-default" type="submit" name="submit" value="<?=$this->transEsc('Go')?>"/>
-        </div>
-      </div>
-    </form>
-    <hr/>
-    <a name="ListSets"></a>
-    <h2>ListSets</h2>
-    <form class="form-horizontal" method="get" action="<?=$baseUrl?>">
-      <div class="row">
-        <div class="col-sm-8">
-            <input type="hidden" name="verb" value="ListSets"/>
-            <p class="help-block">Returns a listing of available sets.</p>
-            <div class="form-group">
-              <label for="ListSets_metadataPrefix" class="col-sm-3 control-label"><?=$this->transEsc('Metadata Prefix')?>:</label>
-              <div class="col-sm-9">
-                <input id="ListSets_metadataPrefix" type="text" name="metadataPrefix" class="form-control"/>
-              </div>
-            </div>
-            <div class="form-group">
-              <label for="ListSets_resumptionToken" class="col-sm-3 control-label"><?=$this->transEsc('Resumption Token')?>:</label>
-              <div class="col-sm-9">
-                <input id="ListSets_resumptionToken" type="text" name="resumptionToken" class="form-control"/>
-              </div>
-            </div>
-        </div>
-        <div class="col-sm-4">
-          <input class="btn btn-default" type="submit" name="submit" value="<?=$this->transEsc('Go')?>"/>
-        </div>
-      </div>
-    </form>
-    <hr/>
-    <a name="ListRecords"></a>
-    <h2>ListRecords</h2>
-    <form class="form-horizontal" method="get" action="<?=$baseUrl?>">
-      <div class="row">
-        <div class="col-sm-8">
-            <input type="hidden" name="verb" value="ListRecords"/>
-            <p class="help-block">Returns a listing of available records.</p>
-            <div class="form-group">
-              <label for="ListRecord_from" class="col-sm-3 control-label"><?=$this->transEsc('From')?>:</label>
-              <div class="col-sm-9">
-                <input id="ListRecord_from" type="text" name="from" class="form-control"/>
-              </div>
-            </div>
-            <div class="form-group">
-              <label for="ListRecord_until" class="col-sm-3 control-label"><?=$this->transEsc('Until')?>:</label>
-              <div class="col-sm-9">
-                <input id="ListRecord_until" type="text" name="until" class="form-control"/>
-              </div>
-            </div>
-            <div class="form-group">
-              <label for="ListRecord_set" class="col-sm-3 control-label"><?=$this->transEsc('Set')?>:</label>
-              <div class="col-sm-9">
-                <input id="ListRecord_set" type="text" name="set" class="form-control"/>
-              </div>
-            </div>
-            <div class="form-group">
-              <label for="ListRecord_metadataPrefix" class="col-sm-3 control-label"><?=$this->transEsc('Metadata Prefix')?>:</label>
-              <div class="col-sm-9">
-                <input id="ListRecord_metadataPrefix" type="text" name="metadataPrefix" class="form-control"/>
-              </div>
-            </div>
-            <div class="form-group">
-              <label for="ListRecord_resumptionToken" class="col-sm-3 control-label"><?=$this->transEsc('Resumption Token')?>:</label>
-              <div class="col-sm-9">
-                <input id="ListRecord_resumptionToken" type="text" name="resumptionToken" class="form-control"/>
-              </div>
-            </div>
-        </div>
-        <div class="col-sm-4">
-          <input class="btn btn-default" type="submit" name="submit" value="<?=$this->transEsc('Go')?>"/>
-        </div>
-      </div>
-    </form>
-    <hr/>
-    <a name="GetRecord"></a>
-    <h2>GetRecord</h2>
-    <form class="form-horizontal" method="get" action="<?=$baseUrl?>">
-      <div class="row">
-        <div class="col-sm-8">
-            <input type="hidden" name="verb" value="GetRecord"/>
-            <p class="help-block">Returns a single record.</p>
-            <div class="form-group">
-              <label for="GetRecord_identifier" class="col-sm-3 control-label"><?=$this->transEsc('Identifier')?>:</label>
-              <div class="col-sm-9">
-                <input id="GetRecord_identifier" type="text" name="identifier" class="form-control"/>
-              </div>
-            </div>
-            <div class="form-group">
-              <label for="GetRecord_metadataPrefix" class="col-sm-3 control-label"><?=$this->transEsc('Metadata Token')?>:</label>
-              <div class="col-sm-9">
-                <input id="GetRecord_metadataPrefix" type="text" name="metadataPrefix" class="form-control"/>
-              </div>
-            </div>
-        </div>
-        <div class="col-sm-4">
-          <input class="btn btn-default" type="submit" name="submit" value="<?=$this->transEsc('Go')?>"/>
-        </div>
-      </div>
-    </form>
-  </div>
-  <div class="col-sm-3">
-    <h2><?=$this->transEsc('Available Functionality') ?>:</h2>
-    <div class="list-group">
-      <a href="#Identify" class="list-group-item active">Identify</a>
-      <a href="#ListIdentifiers" class="list-group-item">ListIdentifiers</a>
-      <a href="#ListMetadataFormats" class="list-group-item">ListMetadataFormats</a>
-      <a href="#ListSets" class="list-group-item">ListSets</a>
-      <a href="#ListRecords" class="list-group-item">ListRecords</a>
-      <a href="#GetRecord" class="list-group-item">GetRecord</a>
+<div class="<?=$this->layoutClass('mainbody')?>">
+  <h2><?=$this->transEsc('OAI Server')?></h2>
+  <p>This OAI server is OAI 2.0 compliant.</p>
+  <p>The OAI Server URL is: <?=$this->serverUrl($baseUrl)?></p>
+  <hr/>
+  <a name="Identify"></a>
+  <h2>Identify</h2>
+  <form class="form-oai-home" method="get" action="<?=$baseUrl?>">
+    <input type="hidden" name="verb" value="Identify"/>
+    <p class="help-block">Returns the Identification information of this OAI Server.</p>
+    <p class="help-block">Accepts no additional parameters.</p>
+    <div class="form-group">
+      <input class="btn btn-default" type="submit" name="submit" value="<?=$this->transEsc('Go')?>"/>
+    </div>
+  </form>
+  <hr/>
+  <a name="ListIdentifiers"></a>
+  <h2>ListIdentifiers</h2>
+  <form class="form-oai-home" method="get" action="<?=$baseUrl?>">
+    <input type="hidden" name="verb" value="ListIdentifiers"/>
+    <p class="help-block">Returns a listing of available identifiers</p>
+    <div class="form-group">
+      <label for="ListIdentifier_from" class="control-label"><?=$this->transEsc('From')?>:</label>
+      <input id="ListIdentifier_from" type="text" name="from" class="form-control"/>
+    </div>
+    <div class="form-group">
+      <label for="ListIdentifier_until" class="control-label"><?=$this->transEsc('Until')?>:</label>
+      <input id="ListIdentifier_until" type="text" name="until" class="form-control"/>
+    </div>
+    <div class="form-group">
+      <label for="ListIdentifier_set" class="control-label"><?=$this->transEsc('Set')?>:</label>
+      <input id="ListIdentifier_set" type="text" name="set" class="form-control"/>
+    </div>
+    <div class="form-group">
+      <label for="ListIdentifier_metadataPrefix" class="control-label"><?=$this->transEsc('Metadata Prefix')?>:</label>
+      <input id="ListIdentifier_metadataPrefix" type="text" name="metadataPrefix" class="form-control"/>
+    </div>
+    <div class="form-group">
+      <label for="ListIdentifier_resumptionToken" class="control-label"><?=$this->transEsc('Resumption Token')?>:</label>
+      <input id="ListIdentifier_resumptionToken" type="text" name="resumptionToken" class="form-control"/>
+    </div>
+    <div class="form-group">
+      <input class="btn btn-default" type="submit" name="submit" value="<?=$this->transEsc('Go')?>"/>
+    </div>
+  </form>
+  <hr/>
+  <a name="ListMetadataFormats"></a>
+  <h2>ListMetadataFormats</h2>
+  <form class="form-oai-home" method="get" action="<?=$baseUrl?>">
+    <input type="hidden" name="verb" value="ListMetadataFormats"/>
+    <p class="help-block">Returns a listing of available metadata formats.</p>
+    <div class="form-group">
+      <label for="ListMetadataFormats_identifier" class="control-label"><?=$this->transEsc('Identifier')?>:</label>
+      <input id="ListMetadataFormats_identifier" type="text" name="identifier" class="form-control"/>
+    </div>
+    <div class="form-group">
+      <input class="btn btn-default" type="submit" name="submit" value="<?=$this->transEsc('Go')?>"/>
+    </div>
+  </form>
+  <hr/>
+  <a name="ListSets"></a>
+  <h2>ListSets</h2>
+  <form class="form-oai-home" method="get" action="<?=$baseUrl?>">
+    <input type="hidden" name="verb" value="ListSets"/>
+    <p class="help-block">Returns a listing of available sets.</p>
+    <div class="form-group">
+      <label for="ListSets_metadataPrefix" class="control-label"><?=$this->transEsc('Metadata Prefix')?>:</label>
+      <input id="ListSets_metadataPrefix" type="text" name="metadataPrefix" class="form-control"/>
+    </div>
+    <div class="form-group">
+      <label for="ListSets_resumptionToken" class="control-label"><?=$this->transEsc('Resumption Token')?>:</label>
+      <input id="ListSets_resumptionToken" type="text" name="resumptionToken" class="form-control"/>
+    </div>
+    <div class="form-group">
+      <input class="btn btn-default" type="submit" name="submit" value="<?=$this->transEsc('Go')?>"/>
+    </div>
+  </form>
+  <hr/>
+  <a name="ListRecords"></a>
+  <h2>ListRecords</h2>
+  <form class="form-oai-home" method="get" action="<?=$baseUrl?>">
+    <input type="hidden" name="verb" value="ListRecords"/>
+    <p class="help-block">Returns a listing of available records.</p>
+    <div class="form-group">
+      <label for="ListRecord_from" class="control-label"><?=$this->transEsc('From')?>:</label>
+      <input id="ListRecord_from" type="text" name="from" class="form-control"/>
+    </div>
+    <div class="form-group">
+      <label for="ListRecord_until" class="control-label"><?=$this->transEsc('Until')?>:</label>
+      <input id="ListRecord_until" type="text" name="until" class="form-control"/>
+    </div>
+    <div class="form-group">
+      <label for="ListRecord_set" class="control-label"><?=$this->transEsc('Set')?>:</label>
+      <input id="ListRecord_set" type="text" name="set" class="form-control"/>
+    </div>
+    <div class="form-group">
+      <label for="ListRecord_metadataPrefix" class="control-label"><?=$this->transEsc('Metadata Prefix')?>:</label>
+      <input id="ListRecord_metadataPrefix" type="text" name="metadataPrefix" class="form-control"/>
+    </div>
+    <div class="form-group">
+      <label for="ListRecord_resumptionToken" class="control-label"><?=$this->transEsc('Resumption Token')?>:</label>
+      <input id="ListRecord_resumptionToken" type="text" name="resumptionToken" class="form-control"/>
+    </div>
+    <div class="form-group">
+      <input class="btn btn-default" type="submit" name="submit" value="<?=$this->transEsc('Go')?>"/>
+    </div>
+  </form>
+  <hr/>
+  <a name="GetRecord"></a>
+  <h2>GetRecord</h2>
+  <form class="form-oai-home" method="get" action="<?=$baseUrl?>">
+    <input type="hidden" name="verb" value="GetRecord"/>
+    <p class="help-block">Returns a single record.</p>
+    <div class="form-group">
+      <label for="GetRecord_identifier" class="control-label"><?=$this->transEsc('Identifier')?>:</label>
+      <input id="GetRecord_identifier" type="text" name="identifier" class="form-control"/>
+    </div>
+    <div class="form-group">
+      <label for="GetRecord_metadataPrefix" class="control-label"><?=$this->transEsc('Metadata Token')?>:</label>
+      <input id="GetRecord_metadataPrefix" type="text" name="metadataPrefix" class="form-control"/>
+    </div>
+    <div class="form-group">
+      <input class="btn btn-default" type="submit" name="submit" value="<?=$this->transEsc('Go')?>"/>
     </div>
+  </form>
+</div>
+<div class="<?=$this->layoutClass('sidebar')?>">
+  <h2><?=$this->transEsc('Available Functionality') ?>:</h2>
+  <div class="list-group">
+    <a href="#Identify" class="list-group-item">Identify</a>
+    <a href="#ListIdentifiers" class="list-group-item">ListIdentifiers</a>
+    <a href="#ListMetadataFormats" class="list-group-item">ListMetadataFormats</a>
+    <a href="#ListSets" class="list-group-item">ListSets</a>
+    <a href="#ListRecords" class="list-group-item">ListRecords</a>
+    <a href="#GetRecord" class="list-group-item">GetRecord</a>
   </div>
-</div>
\ No newline at end of file
+</div>
diff --git a/themes/bootstrap3/templates/pazpar2/home.phtml b/themes/bootstrap3/templates/pazpar2/home.phtml
index d13d4348c1e39e2222b5f16ce7d65ecd7816ef92..bc5b700660ea8e7baee8cc01de0600b0b4611521 100644
--- a/themes/bootstrap3/templates/pazpar2/home.phtml
+++ b/themes/bootstrap3/templates/pazpar2/home.phtml
@@ -1 +1 @@
-<?=$this->render('search/home.phtml');?>
\ No newline at end of file
+<?=$this->render('search/home.phtml');?>
diff --git a/themes/bootstrap3/templates/pazpar2/search.phtml b/themes/bootstrap3/templates/pazpar2/search.phtml
index c1797c1cd4a1ebb2ccad84718b1e225e51cac6a8..a0c6dd4bbf5077e0b43b335e98733b44bba7b4e6 100644
--- a/themes/bootstrap3/templates/pazpar2/search.phtml
+++ b/themes/bootstrap3/templates/pazpar2/search.phtml
@@ -1,4 +1,4 @@
 <?
     // Load standard settings from the default search results screen:
     echo $this->render('search/results.phtml');
-?>
\ No newline at end of file
+?>
diff --git a/themes/bootstrap3/templates/primo/advanced.phtml b/themes/bootstrap3/templates/primo/advanced.phtml
index d2286aee4e619d113824fa938a0fc833614a32d1..586975e45f3f90fb9932542771a5df20d295275a 100644
--- a/themes/bootstrap3/templates/primo/advanced.phtml
+++ b/themes/bootstrap3/templates/primo/advanced.phtml
@@ -23,100 +23,92 @@
         $hasDefaultsApplied = $searchDetails = $searchFilters = $groups = false;
     }
 ?>
-<form id="advSearchForm" name="searchForm"  method="get" action="<?=$this->url($this->options->getSearchAction())?>" class="form-horizontal">
+<form class="primo-adv-search" id="advSearchForm" name="searchForm"  method="get" action="<?=$this->url($this->options->getSearchAction())?>">
   <input type="hidden" name="join" value="AND" />
-  <div class="row">
-    <div class="<?=$this->layoutClass('mainbody')?>">
-      <h3><?=$this->transEsc('Advanced Search')?></h3>
-      <? /* fallback to a fixed set of search groups/fields if JavaScript is turned off */ ?>
-      <? if ($groups !== false) {
-          $numGroups = count($groups);
-        }
-        if (!isset($numGroups) || $numGroups < 3) {
-          $numGroups = 1;
-        }
-      ?>
-      <? for ($i = 0; $i < $numGroups; $i++): ?>
-        <input type="hidden" name="bool<?=$i?>[]" value="AND" />
-        <div class="group well row" id="group<?=$i?>">
-          <div class="col-sm-2" id="group<?=$i?>SearchHolder"><label><?=$this->transEsc("adv_search_label")?>:</label></div>
-          <div class="col-sm-10">
-            <?
-              if (isset($groups[$i])) {
-                $currentGroup = $groups[$i]->getQueries();
-                $numRows = count($currentGroup);
-              } else {
-                $currentGroup = false;
-              }
-              if (!isset($numRows) || $numRows < 3) {
-                $numRows = 3;
-              }
-            ?>
-            <? for ($j = 0; $j < $numRows; $j++): ?>
-              <? $currRow = isset($currentGroup[$j]) ? $currentGroup[$j] : false; ?>
-              <div class="row">
-                <div class="col-sm-3">
-                  <select id="search_type<?=$i?>_<?=$j?>" name="type<?=$i?>[]" class="form-control">
-                  <? foreach ($this->options->getAdvancedHandlers() as $searchVal => $searchDesc): ?>
-                    <option value="<?=$this->escapeHtmlAttr($searchVal)?>"<?=($currRow && $currRow->getHandler() == $searchVal)?' selected="selected"':''?>><?=$this->transEsc($searchDesc)?></option>
-                  <? endforeach; ?>
-                  </select>
-                </div>
-                <div class="col-sm-3">
-                  <select name="op<?=$i?>[]" id="searchForm_op<?=$i?>_<?=$j?>" class="form-control">
-                    <? foreach ($this->options->getAdvancedOperators() as $searchVal => $searchDesc): ?>
-                      <option value="<?=$this->escapeHtmlAttr($searchVal)?>"<?=($currRow && $currRow->getOperator() == $searchVal)?' selected="selected"':''?>><?=$this->transEsc($searchDesc)?></option>
-                    <? endforeach; ?>
-                  </select>
-                </div>
-                <div class="col-sm-6">
-                  <input id="search_lookfor<?=$i?>_<?=$j?>" type="text" value="<?=$currRow?$this->escapeHtmlAttr($currRow->getString()):''?>" size="30" name="lookfor<?=$i?>[]" class="form-control"/>
-                </div>
-              </div>
-            <? endfor; ?>
-          </div>
+  <div class="<?=$this->layoutClass('mainbody')?>">
+    <h3><?=$this->transEsc('Advanced Search')?></h3>
+    <? /* fallback to a fixed set of search groups/fields if JavaScript is turned off */ ?>
+    <? if ($groups !== false) {
+        $numGroups = count($groups);
+      }
+      if (!isset($numGroups) || $numGroups < 3) {
+        $numGroups = 1;
+      }
+    ?>
+    <? for ($i = 0; $i < $numGroups; $i++): ?>
+      <input type="hidden" name="bool<?=$i?>[]" value="AND" />
+      <div class="primo adv-group" id="group<?=$i?>">
+        <label class="primo-adv-label" id="group<?=$i?>SearchHolder"><?=$this->transEsc("adv_search_label")?>:</label>
+        <div class="search-container">
+          <?
+            if (isset($groups[$i])) {
+              $currentGroup = $groups[$i]->getQueries();
+              $numRows = count($currentGroup);
+            } else {
+              $currentGroup = false;
+            }
+            if (!isset($numRows) || $numRows < 3) {
+              $numRows = 3;
+            }
+          ?>
+          <? for ($j = 0; $j < $numRows; $j++): ?>
+            <? $currRow = isset($currentGroup[$j]) ? $currentGroup[$j] : false; ?>
+            <div class="search">
+              <select id="search_type<?=$i?>_<?=$j?>" name="type<?=$i?>[]" class="form-control">
+                <? foreach ($this->options->getAdvancedHandlers() as $searchVal => $searchDesc): ?>
+                  <option value="<?=$this->escapeHtmlAttr($searchVal)?>"<?=($currRow && $currRow->getHandler() == $searchVal)?' selected="selected"':''?>><?=$this->transEsc($searchDesc)?></option>
+                <? endforeach; ?>
+              </select>
+              <select name="op<?=$i?>[]" id="searchForm_op<?=$i?>_<?=$j?>" class="form-control">
+                <? foreach ($this->options->getAdvancedOperators() as $searchVal => $searchDesc): ?>
+                  <option value="<?=$this->escapeHtmlAttr($searchVal)?>"<?=($currRow && $currRow->getOperator() == $searchVal)?' selected="selected"':''?>><?=$this->transEsc($searchDesc)?></option>
+                <? endforeach; ?>
+              </select>
+                <input id="search_lookfor<?=$i?>_<?=$j?>" type="text" value="<?=$currRow?$this->escapeHtmlAttr($currRow->getString()):''?>" size="30" name="lookfor<?=$i?>[]" class="form-control primo-adv-input"/>
+            </div>
+          <? endfor; ?>
         </div>
-      <? endfor; ?>
-      <? $lastSort = $this->searchMemory()->getLastSort($this->options->getSearchClassId()); ?>
-      <? if (!empty($lastSort)): ?>
-        <input type="hidden" name="sort" value="<?=$this->escapeHtmlAttr($lastSort)?>" />
-      <? endif; ?>
-      <input type="submit" class="btn btn-primary" name="submit" value="<?=$this->transEsc("Find")?>"/>
-    </div>
+      </div>
+    <? endfor; ?>
+    <? $lastSort = $this->searchMemory()->getLastSort($this->options->getSearchClassId()); ?>
+    <? if (!empty($lastSort)): ?>
+      <input type="hidden" name="sort" value="<?=$this->escapeHtmlAttr($lastSort)?>" />
+    <? endif; ?>
+    <input type="submit" class="btn btn-primary" name="submit" value="<?=$this->transEsc("Find")?>"/>
+  </div>
 
-    <div class="<?=$this->layoutClass('sidebar')?>">
-      <? if ($hasDefaultsApplied): ?>
-        <input type="hidden" name="dfApplied" value="1" />
-      <? endif ?>
-      <? if (!empty($searchFilters)): ?>
-        <h4><?=$this->transEsc("adv_search_filters")?></h4>
-        <ul class="list-group">
-          <li class="list-group-item">
-            <div class="checkbox">
-              <label>
-                <?=$this->transEsc("adv_search_select_all")?>
-                <input type="checkbox" checked="checked" class="checkbox-select-all" />
-              </label>
-            </div>
-          </li>
-        </ul>
-        <? foreach ($searchFilters as $field => $data): ?>
-          <div>
-            <ul class="list-group">
-              <li class="list-group-item title"><?=$this->transEsc($field)?></li>
-              <? foreach ($data as $value): ?>
-                <li class="list-group-item">
-                  <div class="checkbox">
-                    <label>
-                      <input type="checkbox" class="checkbox-select-item" checked="checked" name="filter[]" value='<?=$this->escapeHtmlAttr($value['field'])?>:"<?=$this->escapeHtmlAttr($value['value'])?>"' /> <?=$this->escapeHtml($value['displayText'])?>
-                    </label>
-                  </div>
-                </li>
-              <? endforeach; ?>
-            </ul>
+  <div class="<?=$this->layoutClass('sidebar')?>">
+    <? if ($hasDefaultsApplied): ?>
+      <input type="hidden" name="dfApplied" value="1" />
+    <? endif ?>
+    <? if (!empty($searchFilters)): ?>
+      <h4><?=$this->transEsc("adv_search_filters")?></h4>
+      <ul class="list-group">
+        <li class="list-group-item">
+          <div class="checkbox">
+            <label>
+              <?=$this->transEsc("adv_search_select_all")?>
+              <input type="checkbox" checked="checked" class="checkbox-select-all" />
+            </label>
           </div>
-        <? endforeach; ?>
-      <? endif; ?>
-    </div>
+        </li>
+      </ul>
+      <? foreach ($searchFilters as $field => $data): ?>
+        <div>
+          <ul class="list-group">
+            <li class="list-group-item title"><?=$this->transEsc($field)?></li>
+            <? foreach ($data as $value): ?>
+              <li class="list-group-item">
+                <div class="checkbox">
+                  <label>
+                    <input type="checkbox" class="checkbox-select-item" checked="checked" name="filter[]" value='<?=$this->escapeHtmlAttr($value['field'])?>:"<?=$this->escapeHtmlAttr($value['value'])?>"' /> <?=$this->escapeHtml($value['displayText'])?>
+                  </label>
+                </div>
+              </li>
+            <? endforeach; ?>
+          </ul>
+        </div>
+      <? endforeach; ?>
+    <? endif; ?>
   </div>
 </form>
diff --git a/themes/bootstrap3/templates/primo/home.phtml b/themes/bootstrap3/templates/primo/home.phtml
index d13d4348c1e39e2222b5f16ce7d65ecd7816ef92..bc5b700660ea8e7baee8cc01de0600b0b4611521 100644
--- a/themes/bootstrap3/templates/primo/home.phtml
+++ b/themes/bootstrap3/templates/primo/home.phtml
@@ -1 +1 @@
-<?=$this->render('search/home.phtml');?>
\ No newline at end of file
+<?=$this->render('search/home.phtml');?>
diff --git a/themes/bootstrap3/templates/primo/search.phtml b/themes/bootstrap3/templates/primo/search.phtml
index c1797c1cd4a1ebb2ccad84718b1e225e51cac6a8..a0c6dd4bbf5077e0b43b335e98733b44bba7b4e6 100644
--- a/themes/bootstrap3/templates/primo/search.phtml
+++ b/themes/bootstrap3/templates/primo/search.phtml
@@ -1,4 +1,4 @@
 <?
     // Load standard settings from the default search results screen:
     echo $this->render('search/results.phtml');
-?>
\ No newline at end of file
+?>
diff --git a/themes/bootstrap3/templates/record/addtag.phtml b/themes/bootstrap3/templates/record/addtag.phtml
index 2d0ea2f33ac535fcf9c6dabc0a04cc0fc871ce08..dd120a1f2c6f6a461cb1c64a15e1f98d4d682c23 100644
--- a/themes/bootstrap3/templates/record/addtag.phtml
+++ b/themes/bootstrap3/templates/record/addtag.phtml
@@ -7,23 +7,17 @@
       . '<li>' . $this->recordLink()->getBreadcrumb($this->driver) . '</li> '
       . '<li class="active">' . $this->transEsc('Add Tag') . '</li>';
 ?>
-<div class="record">
-  <h2><?=$this->transEsc('Add Tags') ?></h2>
-  <form method="post" name="tagRecord" class="form-horizontal" data-lightbox-onclose="refreshTagList();">
-    <input type="hidden" name="submit" value="1" />
-    <input type="hidden" name="id" value="<?=$this->escapeHtmlAttr($this->driver->getUniqueId())?>" />
-    <input type="hidden" name="source" value="<?=$this->escapeHtmlAttr($this->driver->getSourceIdentifier())?>" />
-    <div class="form-group">
-      <label class="col-sm-3 control-label" for="addtag_tag"><?=$this->transEsc("Tags")?>:</label>
-      <div class="col-sm-9">
-        <input id="addtag_tag" type="text" name="tag" value="" size="40"  class="form-control"/>
-        <p class="help-block"><?=$this->transEsc("add_tag_note")?></p>
-      </div>
-    </div>
-    <div class="form-group">
-      <div class="col-sm-9 col-sm-offset-3">
-        <input class="btn btn-primary" type="submit" value="<?=$this->transEsc('Save')?>"/>
-      </div>
-    </div>
-  </form>
-</div>
\ No newline at end of file
+<h2><?=$this->transEsc('Add Tags') ?></h2>
+<form method="post" name="tagRecord" class="form-add-tag" data-lightbox-onclose="refreshTagList">
+  <input type="hidden" name="submit" value="1" />
+  <input type="hidden" name="id" value="<?=$this->escapeHtmlAttr($this->driver->getUniqueId())?>" />
+  <input type="hidden" name="source" value="<?=$this->escapeHtmlAttr($this->driver->getSourceIdentifier())?>" />
+  <div class="form-group">
+    <label class="control-label" for="addtag_tag"><?=$this->transEsc("Tags")?>:</label>
+    <input id="addtag_tag" type="text" name="tag" value="" size="40"  class="form-control"/>
+    <p class="help-block"><?=$this->transEsc("add_tag_note")?></p>
+  </div>
+  <div class="form-group">
+    <input class="btn btn-primary" type="submit" value="<?=$this->transEsc('Save')?>"/>
+  </div>
+</form
diff --git a/themes/bootstrap3/templates/record/ajaxtab.phtml b/themes/bootstrap3/templates/record/ajaxtab.phtml
index 6f7d520981ebef08a220bd6ef46f1afaf76ecd02..5ee8df818ac6aee54b28d1ab7f4cb03e1c8d4f0e 100644
--- a/themes/bootstrap3/templates/record/ajaxtab.phtml
+++ b/themes/bootstrap3/templates/record/ajaxtab.phtml
@@ -4,4 +4,4 @@ foreach ($this->tabs as $tab => $obj) {
         echo $this->record($this->driver)->getTab($obj);
     }
 }
-?>
\ No newline at end of file
+?>
diff --git a/themes/bootstrap3/templates/record/ajaxview-accordion.phtml b/themes/bootstrap3/templates/record/ajaxview-accordion.phtml
index c67b69aaa76762170bdc7cfd16fbc97517372d8a..7576877969517c33a2ab494c010b28dd06703ff4 100644
--- a/themes/bootstrap3/templates/record/ajaxview-accordion.phtml
+++ b/themes/bootstrap3/templates/record/ajaxview-accordion.phtml
@@ -17,7 +17,7 @@
       <div id="information_<?=$idSuffix?>-content" class="panel-collapse collapse<? if($this->defaultTab === 'information'): ?> in<? endif; ?>">
         <div class="list-tab-content record panel-body">
           <input type="hidden" value="<?=$this->escapeHtmlAttr($this->driver->getUniqueId())?>" class="hiddenId" id="record_id_<?=$idSuffix?>" />
-          <input type="hidden" value="<?=$this->escapeHtmlAttr($this->driver->getResourceSource()) ?>" class="hiddenSource" />
+          <input type="hidden" value="<?=$this->escapeHtmlAttr($this->driver->getSourceIdentifier()) ?>" class="hiddenSource" />
           <?=$coreMetadata ?>
         </div>
       </div>
@@ -65,7 +65,7 @@
     <? foreach ($this->tabs as $tab => $obj): ?>
       <? // add current tab to breadcrumbs if applicable:
         $desc = $obj->getDescription();
-        $tab_classes = array();
+        $tab_classes = [];
         if (!$obj->isVisible()) { $tab_classes[] = 'hidden'; }
         if (!$obj->supportsAjax()) { $tab_classes[] = 'noajax'; }
         if ($this->defaultTab === strtolower($tab)) { $tab_classes[] = 'default'; }
diff --git a/themes/bootstrap3/templates/record/ajaxview-tabs.phtml b/themes/bootstrap3/templates/record/ajaxview-tabs.phtml
index a995b43151542b2ef4e59c86ded443ba0405e5c0..3f4431c76c16f7df1ac003651939bf65a23c7464 100644
--- a/themes/bootstrap3/templates/record/ajaxview-tabs.phtml
+++ b/themes/bootstrap3/templates/record/ajaxview-tabs.phtml
@@ -33,7 +33,7 @@
   <? foreach ($this->tabs as $tab => $obj): ?>
     <? // add current tab to breadcrumbs if applicable:
       $desc = $obj->getDescription();
-      $tab_classes = array();
+      $tab_classes = [];
       if ($this->defaultTab === strtolower($tab)) {
         if (!$this->ajaxTabs || !$obj->supportsAjax()) {
           $tab_classes[] = 'active';
@@ -51,7 +51,7 @@
   <? if (!empty($coreMetadata)): ?>
     <div class="list-tab-content record tab-pane<? if($this->defaultTab === 'information'): ?> active<? endif; ?>" id="information_<?=$idSuffix?>-content">
       <input type="hidden" value="<?=$this->escapeHtmlAttr($this->driver->getUniqueId())?>" class="hiddenId" id="record_id_<?=$idSuffix?>" />
-      <input type="hidden" value="<?=$this->escapeHtmlAttr($this->driver->getResourceSource()) ?>" class="hiddenSource" />
+      <input type="hidden" value="<?=$this->escapeHtmlAttr($this->driver->getSourceIdentifier()) ?>" class="hiddenSource" />
       <?=$coreMetadata ?>
     </div>
   <? endif; ?>
diff --git a/themes/bootstrap3/templates/record/cart-buttons.phtml b/themes/bootstrap3/templates/record/cart-buttons.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..c90799a3c45535f97de0ad9e7ed4cd0bb05b0547
--- /dev/null
+++ b/themes/bootstrap3/templates/record/cart-buttons.phtml
@@ -0,0 +1,24 @@
+<? $cart = $this->cart(); ?>
+<? if ($cart->isActive()): ?>
+  <? $cartId = $this->source . '|' . $this->id; ?>
+  <span class="btn-bookbag-toggle" data-cart-id="<?=$this->escapeHtmlAttr($this->id)?>" data-cart-source="<?=$this->escapeHtmlAttr($this->source)?>">
+    <a class="cart-add hidden<? if(!$cart->contains($cartId)): ?> correct<? endif ?>">
+      <i class="cart-link-icon fa fa-plus" title="<?=$this->transEsc('Add to Book Bag') ?>"></i><!--
+   --><span class="cart-link-label"><?=$this->transEsc('Add to Book Bag') ?></span><!--
+ --></a>
+    <a class="cart-remove hidden<? if($cart->contains($cartId)): ?> correct<? endif ?>">
+      <i class="cart-link-icon fa fa-minus-circle" title="<?=$this->transEsc('Remove from Book Bag') ?>"></i><!--
+   --><span class="cart-link-label"><?=$this->transEsc('Remove from Book Bag') ?></span>
+    </a>
+    <noscript>
+      <form method="post" name="addForm" action="<?=$this->url('cart-processor')?>">
+        <input type="hidden" name="ids[]" value="<?=$this->escapeHtmlAttr($cartId)?>" />
+        <? if ($cart->contains($cartId)): ?>
+          <input class="btn btn-default" type="submit" name="delete" value="<?=$this->transEsc('Remove from Book Bag')?>"/>
+        <? else: ?>
+          <input class="btn btn-default" type="submit" name="add" value="<?=$this->transEsc('Add to Book Bag')?>"/>
+        <? endif; ?>
+      </form>
+    </noscript>
+  </span>
+<? endif; ?>
diff --git a/themes/bootstrap3/templates/record/checkbox.phtml b/themes/bootstrap3/templates/record/checkbox.phtml
index e6cba3addf1e6543a4b819106b3202cd3cf13836..84663f8ab13dba75c2975903b1e051446641b31c 100644
--- a/themes/bootstrap3/templates/record/checkbox.phtml
+++ b/themes/bootstrap3/templates/record/checkbox.phtml
@@ -1,2 +1,5 @@
-<input class="checkbox-select-item" type="checkbox" name="ids[]" value="<?=$this->escapeHtmlAttr($this->id) ?>"/>
-<input type="hidden" name="idsAll[]" value="<?=$this->escapeHtmlAttr($this->id) ?>"/>
+<label class="record-checkbox hidden-print">
+  <input class="checkbox-select-item" type="checkbox" name="ids[]" value="<?=$this->escapeHtmlAttr($this->id) ?>"<? if(isset($this->formAttr)): ?> form="<?=$this->formAttr ?>"<? endif; ?>/>
+  <span class="checkbox-icon"></span>
+</label>
+<input type="hidden" name="idsAll[]" value="<?=$this->escapeHtmlAttr($this->id) ?>"<? if(isset($this->formAttr)): ?> form="<?=$this->formAttr ?>"<? endif; ?>/>
diff --git a/themes/bootstrap3/templates/record/cite.phtml b/themes/bootstrap3/templates/record/cite.phtml
index a6db3edaea7ac8c160d76b16a3ec535e4d870133..09798ecd6701748217dc7590abc1a83982895983 100644
--- a/themes/bootstrap3/templates/record/cite.phtml
+++ b/themes/bootstrap3/templates/record/cite.phtml
@@ -9,7 +9,7 @@
 
   // Collect citation data:
   $helper = $this->citation($this->driver);
-  $citations = array();
+  $citations = [];
   foreach ($this->driver->getCitationFormats() as $format) {
     $citations[$format . ' Citation'] = $helper->getCitation($format);
   }
diff --git a/themes/bootstrap3/templates/record/comments-list.phtml b/themes/bootstrap3/templates/record/comments-list.phtml
index 3374fadea591ef52b99ffab47c0c3b43156295fc..ec9faf569a1abf16528ec96140547b5e9837cdf9 100644
--- a/themes/bootstrap3/templates/record/comments-list.phtml
+++ b/themes/bootstrap3/templates/record/comments-list.phtml
@@ -3,19 +3,19 @@
   <div class="alert alert-info"><?=$this->transEsc('Be the first to leave a comment')?>!</div>
 <? else: ?>
   <? foreach ($comments as $comment): ?>
-    <div class="comment row">
-      <div class="col-sm-3 name">
+    <div class="comment">
+      <div class="comment-name">
         <strong><?=$this->escapeHtml(trim($comment->firstname . ' ' . $comment->lastname))?></strong><br/>
         <small>
           <?=$this->escapeHtml($comment->created)?>
           <? if (($user = $this->auth()->isLoggedIn()) && $comment->user_id == $user->id): ?>
-            <a href="<?=$this->recordLink()->getActionUrl($this->driver, 'DeleteComment')?>?delete=<?=urlencode($comment->id)?>" id="recordComment<?=$this->escapeHtml($comment->id)?>" class="delete text-danger"><?=$this->transEsc('Delete')?></a>
+            <a href="<?=$this->recordLink()->getActionUrl($this->driver, 'DeleteComment')?>?delete=<?=urlencode($comment->id)?>" id="recordComment<?=$this->escapeHtml($comment->id)?>" class="delete"><?=$this->transEsc('Delete')?></a>
           <? endif; ?>
         </small>
       </div>
-      <div class="col-sm-9">
+      <div class="comment-text">
         <?=$this->escapeHtml($comment->comment)?>
       </div>
     </div>
   <? endforeach; ?>
-<? endif; ?>
\ No newline at end of file
+<? endif; ?>
diff --git a/themes/bootstrap3/templates/record/email.phtml b/themes/bootstrap3/templates/record/email.phtml
index 680ba4fb4cbfc0ed6e4ccecabc21a5ff94dfd92e..470625daf8b0a73c77439b577c0cc5f801774886 100644
--- a/themes/bootstrap3/templates/record/email.phtml
+++ b/themes/bootstrap3/templates/record/email.phtml
@@ -8,7 +8,7 @@
     . '<li class="active">' . $this->transEsc('Email Record') . '</li>';
 ?>
 <h2><?=$this->transEsc('Email Record') ?>: <span class="title-in-heading"><?=$this->escapeHtml($this->driver->getBreadcrumb())?></span></h2>
-<form class="form-horizontal" method="post" action="<?=$this->recordLink()->getActionUrl($this->driver, 'Email')?>" name="emailRecord">
+<form class="form-record-email" method="post" action="<?=$this->recordLink()->getActionUrl($this->driver, 'Email')?>" name="emailRecord">
   <?=$this->flashmessages()?>
   <input type="hidden" name="id" value="<?=$this->escapeHtmlAttr($this->driver->getUniqueId())?>" />
   <input type="hidden" name="source" value="<?=$this->escapeHtmlAttr($this->driver->getSourceIdentifier())?>" />
diff --git a/themes/bootstrap3/templates/record/hold.phtml b/themes/bootstrap3/templates/record/hold.phtml
index 5abbdf6c9b2472911a6106796e6d92cfba117183..36f7d3af002f17abe0dc7cac36bad0e6313547ac 100644
--- a/themes/bootstrap3/templates/record/hold.phtml
+++ b/themes/bootstrap3/templates/record/hold.phtml
@@ -12,115 +12,99 @@
 <p class="helptext"><?=$this->helpText?></p>
 <? endif; ?>
 
-<div class="hold-form">
-  <form class="form-horizontal" method="post" name="placeHold">
-    <?=$this->flashmessages()?>
-    <label class="col-sm-3 control-label"><?=$this->transEsc('Title')?></label>
-    <div class="col-sm-9">
-      <p class="form-control-static"><?=$this->driver->getBreadcrumb() ?></p>
+<form class="form-record-hold" method="post" name="placeHold">
+  <?=$this->flashmessages()?>
+  <label class="control-label"><?=$this->transEsc('Title')?></label>
+  <p class="form-control-static"><?=$this->driver->getBreadcrumb() ?></p>
+  <? if (in_array("comments", $this->extraHoldFields)): ?>
+    <div class="form-group hold-comment">
+      <label class="control-label"><?=$this->transEsc("Comments")?>:</label>
+      <textarea rows="3" cols="20" name="gatheredDetails[comment]" class="form-control"><?=isset($this->gatheredDetails['comment']) ? $this->escapeHtml($this->gatheredDetails['comment']) : ''?></textarea>
     </div>
-    <? if (in_array("comments", $this->extraHoldFields)): ?>
-      <div class="form-group hold-comment">
-        <label class="col-sm-3 control-label"><?=$this->transEsc("Comments")?>:</label>
-        <div class="col-sm-9">
-          <textarea rows="3" cols="20" name="gatheredDetails[comment]" class="form-control"><?=isset($this->gatheredDetails['comment']) ? $this->escapeHtml($this->gatheredDetails['comment']) : ''?></textarea>
-        </div>
-      </div>
-    <? endif; ?>
+  <? endif; ?>
 
-    <? if (in_array("requiredByDate", $this->extraHoldFields)): ?>
-      <div class="form-group hold-required-by">
-        <label class="col-sm-3 control-label"><?=$this->transEsc("hold_required_by")?>:</label>
-        <div class="col-sm-9">
-          <input id="requiredByDate" type="text" name="gatheredDetails[requiredBy]" value="<?=(isset($this->gatheredDetails['requiredBy']) && !empty($this->gatheredDetails['requiredBy'])) ? $this->escapeHtmlAttr($this->gatheredDetails['requiredBy']) : $this->escapeHtmlAttr($this->defaultRequiredDate)?>" size="8" class="form-control"/>
-          (<?=$this->dateTime()->getDisplayDateFormat()?>)
-        </div>
-      </div>
-    <? endif; ?>
+  <? if (in_array("requiredByDate", $this->extraHoldFields)): ?>
+    <div class="form-group hold-required-by">
+      <label class="control-label"><?=$this->transEsc("hold_required_by")?>:</label>
+      <input id="requiredByDate" type="text" name="gatheredDetails[requiredBy]" value="<?=(isset($this->gatheredDetails['requiredBy']) && !empty($this->gatheredDetails['requiredBy'])) ? $this->escapeHtmlAttr($this->gatheredDetails['requiredBy']) : $this->escapeHtmlAttr($this->defaultRequiredDate)?>" size="8" class="form-control"/>
+      (<?=$this->dateTime()->getDisplayDateFormat()?>)
+    </div>
+  <? endif; ?>
+
+  <? if ($this->requestGroupNeeded): ?>
+    <div class="form-group hold-request-group">
+      <?
+        if (isset($this->gatheredDetails['requestGroupId']) && $this->gatheredDetails['requestGroupId'] !== "") {
+            $selected = $this->gatheredDetails['requestGroupId'];
+        } else {
+            $selected = $this->defaultRequestGroup;
+        }
+     ?>
+      <label class="control-label"><?=$this->transEsc("hold_request_group")?>:</label>
+      <select id="requestGroupId" name="gatheredDetails[requestGroupId]" class="form-control">
+        <? if ($selected === false): ?>
+          <option value="" selected="selected">
+            <?=$this->transEsc('select_request_group')?>
+          </option>
+        <? endif; ?>
+        <? foreach ($this->requestGroups as $group): ?>
+          <option value="<?=$this->escapeHtmlAttr($group['id'])?>"<?=($selected == $group['id']) ? ' selected="selected"' : ''?>>
+            <?=$this->transEsc('request_group_' . $group['name'], null, $group['name'])?>
+          </option>
+        <? endforeach; ?>
+      </select>
+    </div>
+  <? endif; ?>
 
+  <? if (in_array("pickUpLocation", $this->extraHoldFields)): ?>
+    <?
+      if (isset($this->gatheredDetails['pickUpLocation']) && $this->gatheredDetails['pickUpLocation'] !== "") {
+        $selected = $this->gatheredDetails['pickUpLocation'];
+      } elseif (isset($this->homeLibrary) && $this->homeLibrary !== "") {
+        $selected = $this->homeLibrary;
+      } else {
+        $selected = $this->defaultPickup;
+      }
+    ?>
     <? if ($this->requestGroupNeeded): ?>
-      <div class="form-group hold-request-group">
-        <?
-          if (isset($this->gatheredDetails['requestGroupId']) && $this->gatheredDetails['requestGroupId'] !== "") {
-              $selected = $this->gatheredDetails['requestGroupId'];
-          } else {
-              $selected = $this->defaultRequestGroup;
-          }
-       ?>
-        <label class="col-sm-3 control-label"><?=$this->transEsc("hold_request_group")?>:</label>
-        <div class="col-sm-9">
-          <select id="requestGroupId" name="gatheredDetails[requestGroupId]" class="form-control">
+      <div class="form-group hold-pickup-location">
+        <label id="pickUpLocationLabel" class="control-label"><i></i> <?=$this->transEsc("pick_up_location")?>:
+          <? if (in_array("requestGroup", $this->extraHoldFields)): ?>
+            <noscript> (<?=$this->transEsc("Please enable JavaScript.")?>)</noscript>
+          <? endif; ?>
+        </label>
+        <select id="pickUpLocation" name="gatheredDetails[pickUpLocation]" data-default="<?=$this->escapeHtmlAttr($selected)?>" class="form-control">
           <? if ($selected === false): ?>
+          <option value="" selected="selected">
+            <?=$this->transEsc('select_pickup_location')?>
+          </option>
+          <? endif; ?>
+        </select>
+      </div>
+    <? elseif ($this->pickup): ?>
+      <div class="form-group hold-pickup-location">
+        <label class="control-label"><?=$this->transEsc("pick_up_location")?>:</label>
+        <select id="pickUpLocation" name="gatheredDetails[pickUpLocation]" class="form-control">
+          <? if ($selected === false && count($this->pickup) > 1): ?>
             <option value="" selected="selected">
-              <?=$this->transEsc('select_request_group')?>
+              <?=$this->transEsc('select_pickup_location')?>
             </option>
           <? endif; ?>
-          <? foreach ($this->requestGroups as $group): ?>
-            <option value="<?=$this->escapeHtmlAttr($group['id'])?>"<?=($selected == $group['id']) ? ' selected="selected"' : ''?>>
-              <?=$this->transEsc('request_group_' . $group['name'], null, $group['name'])?>
+          <? foreach ($this->pickup as $lib): ?>
+            <option value="<?=$this->escapeHtmlAttr($lib['locationID'])?>"<?=($selected == $lib['locationID']) ? ' selected="selected"' : ''?>>
+              <?=$this->transEsc('location_' . $lib['locationDisplay'], null, $lib['locationDisplay'])?>
             </option>
           <? endforeach; ?>
-          </select>
-        </div>
+        </select>
       </div>
+    <? else: ?>
+      <input type="hidden" name="gatheredDetails[pickUpLocation]" value="<?=$this->escapeHtmlAttr($this->defaultPickup)?>" />
     <? endif; ?>
-
-    <? if (in_array("pickUpLocation", $this->extraHoldFields)): ?>
-      <?
-        if (isset($this->gatheredDetails['pickUpLocation']) && $this->gatheredDetails['pickUpLocation'] !== "") {
-            $selected = $this->gatheredDetails['pickUpLocation'];
-        } elseif (isset($this->homeLibrary) && $this->homeLibrary !== "") {
-            $selected = $this->homeLibrary;
-        } else {
-            $selected = $this->defaultPickup;
-        }
-      ?>
-      <? if ($this->requestGroupNeeded): ?>
-        <div class="form-group hold-pickup-location">
-          <label id="pickUpLocationLabel" class="col-sm-3 control-label"><i></i> <?=$this->transEsc("pick_up_location")?>:
-            <? if (in_array("requestGroup", $this->extraHoldFields)): ?>
-              <noscript> (<?=$this->transEsc("Please enable JavaScript.")?>)</noscript>
-            <? endif; ?>
-          </label>
-          <div class="col-sm-9">
-            <select id="pickUpLocation" name="gatheredDetails[pickUpLocation]" data-default="<?=$this->escapeHtmlAttr($selected)?>" class="form-control">
-              <? if ($selected === false): ?>
-              <option value="" selected="selected">
-                <?=$this->transEsc('select_pickup_location')?>
-              </option>
-              <? endif; ?>
-            </select>
-          </div>
-        </div>
-      <? elseif ($this->pickup): ?>
-        <div class="form-group hold-pickup-location">
-          <label class="col-sm-3 control-label"><?=$this->transEsc("pick_up_location")?>:</label>
-          <div class="col-sm-9">
-            <select id="pickUpLocation" name="gatheredDetails[pickUpLocation]" class="form-control">
-            <? if ($selected === false && count($this->pickup) > 1): ?>
-              <option value="" selected="selected">
-                <?=$this->transEsc('select_pickup_location')?>
-              </option>
-            <? endif; ?>
-            <? foreach ($this->pickup as $lib): ?>
-              <option value="<?=$this->escapeHtmlAttr($lib['locationID'])?>"<?=($selected == $lib['locationID']) ? ' selected="selected"' : ''?>>
-                <?=$this->transEsc('location_' . $lib['locationDisplay'], null, $lib['locationDisplay'])?>
-              </option>
-            <? endforeach; ?>
-            </select>
-          </div>
-        </div>
-      <? else: ?>
-        <input type="hidden" name="gatheredDetails[pickUpLocation]" value="<?=$this->escapeHtmlAttr($this->defaultPickup)?>" />
-      <? endif; ?>
-    <? endif; ?>
-    <div class="form-group">
-      <div class="col-sm-9 col-sm-offset-3">
-        <input class="btn btn-primary" type="submit" name="placeHold" value="<?=$this->transEsc('request_submit_text')?>"/>
-      </div>
-    </div>
-  </form>
-</div>
+  <? endif; ?>
+  <div class="form-group">
+    <input class="btn btn-primary" type="submit" name="placeHold" value="<?=$this->transEsc('request_submit_text')?>"/>
+  </div>
+</form>
 
 <?
     // Set up hold script; we do this inline instead of in the header for lightbox compatibility:
diff --git a/themes/bootstrap3/templates/record/illrequest.phtml b/themes/bootstrap3/templates/record/illrequest.phtml
index 03926e2deb59437a67697672d4a8c0b5e75a5e4c..e5cc902422000c5bbdf5f13abaead99f2b2c05bc 100644
--- a/themes/bootstrap3/templates/record/illrequest.phtml
+++ b/themes/bootstrap3/templates/record/illrequest.phtml
@@ -9,119 +9,102 @@
 ?>
 <h2><?=$this->transEsc('ill_request_place_text')?></h2>
 <? if ($this->helpText): ?>
-<p class="helptext"><?=$this->helpText?></p>
+  <p class="help-block"><?=$this->helpText?></p>
 <? endif; ?>
 
-<div id="ILLRequestForm" class="storage-retrieval-request-form">
-  <form name="placeILLRequest" class="form-horizontal" method="post">
-    <?=$this->flashmessages()?>
-    <? if (in_array("itemId", $this->extraFields)): ?>
-      <div class="form-group">
-        <label class="col-sm-3 control-label"><?=$this->transEsc('ill_request_item')?>:</label>
-        <div class="col-sm-9">
-          <select id="itemId" name="gatheredDetails[itemId]" class="form-control">
-          <? foreach ($this->items as $item): ?>
-            <option value="<?=$this->escapeHtmlAttr($item['id'])?>"<?=($this->gatheredDetails['itemId'] == $item['id']) ? ' selected="selected"' : ''?>>
-              <?=$this->escapeHtml($item['name'])?>
-            </option>
-         <? endforeach; ?>
-          </select>
-        </div>
-      </div>
-    <? endif; ?>
-
-    <? if (in_array("pickUpLibrary", $this->extraFields) && !empty($this->pickupLibraries)): ?>
-      <div class="form-group">
-        <label class="col-sm-3 control-label"><?=$this->transEsc("ill_request_pick_up_library")?>:</label>
-        <div class="col-sm-9">
-          <? if (count($this->pickupLibraries) > 1): ?>
-            <select id="pickupLibrary" name="gatheredDetails[pickUpLibrary]" class="form-control">
-            <?
-              if (isset($this->gatheredDetails['pickUpLibrary']) && $this->gatheredDetails['pickUpLibrary'] !== "") {
-                  $selected = $this->gatheredDetails['pickUpLibrary'];
-              } else {
-                  $selected = false;
-              }
-            ?>
-            <? foreach ($this->pickupLibraries as $lib): ?>
-              <option value="<?=$this->escapeHtmlAttr($lib['id'])?>"<?=(($selected === false && isset($lib['isDefault']) && $lib['isDefault']) || $selected === $lib['id']) ? ' selected="selected"' : ''?>>
-                <?=$this->transEsc('library_' . $lib['name'], null, $lib['name'])?>
-              </option>
-            <? endforeach; ?>
-            </select>
-          <? else: ?>
-            <? $lib = $this->pickupLibraries[0]; ?>
-            <input type="text" class="form-control" size="40" readonly="readonly" value="<?=$this->escapeHtmlAttr($this->translate('library_' . $lib['name'], null, $lib['name']))?>" />
-            <input type="hidden" id="pickupLibrary" name="gatheredDetails[pickUpLibrary]" value="<?=$this->escapeHtmlAttr($lib['id'])?>" />
-          <? endif; ?>
-        </div>
-      </div>
-    <? endif; ?>
-
-    <? if (in_array("pickUpLibraryLocation", $this->extraFields)): ?>
-      <div class="form-group">
-        <label id="pickupLibraryLocationLabel" class="col-sm-3 control-label"><i></i>&nbsp;<?=$this->transEsc("ill_request_pick_up_location")?>:<noscript> (<?=$this->transEsc("Please enable JavaScript.")?>)</noscript></label>
-        <div class="col-sm-9">
-          <select id="pickupLibraryLocation" name="gatheredDetails[pickUpLibraryLocation]" class="form-control">
-          </select>
-        </div>
-      </div>
-    <? endif; ?>
+<form id="ILLRequestForm" name="placeILLRequest" class="form-ill-retrieval-request" method="post">
+  <?=$this->flashmessages()?>
+  <? if (in_array("itemId", $this->extraFields)): ?>
+    <div class="form-group">
+      <label class="control-label"><?=$this->transEsc('ill_request_item')?>:</label>
+      <select id="itemId" name="gatheredDetails[itemId]" class="form-control">
+        <? foreach ($this->items as $item): ?>
+          <option value="<?=$this->escapeHtmlAttr($item['id'])?>"<?=($this->gatheredDetails['itemId'] == $item['id']) ? ' selected="selected"' : ''?>>
+            <?=$this->escapeHtml($item['name'])?>
+          </option>
+        <? endforeach; ?>
+      </select>
+    </div>
+  <? endif; ?>
 
-    <? if (in_array("pickUpLocation", $this->extraFields)): ?>
-      <? if (count($this->pickup) > 1): ?>
-        <div class="form-group">
-          <?
-            if (isset($this->gatheredDetails['pickUpLocation']) && $this->gatheredDetails['pickUpLocation'] !== "") {
-                $selected = $this->gatheredDetails['pickUpLocation'];
-            } elseif (isset($this->homeLibrary) && $this->homeLibrary !== "") {
-                $selected = $this->homeLibrary;
-            } else {
-                $selected = $this->defaultPickup;
-            }
-          ?>
-          <label class="col-sm-3 control-label"><?=$this->transEsc("pick_up_location")?>:</label>
-          <div class="col-sm-9">
-            <select name="gatheredDetails[pickUpLocation]" class="form-control">
-            <? foreach ($this->pickup as $lib): ?>
-              <option value="<?=$this->escapeHtmlAttr($lib['locationID'])?>"<?=($selected == $lib['locationID']) ? ' selected="selected"' : ''?>>
-                <?=$this->escapeHtml($lib['locationDisplay'])?>
-              </option>
-            <? endforeach; ?>
-            </select>
-          </div>
-        </div>
+  <? if (in_array("pickUpLibrary", $this->extraFields) && !empty($this->pickupLibraries)): ?>
+    <div class="form-group">
+      <label class="control-label"><?=$this->transEsc("ill_request_pick_up_library")?>:</label>
+      <? if (count($this->pickupLibraries) > 1): ?>
+        <select id="pickupLibrary" name="gatheredDetails[pickUpLibrary]" class="form-control">
+        <?
+          if (isset($this->gatheredDetails['pickUpLibrary']) && $this->gatheredDetails['pickUpLibrary'] !== "") {
+              $selected = $this->gatheredDetails['pickUpLibrary'];
+          } else {
+              $selected = false;
+          }
+        ?>
+        <? foreach ($this->pickupLibraries as $lib): ?>
+          <option value="<?=$this->escapeHtmlAttr($lib['id'])?>"<?=(($selected === false && isset($lib['isDefault']) && $lib['isDefault']) || $selected === $lib['id']) ? ' selected="selected"' : ''?>>
+            <?=$this->transEsc('library_' . $lib['name'], null, $lib['name'])?>
+          </option>
+        <? endforeach; ?>
+        </select>
       <? else: ?>
-        <input type="hidden" name="gatheredDetails[pickUpLocation]" value="<?=$this->escapeHtmlAttr($this->defaultPickup)?>" />
+        <? $lib = $this->pickupLibraries[0]; ?>
+        <input type="text" class="form-control" size="40" readonly="readonly" value="<?=$this->escapeHtmlAttr($this->translate('library_' . $lib['name'], null, $lib['name']))?>" />
+        <input type="hidden" id="pickupLibrary" name="gatheredDetails[pickUpLibrary]" value="<?=$this->escapeHtmlAttr($lib['id'])?>" />
       <? endif; ?>
-    <? endif; ?>
+    </div>
+  <? endif; ?>
 
-    <? if (in_array("requiredByDate", $this->extraFields)): ?>
-      <div class="form-group">
-        <label class="col-sm-3 control-label"><?=$this->transEsc("hold_required_by")?>:</label>
-        <div class="col-sm-9">
-          <input id="requiredByDate" type="text" name="gatheredDetails[requiredBy]" value="<?=(isset($this->gatheredDetails['requiredBy']) && !empty($this->gatheredDetails['requiredBy'])) ? $this->escapeHtmlAttr($this->gatheredDetails['requiredBy']) : $this->escapeHtmlAttr($this->defaultRequiredDate)?>" size="8" class="form-control"/>
-          (<?=$this->dateTime()->getDisplayDateFormat()?>)
-        </div>
-      </div>
-    <? endif; ?>
+  <? if (in_array("pickUpLibraryLocation", $this->extraFields)): ?>
+    <div class="form-group">
+      <label id="pickupLibraryLocationLabel" class="control-label"><i></i>&nbsp;<?=$this->transEsc("ill_request_pick_up_location")?>:<noscript> (<?=$this->transEsc("Please enable JavaScript.")?>)</noscript></label>
+      <select id="pickupLibraryLocation" name="gatheredDetails[pickUpLibraryLocation]" class="form-control"></select>
+    </div>
+  <? endif; ?>
 
-    <? if (in_array("comments", $this->extraFields)): ?>
+  <? if (in_array("pickUpLocation", $this->extraFields)): ?>
+    <? if (count($this->pickup) > 1): ?>
       <div class="form-group">
-        <label class="col-sm-3 control-label"><?=$this->transEsc("Comments")?>:</label>
-        <div class="col-sm-9">
-          <textarea rows="3" cols="20" name="gatheredDetails[comment]" class="form-control"><?=isset($this->gatheredDetails['comment']) ? $this->escapeHtml($this->gatheredDetails['comment']) : ''?></textarea>
-        </div>
+        <?
+          if (isset($this->gatheredDetails['pickUpLocation']) && $this->gatheredDetails['pickUpLocation'] !== "") {
+            $selected = $this->gatheredDetails['pickUpLocation'];
+          } elseif (isset($this->homeLibrary) && $this->homeLibrary !== "") {
+            $selected = $this->homeLibrary;
+          } else {
+            $selected = $this->defaultPickup;
+          }
+        ?>
+        <label class="control-label"><?=$this->transEsc("pick_up_location")?>:</label>
+        <select name="gatheredDetails[pickUpLocation]" class="form-control">
+          <? foreach ($this->pickup as $lib): ?>
+            <option value="<?=$this->escapeHtmlAttr($lib['locationID'])?>"<?=($selected == $lib['locationID']) ? ' selected="selected"' : ''?>>
+              <?=$this->escapeHtml($lib['locationDisplay'])?>
+            </option>
+          <? endforeach; ?>
+        </select>
       </div>
+    <? else: ?>
+      <input type="hidden" name="gatheredDetails[pickUpLocation]" value="<?=$this->escapeHtmlAttr($this->defaultPickup)?>" />
     <? endif; ?>
+  <? endif; ?>
 
+  <? if (in_array("requiredByDate", $this->extraFields)): ?>
     <div class="form-group">
-      <div class="col-sm-9 col-sm-offset-3">
-        <input class="btn btn-primary" type="submit" name="placeILLRequest" value="<?=$this->transEsc('ill_request_submit_text')?>"/>
-      </div>
+      <label class="control-label"><?=$this->transEsc("hold_required_by")?>:</label>
+      <input id="requiredByDate" type="text" name="gatheredDetails[requiredBy]" value="<?=(isset($this->gatheredDetails['requiredBy']) && !empty($this->gatheredDetails['requiredBy'])) ? $this->escapeHtmlAttr($this->gatheredDetails['requiredBy']) : $this->escapeHtmlAttr($this->defaultRequiredDate)?>" size="8" class="form-control"/>
+      (<?=$this->dateTime()->getDisplayDateFormat()?>)
     </div>
-  </form>
-</div>
+  <? endif; ?>
+
+  <? if (in_array("comments", $this->extraFields)): ?>
+    <div class="form-group">
+      <label class="control-label"><?=$this->transEsc("Comments")?>:</label>
+      <textarea rows="3" cols="20" name="gatheredDetails[comment]" class="form-control"><?=isset($this->gatheredDetails['comment']) ? $this->escapeHtml($this->gatheredDetails['comment']) : ''?></textarea>
+    </div>
+  <? endif; ?>
+
+  <div class="form-group">
+    <input class="btn btn-primary" type="submit" name="placeILLRequest" value="<?=$this->transEsc('ill_request_submit_text')?>"/>
+  </div>
+</form>
 
 <?
     // Set up ill script; we do this inline instead of in the header for lightbox compatibility:
diff --git a/themes/bootstrap3/templates/record/save.phtml b/themes/bootstrap3/templates/record/save.phtml
index 8124416e968d4a6802db3077b7b08b0075713244..33ee765c2a4ce1f3fce007312a6926e98145a3a2 100644
--- a/themes/bootstrap3/templates/record/save.phtml
+++ b/themes/bootstrap3/templates/record/save.phtml
@@ -7,15 +7,15 @@
     . '<li>' . $this->recordLink()->getBreadcrumb($this->driver) . '</li> '
     . '<li class="active">' . $this->transEsc('Save') . '</li>';
 ?>
-<h2><?=$this->transEsc("add_favorite_prefix") ?> <span class="title-in-heading"><?=$this->escapeHtml($this->driver->getBreadcrumb())?></span> <?=$this->transEsc("add_favorite_suffix") ?></h2>
-<form id="edit-save-form" class="form-horizontal" method="post" action="<?=$this->recordLink()->getActionUrl($this->driver, 'Save')?>" name="saveRecord" data-lightbox-onclose="checkSaveStatuses();">
+<h2><?=$this->translate("add_to_favorites_html", ['%%title%%' => $this->escapeHtml($this->driver->getBreadcrumb())]) ?></h2>
+<form class="form-record-save" method="post" action="<?=$this->recordLink()->getActionUrl($this->driver, 'Save')?>" name="saveRecord" data-lightbox-onclose="checkSaveStatusesCallback">
   <input type="hidden" name="submit" value="1" />
   <input type="hidden" name="id" value="<?=$this->escapeHtmlAttr($this->driver->getUniqueId()) ?>" />
   <input type="hidden" name="source" value="<?=$this->escapeHtmlAttr($this->driver->getSourceIdentifier())?>" />
   <? if (!empty($this->containingLists)): ?>
     <p><?=$this->transEsc('This item is already part of the following list/lists') ?>:
     <? foreach ($this->containingLists as $i=>$list): ?>
-      <a href="<?=$this->url('userList', array('id' => $list['id'])) ?>" data-lightbox-ignore><?=$this->escapeHtml($list['title'])?></a><? if($i<count($this->containingLists)-1): ?>, <? endif; ?>
+      <a href="<?=$this->url('userList', ['id' => $list['id']]) ?>" data-lightbox-ignore><?=$this->escapeHtml($list['title'])?></a><? if($i<count($this->containingLists)-1): ?>, <? endif; ?>
     <? endforeach; ?>
     </p><hr/>
   <? endif; ?>
@@ -26,9 +26,8 @@
 
   <div class="form-group">
     <? if ($showLists): ?>
-      <label class="col-sm-3 control-label" for="save_list"><?=$this->transEsc('Choose a List') ?></label>
+      <label class="control-label" for="save_list"><?=$this->transEsc('Choose a List') ?></label>
     <? endif; ?>
-    <div class="col-sm-9">
     <? if ($showLists): ?>
       <select class="form-control" id="save_list" name="list">
       <? if ($this->nonContainingLists): ?>
@@ -40,30 +39,23 @@
       <? endif; ?>
       </select>
     <? endif; ?>
-      <a class="btn btn-link" id="make-list" href="<?=$this->url('editList', array('id' => 'NEW'))?>?recordId=<?=urlencode($this->driver->getUniqueId())?>&amp;recordSource=<?=urlencode($this->driver->getSourceIdentifier())?>"><?=$showLists ? $this->transEsc('or create a new list') : $this->transEsc('Create a List'); ?></a>
-    </div>
+    <a class="btn btn-link" id="make-list" href="<?=$this->url('editList', ['id' => 'NEW'])?>?recordId=<?=urlencode($this->driver->getUniqueId())?>&amp;recordSource=<?=urlencode($this->driver->getSourceIdentifier())?>"><?=$showLists ? $this->transEsc('or create a new list') : $this->transEsc('Create a List'); ?></a>
   </div>
 
   <? if ($showLists): ?>
     <? if ($this->usertags()->getMode() !== 'disabled'): ?>
       <div class="form-group">
-        <label class="col-sm-3 control-label" for="add_mytags"><?=$this->transEsc('Add Tags') ?></label>
-        <div class="col-sm-9">
-          <input class="form-control" id="add_mytags" type="text" name="mytags" value=""/>
-          <span class="help-block"><?=$this->transEsc("add_tag_note") ?></span>
-        </div>
+        <label class="control-label" for="add_mytags"><?=$this->transEsc('Add Tags') ?></label>
+        <input class="form-control" id="add_mytags" type="text" name="mytags" value=""/>
+        <span class="help-block"><?=$this->transEsc("add_tag_note") ?></span>
       </div>
     <? endif; ?>
     <div class="form-group">
-      <label class="col-sm-3 control-label" for="add_notes"><?=$this->transEsc('Add a Note') ?></label>
-      <div class="col-sm-9">
-        <textarea class="form-control" id="add_notes" name="notes" rows="3"></textarea>
-      </div>
+      <label class="control-label" for="add_notes"><?=$this->transEsc('Add a Note') ?></label>
+      <textarea class="form-control" id="add_notes" name="notes" rows="3"></textarea>
     </div>
     <div class="form-group">
-      <div class="col-sm-9 col-sm-offset-3">
-        <input class="btn btn-primary" type="submit" value="<?=$this->transEsc('Save') ?>"/>
-      </div>
+      <input class="btn btn-primary" type="submit" value="<?=$this->transEsc('Save') ?>"/>
     </div>
   <? endif; ?>
-</form>
\ No newline at end of file
+</form>
diff --git a/themes/bootstrap3/templates/record/sms.phtml b/themes/bootstrap3/templates/record/sms.phtml
index bada672d77e466031a470868d5def4df3a771e8f..58cd4b2223a23199abf858bc25193af57cdbaac3 100644
--- a/themes/bootstrap3/templates/record/sms.phtml
+++ b/themes/bootstrap3/templates/record/sms.phtml
@@ -8,38 +8,39 @@
     . '<li>' . $this->recordLink()->getBreadcrumb($this->driver) . '</li> '
     . '<li class="active">' . $this->transEsc('Text this') . '</li>';
 ?>
+<? $validatorCallback = <<<JS
+  function phoneNumberValidation() {
+    return phoneNumberFormHandler('sms_to', '{$this->validation}');
+  }
+JS;
+?>
+<?=$this->inlineScript(\Zend\View\Helper\HeadScript::SCRIPT, $validatorCallback, 'SET'); ?>
 <h2><?=$this->transEsc('Text this') ?>: <span class="title-in-heading"><?=$this->escapeHtml($this->driver->getBreadcrumb())?></span></h2>
-<form method="post" name="smsRecord" class="form-horizontal"<? if(isset($this->validation) && !empty($this->validation)):?> data-lightbox-onsubmit="return phoneNumberFormHandler('sms_to', '<?=$this->validation ?>')"<? endif; ?>>
+<form method="post" name="smsRecord" class="form-record-sms"<? if(isset($this->validation) && !empty($this->validation)):?> data-lightbox-onsubmit="phoneNumberValidation"<? endif; ?>>
   <?=$this->flashmessages()?>
   <input type="hidden" name="id" value="<?=$this->escapeHtmlAttr($this->driver->getUniqueId())?>" />
   <input type="hidden" name="source" value="<?=$this->escapeHtmlAttr($this->driver->getSourceIdentifier())?>" />
   <div class="form-group">
-    <label class="col-sm-3 control-label" for="sms_to"><?=$this->transEsc('Number')?>:</label>
-    <div class="col-sm-9">
-      <input id="sms_to" type="tel" name="to" placeholder="<?=$this->transEsc('sms_phone_number')?>" class="form-control"/>
-      <div class="help-block with-errors"></div>
-    </div>
+    <label class="control-label" for="sms_to"><?=$this->transEsc('Number')?>:</label>
+    <input id="sms_to" type="tel" name="to" placeholder="<?=$this->transEsc('sms_phone_number')?>" class="form-control"/>
+    <div class="help-block with-errors"></div>
   </div>
   <? if (is_array($this->carriers) && count($this->carriers) > 1): ?>
     <div class="form-group">
-      <label class="col-sm-3 control-label" for="sms_provider"><?=$this->transEsc('Provider')?>:</label>
-      <div class="col-sm-9">
-        <select id="sms_provider" name="provider" class="form-control">
-          <option selected="selected" value=""><?=$this->transEsc('Select your carrier')?></option>
-          <? foreach ($this->carriers as $val => $details): ?>
-            <option value="<?=$this->escapeHtmlAttr($val)?>"><?=$this->escapeHtml($details['name'])?></option>
-          <? endforeach; ?>
-        </select>
-      </div>
+      <label class="control-label" for="sms_provider"><?=$this->transEsc('Provider')?>:</label>
+      <select id="sms_provider" name="provider" class="form-control">
+        <option selected="selected" value=""><?=$this->transEsc('Select your carrier')?></option>
+        <? foreach ($this->carriers as $val => $details): ?>
+          <option value="<?=$this->escapeHtmlAttr($val)?>"><?=$this->escapeHtml($details['name'])?></option>
+        <? endforeach; ?>
+      </select>
     </div>
   <? else: ?>
-    <? $keys = is_array($this->carriers) ? array_keys($this->carriers) : array(); ?>
+    <? $keys = is_array($this->carriers) ? array_keys($this->carriers) : []; ?>
     <input type="hidden" name="provider" value="<?=isset($keys[0]) ? $keys[0] : ''?>" />
   <? endif; ?>
   <?=$this->recaptcha()->html($this->useRecaptcha) ?>
   <div class="form-group">
-    <div class="col-sm-9 col-sm-offset-3">
-      <input class="btn btn-primary" type="submit" name="submit" value="<?=$this->transEsc('Send Text')?>"/>
-    </div>
+    <input class="btn btn-primary" type="submit" name="submit" value="<?=$this->transEsc('Send Text')?>"/>
   </div>
 </form>
diff --git a/themes/bootstrap3/templates/record/storageretrievalrequest.phtml b/themes/bootstrap3/templates/record/storageretrievalrequest.phtml
index 939bf9d36434ee6c51199d21bba9821ecd9e90db..315f4d77a26dd836caaade4d1c9c4994afd7da69 100644
--- a/themes/bootstrap3/templates/record/storageretrievalrequest.phtml
+++ b/themes/bootstrap3/templates/record/storageretrievalrequest.phtml
@@ -12,104 +12,86 @@
 <p class="helptext"><?=$this->helpText?></p>
 <? endif; ?>
 
-<div class="storage-retrieval-request-form">
-  <form name="placeStorageRetrievalRequest" class="form-horizontal" method="post">
-    <?=$this->flashmessages()?>
-    <? if (in_array("item-issue", $this->extraFields)): ?>
-      <div class="form-group">
-        <div class="col-sm-3 controls">
-          <div class="radio">
-            <label>
-              <input type="radio" id="storageRetrievalRequestItem" name="gatheredDetails[level]" value="copy"<?=!isset($this->gatheredDetails['level']) || $this->gatheredDetails['level'] != 'title' ? ' checked="checked"' : ''?>>
-              <?=$this->transEsc('storage_retrieval_request_selected_item')?>
-            </label>
-          </div>
-
-          <div class="radio">
-            <label>
-              <input type="radio" id="storageRetrievalRequestTitle" name="gatheredDetails[level]" value="title"<?=isset($this->gatheredDetails['level']) && $this->gatheredDetails['level'] == 'title' ? ' checked="checked"' : ''?>>
-              <?=$this->transEsc('storage_retrieval_request_reference')?>
-            </label>
-          </div>
-        </div>
-      </div>
-      <div class="form-group">
-        <div id="storageRetrievalRequestReference" class="storageRetrievalRequestReference">
-          <label class="col-sm-3 control-label"><?=$this->transEsc('storage_retrieval_request_volume')?>:</label>
-          <div class="col-sm-9">
-            <input type="text" name="gatheredDetails[volume]" value="<?=isset($this->gatheredDetails['volume']) ? $this->escapeHtmlAttr($this->gatheredDetails['volume']) : ''?>" class="form-control"/><br/>
-          </div>
-          <label class="col-sm-3 control-label"><?=$this->transEsc('storage_retrieval_request_issue')?>:</label>
-          <div class="col-sm-9">
-            <input type="text" name="gatheredDetails[issue]" value="<?=isset($this->gatheredDetails['issue']) ? $this->escapeHtmlAttr($this->gatheredDetails['issue']) : ''?>" class="form-control"/><br/>
-          </div>
-          <label class="col-sm-3 control-label"><?=$this->transEsc('storage_retrieval_request_year')?>:</label>
-          <div class="col-sm-9">
-            <input type="text" name="gatheredDetails[year]" value="<?=isset($this->gatheredDetails['year']) ? $this->escapeHtmlAttr($this->gatheredDetails['year']) : ''?>" class="form-control"/><br/>
-          </div>
-        </div>
+<form name="placeStorageRetrievalRequest" class="form-storage-retrieval-request" method="post">
+  <?=$this->flashmessages()?>
+  <? if (in_array("item-issue", $this->extraFields)): ?>
+    <div class="form-group controls">
+      <div class="radio">
+        <label>
+          <input type="radio" id="storageRetrievalRequestItem" name="gatheredDetails[level]" value="copy"<?=!isset($this->gatheredDetails['level']) || $this->gatheredDetails['level'] != 'title' ? ' checked="checked"' : ''?>>
+          <?=$this->transEsc('storage_retrieval_request_selected_item')?>
+        </label>
       </div>
-    <? endif; ?>
 
-    <? if (in_array("requiredByDate", $this->extraFields)): ?>
-      <div class="form-group">
-        <label class="col-sm-3 control-label"><?=$this->transEsc("hold_required_by")?>:</label>
-        <div class="col-sm-9">
-          <input id="requiredByDate" type="text" name="gatheredDetails[requiredBy]" value="<?=(isset($this->gatheredDetails['requiredBy']) && !empty($this->gatheredDetails['requiredBy'])) ? $this->escapeHtmlAttr($this->gatheredDetails['requiredBy']) : $this->escapeHtmlAttr($this->defaultRequiredDate)?>" size="8" class="form-control"/>
-          (<?=$this->dateTime()->getDisplayDateFormat()?>)
-        </div>
+      <div class="radio">
+        <label>
+          <input type="radio" id="storageRetrievalRequestTitle" name="gatheredDetails[level]" value="title"<?=isset($this->gatheredDetails['level']) && $this->gatheredDetails['level'] == 'title' ? ' checked="checked"' : ''?>>
+          <?=$this->transEsc('storage_retrieval_request_reference')?>
+        </label>
       </div>
-    <? endif; ?>
+    </div>
+    <div class="form-group">
+      <div id="storageRetrievalRequestReference" class="storageRetrievalRequestReference">
+        <label class="control-label"><?=$this->transEsc('storage_retrieval_request_volume')?>:</label>
+        <input type="text" name="gatheredDetails[volume]" value="<?=isset($this->gatheredDetails['volume']) ? $this->escapeHtmlAttr($this->gatheredDetails['volume']) : ''?>" class="form-control"/><br/>
+        <label class="control-label"><?=$this->transEsc('storage_retrieval_request_issue')?>:</label>
+        <input type="text" name="gatheredDetails[issue]" value="<?=isset($this->gatheredDetails['issue']) ? $this->escapeHtmlAttr($this->gatheredDetails['issue']) : ''?>" class="form-control"/><br/>
+        <label class="control-label"><?=$this->transEsc('storage_retrieval_request_year')?>:</label>
+        <input type="text" name="gatheredDetails[year]" value="<?=isset($this->gatheredDetails['year']) ? $this->escapeHtmlAttr($this->gatheredDetails['year']) : ''?>" class="form-control"/><br/>
+      </div>
+    </div>
+  <? endif; ?>
 
-    <? if (in_array("pickUpLocation", $this->extraFields)): ?>
-      <? if ($this->pickup): ?>
-        <div class="form-group">
-          <?
-            if (isset($this->gatheredDetails['pickUpLocation']) && $this->gatheredDetails['pickUpLocation'] !== "") {
-                $selected = $this->gatheredDetails['pickUpLocation'];
-            } elseif (isset($this->homeLibrary) && $this->homeLibrary !== "") {
-                $selected = $this->homeLibrary;
-            } else {
-                $selected = $this->defaultPickup;
-            }
-          ?>
-          <label class="col-sm-3 control-label"><?=$this->transEsc("pick_up_location")?>:</label>
-          <div class="col-sm-9">
-            <select name="gatheredDetails[pickUpLocation]" class="form-control">
-            <? if ($selected === false && count($this->pickup) > 1): ?>
-              <option value="" selected="selected">
-                <?=$this->transEsc('select_pickup_location')?>
-              </option>
-            <? endif; ?>
-            <? foreach ($this->pickup as $lib): ?>
-              <option value="<?=$this->escapeHtmlAttr($lib['locationID'])?>"<?=($selected == $lib['locationID']) ? ' selected="selected"' : ''?>>
-                <?=$this->transEsc('location_' . $lib['locationDisplay'], null, $lib['locationDisplay'])?>
-              </option>
-            <? endforeach; ?>
-            </select>
-          </div>
-        </div>
-      <? else: ?>
-        <input type="hidden" name="gatheredDetails[pickUpLocation]" value="<?=$this->escapeHtmlAttr($this->defaultPickup)?>" />
-      <? endif; ?>
-    <? endif; ?>
+  <? if (in_array("requiredByDate", $this->extraFields)): ?>
+    <div class="form-group">
+      <label class="control-label"><?=$this->transEsc("hold_required_by")?>:</label>
+      <input id="requiredByDate" type="text" name="gatheredDetails[requiredBy]" value="<?=(isset($this->gatheredDetails['requiredBy']) && !empty($this->gatheredDetails['requiredBy'])) ? $this->escapeHtmlAttr($this->gatheredDetails['requiredBy']) : $this->escapeHtmlAttr($this->defaultRequiredDate)?>" size="8" class="form-control"/>
+      (<?=$this->dateTime()->getDisplayDateFormat()?>)
+    </div>
+  <? endif; ?>
 
-    <? if (in_array("comments", $this->extraFields)): ?>
+  <? if (in_array("pickUpLocation", $this->extraFields)): ?>
+    <? if ($this->pickup): ?>
       <div class="form-group">
-        <label class="col-sm-3 control-label"><?=$this->transEsc("Comments")?>:</label>
-        <div class="col-sm-9">
-          <textarea rows="3" cols="20" name="gatheredDetails[comment]" class="form-control"><?=isset($this->gatheredDetails['comment']) ? $this->escapeHtml($this->gatheredDetails['comment']) : ''?></textarea>
-        </div>
+        <?
+          if (isset($this->gatheredDetails['pickUpLocation']) && $this->gatheredDetails['pickUpLocation'] !== "") {
+            $selected = $this->gatheredDetails['pickUpLocation'];
+          } elseif (isset($this->homeLibrary) && $this->homeLibrary !== "") {
+            $selected = $this->homeLibrary;
+          } else {
+            $selected = $this->defaultPickup;
+          }
+        ?>
+        <label class="control-label"><?=$this->transEsc("pick_up_location")?>:</label>
+        <select name="gatheredDetails[pickUpLocation]" class="form-control">
+          <? if ($selected === false && count($this->pickup) > 1): ?>
+            <option value="" selected="selected">
+              <?=$this->transEsc('select_pickup_location')?>
+            </option>
+          <? endif; ?>
+          <? foreach ($this->pickup as $lib): ?>
+            <option value="<?=$this->escapeHtmlAttr($lib['locationID'])?>"<?=($selected == $lib['locationID']) ? ' selected="selected"' : ''?>>
+              <?=$this->transEsc('location_' . $lib['locationDisplay'], null, $lib['locationDisplay'])?>
+            </option>
+          <? endforeach; ?>
+        </select>
       </div>
+    <? else: ?>
+      <input type="hidden" name="gatheredDetails[pickUpLocation]" value="<?=$this->escapeHtmlAttr($this->defaultPickup)?>" />
     <? endif; ?>
+  <? endif; ?>
 
+  <? if (in_array("comments", $this->extraFields)): ?>
     <div class="form-group">
-      <div class="col-sm-9 col-sm-offset-3">
-        <input class="btn btn-primary" type="submit" name="placeStorageRetrievalRequest" value="<?=$this->transEsc('storage_retrieval_request_submit_text')?>"/>
-      </div>
+      <label class="control-label"><?=$this->transEsc("Comments")?>:</label>
+      <textarea rows="3" cols="20" name="gatheredDetails[comment]" class="form-control"><?=isset($this->gatheredDetails['comment']) ? $this->escapeHtml($this->gatheredDetails['comment']) : ''?></textarea>
     </div>
-  </form>
-</div>
+  <? endif; ?>
+
+  <div class="form-group">
+    <input class="btn btn-primary" type="submit" name="placeStorageRetrievalRequest" value="<?=$this->transEsc('storage_retrieval_request_submit_text')?>"/>
+  </div>
+</form>
 
 <script type="text/javascript">
 $(document).ready(function() {
diff --git a/themes/bootstrap3/templates/record/taglist.phtml b/themes/bootstrap3/templates/record/taglist.phtml
index aa6de6c4ed32013ef08bc4a365950f20f288333f..b0bb61475f993a8bfdc18a93ab732ff2582d8bb8 100644
--- a/themes/bootstrap3/templates/record/taglist.phtml
+++ b/themes/bootstrap3/templates/record/taglist.phtml
@@ -23,4 +23,4 @@
   <? else: ?>
     <?=$this->transEsc('No Tags')?>, <?=$this->transEsc('Be the first to tag this record')?>!
   <? endif; ?>
-</div>
\ No newline at end of file
+</div>
diff --git a/themes/bootstrap3/templates/record/view.phtml b/themes/bootstrap3/templates/record/view.phtml
index d17786fd5b43a7ddcd00221c1b919edda019ba75..e91119ba4e7d483401dc4a22dedfd76b9107bfe9 100644
--- a/themes/bootstrap3/templates/record/view.phtml
+++ b/themes/bootstrap3/templates/record/view.phtml
@@ -35,7 +35,10 @@
       <? endif; ?>
       <li class="disabled"><a href="#">&laquo; <?=$this->transEsc('Prev')?></a></li>
     <? endif; ?>
-    #<?=$this->localizedNumber($this->scrollData['currentPosition']) . ' ' . $this->transEsc('of') . ' ' . $this->localizedNumber($this->scrollData['resultTotal']) . ' ' . $this->transEsc('results') ?>
+    <?=$this->transEsc('of_num_results', [
+      '%%position%%' => $this->localizedNumber($this->scrollData['currentPosition']),
+      '%%total%%' => $this->localizedNumber($this->scrollData['resultTotal'])
+    ]) ?>
     <? if ($this->scrollData['nextRecord']): ?>
       <li>
         <a href="<?=$this->recordLink()->getUrl($this->scrollData['nextRecord'])?>" title="<?=$this->transEsc('Next Search Result')?>" rel="nofollow"><?=$this->transEsc('Next')?> &raquo;</a>
@@ -56,7 +59,7 @@
 
 <?=$this->record($this->driver)->getToolbar()?>
 
-<div class="record source<?=$this->escapeHtmlAttr($this->driver->getSourceIdentifier())?> row">
+<div class="record source<?=$this->escapeHtmlAttr($this->driver->getSourceIdentifier())?>">
   <div class="<?=$this->layoutClass('mainbody')?>">
     <input type="hidden" value="<?=$this->escapeHtmlAttr($this->driver->getUniqueId())?>" class="hiddenId" />
     <input type="hidden" value="<?=$this->escapeHtmlAttr($this->driver->getSourceIdentifier()) ?>" class="hiddenSource" />
@@ -70,7 +73,7 @@
           <? foreach ($this->tabs as $tab => $obj): ?>
             <? // add current tab to breadcrumbs if applicable:
               $desc = $obj->getDescription();
-              $tab_classes = array();
+              $tab_classes = [];
               if (0 === strcasecmp($this->activeTab, $tab)) {
                 if (!$this->loadInitialTabWithAjax || !$obj->supportsAjax()) {
                   $tab_classes[] = 'active';
diff --git a/themes/bootstrap3/templates/records/home.phtml b/themes/bootstrap3/templates/records/home.phtml
index dbf1e7cebcde81c81cd16a35f803e6602ace6b9a..2aa66836fa1c09bcc9741a1b6fbf15acfc87a167 100644
--- a/themes/bootstrap3/templates/records/home.phtml
+++ b/themes/bootstrap3/templates/records/home.phtml
@@ -7,4 +7,4 @@
 
     // Disable top search box -- it doesn't make sense in this module.
     $this->layout()->searchbox = false;
-?>
\ No newline at end of file
+?>
diff --git a/themes/bootstrap3/templates/search/advanced.phtml b/themes/bootstrap3/templates/search/advanced.phtml
index c1774e75c4f95a85a471fa5789a84a99511cc09e..779b5a8ea594c3d167e13fe118238eac1f8e66ac 100644
--- a/themes/bootstrap3/templates/search/advanced.phtml
+++ b/themes/bootstrap3/templates/search/advanced.phtml
@@ -3,4 +3,4 @@
   // standard advanced search layout:
   $this->extraAdvancedControls = $this->render('search/advanced/solr.phtml');
   echo $this->render('search/advanced/layout.phtml');
-?>
\ No newline at end of file
+?>
diff --git a/themes/bootstrap3/templates/search/advanced/build_page.phtml b/themes/bootstrap3/templates/search/advanced/build_page.phtml
index 35a717fe42aa0c0c632322a9270b2221ce609ca9..cfb4ad36d925c51a4be2cb0202b05a29919c2747 100644
--- a/themes/bootstrap3/templates/search/advanced/build_page.phtml
+++ b/themes/bootstrap3/templates/search/advanced/build_page.phtml
@@ -3,12 +3,12 @@ $(document).ready(function() {
   $('#groupJoin').addClass('hidden');
   $('#groupPlaceHolder').removeClass('hidden');
   $('#new_search_template').addClass('hidden').detach().appendTo('[role="main"]');
-  $('#new_search_template').find('.search').removeAttr('id');
+  $('#new_search_template').find('.adv-search').removeAttr('id');
   $('#new_search_template').find('input').removeAttr('value');
   $('#new_search_template').find('option').removeAttr('selected');
   $('#new_group_template').addClass('hidden').detach().appendTo('[role="main"]');
-  $('#new_group_template').find('.group').removeAttr('id');
-  $('#new_group_template .search').remove();
+  $('#new_group_template').find('.adv-group').removeAttr('id');
+  $('#new_group_template .adv-search').remove();
   $('#advSearchForm .no-js').remove();
   // Build page
   <? if (isset($this->searchDetails) && is_object($this->searchDetails)): ?>
@@ -26,4 +26,4 @@ $(document).ready(function() {
     addSearch(group);
     addSearch(group);
   <? endif; ?>
-});
\ No newline at end of file
+});
diff --git a/themes/bootstrap3/templates/search/advanced/build_page_eds.phtml b/themes/bootstrap3/templates/search/advanced/build_page_eds.phtml
index 0ebe141a4b27b01436d8f0681b0627c273755edd..6fe08fcebccdf177a74620e1e029da60bb95d1bb 100644
--- a/themes/bootstrap3/templates/search/advanced/build_page_eds.phtml
+++ b/themes/bootstrap3/templates/search/advanced/build_page_eds.phtml
@@ -2,11 +2,11 @@ $(document).ready(function() {
   // Switch and prepare for JS mode
   $('#groupPlaceHolder').addClass('hidden');
   $('#new_search_template').addClass('hidden').detach().appendTo('[role="main"]');
-  $('#new_search_template').find('.search').removeAttr('id');
+  $('#new_search_template').find('.adv-search').removeAttr('id');
   $('#new_search_template').find('input').removeAttr('value');
   $('#new_search_template').find('option').removeAttr('selected');
   $('#new_group_template').addClass('hidden').detach().appendTo('[role="main"]');
-  $('#new_group_template .search').remove();
+  $('#new_group_template .adv-search').remove();
   $('#advSearchForm .no-js').remove();
   $('#groupJoin').remove();
   // Build page
@@ -33,4 +33,4 @@ $(document).ready(function() {
     addSearch(new_group);
     addSearch(new_group);
   <? endif; ?>
-});
\ No newline at end of file
+});
diff --git a/themes/bootstrap3/templates/search/advanced/checkbox-filters.phtml b/themes/bootstrap3/templates/search/advanced/checkbox-filters.phtml
index 1af8c77a7bc1a5066a29ce5f1887c049f47dc59c..8d075ae4c4227d6999aa67f7db60a86d761f965c 100644
--- a/themes/bootstrap3/templates/search/advanced/checkbox-filters.phtml
+++ b/themes/bootstrap3/templates/search/advanced/checkbox-filters.phtml
@@ -1,5 +1,5 @@
 <? if (isset($this->checkboxFacets) && count($this->checkboxFacets) > 0): ?>
-  <fieldset class="checkboxFilter">
+  <div class="checkbox-filters">
     <? foreach ($this->checkboxFacets as $current): ?>
       <div class="checkbox">
         <label>
@@ -8,5 +8,5 @@
         </label>
       </div>
     <? endforeach; ?>
-  </fieldset>
-<?endif;?>
\ No newline at end of file
+  </div>
+<?endif;?>
diff --git a/themes/bootstrap3/templates/search/advanced/eds.phtml b/themes/bootstrap3/templates/search/advanced/eds.phtml
index a3fb6703c76984403a66acd6a91d66f9d2049ada..b2fa127af21a53502f2d42e8266d74ccfe770aeb 100644
--- a/themes/bootstrap3/templates/search/advanced/eds.phtml
+++ b/themes/bootstrap3/templates/search/advanced/eds.phtml
@@ -1,110 +1,108 @@
-<div class="clearfix"></div>
-<div class="row">
-  <? if (!empty($this->expanderList)): ?>
-    <fieldset class="col-sm-4">
-      <legend><?=$this->transEsc('eds_modes_and_expanders')?></legend>
-      <? foreach ($this->expanderList as $field => $expander):
-        $value = $expander['Value'] ?>
-        <div class="checkbox">
-          <label for="expand_<?=$this->escapeHtmlAttr(str_replace(' ', '+', $field))?>">
-            <input id="expand_<?=$this->escapeHtmlAttr(str_replace(' ', '+', $field))?>" type="checkbox" <?=(isset($expander['selected']) && $expander['selected'])?'checked="checked"':''?> name="filter[]" value="EXPAND:<?=$this->escapeHtmlAttr($value)?>">
-            <?=$this->transEsc('eds_expander_' . $value, array(), $expander['Label'])?>
-          </label>
-        </div>
-      <? endforeach; ?>
-
-      <label class="displayBlock" for="searchModes"><?=$this->transEsc('Search Mode')?></label>
-      <select id="searchMode_<?=$this->escapeHtmlAttr($field)?>" name="filter[]" class="form-control">
-        <? foreach ($this->searchModes as $field => $searchMode):
-          $value = $searchMode['Value'] ?>
-          <option <?=(isset($searchMode['selected']) && $searchMode['selected'])?'selected="selected"':''?> value="SEARCHMODE:<?=$this->escapeHtmlAttr($value)?>">
-            <?= /* 'Label' comes from API and is always in English; try to translate structured value before using it: */ $this->transEsc('eds_mode_' . $value, array(), $searchMode['Label']) ?>
-          </option>
-        <? endforeach; ?>
-      </select>
-    </fieldset>
-  <? endif; ?>
+<? if (!empty($this->expanderList)): ?>
+  <fieldset class="eds">
+    <legend><?=$this->transEsc('eds_modes_and_expanders')?></legend>
+    <? foreach ($this->expanderList as $field => $expander):
+      $value = $expander['Value'] ?>
+      <div class="checkbox">
+        <label for="expand_<?=$this->escapeHtmlAttr(str_replace(' ', '+', $field))?>">
+          <input id="expand_<?=$this->escapeHtmlAttr(str_replace(' ', '+', $field))?>" type="checkbox" <?=(isset($expander['selected']) && $expander['selected'])?'checked="checked"':''?> name="filter[]" value="EXPAND:<?=$this->escapeHtmlAttr($value)?>">
+          <?=$this->transEsc('eds_expander_' . $value, array(), $expander['Label'])?>
+        </label>
+      </div>
+    <? endforeach; ?>
 
-  <? if (!empty($this->limiterList)): ?>
-    <fieldset class="col-sm-4">
-      <legend><?=$this->transEsc('Limit To')?></legend>
-      <? foreach ($this->limiterList as $field => $facet): ?>
-        <? switch($facet['Type']){
-            case 'multiselectvalue': ?>
-              <label for="limit_<?=$this->escapeHtmlAttr(str_replace(' ', '+', $field))?>"><?=$this->transEsc($facet['Label'])?></label><br/>
-              <select id="limit_<?=$this->escapeHtmlAttr($field)?>" name="filter[]" multiple="multiple" size="10" class="form-control">
-                <? foreach ($facet['LimiterValues'] as $id => $facetValue): ?>
-                  <? $value = $facetValue['Value']; ?>
-                  <option value="<?='LIMIT|'.$this->escapeHtmlAttr($field . ':' . $facetValue['Value'])?>"<?=(isset($facetValue['selected']) && $facetValue['selected'])?' selected="selected"':''?>><?=$this->escapeHtml($facetValue['Value'])?></option>
-                <? endforeach; ?>
-              </select>
-              <!-- <br/> -->
-              <? break;
-            case 'select':
-              $value = $facet['LimiterValues'][0]['Value'] ?>
-              <div class="checkbox">
-                <label for="limit_<?=$this->escapeHtmlAttr(str_replace(' ', '+', $field))?>">
-                  <input id="limit_<?=$this->escapeHtmlAttr(str_replace(' ', '+', $field))?>" type="checkbox" <?=(isset($facet['LimiterValues'][0]['selected']) && $facet['LimiterValues'][0]['selected'])?'checked="checked"':''?> name="filter[]" value="<?=$this->escapeHtmlAttr('LIMIT|'.$field . ':' . $value)?>">
-                  <?=$this->transEsc('eds_limiter_' . $field, array(), $facet['Label'])?>
-                </label>
-              </div>
-              <? break;
-            case 'text': ?>
-              <!-- not implemented -->
-              <? break;
-            case 'numeric':?>
-              <!-- not implemented -->
-              <? break;
-            case 'numericrange':?>
-              <!-- not implemented -->
-              <? break;
-            case 'ymrange': ?>
-              <!-- not implemented -->
-              <? break;
-            case 'yrange': ?>
-              <!-- not implemented -->
-              <? break;
-            case 'historicalrange':?>
-              <!-- not implemented -->
-              <? break;
-            case 'singleselectvalue':?>
-              <!-- not implemented -->
-              <? break;
-          }; ?>
+    <label for="searchModes"><?=$this->transEsc('Search Mode')?></label>
+    <select id="searchMode_<?=$this->escapeHtmlAttr($field)?>" name="filter[]" class="form-control">
+      <? foreach ($this->searchModes as $field => $searchMode):
+        $value = $searchMode['Value'] ?>
+        <option <?=(isset($searchMode['selected']) && $searchMode['selected'])?'selected="selected"':''?> value="SEARCHMODE:<?=$this->escapeHtmlAttr($value)?>">
+          <?= /* 'Label' comes from API and is always in English; try to translate structured value before using it: */ $this->transEsc('eds_mode_' . $value, array(), $searchMode['Label']) ?>
+        </option>
       <? endforeach; ?>
-    </fieldset>
-  <? endif; ?>
-  <? if (isset($this->dateRangeLimit)): ?>
-    <fieldset class="col-sm-4">
-      <legend><?=$this->transEsc('adv_search_year')?></legend>
-      <input type="hidden" name="daterange[]" value="PublicationDate"/>
-      <div class="row">
-        <div class="col-sm-6">
-          <label for="PublicationDatefrom"><?=$this->transEsc('date_from')?>:</label>
-          <input type="text" name="PublicationDatefrom" id="PublicationDatefrom" value="<?=$this->escapeHtmlAttr($this->dateRangeLimit[0])?>" class="form-control"/>
-        </div>
-        <div class="col-sm-6">
-          <label for="PublicationDateto"><?=$this->transEsc('date_to')?>:</label>
-          <input type="text" name="PublicationDateto" id="PublicationDateto" value="<?=$this->escapeHtmlAttr($this->dateRangeLimit[1])?>" class="form-control"/>
-        </div>
+    </select>
+  </fieldset>
+<? endif; ?>
+
+<? if (!empty($this->limiterList)): ?>
+  <fieldset class="eds">
+    <legend><?=$this->transEsc('Limit To')?></legend>
+    <? foreach ($this->limiterList as $field => $facet): ?>
+      <? switch($facet['Type']){
+          case 'multiselectvalue': ?>
+            <label for="limit_<?=$this->escapeHtmlAttr(str_replace(' ', '+', $field))?>"><?=$this->transEsc($facet['Label'])?></label><br/>
+            <select id="limit_<?=$this->escapeHtmlAttr($field)?>" name="filter[]" multiple="multiple" size="10" class="form-control">
+              <? foreach ($facet['LimiterValues'] as $id => $facetValue): ?>
+                <? $value = $facetValue['Value']; ?>
+                <option value="<?='LIMIT|'.$this->escapeHtmlAttr($field . ':' . $facetValue['Value'])?>"<?=(isset($facetValue['selected']) && $facetValue['selected'])?' selected="selected"':''?>><?=$this->escapeHtml($facetValue['Value'])?></option>
+              <? endforeach; ?>
+            </select>
+            <!-- <br/> -->
+            <? break;
+          case 'select':
+            $value = $facet['LimiterValues'][0]['Value'] ?>
+            <div class="checkbox">
+              <label for="limit_<?=$this->escapeHtmlAttr(str_replace(' ', '+', $field))?>">
+                <input id="limit_<?=$this->escapeHtmlAttr(str_replace(' ', '+', $field))?>" type="checkbox" <?=(isset($facet['LimiterValues'][0]['selected']) && $facet['LimiterValues'][0]['selected'])?'checked="checked"':''?> name="filter[]" value="<?=$this->escapeHtmlAttr('LIMIT|'.$field . ':' . $value)?>">
+                <?=$this->transEsc('eds_limiter_' . $field, array(), $facet['Label'])?>
+              </label>
+            </div>
+            <? break;
+          case 'text': ?>
+            <!-- not implemented -->
+            <? break;
+          case 'numeric':?>
+            <!-- not implemented -->
+            <? break;
+          case 'numericrange':?>
+            <!-- not implemented -->
+            <? break;
+          case 'ymrange': ?>
+            <!-- not implemented -->
+            <? break;
+          case 'yrange': ?>
+            <!-- not implemented -->
+            <? break;
+          case 'historicalrange':?>
+            <!-- not implemented -->
+            <? break;
+          case 'singleselectvalue':?>
+            <!-- not implemented -->
+            <? break;
+        }; ?>
+    <? endforeach; ?>
+  </fieldset>
+<? endif; ?>
+<? if (isset($this->dateRangeLimit)): ?>
+  <fieldset class="eds">
+    <legend><?=$this->transEsc('adv_search_year')?></legend>
+    <input type="hidden" name="daterange[]" value="PublicationDate"/>
+    <div class="date-fields">
+      <div class="date-from">
+        <label for="PublicationDatefrom"><?=$this->transEsc('date_from')?>:</label>
+        <input type="text" name="PublicationDatefrom" id="PublicationDatefrom" value="<?=$this->escapeHtmlAttr($this->dateRangeLimit[0])?>" class="form-control"/>
+      </div>
+      <div class="date-to">
+        <label for="PublicationDateto"><?=$this->transEsc('date_to')?>:</label>
+        <input type="text" name="PublicationDateto" id="PublicationDateto" value="<?=$this->escapeHtmlAttr($this->dateRangeLimit[1])?>" class="form-control"/>
+      </div>
+    </div>
+      <div class="slider-container">
+        <input type="text" id="PublicationDateSlider">
       </div>
-        <div class="slider-container">
-          <input type="text" id="PublicationDateSlider">
-        </div>
-        <?
-          $this->headScript()->appendFile('vendor/bootstrap-slider.js');
-          $this->headLink()->appendStylesheet('vendor/bootstrap-slider.min.css');
-          $min = !empty($current['values'][0]) ? min($current['values'][0], 1400) : 1400;
-          $future = date('Y', time()+31536000);
-          $max = !empty($current['values'][1]) ? max($future, $current['values'][1]) : $future;
-          $low  = !empty($current['values'][0]) ? $current['values'][0] : $min;
-          $high = !empty($current['values'][1]) ? $current['values'][1] : $max;
-          $min = intval($min);
-          $max = intval($max);
-          $low = intval($low);
-          $high = intval($high);
-          $init = !empty($current['values'][0]) ? 'fillTexts()' : '';
-          $script = <<<JS
+      <?
+        $this->headScript()->appendFile('vendor/bootstrap-slider.min.js');
+        $this->headLink()->appendStylesheet('vendor/bootstrap-slider.min.css');
+        $min = !empty($current['values'][0]) ? min($current['values'][0], 1400) : 1400;
+        $future = date('Y', time()+31536000);
+        $max = !empty($current['values'][1]) ? max($future, $current['values'][1]) : $future;
+        $low  = !empty($current['values'][0]) ? $current['values'][0] : $min;
+        $high = !empty($current['values'][1]) ? $current['values'][1] : $max;
+        $min = intval($min);
+        $max = intval($max);
+        $low = intval($low);
+        $high = intval($high);
+        $init = !empty($current['values'][0]) ? 'fillTexts()' : '';
+        $script = <<<JS
 $(document).ready(function() {
   var fillTexts = function() {
     var v = PublicationDateSlider.getValue();
@@ -124,8 +122,7 @@ $(document).ready(function() {
   {$init}
 });
 JS;
-      ?>
-      <?=$this->inlineScript(\Zend\View\Helper\HeadScript::SCRIPT, $script, 'SET'); ?>
-    </fieldset>
-  <? endif; ?>
-</div>
+    ?>
+    <?=$this->inlineScript(\Zend\View\Helper\HeadScript::SCRIPT, $script, 'SET'); ?>
+  </fieldset>
+<? endif; ?>
diff --git a/themes/bootstrap3/templates/search/advanced/layout.phtml b/themes/bootstrap3/templates/search/advanced/layout.phtml
index 4b68fd43938101432c7936da8be5b13cb4a1ece4..0937a28a066621c8bca05b5b43836d5906902608 100644
--- a/themes/bootstrap3/templates/search/advanced/layout.phtml
+++ b/themes/bootstrap3/templates/search/advanced/layout.phtml
@@ -69,128 +69,115 @@
         <input type="hidden" name="hiddenFilters[]" value="<?=$this->escapeHtmlAttr($key) . ':' . $this->escapeHtmlAttr($value)?>" />
       <? endforeach; ?>
     <? endforeach; ?>
-    <div class="row">
-      <div class="<?=$this->layoutClass('mainbody')?>">
-        <? $lastSort = $this->searchMemory()->getLastSort($this->searchClassId); ?>
-        <? if (!empty($lastSort)): ?>
-          <input type="hidden" name="sort" value="<?=$this->escapeHtmlAttr($lastSort)?>" />
-        <? endif; ?>
-        <div class="clearfix">
-          <h2 class="pull-left flip"><?=$this->transEsc('Advanced Search')?></h2>
-          <div id="groupJoin" class="form-inline pull-right flip">
-            <label for="groupJoinOptions"><?=$this->transEsc("search_match")?>:</label>
-            <select id="groupJoinOptions" name="join" class="form-control">
-              <option value="AND"<? if($searchDetails && $searchDetails->getOperator()=='ALL'):?> selected<?endif?>><?= $this->transEsc('group_AND') ?></option>
-              <option value="OR"<? if($searchDetails && $searchDetails->getOperator()=='OR'):?> selected<?endif?>><?= $this->transEsc('group_OR') ?></option>
-            </select>
-          </div>
+    <div class="<?=$this->layoutClass('mainbody')?>">
+      <? $lastSort = $this->searchMemory()->getLastSort($this->searchClassId); ?>
+      <? if (!empty($lastSort)): ?>
+        <input type="hidden" name="sort" value="<?=$this->escapeHtmlAttr($lastSort)?>" />
+      <? endif; ?>
+      <div class="clearfix">
+        <h2 class="pull-left flip"><?=$this->transEsc('Advanced Search')?></h2>
+        <div id="groupJoin" class="form-inline pull-right flip">
+          <label for="groupJoinOptions"><?=$this->transEsc("search_match")?>:</label>
+          <select id="groupJoinOptions" name="join" class="form-control">
+            <option value="AND"<? if($searchDetails && $searchDetails->getOperator()=='ALL'):?> selected<?endif?>><?= $this->transEsc('group_AND') ?></option>
+            <option value="OR"<? if($searchDetails && $searchDetails->getOperator()=='OR'):?> selected<?endif?>><?= $this->transEsc('group_OR') ?></option>
+          </select>
         </div>
-        <? /* An empty div. This is the target for the javascript that builds this screen */ ?>
-        <span id="groupPlaceHolder" class="hidden">
-          <i class="fa fa-plus-circle" aria-hidden="true"></i> <a href="#" onClick="addGroup()"><?= $this->transEsc('add_search_group') ?></a>
-        </span>
-        <? /* fallback to a fixed set of search groups/fields if JavaScript is turned off */ ?>
-        <div class="no-js">
-          <? if(!empty($this->formOverride)): ?>
-            <?=$this->formOverride ?>
-          <? else: ?>
-            <? for($group=0 ; $group<3 || $group<=$setGroupCount ; $group++): ?>
-              <? if($group == 0): ?>
-                <div id="new_group_template">
-              <? endif; ?>
-              <div id="group<?=$group ?>" class="group row">
-                <a href="#" class="group-close hidden" title="<?=$this->transEsc("del_search")?>">&times;</a>
-                <div class="col-sm-9">
-                  <div class="row">
-                    <div class="col-sm-3">
-                      <label class="help-block"><?=$this->transEsc("adv_search_label")?>:</label>
-                    </div>
-                    <div class="col-sm-9">
-                      <? for($search=0 ; $search<3 || (isset($setQueries[$group]) && $search<count($setQueries[$group])) ; $search++): ?>
-                        <? if($group == 0 && $search == 0): ?>
-                          <div id="new_search_template">
-                        <? endif; ?>
-                        <div id="search<?=$group.'_'.$search ?>" class="search">
-                          <div class="row">
-                            <div class="col-sm-7 left">
-                              <input name="lookfor<?=$group ?>[]" id="search_lookfor<?=$group.'_'.$search ?>" class="form-control" type="text"<?if(isset($setQueries[$group][$search])):?> value="<?=$this->escapeHtml($setQueries[$group][$search]->getString())?>"<?endif;?>>
-                            </div>
-                            <div class="col-sm-4 middle">
-                              <select class="type form-control" name="type<?=$group ?>[]">
-                                <? foreach ($this->options->getAdvancedHandlers() as $searchVal => $searchDesc): ?>
-                                  <option value="<?=$this->escapeHtml($searchVal)?>"<?if(isset($setQueries[$group][$search]) && $searchVal == $setQueries[$group][$search]->getHandler()):?> selected<?endif;?>><?=$this->transEsc($searchDesc)?></option>
-                                <? endforeach; ?>
-                              </select>
-                            </div>
-                            <div class="col-sm-1 close hidden">
-                              <a class="help-block" href="#">&times;</a>
-                            </div>
-                          </div>
-                        </div>
-                        <? if($group == 0 && $search == 0): ?>
-                            </div>
-                          <i class="fa fa-plus-circle search_place_holder hidden" aria-hidden="true"></i> <a href="#" class="add_search_link hidden"><?=$this->transEsc("add_search")?></a>
-                        <? endif; ?>
-                      <? endfor; ?>
-                    </div>
+      </div>
+      <span id="groupPlaceHolder" class="hidden">
+        <i class="fa fa-plus-circle" aria-hidden="true"></i>
+        <a href="#" onClick="addGroup();return false"><?= $this->transEsc('add_search_group') ?></a>
+      </span>
+      <? /* fallback to a fixed set of search groups/fields if JavaScript is turned off */ ?>
+      <div class="no-js">
+        <? if(!empty($this->formOverride)): ?>
+          <?=$this->formOverride ?>
+        <? else: ?>
+          <? for($group=0 ; $group<3 || $group<=$setGroupCount ; $group++): ?>
+            <? if($group == 0): ?>
+              <div id="new_group_template">
+            <? endif; ?>
+            <div id="group<?=$group ?>" class="adv-group">
+              <div class="adv-group-terms">
+                <label class="adv-group-label"><?=$this->transEsc("adv_search_label")?>:</label>
+                <? for($search=0 ; $search<3 || (isset($setQueries[$group]) && $search<count($setQueries[$group])) ; $search++): ?>
+                  <? if($group == 0 && $search == 0): ?>
+                    <div id="new_search_template">
+                  <? endif; ?>
+                  <div id="search<?=$group.'_'.$search ?>" class="adv-search">
+                    <input name="lookfor<?=$group ?>[]" id="search_lookfor<?=$group.'_'.$search ?>" class="adv-term-input form-control" type="text"<?if(isset($setQueries[$group][$search])):?> value="<?=$this->escapeHtml($setQueries[$group][$search]->getString())?>"<?endif;?>>
+                    <select class="adv-term-type form-control" name="type<?=$group ?>[]">
+                      <? foreach ($this->options->getAdvancedHandlers() as $searchVal => $searchDesc): ?>
+                        <option value="<?=$this->escapeHtml($searchVal)?>"<?if(isset($setQueries[$group][$search]) && $searchVal == $setQueries[$group][$search]->getHandler()):?> selected<?endif;?>><?=$this->transEsc($searchDesc)?></option>
+                      <? endforeach; ?>
+                    </select>
+                    <a href="#" class="adv-term-remove hidden">&times;</a>
                   </div>
-                </div>
-                <div class="col-sm-3 match">
-                  <label class="search_bool"><?=$this->transEsc("search_match")?>:&nbsp;</label>
-                  <select name="bool<?=$group ?>[]" id="search_bool<?=$group ?>" class="form-control">
-                    <option value="AND"<? if(isset($setSearchGroups[$group]) && 'AND' == $setSearchGroups[$group]):?> selected<?endif;?>><?=$this->transEsc("search_AND")?></option>
-                    <option value="OR"<? if(isset($setSearchGroups[$group]) && 'OR' == $setSearchGroups[$group]):?> selected<?endif;?>><?=$this->transEsc("search_OR")?></option>
-                    <option value="NOT"<? if(isset($setSearchGroups[$group]) && 'NOT' == $setSearchGroups[$group]):?> selected<?endif;?>><?=$this->transEsc("search_NOT")?></option>
-                  </select>
-                </div>
+                  <? if($group == 0 && $search == 0): ?>
+                      </div>
+                    <span class="float-left">
+                      <i class="fa fa-plus-circle search_place_holder hidden" aria-hidden="true"></i>
+                      <a href="#" class="add_search_link hidden"><?=$this->transEsc("add_search")?></a>
+                    </span>
+                  <? endif; ?>
+                <? endfor; ?>
               </div>
-              <? if($group == 0): ?>
-                </div>
-              <? endif; ?>
-            <? endfor; ?>
-          <? endif; ?>
-        </div>
-        <div class="clearfix">
-          <input class="btn btn-default clear-btn" type="button" value="<?= $this->transEsc('Clear')?>">
-          <input class="btn btn-primary pull-right flip" type="submit" value="<?= $this->transEsc('Find')?>">
-        </div>
-        <? if (isset($this->extraAdvancedControls)): ?>
-          <?=$this->extraAdvancedControls ?>
-          <div class="clearfix">
-            <input class="btn btn-default clear-btn" type="button" value="<?= $this->transEsc('Clear')?>">
-            <input class="btn btn-primary pull-right flip" type="submit" value="<?= $this->transEsc('Find')?>">
-          </div>
+              <div class="adv-group-match">
+                <label class="search_bool"><?=$this->transEsc("search_match")?>:&nbsp;</label>
+                <select name="bool<?=$group ?>[]" id="search_bool<?=$group ?>" class="form-control">
+                  <option value="AND"<? if(isset($setSearchGroups[$group]) && 'AND' == $setSearchGroups[$group]):?> selected<?endif;?>><?=$this->transEsc("search_AND")?></option>
+                  <option value="OR"<? if(isset($setSearchGroups[$group]) && 'OR' == $setSearchGroups[$group]):?> selected<?endif;?>><?=$this->transEsc("search_OR")?></option>
+                  <option value="NOT"<? if(isset($setSearchGroups[$group]) && 'NOT' == $setSearchGroups[$group]):?> selected<?endif;?>><?=$this->transEsc("search_NOT")?></option>
+                </select>
+              </div>
+              <a href="#" class="adv-group-close hidden"><i class="fa fa-close"></i> <?=$this->transEsc("del_search")?></a>
+            </div>
+            <? if($group == 0): ?>
+              </div>
+            <? endif; ?>
+          <? endfor; ?>
         <? endif; ?>
       </div>
+      <div class="adv-submit">
+        <input class="clear-btn btn btn-default" type="button" value="<?= $this->transEsc('Clear')?>">
+        <input class="btn btn-primary" type="submit" value="<?= $this->transEsc('Find')?>">
+      </div>
+      <? if (isset($this->extraAdvancedControls)): ?>
+        <div class="clearfix">
+          <?=$this->extraAdvancedControls ?>
+        </div>
+        <div class="adv-submit">
+          <input class="clear-btn btn btn-default" type="button" value="<?= $this->transEsc('Clear')?>">
+          <input class="btn btn-primary" type="submit" value="<?= $this->transEsc('Find')?>">
+        </div>
+      <? endif; ?>
+    </div>
 
-      <div class="<?=$this->layoutClass('sidebar')?>">
-        <? if ($hasDefaultsApplied): ?>
-          <input type="hidden" name="dfApplied" value="1" />
-        <? endif ?>
-        <? if (!empty($searchFilters)): ?>
-          <h4><?=$this->transEsc("adv_search_filters")?></h4>
-          <div class="list-group">
-            <label class="list-group-item checkbox">
-              <input type="checkbox" checked="checked" class="checkbox-select-all"/>
-              <?=$this->transEsc("adv_search_select_all")?>
-            </label>
-          </div>
-          <? foreach ($searchFilters as $field => $data): ?>
-            <div class="list-group">
-              <div class="list-group-item title"><?=$this->transEsc($field)?></div>
-              <? foreach ($data as $value): ?>
-                <label class="list-group-item checkbox"><input class="checkbox-select-item" type="checkbox" checked="checked" name="filter[]" value='<?=$this->escapeHtmlAttr($value['field'])?>:"<?=$this->escapeHtmlAttr($value['value'])?>"' /> <?=$this->escapeHtml($value['displayText'])?></label>
-              <? endforeach; ?>
-            </div>
-          <? endforeach; ?>
-        <? endif; ?>
-        <div class="sidegroup">
-          <h4><?=$this->transEsc("Search Tips")?></h4>
-          <div class="list-group">
-            <a class="list-group-item help-link" data-lightbox href="<?=$this->url('help-home')?>?topic=advsearch&amp;_=<?=time() ?>"><?=$this->transEsc("Help with Advanced Search")?></a>
-            <a class="list-group-item help-link" data-lightbox href="<?=$this->url('help-home')?>?topic=search&amp;_=<?=time() ?>"><?=$this->transEsc("Help with Search Operators")?></a>
-          </div>
+    <div class="<?=$this->layoutClass('sidebar')?>">
+      <? if ($hasDefaultsApplied): ?>
+        <input type="hidden" name="dfApplied" value="1" />
+      <? endif ?>
+      <? if (!empty($searchFilters)): ?>
+        <h4><?=$this->transEsc("adv_search_filters")?></h4>
+        <div class="facet-group">
+          <label class="checkbox">
+            <input type="checkbox" checked="checked" class="checkbox-select-all"/>
+            <?=$this->transEsc("adv_search_select_all")?>
+          </label>
         </div>
+        <? foreach ($searchFilters as $field => $data): ?>
+          <div class="facet-group">
+            <div class="title"><?=$this->transEsc($field)?></div>
+            <? foreach ($data as $value): ?>
+              <label class="facet checkbox"><input class="checkbox-select-item" type="checkbox" checked="checked" name="filter[]" value='<?=$this->escapeHtmlAttr($value['field'])?>:"<?=$this->escapeHtmlAttr($value['value'])?>"' /> <?=$this->escapeHtml($value['displayText'])?></label>
+            <? endforeach; ?>
+          </div>
+        <? endforeach; ?>
+      <? endif; ?>
+      <h4><?=$this->transEsc("Search Tips")?></h4>
+      <div class="facet-group">
+        <a class="facet help-link" data-lightbox href="<?=$this->url('help-home')?>?topic=advsearch&amp;_=<?=time() ?>"><?=$this->transEsc("Help with Advanced Search")?></a>
+        <a class="facet help-link" data-lightbox href="<?=$this->url('help-home')?>?topic=search&amp;_=<?=time() ?>"><?=$this->transEsc("Help with Search Operators")?></a>
       </div>
     </div>
   </form>
diff --git a/themes/bootstrap3/templates/search/advanced/limit.phtml b/themes/bootstrap3/templates/search/advanced/limit.phtml
index aaef6afe6e4879ef0cbd70b5be639064b66386f0..2fc51d38e16ecca62e241580df5fc6b6d03fc286 100644
--- a/themes/bootstrap3/templates/search/advanced/limit.phtml
+++ b/themes/bootstrap3/templates/search/advanced/limit.phtml
@@ -7,7 +7,7 @@
     $defaultLimit = empty($lastLimit) ? $this->options->getDefaultLimit() : $lastLimit;
 ?>
 <? if (count($limitList) > 1): ?>
-  <fieldset class="col-sm-4">
+  <fieldset class="limits">
     <legend><?=$this->transEsc('Results per page')?></legend>
     <select id="limit" name="limit" class="form-control">
       <? foreach ($limitList as $limitVal): ?>
@@ -15,4 +15,4 @@
       <? endforeach; ?>
     </select>
   </fieldset>
-<? endif; ?>
\ No newline at end of file
+<? endif; ?>
diff --git a/themes/bootstrap3/templates/search/advanced/ranges.phtml b/themes/bootstrap3/templates/search/advanced/ranges.phtml
index 44dfd9c3ade6a1ed4fdaf6678e6ef9db186f2016..ba22ac62184725654e18728fadaeca07f590b1bf 100644
--- a/themes/bootstrap3/templates/search/advanced/ranges.phtml
+++ b/themes/bootstrap3/templates/search/advanced/ranges.phtml
@@ -2,15 +2,15 @@
   <? $params = $this->searchParams($this->searchClassId); $params->activateAllFacets(); ?>
   <? foreach ($this->ranges as $current): $escField = $this->escapeHtmlAttr($current['field']); ?>
     <? $extraInputAttribs = ($current['type'] == 'date') ? 'maxlength="4" ' : ''; ?>
-    <fieldset class="col-sm-4">
+    <fieldset class="range">
       <legend><?=$this->transEsc($params->getFacetLabel($current['field']))?></legend>
       <input type="hidden" name="<?=$this->escapeHtmlAttr($current['type'])?>range[]" value="<?=$escField?>"/>
-      <div class="row">
-        <div class="col-sm-6">
+      <div class="date-fields">
+        <div class="date-from">
           <label for="<?=$escField?>from"><?=$this->transEsc('date_from')?>:</label>
           <input type="text" name="<?=$escField?>from" id="<?=$escField?>from" value="<?=isset($current['values'][0])?$this->escapeHtmlAttr($current['values'][0]):''?>" class="form-control" <?=$extraInputAttribs?>/>
         </div>
-        <div class="col-sm-6">
+        <div class="date-to">
           <label for="<?=$escField?>to"><?=$this->transEsc('date_to')?>:</label>
           <input type="text" name="<?=$escField?>to" id="<?=$escField?>to" value="<?=isset($current['values'][1])?$this->escapeHtmlAttr($current['values'][1]):''?>" class="form-control" <?=$extraInputAttribs?>/>
         </div>
@@ -20,7 +20,7 @@
           <input type="text" id="<?=$escField?><?=$this->escapeHtmlAttr($current['type'])?>Slider">
         </div>
         <?
-          $this->headScript()->appendFile('vendor/bootstrap-slider.js');
+          $this->headScript()->appendFile('vendor/bootstrap-slider.min.js');
           $this->headLink()->appendStylesheet('vendor/bootstrap-slider.min.css');
           $min = !empty($current['values'][0]) ? min($current['values'][0], 1400) : 1400;
           $future = date('Y', time()+31536000);
@@ -31,7 +31,6 @@
           $max = intval($max);
           $low = intval($low);
           $high = intval($high);
-          $reversed = $this->layout()->rtl ? 'true' : 'false';
           $init = !empty($current['values'][0]) ? 'fillTexts()' : '';
           $script = <<<JS
 $(document).ready(function() {
@@ -46,17 +45,29 @@ $(document).ready(function() {
        'max':{$max},
        'handle':"square",
        'tooltip':"hide",
-       'value':[{$low},{$high}],
-       'reversed': {$reversed}
+       'value':[{$low},{$high}]
     })
     .on('change', fillTexts)
     .data('slider');
   {$init}
 });
+
+$('#{$escField}from, #{$escField}to').change(function () {
+  var fromValue = Number($('#{$escField}from').val());
+  var toValue = Number($('#{$escField}to').val());
+  $('#{$escField}dateSlider').slider(
+    'setValue',
+    [
+      isNaN(fromValue) || fromValue <= 0 ? {$min} : fromValue,
+      isNaN(toValue) || toValue <= 0 ? {$max} : toValue
+    ],
+    true
+  );
+});
 JS;
         ?>
         <?=$this->inlineScript(\Zend\View\Helper\HeadScript::SCRIPT, $script, 'SET'); ?>
-      </fieldset>
-    <? endif; ?>
+      <? endif; ?>
+    </fieldset>
   <? endforeach; ?>
 <? endif; ?>
diff --git a/themes/bootstrap3/templates/search/advanced/solr.phtml b/themes/bootstrap3/templates/search/advanced/solr.phtml
index 008881dc79d4df72fc470dde9e4b06e41f266d18..d6bd4fe422b013eff38dd92690e774c7a2c369d1 100644
--- a/themes/bootstrap3/templates/search/advanced/solr.phtml
+++ b/themes/bootstrap3/templates/search/advanced/solr.phtml
@@ -1,55 +1,51 @@
 <? if (!empty($this->facetList) || !empty($this->checkboxFacets)): ?>
-  <div class="row">
-    <fieldset class="col-sm-12">
-      <legend><?=$this->transEsc('Limit To')?></legend>
-      <? if (!empty($this->checkboxFacets)): ?>
-        <?=$this->render('search/advanced/checkbox-filters.phtml')?>
-      <? endif; ?>
-      <div class="row">
-        <? foreach ($this->facetList as $field => $list): ?>
-          <div class="col-sm-<?=floor(12/count($this->facetList)) ?>">
-            <label for="limit_<?=$this->escapeHtmlAttr(str_replace(' ', '', $field))?>"><?=$this->transEsc($list['label'])?>:</label>
-            <select class="form-control" id="limit_<?=$this->escapeHtmlAttr(str_replace(' ', '', $field))?>" name="filter[]" multiple="multiple" size="10">
-              <? if (is_array($this->hierarchicalFacets) && in_array($field, $this->hierarchicalFacets)): ?>
-                <? foreach ($list['list'] as $value): ?>
-                  <? $display = str_pad('', 4 * $value['level'] * 6, '&nbsp;', STR_PAD_LEFT) . $this->escapeHtml($value['displayText']); ?>
-                  <option value="<?=$this->escapeHtmlAttr(($value['operator'] == 'OR' ? '~' : '') . $field . ':"' . $value['value'] . '"')?>"<?=(isset($value['selected']) && $value['selected'])?' selected="selected"':''?>><?=$display?></option>
-                <? endforeach; ?>
-              <? else: ?>
-                <?
-                // Sort the current facet list alphabetically; we'll use this data
-                // along with the foreach below to display facet options in the
-                // correct order.
-                $sorted = array();
-                foreach ($list['list'] as $i => $value) {
-                  if (!empty($value['displayText'])) {
-                    $sorted[$i] = $value['displayText'];
-                  }
+  <fieldset class="solr-facets">
+    <legend><?=$this->transEsc('Limit To')?></legend>
+    <? if (!empty($this->checkboxFacets)): ?>
+      <?=$this->render('search/advanced/checkbox-filters.phtml')?>
+    <? endif; ?>
+    <div class="solr-facet-container">
+      <? foreach ($this->facetList as $field => $list): ?>
+        <div class="solr-adv-facet">
+          <label for="limit_<?=$this->escapeHtmlAttr(str_replace(' ', '', $field))?>"><?=$this->transEsc($list['label'])?>:</label>
+          <select class="form-control" id="limit_<?=$this->escapeHtmlAttr(str_replace(' ', '', $field))?>" name="filter[]" multiple="multiple" size="10">
+            <? if (is_array($this->hierarchicalFacets) && in_array($field, $this->hierarchicalFacets)): ?>
+              <? foreach ($list['list'] as $value): ?>
+                <? $display = str_pad('', 4 * $value['level'] * 6, '&nbsp;', STR_PAD_LEFT) . $this->escapeHtml($value['displayText']); ?>
+                <option value="<?=$this->escapeHtmlAttr(($value['operator'] == 'OR' ? '~' : '') . $field . ':"' . $value['value'] . '"')?>"<?=(isset($value['selected']) && $value['selected'])?' selected="selected"':''?>><?=$display?></option>
+              <? endforeach; ?>
+            <? else: ?>
+              <?
+              // Sort the current facet list alphabetically; we'll use this data
+              // along with the foreach below to display facet options in the
+              // correct order.
+              $sorted = array();
+              foreach ($list['list'] as $i => $value) {
+                if (!empty($value['displayText'])) {
+                  $sorted[$i] = $value['displayText'];
                 }
-                natcasesort($sorted);
-                ?>
-                <? foreach ($sorted as $i => $display): ?>
-                  <? $value = $list['list'][$i]; ?>
-                  <option value="<?=$this->escapeHtmlAttr(($value['operator'] == 'OR' ? '~' : '') . $field . ':"' . $value['value'] . '"')?>"<?=(isset($value['selected']) && $value['selected'])?' selected="selected"':''?>><?=$this->escapeHtml($display)?></option>
-                <? endforeach; ?>
-              <? endif; ?>
-            </select>
-          </div>
-        <? endforeach; ?>
-      </div>
-    </fieldset>
-  </div>
-<? endif; ?>
-<div class="row">
-  <? if (isset($this->illustratedLimit)): ?>
-    <fieldset class="col-sm-4">
-      <legend><?=$this->transEsc("Illustrated")?>:</legend>
-      <? foreach ($this->illustratedLimit as $current): ?>
-        <input id="illustrated_<?=$this->escapeHtmlAttr($current['value'])?>" type="radio" name="illustration" value="<?=$this->escapeHtmlAttr($current['value'])?>"<?=$current['selected']?' checked="checked"':''?>/>
-        <label for="illustrated_<?=$this->escapeHtmlAttr($current['value'])?>"><?=$this->transEsc($current['text'])?></label><br/>
+              }
+              natcasesort($sorted);
+              ?>
+              <? foreach ($sorted as $i => $display): ?>
+                <? $value = $list['list'][$i]; ?>
+                <option value="<?=$this->escapeHtmlAttr(($value['operator'] == 'OR' ? '~' : '') . $field . ':"' . $value['value'] . '"')?>"<?=(isset($value['selected']) && $value['selected'])?' selected="selected"':''?>><?=$this->escapeHtml($display)?></option>
+              <? endforeach; ?>
+            <? endif; ?>
+          </select>
+        </div>
       <? endforeach; ?>
-    </fieldset>
-  <? endif; ?>
-  <?=$this->render('search/advanced/limit.phtml')?>
-  <?=$this->render('search/advanced/ranges.phtml')?>
-</div>
\ No newline at end of file
+    </div>
+  </fieldset>
+<? endif; ?>
+<? if (isset($this->illustratedLimit)): ?>
+  <fieldset class="solr">
+    <legend><?=$this->transEsc("Illustrated")?>:</legend>
+    <? foreach ($this->illustratedLimit as $current): ?>
+      <input id="illustrated_<?=$this->escapeHtmlAttr($current['value'])?>" type="radio" name="illustration" value="<?=$this->escapeHtmlAttr($current['value'])?>"<?=$current['selected']?' checked="checked"':''?>/>
+      <label for="illustrated_<?=$this->escapeHtmlAttr($current['value'])?>"><?=$this->transEsc($current['text'])?></label><br/>
+    <? endforeach; ?>
+  </fieldset>
+<? endif; ?>
+<?=$this->render('search/advanced/limit.phtml')?>
+<?=$this->render('search/advanced/ranges.phtml')?>
diff --git a/themes/bootstrap3/templates/search/advanced/summon.phtml b/themes/bootstrap3/templates/search/advanced/summon.phtml
index 52a11b254b7fa07ccfb12f0bf80d1091d06ac4d8..7851ce9d99f50bd4bb91d8eb76d3e6aa91247a93 100644
--- a/themes/bootstrap3/templates/search/advanced/summon.phtml
+++ b/themes/bootstrap3/templates/search/advanced/summon.phtml
@@ -1,35 +1,31 @@
 <? if (!empty($this->facetList) || !empty($this->checkboxFacets)): ?>
-  <fieldset>
+  <fieldset class="summon-facets">
     <legend><?=$this->transEsc('Limit To')?></legend>
     <? if (!empty($this->checkboxFacets)): ?>
       <?=$this->render('search/advanced/checkbox-filters.phtml')?>
     <? endif; ?>
-    <div class="row">
-      <? foreach ($this->facetList as $field => $list): ?>
-        <div class="col-sm-<?=floor(12/count($this->facetList)) ?>">
-          <label for="limit_<?=$this->escapeHtmlAttr(str_replace(' ', '', $field))?>"><?=$this->transEsc($list['label'])?>:</label>
-          <select class="form-control" id="limit_<?=$this->escapeHtmlAttr(str_replace(' ', '', $field))?>" name="filter[]" multiple="multiple" size="10">
-            <?
-              // Sort the current facet list alphabetically; we'll use this data
-              // along with the foreach below to display facet options in the
-              // correct order.
-              $sorted = array();
-              foreach ($list['list'] as $i => $value) {
-                $sorted[$i] = $value['displayText'];
-              }
-              natcasesort($sorted);
-            ?>
-            <? foreach ($sorted as $i => $display): ?>
-              <? $value = $list['list'][$i]; ?>
-              <option value="<?=$this->escapeHtmlAttr(($value['operator'] == 'OR' ? '~' : '') . $field . ':"' . $value['value'] . '"')?>"<?=(isset($value['selected']) && $value['selected'])?' selected="selected"':''?>><?=$this->escapeHtml($display)?></option>
-            <? endforeach; ?>
-          </select>
-        </div>
-      <? endforeach; ?>
-    </div>
+    <? foreach ($this->facetList as $field => $list): ?>
+      <div class="facet-fieldset">
+        <label for="limit_<?=$this->escapeHtmlAttr(str_replace(' ', '', $field))?>"><?=$this->transEsc($list['label'])?>:</label>
+        <select class="form-control" id="limit_<?=$this->escapeHtmlAttr(str_replace(' ', '', $field))?>" name="filter[]" multiple="multiple" size="10">
+          <?
+            // Sort the current facet list alphabetically; we'll use this data
+            // along with the foreach below to display facet options in the
+            // correct order.
+            $sorted = array();
+            foreach ($list['list'] as $i => $value) {
+              $sorted[$i] = $value['displayText'];
+            }
+            natcasesort($sorted);
+          ?>
+          <? foreach ($sorted as $i => $display): ?>
+            <? $value = $list['list'][$i]; ?>
+            <option value="<?=$this->escapeHtmlAttr(($value['operator'] == 'OR' ? '~' : '') . $field . ':"' . $value['value'] . '"')?>"<?=(isset($value['selected']) && $value['selected'])?' selected="selected"':''?>><?=$this->escapeHtml($display)?></option>
+          <? endforeach; ?>
+        </select>
+      </div>
+    <? endforeach; ?>
   </fieldset>
 <? endif; ?>
-<div class="row">
-  <?=$this->render('search/advanced/limit.phtml')?>
-  <?=$this->render('search/advanced/ranges.phtml')?>
-</div>
+<?=$this->render('search/advanced/limit.phtml')?>
+<?=$this->render('search/advanced/ranges.phtml')?>
diff --git a/themes/bootstrap3/templates/search/bulk-action-buttons.phtml b/themes/bootstrap3/templates/search/bulk-action-buttons.phtml
index 7122165f7c6273f7b0a63955172af9f4d0ed1455..d2d6f0306bfb98e34eee676b43c6228b0e187446 100644
--- a/themes/bootstrap3/templates/search/bulk-action-buttons.phtml
+++ b/themes/bootstrap3/templates/search/bulk-action-buttons.phtml
@@ -1,25 +1,25 @@
-<? if((isset($this->showBulkOptions)  && $this->showBulkOptions)
-   || (isset($this->showCartControls) && $this->showCartControls)): ?>
+<? if (isset($this->showCheckboxes) && $this->showCheckboxes): ?>
   <div class="bulkActionButtons hidden-print">
-    <div class="checkbox">
-      <label>
-        <input type="checkbox" class="checkbox-select-all" name="selectAll" id="<?=$this->idPrefix?>addFormCheckboxSelectAll"/> <?=$this->transEsc('select_page')?>
+    <div class="bulk-checkbox">
+      <input type="checkbox" class="checkbox-select-all" name="selectAll" id="<?=$this->idPrefix?>addFormCheckboxSelectAll"<?if($this->formAttr):?> form="<?=$this->escapeHtmlAttr($this->formAttr) ?>"<? endif; ?>/>
+      <label for="<?=$this->idPrefix?>addFormCheckboxSelectAll">
+        <?=$this->transEsc('select_page')?>
         &#124; <?=$this->transEsc('with_selected')?>:
       </label>
     </div>
     <div class="btn-group">
       <? if (isset($this->showBulkOptions) && $this->showBulkOptions): ?>
-        <input id="ribbon-email" class="btn btn-default" type="submit" name="email" title="<?=$this->transEsc('bookbag_email_selected')?>" value="<?=$this->transEsc('Email')?>"/>
+        <input id="ribbon-email" class="btn btn-default" type="submit" name="email" title="<?=$this->transEsc('bookbag_email_selected')?>" value="<?=$this->transEsc('Email')?>"<?if($this->formAttr):?> form="<?=$this->escapeHtmlAttr($this->formAttr) ?>"<? endif; ?>/>
         <? $exportOptions = $this->export()->getBulkOptions(); if (count($exportOptions) > 0): ?>
-          <input id="ribbon-export" class="btn btn-default" type="submit" name="export" title="<?=$this->transEsc('bookbag_export_selected')?>" value="<?=$this->transEsc('Export')?>"/>
+          <input id="ribbon-export" class="btn btn-default" type="submit" name="export" title="<?=$this->transEsc('bookbag_export_selected')?>" value="<?=$this->transEsc('Export')?>"<?if($this->formAttr):?> form="<?=$this->escapeHtmlAttr($this->formAttr) ?>"<? endif; ?>/>
         <? endif; ?>
-        <input id="ribbon-print" class="btn btn-default" type="submit" name="print" title="<?=$this->transEsc('bookbag_print_selected')?>" value="<?=$this->transEsc('Print')?>"/>
+        <input id="ribbon-print" class="btn btn-default" type="submit" name="print" title="<?=$this->transEsc('bookbag_print_selected')?>" value="<?=$this->transEsc('Print')?>"<?if($this->formAttr):?> form="<?=$this->escapeHtmlAttr($this->formAttr) ?>"<? endif; ?>/>
         <? if ($this->userlist()->getMode() !== 'disabled'): ?>
-          <input id="ribbon-save" class="btn btn-default" type="submit" name="saveCart" title="<?=$this->transEsc('bookbag_save_selected')?>" value="<?=$this->transEsc('Save')?>"/>
+          <input id="ribbon-save" class="btn btn-default" type="submit" name="saveCart" title="<?=$this->transEsc('bookbag_save_selected')?>" value="<?=$this->transEsc('Save')?>"<?if($this->formAttr):?> form="<?=$this->escapeHtmlAttr($this->formAttr) ?>"<? endif; ?>/>
         <? endif; ?>
       <? endif; ?>
       <? if (isset($this->showCartControls) && $this->showCartControls): ?>
-        <input id="<?=$this->idPrefix?>updateCart" type="submit" class="btn btn-default" name="add" value="<?=$this->transEsc('Add to Book Bag')?>"/>
+        <input id="<?=$this->idPrefix?>updateCart" type="submit" class="btn btn-default" name="add" value="<?=$this->transEsc('Add to Book Bag')?>"<?if($this->formAttr):?> form="<?=$this->escapeHtmlAttr($this->formAttr) ?>"<? endif; ?>/>
       <? endif; ?>
     </div>
   </div>
diff --git a/themes/bootstrap3/templates/search/controls/showing.phtml b/themes/bootstrap3/templates/search/controls/showing.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..6461dc1260b3efa8dea7c6a745ad39eeed957085
--- /dev/null
+++ b/themes/bootstrap3/templates/search/controls/showing.phtml
@@ -0,0 +1,28 @@
+<?
+  $transParams = [
+    '%%start%%' => $this->localizedNumber($this->results->getStartRecord()),
+    '%%end%%'   => $this->localizedNumber($this->results->getEndRecord()),
+    '%%total%%' => $this->localizedNumber($this->recordTotal),
+    '%%lookfor%%' => $this->escapeHtml($this->lookfor)
+  ];
+?>
+<? if (!isset($this->skipTotalCount)): ?>
+  <? $showingResults = $this->translate('showing_results_of_html', $transParams); ?>
+<? else: ?>
+  <? $showingResults = $this->translate('showing_results_html', $transParams); ?>
+<? endif; ?>
+<? if (isset($this->overrideSearchHeading)): ?>
+  <? $showingResults .= ' ' . $this->overrideSearchHeading; ?>
+<? elseif ($this->params->getSearchType() == 'basic'): ?>
+  <? if (!isset($this->skipTotalCount)): ?>
+    <? $showingResults = $this->translate('showing_results_of_for_html', $transParams); ?>
+  <? else: ?>
+    <? $showingResults = $this->translate('showing_results_for_html', $transParams); ?>
+  <? endif; ?>
+<? endif; ?>
+<? $this->layout()->srmessage = $showingResults; ?>
+<? if ($qtime = $this->results->getQuerySpeed()): ?>
+  <?=$showingResults; ?>, <?=$this->transEsc('query time')?>: <?=$this->localizedNumber($qtime, 2).$this->transEsc('seconds_abbrev')?>
+<? else: ?>
+  <?=$showingResults; ?>
+<? endif; ?>
diff --git a/themes/bootstrap3/templates/search/controls/sort.phtml b/themes/bootstrap3/templates/search/controls/sort.phtml
index c5f3cb6f67e14a58c1803c2bf11e246fa49b2823..790b56fe92fa5aa31e84265bcf308f939e49bc52 100644
--- a/themes/bootstrap3/templates/search/controls/sort.phtml
+++ b/themes/bootstrap3/templates/search/controls/sort.phtml
@@ -1,5 +1,5 @@
 <? $list = $this->params->getSortList(); if (!empty($list)): ?>
-  <form class="form-inline" action="<?=$this->currentPath()?>" method="get" name="sort">
+  <form class="search-sort" action="<?=$this->currentPath()?>" method="get" name="sort">
     <?=$this->results->getUrlQuery()->asHiddenFields(array('sort' => '/.*/'));?>
     <label for="sort_options_1"><?=$this->transEsc('Sort')?></label>
     <select id="sort_options_1" name="sort" class="jumpMenu form-control">
diff --git a/themes/bootstrap3/templates/search/controls/view.phtml b/themes/bootstrap3/templates/search/controls/view.phtml
index 91dd324a7e066d40db2ac43a013035724b89cc93..0d8fef0da6b2bdbe4af00211c33d472397e0fcd3 100644
--- a/themes/bootstrap3/templates/search/controls/view.phtml
+++ b/themes/bootstrap3/templates/search/controls/view.phtml
@@ -1,11 +1,20 @@
 <div class="view-buttons hidden-xs">
   <? $viewList = $this->params->getViewList(); if (count($viewList) > 1): ?>
     <? foreach ($viewList as $viewType => $viewData): ?>
+      <? $viewDesc = $this->translate($viewData['desc']); ?>
       <? if (!$viewData['selected']): ?>
-        <a href="<?=$this->results->getUrlQuery()->setViewParam($viewType)?>" title="<?=$this->transEsc('Switch view to')?> <?=$this->transEsc($viewData['desc'])?>" >
+        <a href="<?=$this->results->getUrlQuery()->setViewParam($viewType)?>" title="<?=$this->escapeHtmlAttr($this->translate('switch_view', ['%%view%%' => $viewDesc]))?>" >
+      <? else: ?>
+        <span title="<?=$this->escapeHtmlAttr($this->translate('view_already_selected', ['%%current%%' => $viewDesc])) ?>">
       <? endif; ?>
-      <i class="fa fa-<?=$viewType ?>"<? if($viewData['selected']): ?> title="<?=$this->transEsc($viewData['desc']) ?> <?=$this->transEsc('view already selected') ?>" <? endif ?> alt="<?=$this->transEsc($viewData['desc'])?>"></i>
-      <?=$this->transEsc($viewData['desc']) ?><? if (!$viewData['selected']): ?></a><? endif; ?>&nbsp;
+      <i class="fa fa-<?=$viewType ?>" alt="<?=$this->escapeHtmlAttr($viewDesc)?>"></i>
+      <?=$viewDesc ?>
+      <? if (!$viewData['selected']): ?>
+        </a>
+      <? else: ?>
+        </span>
+      <? endif; ?>
+      &nbsp;
     <? endforeach; ?>
   <? endif; ?>
 </div>
diff --git a/themes/bootstrap3/templates/search/email.phtml b/themes/bootstrap3/templates/search/email.phtml
index eeefdc6db56db744e143716ec1bddf5608aee084..9894222f5454f448abe32fceecbf8e2430093f85 100644
--- a/themes/bootstrap3/templates/search/email.phtml
+++ b/themes/bootstrap3/templates/search/email.phtml
@@ -8,7 +8,7 @@
 ?>
 <h2><?=$this->transEsc('Email this Search') ?></h2>
 <?=$this->flashmessages()?>
-<form class="form-horizontal" method="post"  name="emailSearch">
+<form class="form-search-email" method="post" name="emailSearch">
   <input type="hidden" name="url" value="<?=$this->escapeHtmlAttr($this->url)?>" />
   <?=$this->render('Helpers/email-form-fields.phtml')?>
 </form>
diff --git a/themes/bootstrap3/templates/search/facet-list.phtml b/themes/bootstrap3/templates/search/facet-list.phtml
index cb3a003e5760aa55ac4d36e6a6e6621f4f585ff7..3b73ba6ed0928f33a7a8d3f6e7b2cff2df714c59 100644
--- a/themes/bootstrap3/templates/search/facet-list.phtml
+++ b/themes/bootstrap3/templates/search/facet-list.phtml
@@ -21,10 +21,10 @@
 <div class="lightbox-scroll full-facets">
   <? foreach ($this->sortOptions as $key=>$sort): ?>
     <? $active = $this->sort == $key; ?>
-    <div class="full-facet-list list-group<? if(!$active): ?> hidden<? endif; ?>" id="facet-list-<?=$this->escapeHtmlAttr($key) ?>">
+    <div class="full-facet-list facet-group<? if(!$active): ?> hidden<? endif; ?>" id="facet-list-<?=$this->escapeHtmlAttr($key) ?>">
       <? if ($active): ?>
         <? if ($this->page > 1): ?>
-          <a href="<?=$urlBase . '&amp;facetpage=' . ($this->page-1) . '&amp;facetsort=' . $this->sort ?>" class="list-group-item js-facet-prev-page" data-page="<?=($this->page+1) ?>" data-sort="<?=$this->sort ?>" data-limit="<?=count($this->data) ?>" data-lightbox-ignore><?=$this->translate('prev') ?> ...</a>
+          <a href="<?=$urlBase . '&amp;facetpage=' . ($this->page-1) . '&amp;facetsort=' . $this->sort ?>" class="facet js-facet-prev-page" data-page="<?=($this->page+1) ?>" data-sort="<?=$this->sort ?>" data-limit="<?=count($this->data) ?>" data-lightbox-ignore><?=$this->translate('prev') ?> ...</a>
         <? endif; ?>
         <? foreach ($this->data as $item): ?>
           <? $toggleUrl = $item['isApplied']
@@ -33,10 +33,10 @@
           ?>
           <? $subLinks = $this->exclude && !$item['isApplied']; ?>
           <? if ($subLinks): ?>
-            <li class="list-group-item js-facet-item">
+            <li class="facet js-facet-item">
               <a href="<?=$toggleUrl ?>" data-lightbox-ignore data-title="<?=$this->escapeHtmlAttr($item['displayText']) ?>" data-count="<?=$item['count'] ?>"<? if($item['isApplied']): ?> title="<?=$this->transEsc('applied_filter') ?>"<? endif;?>>
           <? else: ?>
-            <a href="<?=$toggleUrl ?>" data-lightbox-ignore class="js-facet-item list-group-item<? if($item['isApplied']): ?> active<?endif;?>" data-title="<?=$this->escapeHtmlAttr($item['displayText']) ?>" data-count="<?=$item['count'] ?>"<? if($item['isApplied']): ?> title="<?=$this->transEsc('applied_filter') ?>"<? endif;?>>
+            <a href="<?=$toggleUrl ?>" data-lightbox-ignore class="facet js-facet-item<? if($item['isApplied']): ?> active<?endif;?>" data-title="<?=$this->escapeHtmlAttr($item['displayText']) ?>" data-count="<?=$item['count'] ?>"<? if($item['isApplied']): ?> title="<?=$this->transEsc('applied_filter') ?>"<? endif;?>>
           <? endif; ?>
               <? if (!empty($item['displayText'])): ?>
                 <?=$this->escapeHtml($item['displayText']) ?>
@@ -50,9 +50,7 @@
               <? if ($item['operator'] == 'OR'): ?>
                 <i class="fa fa-check-square-o" aria-hidden="true"></i>
               <? else: ?>
-                <span class="pull-right flip">
-                  <i class="fa fa-check" aria-hidden="true"></i>
-                </span>
+                <i class="fa fa-check" aria-hidden="true"></i>
               <? endif; ?>
             <? else: ?>
               <span class="badge">
@@ -66,7 +64,7 @@
         <? endforeach; ?>
       <? endif; ?>
       <? if ($this->anotherPage): ?>
-        <a href="<?=$urlBase . '&amp;facetpage=' . ($this->page+1) . '&amp;facetsort=' . urlencode($key) ?>" class="list-group-item js-facet-next-page" data-page="<?=($this->page+1) ?>" data-sort="<?=$this->escapeHtmlAttr($key) ?>" data-lightbox-ignore><?=$this->translate('more') ?> ...</a>
+        <a href="<?=$urlBase . '&amp;facetpage=' . ($this->page+1) . '&amp;facetsort=' . urlencode($key) ?>" class="facet js-facet-next-page" data-page="<?=($this->page+1) ?>" data-sort="<?=$this->escapeHtmlAttr($key) ?>" data-lightbox-ignore><?=$this->translate('more') ?> ...</a>
       <? endif; ?>
     </div>
   <? endforeach; ?>
diff --git a/themes/bootstrap3/templates/search/history.phtml b/themes/bootstrap3/templates/search/history.phtml
index 377a1020bfd6f482326c8120b2e864ac16499d3a..698b505a2b5937f0b39854d69e2db3753f3eb646 100644
--- a/themes/bootstrap3/templates/search/history.phtml
+++ b/themes/bootstrap3/templates/search/history.phtml
@@ -9,31 +9,29 @@
   $saveSupported = $this->accountCapabilities()->getSavedSearchSetting() === 'enabled';
 ?>
 
-<div class="row">
-  <div class="<?=$this->layoutClass('mainbody')?>">
-    <?=$this->flashmessages()?>
-    <? if ($saveSupported && !empty($this->saved)): ?>
-      <h2><?=$this->transEsc("history_saved_searches")?></h2>
-      <?=$this->context()->renderInContext('search/history-table.phtml', array('showSaved' => true));?>
-    <? endif; ?>
-
-    <h2><?=$this->transEsc("history_recent_searches")?></h2>
-    <? if (!empty($this->unsaved)): ?>
-      <?=$this->context()->renderInContext('search/history-table.phtml', array('showSaved' => false));?>
-      <a href="?purge=true"><i class="fa fa-remove" aria-hidden="true"></i> <?=$this->transEsc("history_purge")?></a>
-    <? else: ?>
-      <?=$this->transEsc("history_no_searches")?>
-    <? endif; ?>
-  </div>
+<div class="<?=$this->layoutClass('mainbody')?>">
+  <?=$this->flashmessages()?>
+  <? if ($saveSupported && !empty($this->saved)): ?>
+    <h2><?=$this->transEsc("history_saved_searches")?></h2>
+    <?=$this->context()->renderInContext('search/history-table.phtml', ['showSaved' => true]);?>
+  <? endif; ?>
 
-  <? if ($saveSupported): ?>
-    <div class="<?=$this->layoutClass('sidebar')?>">
-      <?=$this->context($this)->renderInContext(
-          "myresearch/menu.phtml",
-          // Only activate search history in account menu if user is logged in.
-          $this->auth()->isLoggedIn() ? array('active' => 'history') : array()
-       );
-       ?>
-    </div>
+  <h2><?=$this->transEsc("history_recent_searches")?></h2>
+  <? if (!empty($this->unsaved)): ?>
+    <?=$this->context()->renderInContext('search/history-table.phtml', ['showSaved' => false]);?>
+    <a href="?purge=true"><i class="fa fa-remove" aria-hidden="true"></i> <?=$this->transEsc("history_purge")?></a>
+  <? else: ?>
+    <?=$this->transEsc("history_no_searches")?>
   <? endif; ?>
-</div>
\ No newline at end of file
+</div>
+
+<? if ($saveSupported): ?>
+  <div class="<?=$this->layoutClass('sidebar')?>">
+    <?=$this->context($this)->renderInContext(
+        "myresearch/menu.phtml",
+        // Only activate search history in account menu if user is logged in.
+        $this->auth()->isLoggedIn() ? ['active' => 'history'] : []
+     );
+     ?>
+  </div>
+<? endif; ?>
diff --git a/themes/bootstrap3/templates/search/home.phtml b/themes/bootstrap3/templates/search/home.phtml
index 0ff456b7b4899e80425ba97150b5d78b58308728..3f108689e0e34b80156e60ea9b80e5f6fec1f821 100644
--- a/themes/bootstrap3/templates/search/home.phtml
+++ b/themes/bootstrap3/templates/search/home.phtml
@@ -19,15 +19,29 @@
 ?>
 
 <div class="searchHomeContent">
-  <?=($this->ils()->getOfflineMode() == "ils-offline") ? $this->render('Helpers/ils-offline.phtml', ['offlineModeMsg' => 'ils_offline_home_message']) : ''?>
-  <div class="well well-lg clearfix" role="search">
-    <?=$this->context($this)->renderInContext("search/searchbox.phtml", ['ignoreHiddenFilterMemory' => true])?>
-  </div>
+  <?
+  $ilsStatusScript = <<<JS
+$(document).ready(function() {
+  $.ajax({
+      dataType: 'json',
+      method: 'GET',
+      data: {'offlineModeMsg':'ils_offline_home_message'},
+      url: VuFind.path + '/AJAX/JSON?method=getIlsStatus',
+      success: function(response) {
+          $('.searchHomeContent').prepend(response.data);
+      }
+  });
+});
+JS;
+  ?>
+  <?=$this->inlineScript(\Zend\View\Helper\HeadScript::SCRIPT, $ilsStatusScript, 'SET'); ?>
+
+  <?=$this->context($this)->renderInContext("search/searchbox.phtml", ['ignoreHiddenFilterMemory' => true])?>
+  <?=$this->inlineScript(\Zend\View\Helper\HeadScript::SCRIPT, '$("#searchForm_lookfor").focus();', 'SET'); ?>
 </div>
 
-<? $facetList = is_object($this->results) ? $this->results->getFacetList() : array(); ?>
 <? if (isset($facetList) && is_array($facetList)): ?>
-  <div class="row">
+  <div class="search-home-facets">
     <? foreach ($facetList as $field => $details): ?>
       <? if (isset($this->hierarchicalFacets) && in_array($field, $this->hierarchicalFacets)): ?>
         <? $this->headScript()->appendFile('vendor/jsTree/jstree.min.js'); ?>
@@ -41,7 +55,7 @@ $(document).ready(function() {
 JS;
         ?>
         <?=$this->inlineScript(\Zend\View\Helper\HeadScript::SCRIPT, $script, 'SET'); ?>
-        <div class="facet <?=$field=='callnumber-first' ? 'col-sm-6' : 'col-sm-3' ?>">
+        <div class="home-facet <?=$this->escapeHtmlAttr($field) ?>">
           <h2><?=$this->transEsc('home_browse') . ' ' . $this->transEsc($details['label'])?></h2>
           <div id="facet_<?=$this->escapeHtml($field)?>" class="jstree-facet"
               data-facet="<?=$this->escapeHtml($field)?>"
@@ -55,42 +69,41 @@ JS;
         <noscript>
       <? endif; ?>
       <? $sortedList = $this->sortFacetList($this->results, $field, $details['list'], $basicSearch); ?>
-      <div class="<?=$field=='callnumber-first' ? 'col-sm-6' : 'col-sm-3' ?>">
+      <div class="home-facet <?=$this->escapeHtmlAttr($field) ?>">
         <h2><?=$this->transEsc('home_browse') . ' ' . $this->transEsc($details['label'])?></h2>
-        <div class="row">
-          <ul class="list-unstyled <?=$field == "callnumber-first" ? 'col-sm-6' : 'col-sm-12' ?>">
-          <? /* Special case: two columns for LC call numbers... */ ?>
-          <? if ($field == "callnumber-first"): ?>
-            <? $i = 0; foreach ($sortedList as $url => $value): ?>
-              <? if (!empty($value)): ?>
-                <li><a href="<?=$url?>"><?=$this->escapeHtml($value)?></a></li>
-              <? else: $i--; ?>
-              <? endif; ?>
-              <? if (++$i == 10): ?>
-                </ul><ul class="list-unstyled col-sm-6">
-              <? endif; ?>
-            <? endforeach; ?>
-          <? /* Special case: collections */ ?>
-          <? elseif ($field == 'hierarchy_top_title'): ?>
-            <? $i = 0; foreach ($sortedList as $url => $value): ?>
-              <? if (++$i > 10): ?>
-                <li><a href="<?=$this->url('collections-home')?>"><strong><?=$this->transEsc("More options")?>...</strong></a></li>
-                <? break; ?>
-              <? else: ?>
+        <div class="home-facet-container">
+          <ul class="home-facet-list">
+            <? /* Special case: two columns for LC call numbers... */ ?>
+            <? if ($field == "callnumber-first"): ?>
+              <? $i = 0; foreach ($sortedList as $url => $value): ?>
+                <? if (!empty($value)): ?>
+                  <li><a href="<?=$url?>"><?=$this->escapeHtml($value)?></a></li>
+                <? else: $i--; ?>
+                <? endif; ?>
+                <? if (++$i == 10): ?>
+                  </ul><ul class="home-facet-list">
+                <? endif; ?>
+              <? endforeach; ?>
+            <? /* Special case: collections */ ?>
+            <? elseif ($field == 'hierarchy_top_title'): ?>
+              <? $i = 0; foreach ($sortedList as $url => $value): ?>
+                <? if (++$i > 10): ?>
+                  <li><a href="<?=$this->url('collections-home')?>"><strong><?=$this->transEsc("More options")?>...</strong></a></li>
+                  <? break; ?>
+                <? endif; ?>
                 <li><a href="<?=$this->url('collections-bytitle')?>?title=<?=urlencode($value)?>"><?=$this->escapeHtml($value)?></a></li>
-              <? endif; ?>
-            <? endforeach; ?>
-          <? else: ?>
-            <? $i = 0; foreach ($sortedList as $url => $value): ?>
-              <? if (++$i > 10): ?>
-                <li><a href="<?=$this->url($advSearch)?>"><strong><?=$this->transEsc("More options")?>...</strong></a></li>
-                <? break; ?>
-              <? elseif (!empty($value)): ?>
-                <li><a href="<?=$url?>"><?=$this->escapeHtml($value)?></a></li>
-              <? else: $i--; ?>
-              <? endif; ?>
-            <? endforeach; ?>
-          <? endif; ?>
+              <? endforeach; ?>
+            <? else: ?>
+              <? $i = 0; foreach ($sortedList as $url => $value): ?>
+                <? if (++$i > 10): ?>
+                  <li><a href="<?=$this->url($advSearch)?>"><strong><?=$this->transEsc("More options")?>...</strong></a></li>
+                  <? break; ?>
+                <? elseif (!empty($value)): ?>
+                  <li><a href="<?=$url?>"><?=$this->escapeHtml($value)?></a></li>
+                <? else: $i--; ?>
+                <? endif; ?>
+              <? endforeach; ?>
+            <? endif; ?>
           </ul>
         </div>
       </div>
@@ -99,4 +112,4 @@ JS;
       <? endif; ?>
     <? endforeach; ?>
   </div>
-<? endif; ?>
\ No newline at end of file
+<? endif; ?>
diff --git a/themes/bootstrap3/templates/search/list-grid.phtml b/themes/bootstrap3/templates/search/list-grid.phtml
index 1c76b69c593ce9db97439f0f3e786462b14e601e..141a04894addf5cafee9c6c6e1b4a637b76ee96d 100644
--- a/themes/bootstrap3/templates/search/list-grid.phtml
+++ b/themes/bootstrap3/templates/search/list-grid.phtml
@@ -1,8 +1,12 @@
-<div class="row">
-<? $i = 0; foreach ($this->results->getResults() as $current): ?>
-  <div id="result<?=$i++ ?>" class="col-sm-3 col-xs-6 grid">
+<div class="search-grid">
+  <? $it = 0; ?>
+  <? foreach ($this->results->getResults() as $current): ?>
     <?=$this->record($current)->getSearchResult('grid')?>
-  </div>
-  <?=($i%4==0)?'</div><div class="row">':''?>
-<? endforeach; ?>
+    <? $it++; ?>
+    <? if ($it % 4 === 0): ?>
+      <br class="grid-large-break"/>
+    <? elseif ($it % 2 === 0): ?>
+      <br class="grid-small-break"/>
+    <? endif; ?>
+  <? endforeach; ?>
 </div>
diff --git a/themes/bootstrap3/templates/search/list-list.phtml b/themes/bootstrap3/templates/search/list-list.phtml
index b6adf0cd9e9f3ab7262720834173953cdc6e12b0..a3d3673e14d7651612c7399fe6763371395324f4 100644
--- a/themes/bootstrap3/templates/search/list-list.phtml
+++ b/themes/bootstrap3/templates/search/list-list.phtml
@@ -1,19 +1,14 @@
 <? if (!isset($this->indexStart)) $this->indexStart = 0; ?>
-<? $showCheckboxes = (isset($this->showCartControls) && $this->showCartControls)
-  || (isset($this->showBulkOptions) && $this->showBulkOptions); ?>
-<? $i = $this->indexStart; foreach ($this->results->getResults() as $current):
-  $recordNumber = $this->results->getStartRecord()+$i-$this->indexStart; ?>
+<? $i = $this->indexStart; ?>
+<? foreach ($this->results->getResults() as $current): ?>
+  <? $recordNumber = $this->results->getStartRecord() + $i-$this->indexStart; ?>
   <div id="result<?=$i++ ?>" class="result<?=$current->supportsAjaxStatus()?' ajaxItem':''?>">
-    <div class="checkbox hidden-print">
-      <? if ($showCheckboxes): ?>
-        <label>
-          <?=$this->record($current)->getCheckbox()?>
-          <?=$recordNumber ?>
-        </label>
-      <? else: ?>
-        <?=$recordNumber ?>
-      <? endif; ?>
+    <? if (isset($this->showCheckboxes) && $this->showCheckboxes): ?>
+      <?=$this->record($current)->getCheckbox('', 'search-cart-form')?>
+    <? endif; ?>
+    <div class="record-number">
+      <?=$recordNumber ?>
     </div>
     <?=$this->record($current)->getSearchResult('list')?>
   </div>
-<? endforeach; ?>
\ No newline at end of file
+<? endforeach; ?>
diff --git a/themes/bootstrap3/templates/search/list-visual.phtml b/themes/bootstrap3/templates/search/list-visual.phtml
index 350256083851917565e1f04339bb24fe8a7b9b5c..2c85dba1450d648cbba6a9469969ee0903025e51 100644
--- a/themes/bootstrap3/templates/search/list-visual.phtml
+++ b/themes/bootstrap3/templates/search/list-visual.phtml
@@ -5,6 +5,6 @@
   </div>
 
   <div id="viz-instructions">
-    <p><strong><a href="<?=$this->url('help-home', array(), array('query' => array('topic' => 'visualization')))?>" class="visualizationHelp"><?=$this->transEsc('What am I looking at')?></a></strong></p>
+    <p><strong><a href="<?=$this->url('help-home', [], ['query' => ['topic' => 'visualization']])?>" class="visualizationHelp"><?=$this->transEsc('What am I looking at')?></a></strong></p>
   </div>
 </div>
diff --git a/themes/bootstrap3/templates/search/newitem.phtml b/themes/bootstrap3/templates/search/newitem.phtml
index a1443f9948b3c6fa9c5bb39aed3cc0ce477c2b8a..96163f91d4ad2fed9f0c8ed7b69fcb4e62389bc4 100644
--- a/themes/bootstrap3/templates/search/newitem.phtml
+++ b/themes/bootstrap3/templates/search/newitem.phtml
@@ -4,37 +4,35 @@
 
     // Set up breadcrumbs:
     $this->layout()->breadcrumbs = '<li class="active">' . $this->transEsc('New Items') . '</li>';
+
+    // Convenience variable:
+    $offlineMode = $this->ils()->getOfflineMode();
 ?>
 <h2><?=$this->transEsc('Find New Items')?></h2>
-<form method="get" class="form-horizontal">
+<? if ($offlineMode == "ils-offline"): ?>
+  <?=$this->render('Helpers/ils-offline.phtml', ['offlineModeMsg' => 'ils_offline_holdings_message'])?>
+<? endif; ?>
+<form method="get" class="form-search-newitem">
   <div class="form-group">
-    <label class="col-sm-3 control-label"><?=$this->transEsc('Range')?>:</label>
-    <div class="col-sm-9">
-      <div class="btn-group" data-toggle="buttons">
-        <? foreach ($this->ranges as $key => $range): ?>
-          <label class="btn btn-primary<? if($key == 0): ?> active<? endif ?>">
-            <input type="radio" name="range" id="newitem_range_<?=$this->escapeHtmlAttr($key)?>" value="<?=$this->escapeHtmlAttr($range)?>"<?=($key == 0) ? ' checked="checked"' : ''?>/>
-            <?=($range == 1) ? $this->transEsc('Yesterday') : $this->transEsc('Past') . ' ' . $this->escapeHtml($range) . ' ' . $this->transEsc('Days')?>
-          </label>
-        <? endforeach; ?>
-      </div>
+    <label class="control-label"><?=$this->transEsc('Range')?>:</label>
+    <div class="btn-group" data-toggle="buttons">
+      <? foreach ($this->ranges as $key => $range): ?>
+        <label class="btn btn-primary<? if($key == 0): ?> active<? endif ?>">
+          <input type="radio" name="range" id="newitem_range_<?=$this->escapeHtmlAttr($key)?>" value="<?=$this->escapeHtmlAttr($range)?>"<?=($key == 0) ? ' checked="checked"' : ''?>/>
+          <?=($range == 1) ? $this->transEsc('Yesterday') : $this->transEsc('Past') . ' ' . $this->escapeHtml($range) . ' ' . $this->transEsc('Days')?>
+        </label>
+      <? endforeach; ?>
     </div>
   </div>
   <? if (is_array($this->fundList) && !empty($this->fundList)): ?>
     <div class="form-group">
-      <label class="col-sm-3 control-label" for="newitem_department"><?=$this->transEsc('Department')?>:</label>
-      <div class="col-sm-9">
-        <select id="newitem_department" name="department" size="10" class="form-control">
-        <? foreach ($this->fundList as $fundId => $fund): ?>
-          <option value="<?=$this->escapeHtmlAttr($fundId)?>"><?=$this->transEsc($fund)?></option>
-        <? endforeach; ?>
-        </select>
-      </div>
+      <label class="control-label" for="newitem_department"><?=$this->transEsc('Department')?>:</label>
+      <select id="newitem_department" name="department" size="10" class="form-control">
+      <? foreach ($this->fundList as $fundId => $fund): ?>
+        <option value="<?=$this->escapeHtmlAttr($fundId)?>"><?=$this->transEsc($fund)?></option>
+      <? endforeach; ?>
+      </select>
     </div>
   <? endif; ?>
-  <div class="form-group">
-    <div class="col-sm-9 col-sm-offset-3">
-      <input class="btn btn-primary" type="submit" name="submit" value="<?=$this->transEsc('Find')?>"/>
-    </div>
-  </div>
-</form>
\ No newline at end of file
+  <input class="btn btn-primary" type="submit" name="submit" value="<?=$this->transEsc('Find')?>"/>
+</form>
diff --git a/themes/bootstrap3/templates/search/newitemresults.phtml b/themes/bootstrap3/templates/search/newitemresults.phtml
index fc8546b78150cd46d9777def5c2acfd0cb649614..0115a979ea7c4ca6c2a0e28a28ac1483d0042f5c 100644
--- a/themes/bootstrap3/templates/search/newitemresults.phtml
+++ b/themes/bootstrap3/templates/search/newitemresults.phtml
@@ -4,4 +4,4 @@
   $this->overrideSearchHeading = $this->transEsc('New Items');
   $this->overrideEmptyMessage = $this->transEsc('No new item information is currently available.');
   echo $this->render('search/results.phtml');
-?>
\ No newline at end of file
+?>
diff --git a/themes/bootstrap3/templates/search/pagination.phtml b/themes/bootstrap3/templates/search/pagination.phtml
index b4c32f34512b4568e89e3e2df9f4655e69aea403..6eda62a3bfa321b46a2bbf6288b7eedd0a298794 100644
--- a/themes/bootstrap3/templates/search/pagination.phtml
+++ b/themes/bootstrap3/templates/search/pagination.phtml
@@ -4,7 +4,7 @@
       <? if (!isset($this->options['disableFirst']) || !$this->options['disableFirst']): ?>
         <li><a href="<?=$this->currentPath() . $this->results->getUrlQuery()->setPage(1)?>">[1]</a></li>
       <? endif; ?>
-      <li><a href="<?=$this->currentPath() . $this->results->getUrlQuery()->setPage($this->previous)?>">&laquo; <?=$this->transEsc('Prev')?></a></li>
+      <li><a class="page-prev" href="<?=$this->currentPath() . $this->results->getUrlQuery()->setPage($this->previous)?>">&laquo; <?=$this->transEsc('Prev')?></a></li>
     <? endif; ?>
 
     <? if (count($this->pagesInRange) > 1): ?>
@@ -18,10 +18,10 @@
     <? endif; ?>
 
     <? if (isset($this->next)): ?>
-      <li><a href="<?=$this->currentPath() . $this->results->getUrlQuery()->setPage($this->next)?>"><?=$this->transEsc('Next');?> &raquo;</a></li>
+      <li><a class="page-next" href="<?=$this->currentPath() . $this->results->getUrlQuery()->setPage($this->next)?>"><?=$this->transEsc('Next');?> &raquo;</a></li>
       <? if (!isset($this->options['disableLast']) || !$this->options['disableLast']): ?>
         <li><a href="<?=$this->currentPath() . $this->results->getUrlQuery()->setPage($this->pageCount)?>">[<?=$this->pageCount?>]</a></li>
       <? endif; ?>
     <? endif; ?>
   </ul>
-<? endif; ?>
\ No newline at end of file
+<? endif; ?>
diff --git a/themes/bootstrap3/templates/search/reserves.phtml b/themes/bootstrap3/templates/search/reserves.phtml
index 8984ceca912fb750b252a2b4d9ddaa2f3a94f2e0..1ed5be825d11b01202e69451e535c20574a54ce4 100644
--- a/themes/bootstrap3/templates/search/reserves.phtml
+++ b/themes/bootstrap3/templates/search/reserves.phtml
@@ -4,57 +4,52 @@
 
     // Set up breadcrumbs:
     $this->layout()->breadcrumbs = '<li class="active">' . $this->transEsc('Reserves') . '</li>';
+
+    // Convenience variable:
+    $offlineMode = $this->ils()->getOfflineMode();
 ?>
-<h2><?=$this->transEsc('Search For Items on Reserve')?></h2>
-<form method="get" name="searchForm" class="form-horizontal">
-  <? if (is_array($this->courseList)): ?>
-    <div class="form-group">
-      <label for="reserves_by_course" class="col-sm-2 control-label"><?=$this->transEsc('By Course')?>:</label>
-      <div class="col-sm-5">
+<? if ($offlineMode == "ils-offline"): ?>
+  <?=$this->render('Helpers/ils-offline.phtml', ['offlineModeMsg' => 'ils_offline_holdings_message'])?>
+<? else: ?>
+  <h2><?=$this->transEsc('Search For Items on Reserve')?></h2>
+  <form method="get" name="searchForm" class="form-search-reserves">
+    <? if (is_array($this->courseList)): ?>
+      <div class="form-group">
+        <label for="reserves_by_course" class="control-label"><?=$this->transEsc('By Course')?>:</label>
         <select name="course" id="reserves_by_course" class="form-control">
           <option></option>
           <? foreach ($this->courseList as $courseId => $courseName): ?>
             <option value="<?=$this->escapeHtmlAttr($courseId)?>"><?=$this->escapeHtml($courseName)?></option>
           <? endforeach; ?>
         </select>
-      </div>
-      <div class="col-sm-2">
         <input class="btn btn-primary" type="submit" name="submit" value="<?=$this->transEsc('Find')?>"/>
       </div>
-    </div>
-  <? endif; ?>
+    <? endif; ?>
 
-  <? if (is_array($this->instList)): ?>
-    <div class="form-group">
-      <label for="reserves_by_inst" class="col-sm-2 control-label"><?=$this->transEsc('By Instructor')?>:</label>
-      <div class="col-sm-5">
+    <? if (is_array($this->instList)): ?>
+      <div class="form-group">
+        <label for="reserves_by_inst" class="control-label"><?=$this->transEsc('By Instructor')?>:</label>
         <select name="inst" id="reserves_by_inst" class="form-control">
           <option></option>
           <? foreach ($this->instList as $instId => $instName): ?>
             <option value="<?=$this->escapeHtmlAttr($instId)?>"><?=$this->escapeHtml($instName)?></option>
           <? endforeach; ?>
         </select>
-      </div>
-      <div class="col-sm-2">
         <input class="btn btn-primary" type="submit" name="submit" value="<?=$this->transEsc('Find')?>"/>
       </div>
-    </div>
-  <? endif; ?>
+    <? endif; ?>
 
-  <? if (is_array($this->deptList)): ?>
-    <div class="form-group">
-      <label for="reserves_by_dept" class="col-sm-2 control-label"><?=$this->transEsc('By Department')?>:</label>
-      <div class="col-sm-5">
+    <? if (is_array($this->deptList)): ?>
+      <div class="form-group">
+        <label for="reserves_by_dept" class="control-label"><?=$this->transEsc('By Department')?>:</label>
         <select name="dept" id="reserves_by_dept" class="form-control">
           <option></option>
           <? foreach ($this->deptList as $deptId => $deptName): ?>
             <option value="<?=$this->escapeHtmlAttr($deptId)?>"><?=$this->escapeHtml($deptName)?></option>
           <? endforeach; ?>
         </select>
-      </div>
-      <div class="col-sm-2">
         <input class="btn btn-primary" type="submit" name="submit" value="<?=$this->transEsc('Find')?>"/>
       </div>
-    </div>
-  <? endif; ?>
-</form>
\ No newline at end of file
+    <? endif; ?>
+  </form>
+<? endif; ?>
diff --git a/themes/bootstrap3/templates/search/reservesresults.phtml b/themes/bootstrap3/templates/search/reservesresults.phtml
index 55c40b494cf556c50471fae560a8ad3079d36a65..cbf99ffddda3896e503f9cdd61df95cca3f9baf9 100644
--- a/themes/bootstrap3/templates/search/reservesresults.phtml
+++ b/themes/bootstrap3/templates/search/reservesresults.phtml
@@ -17,4 +17,4 @@
     }
     $this->overrideEmptyMessage = $this->transEsc('course_reserves_empty_list');
     echo $this->render('search/results.phtml');
-?>
\ No newline at end of file
+?>
diff --git a/themes/bootstrap3/templates/search/reservessearch.phtml b/themes/bootstrap3/templates/search/reservessearch.phtml
index 5157b1bf30b3bdd888e99e8f00f1e3370763cf6f..d6219e06f30cb70b4b2759a13c3c9dc5bc213314 100644
--- a/themes/bootstrap3/templates/search/reservessearch.phtml
+++ b/themes/bootstrap3/templates/search/reservessearch.phtml
@@ -11,73 +11,77 @@
     $this->searchClassId = 'SolrReserves';
 ?>
 
-<div class="row">
-  <div class="<?=$this->layoutClass('mainbody')?>">
-    <h3><?=$this->transEsc('Search For Items on Reserve')?></h3>
-    <form class="form-inline" method="get" name="reservesSearchForm">
-      <label for="reservesSearchForm_lookfor"><?=$this->transEsc("Your search terms")?></label>
-      <input id="reservesSearchForm_lookfor" type="text" name="lookfor" size="40" value="<?=$this->escapeHtmlAttr($reservesLookfor)?>" <?=$this->searchOptions('SolrReserves')->autocompleteEnabled() ? ' class="autocomplete searcher:SolrReserves type:Reserves"' : ''?> />
-      <input class="btn btn-default" type="submit" name="submit" value="<?=$this->transEsc("Find")?>"/>
-    </form>
-    <script type="text/javascript">$("#reservesSearchForm_lookfor").focus()</script>
+<div class="<?=$this->layoutClass('mainbody')?>">
+  <h3><?=$this->transEsc('Search For Items on Reserve')?></h3>
+  <form class="form-inline" method="get" name="reservesSearchForm">
+    <label for="reservesSearchForm_lookfor"><?=$this->transEsc("Your search terms")?></label>
+    <input id="reservesSearchForm_lookfor" type="text" name="lookfor" size="40" value="<?=$this->escapeHtmlAttr($reservesLookfor)?>" <?=$this->searchOptions('SolrReserves')->autocompleteEnabled() ? ' class="autocomplete searcher:SolrReserves type:Reserves"' : ''?> />
+    <input class="btn btn-primary" type="submit" name="submit" value="<?=$this->transEsc("Find")?>"/>
+  </form>
+  <script type="text/javascript">$("#reservesSearchForm_lookfor").focus()</script>
 
-    <div class="resulthead">
-      <div class="pull-left flip">
-        <? if (($recordTotal = $this->results->getResultTotal()) > 0): ?>
-          <?=$this->transEsc("Showing")?>
-          <strong><?=$this->localizedNumber($this->results->getStartRecord())?></strong> - <strong><?=$this->localizedNumber($this->results->getEndRecord())?></strong>
-          <?=$this->transEsc('of')?> <strong><?=$this->localizedNumber($recordTotal)?></strong>
-          <?=$this->transEsc('for search')?>: <strong>'<?=$this->escapeHtml($reservesLookfor)?>'</strong>,
-          <? if ($qtime = $this->results->getQuerySpeed()): ?>
-            <?=$this->transEsc('query time')?>: <?=$this->localizedNumber($qtime, 2).$this->transEsc('seconds_abbrev')?>
-          <? endif; ?>
-        <? endif; ?>
-      </div>
-
-      <? if ($recordTotal > 0): ?>
-        <div class="pull-right flip">
-          <?=$this->render('search/controls/sort.phtml')?>
-        </div>
-      <? endif; ?>
-    </div>
-    <? if ($recordTotal < 1): ?>
-      <p class="error"><?=$this->transEsc('nohit_prefix')?> - <strong><?=$this->escapeHtml($reservesLookfor)?></strong> - <?=$this->transEsc('nohit_suffix')?></p>
-      <? if (isset($this->parseError)): ?>
-        <p class="error"><?=$this->transEsc('nohit_parse_error')?></p>
-      <? endif; ?>
-    <? else: ?>
-      <table class="table table-striped">
-      <tr>
-        <th class="department"><?=$this->transEsc('Department')?></th>
-        <th class="course"><?=$this->transEsc('Course')?></th>
-        <th class="instructor"><?=$this->transEsc('Instructor')?></th>
-        <th class="items"><?=$this->transEsc('Items')?></th>
-      </tr>
-      <? foreach ($this->results->getResults() as $record): ?>
+  <div class="resulthead">
+    <div class="pull-left flip">
+      <? $qtime = $this->results->getQuerySpeed(); ?>
+      <? if (($recordTotal = $this->results->getResultTotal()) > 0): ?>
         <?
-            $url = $this->currentPath() . $this->escapeHtmlAttr(
-                '?inst=' . urlencode($record->getInstructorId())
-                . '&course=' . urlencode($record->getCourseId())
-                . '&dept=' . urlencode($record->getDepartmentId())
-            );
+          $transParams = [
+            '%%start%%' => $this->localizedNumber($this->results->getStartRecord()),
+            '%%end%%'   => $this->localizedNumber($this->results->getEndRecord()),
+            '%%total%%' => $this->localizedNumber($recordTotal),
+            '%%lookfor%%' => $this->escapeHtml($reservesLookfor)
+          ];
         ?>
-        <tr>
-          <td class="department"><a href="<?=$url?>"><?=$this->escapeHtml($record->getDepartment())?></a></td>
-          <td class="course"><a href="<?=$url?>"><?=$this->escapeHtml($record->getCourse())?></a></td>
-          <td class="instructor"><a href="<?=$url?>"><?=$this->escapeHtml($record->getInstructor())?></a></td>
-          <td class="items"><?=$this->escapeHtml($record->getItemCount())?></td>
-        </tr>
-      <? endforeach; ?>
-      </table>
-      <?=$this->paginationControl($this->results->getPaginator(), 'Sliding', 'search/pagination.phtml', array('results' => $this->results))?>
+        <?=$this->translate('showing_results_of_for_html', $transParams); ?><? if($qtime): ?>,<? endif; ?>
+      <? endif; ?>
+      <? if ($qtime): ?>
+        <?=$this->transEsc('query time')?>: <?=$this->localizedNumber($qtime, 2).$this->transEsc('seconds_abbrev')?>
+      <? endif; ?>
+    </div>
+
+    <? if ($recordTotal > 0): ?>
+      <div class="pull-right flip">
+        <?=$this->render('search/controls/sort.phtml')?>
+      </div>
     <? endif; ?>
   </div>
-
-  <? /* Narrow Search Options */ ?>
-  <div class="<?=$this->layoutClass('sidebar')?>">
-    <? foreach ($this->results->getRecommendations('side') as $current): ?>
-      <?=$this->recommend($current)?>
+  <? if ($recordTotal < 1): ?>
+    <p class="error"><?=$this->translate('nohit_lookfor_html', ['%%lookfor%%' => $this->escapeHtml($reservesLookfor)]) ?></p>
+    <? if (isset($this->parseError)): ?>
+      <p class="error"><?=$this->transEsc('nohit_parse_error')?></p>
+    <? endif; ?>
+  <? else: ?>
+    <table class="table table-striped">
+    <tr>
+      <th class="department"><?=$this->transEsc('Department')?></th>
+      <th class="course"><?=$this->transEsc('Course')?></th>
+      <th class="instructor"><?=$this->transEsc('Instructor')?></th>
+      <th class="items"><?=$this->transEsc('Items')?></th>
+    </tr>
+    <? foreach ($this->results->getResults() as $record): ?>
+      <?
+          $url = $this->currentPath() . $this->escapeHtmlAttr(
+              '?inst=' . urlencode($record->getInstructorId())
+              . '&course=' . urlencode($record->getCourseId())
+              . '&dept=' . urlencode($record->getDepartmentId())
+          );
+      ?>
+      <tr>
+        <td class="department"><a href="<?=$url?>"><?=$this->escapeHtml($record->getDepartment())?></a></td>
+        <td class="course"><a href="<?=$url?>"><?=$this->escapeHtml($record->getCourse())?></a></td>
+        <td class="instructor"><a href="<?=$url?>"><?=$this->escapeHtml($record->getInstructor())?></a></td>
+        <td class="items"><?=$this->escapeHtml($record->getItemCount())?></td>
+      </tr>
     <? endforeach; ?>
-  </div>
-  <? /* End Narrow Search Options */ ?>
+    </table>
+    <?=$this->paginationControl($this->results->getPaginator(), 'Sliding', 'search/pagination.phtml', ['results' => $this->results])?>
+  <? endif; ?>
+</div>
+
+<? /* Narrow Search Options */ ?>
+<div class="<?=$this->layoutClass('sidebar')?>">
+  <? foreach ($this->results->getRecommendations('side') as $current): ?>
+    <?=$this->recommend($current)?>
+  <? endforeach; ?>
 </div>
+<? /* End Narrow Search Options */ ?>
diff --git a/themes/bootstrap3/templates/search/results.phtml b/themes/bootstrap3/templates/search/results.phtml
index c0fb8203084d52e7b5cfe6565929bda832df295a..f2782d321f6ff3f9f15780d61998c89bd23f5c9d 100644
--- a/themes/bootstrap3/templates/search/results.phtml
+++ b/themes/bootstrap3/templates/search/results.phtml
@@ -33,9 +33,12 @@
   }
 
   // Enable cart if appropriate:
-  $this->showCartControls = $this->params->getOptions()->supportsCart() && $this->cart()->isActive();
-  // Enable bulk options if appropriate:
   $this->showBulkOptions = $this->params->getOptions()->supportsCart() && $this->showBulkOptions;
+  // Checkboxes if appropriate:
+  $this->showCartControls = $this->params->getOptions()->supportsCart() && $this->cart()->isActive()
+    && ($this->showBulkOptions || !$this->cart()->isActiveInSearch());
+  // Enable bulk options if appropriate:
+  $this->showCheckboxes = $this->showCartControls || $this->showBulkOptions;
 
   // Load Javascript only if list view parameter is NOT full:
   if ($this->params->getOptions()->getListViewOption() != "full") {
@@ -48,101 +51,86 @@
   $this->headScript()->appendFile("check_save_statuses.js");
 ?>
 
-<div class="row">
-  <div class="<?=$this->layoutClass('mainbody')?>">
-    <? if (($recordTotal = $this->results->getResultTotal()) > 0): // only display these at very top if we have results ?>
-      <? foreach ($this->results->getRecommendations('top') as $current): ?>
-        <?=$this->recommend($current)?>
-      <? endforeach; ?>
-    <? endif; ?>
-    <?=$this->flashmessages()?>
-    <div class="hidden-print search-controls row">
-      <div class="col-sm-6">
-        <? if ($recordTotal > 0): ?>
-          <?=$this->transEsc("Showing")?>
-          <strong><?=$this->localizedNumber($this->results->getStartRecord())?></strong> - <strong><?=$this->localizedNumber($this->results->getEndRecord())?></strong>
-          <? if (!isset($this->skipTotalCount)): ?>
-            <? $this->layout()->srmessage = $this->transEsc('result_count', ['%%count%%' => $this->localizedNumber($recordTotal)]); ?>
-            <?=$this->transEsc('of')?> <strong><?=$this->localizedNumber($recordTotal)?></strong>
-          <? endif; ?>
-          <? if (isset($this->overrideSearchHeading)): ?>
-            <?=$this->overrideSearchHeading?>
-          <? elseif ($this->params->getSearchType() == 'basic'): ?>
-            <?=$this->transEsc('for search')?>: <strong>'<?=$this->escapeHtml($lookfor)?>'</strong>,
-          <? endif; ?>
-          <? if ($qtime = $this->results->getQuerySpeed()): ?>
-            <?=$this->transEsc('query time')?>: <?=$this->localizedNumber($qtime, 2).$this->transEsc('seconds_abbrev')?>
-          <? endif; ?>
-        <? else: ?>
-          <h2><?=$this->transEsc('nohit_heading')?></h2>
-        <? endif; ?>
-      </div>
-
+<div class="<?=$this->layoutClass('mainbody')?>">
+  <? if (($recordTotal = $this->results->getResultTotal()) > 0): // only display these at very top if we have results ?>
+    <? foreach ($this->results->getRecommendations('top') as $current): ?>
+      <?=$this->recommend($current)?>
+    <? endforeach; ?>
+  <? endif; ?>
+  <?=$this->flashmessages()?>
+  <nav class="search-header hidden-print">
+    <div class="search-stats">
       <? if ($recordTotal > 0): ?>
-        <div class="col-sm-6 text-right">
-          <?=$this->render('search/controls/limit.phtml')?>
-          <?=$this->render('search/controls/sort.phtml')?>
-          <?=$this->render('search/controls/view.phtml')?>
-        </div>
+        <?=$this->context()->renderInContext('search/controls/showing.phtml', ['lookfor' => $lookfor, 'recordTotal' => $recordTotal]) ?>
+      <? else: ?>
+        <h2><?=$this->transEsc('nohit_heading')?></h2>
       <? endif; ?>
     </div>
-    <? /* End Listing Options */ ?>
 
-    <? if ($recordTotal < 1): ?>
-      <p>
-        <? if (isset($this->overrideEmptyMessage)): ?>
-          <?=$this->overrideEmptyMessage?>
-        <? else: ?>
-          <? $this->layout()->srmessage = $this->transEsc('nohit_prefix') . ' - ' . $this->escapeHtml($lookfor) . ' - ' . $this->transEsc('nohit_suffix'); ?>
-          <?=$this->layout()->srmessage ?>
-        <? endif; ?>
-      </p>
-      <? if (isset($this->parseError)): ?>
-        <p class="alert alert-danger"><?=$this->transEsc('nohit_parse_error')?></p>
+    <? if ($recordTotal > 0): ?>
+      <div class="search-controls">
+        <?=$this->render('search/controls/limit.phtml')?>
+        <?=$this->render('search/controls/sort.phtml')?>
+        <?=$this->render('search/controls/view.phtml')?>
+      </div>
+    <? endif; ?>
+  </nav>
+  <? /* End Listing Options */ ?>
+
+  <? if ($recordTotal < 1): ?>
+    <p>
+      <? if (isset($this->overrideEmptyMessage)): ?>
+        <?=$this->overrideEmptyMessage?>
+      <? else: ?>
+        <? $this->layout()->srmessage = $this->translate('nohit_lookfor_html', ['%%lookfor%%' => $this->escapeHtml($lookfor)]); ?>
+        <?=$this->layout()->srmessage ?>
       <? endif; ?>
-      <? foreach (($top = $this->results->getRecommendations('top')) as $current): ?>
+    </p>
+    <? if (isset($this->parseError)): ?>
+      <p class="alert alert-danger"><?=$this->transEsc('nohit_parse_error')?></p>
+    <? endif; ?>
+    <? foreach (($top = $this->results->getRecommendations('top')) as $current): ?>
+      <?=$this->recommend($current)?>
+    <? endforeach; ?>
+    <? foreach ($this->results->getRecommendations('noresults') as $current): ?>
+      <? if (!in_array($current, $top)): ?>
         <?=$this->recommend($current)?>
-      <? endforeach; ?>
-      <? foreach ($this->results->getRecommendations('noresults') as $current): ?>
-        <? if (!in_array($current, $top)): ?>
-          <?=$this->recommend($current)?>
-        <? endif; ?>
-      <? endforeach; ?>
-    <? else: ?>
-      <form class="form-inline" method="post" name="bulkActionForm" action="<?=$this->url('cart-searchresultsbulk')?>" data-lightbox data-lightbox-onsubmit="bulkFormHandler">
-        <?=$this->context($this)->renderInContext('search/bulk-action-buttons.phtml', array('idPrefix' => ''))?>
-        <?=$this->render('search/list-' . $this->params->getView() . '.phtml')?>
-        <?=$this->context($this)->renderInContext('search/bulk-action-buttons.phtml', array('idPrefix' => 'bottom_'))?>
-        <?=$this->paginationControl($this->results->getPaginator(), 'Sliding', 'search/pagination.phtml', array('results' => $this->results, 'options' => isset($this->paginationOptions) ? $this->paginationOptions : []))?>
-      </form>
+      <? endif; ?>
+    <? endforeach; ?>
+  <? else: ?>
+    <form id="search-cart-form" method="post" name="bulkActionForm" action="<?=$this->url('cart-searchresultsbulk')?>" data-lightbox data-lightbox-onsubmit="bulkFormHandler">
+      <?=$this->context($this)->renderInContext('search/bulk-action-buttons.phtml', ['idPrefix' => ''])?>
+    </form>
+    <?=$this->render('search/list-' . $this->params->getView() . '.phtml')?>
+    <?=$this->context($this)->renderInContext('search/bulk-action-buttons.phtml', ['idPrefix' => 'bottom_', 'formAttr' => 'search-cart-form'])?>
+    <?=$this->paginationControl($this->results->getPaginator(), 'Sliding', 'search/pagination.phtml', ['results' => $this->results, 'options' => isset($this->paginationOptions) ? $this->paginationOptions : []])?>
 
-      <div class="searchtools hidden-print">
-        <strong><?=$this->transEsc('Search Tools')?>:</strong>
-        <a href="<?=$this->results->getUrlQuery()->setViewParam('rss')?>"><i class="fa fa-bell" aria-hidden="true"></i> <?=$this->transEsc('Get RSS Feed')?></a>
+    <div class="searchtools hidden-print">
+      <strong><?=$this->transEsc('Search Tools')?>:</strong>
+      <a href="<?=$this->results->getUrlQuery()->setViewParam('rss')?>"><i class="fa fa-bell" aria-hidden="true"></i> <?=$this->transEsc('Get RSS Feed')?></a>
+      &mdash;
+      <a href="<?=$this->url('search-email')?>" class="mailSearch" data-lightbox id="mailSearch<?=$this->escapeHtmlAttr($this->results->getSearchId())?>">
+        <i class="fa fa-envelope" aria-hidden="true"></i> <?=$this->transEsc('Email this Search')?>
+      </a>
+      <? if ($this->accountCapabilities()->getSavedSearchSetting() === 'enabled'): ?>
         &mdash;
-        <a href="<?=$this->url('search-email')?>" class="mailSearch" data-lightbox id="mailSearch<?=$this->escapeHtmlAttr($this->results->getSearchId())?>">
-          <i class="fa fa-envelope" aria-hidden="true"></i> <?=$this->transEsc('Email this Search')?>
-        </a>
-        <? if ($this->accountCapabilities()->getSavedSearchSetting() === 'enabled'): ?>
-          &mdash;
-          <? if (is_numeric($this->results->getSearchId())): ?>
-            <? if ($this->results->isSavedSearch()): ?>
-              <a href="<?=$this->url('myresearch-savesearch')?>?delete=<?=urlencode($this->results->getSearchId())?>"><i class="fa fa-remove" aria-hidden="true"></i> <?=$this->transEsc('save_search_remove')?></a>
-            <? else: ?>
-              <a href="<?=$this->url('myresearch-savesearch')?>?save=<?=urlencode($this->results->getSearchId())?>"><i class="fa fa-save" aria-hidden="true"></i> <?=$this->transEsc('save_search')?></a>
-            <? endif; ?>
+        <? if (is_numeric($this->results->getSearchId())): ?>
+          <? if ($this->results->isSavedSearch()): ?>
+            <a href="<?=$this->url('myresearch-savesearch')?>?delete=<?=urlencode($this->results->getSearchId())?>"><i class="fa fa-remove" aria-hidden="true"></i> <?=$this->transEsc('save_search_remove')?></a>
+          <? else: ?>
+            <a href="<?=$this->url('myresearch-savesearch')?>?save=<?=urlencode($this->results->getSearchId())?>"><i class="fa fa-save" aria-hidden="true"></i> <?=$this->transEsc('save_search')?></a>
           <? endif; ?>
         <? endif; ?>
-      </div>
-    <? endif; ?>
-  </div>
-  <? /* End Main Listing */ ?>
+      <? endif; ?>
+    </div>
+  <? endif; ?>
+</div>
+<? /* End Main Listing */ ?>
 
-  <? /* Narrow Search Options */ ?>
-  <div class="<?=$this->layoutClass('sidebar')?>">
-    <? foreach ($this->results->getRecommendations('side') as $current): ?>
-      <?=$this->recommend($current)?>
-    <? endforeach; ?>
-  </div>
-  <? /* End Narrow Search Options */ ?>
+<? /* Narrow Search Options */ ?>
+<div class="<?=$this->layoutClass('sidebar')?>">
+  <? foreach ($this->results->getRecommendations('side') as $current): ?>
+    <?=$this->recommend($current)?>
+  <? endforeach; ?>
 </div>
+<? /* End Narrow Search Options */ ?>
diff --git a/themes/bootstrap3/templates/search/searchTabs.phtml b/themes/bootstrap3/templates/search/searchTabs.phtml
index 05ba2bf5cf6f67ba2c68d6f22526c760d5ab3b6b..a07b4a355ec215f47f2da05c5991c064ac707592 100644
--- a/themes/bootstrap3/templates/search/searchTabs.phtml
+++ b/themes/bootstrap3/templates/search/searchTabs.phtml
@@ -1,4 +1,3 @@
-<? $searchTabs = $this->searchtabs()->getTabConfig($this->searchClassId, $this->lookfor, $this->searchIndex, $this->searchType, $this->hiddenFilters); ?>
 <? if (count($searchTabs) > 0): ?>
   <ul class="nav nav-tabs">
     <? foreach ($searchTabs as $tab): ?>
@@ -7,4 +6,4 @@
       </li>
     <? endforeach; ?>
   </ul>
-<? endif; ?>
\ No newline at end of file
+<? endif; ?>
diff --git a/themes/bootstrap3/templates/search/searchbox.phtml b/themes/bootstrap3/templates/search/searchbox.phtml
index e7d0c4ea19db9434d8d1cc4d473d032ece871cdb..7ae85885ee8c3e72607eca4b6c156d4f6bcf117f 100644
--- a/themes/bootstrap3/templates/search/searchbox.phtml
+++ b/themes/bootstrap3/templates/search/searchbox.phtml
@@ -27,9 +27,10 @@
     }
     $hiddenFilterParams = $this->searchtabs()->getCurrentHiddenFilterParams($this->searchClassId, $ignoreHiddenFilterMemory, '?');
 ?>
+<? $searchTabs = $this->searchtabs()->getTabConfig($this->searchClassId, $this->lookfor, $this->searchIndex, $this->searchType, $hiddenFilters); ?>
 <? if ($this->searchType == 'advanced'): ?>
-  <div class="searchForm navbar-form navbar-left flip">
-    <? $tabs = $this->context($this)->renderInContext('search/searchTabs', ['hiddenFilters' => $hiddenFilters]); ?>
+  <div class="navbar-form navbar-left flip">
+    <? $tabs = $this->context($this)->renderInContext('search/searchTabs', ['searchTabs' => $searchTabs['tabs']]); ?>
     <? if (!empty($tabs)): ?><?=$tabs ?><div class="tab-content clearfix"><? endif; ?>
       <p class="adv_search_terms"><?=$this->transEsc("Your search terms")?> : "<strong><?=$this->escapeHtml($this->lookfor)?></strong>"</p>
       <p class="adv_search_links">
@@ -40,11 +41,12 @@
     <? if (!empty($tabs)): ?></div><? endif; ?>
   </div>
 <? else: ?>
-  <form class="searchForm navbar-form navbar-left flip" method="get" action="<?=$this->url($basicSearch)?>" name="searchForm" autocomplete="off">
-    <?= $this->context($this)->renderInContext('search/searchTabs', ['hiddenFilters' => $hiddenFilters]); ?>
-    <input class="searchForm_lookfor form-control search-query<? if($this->searchbox()->autocompleteEnabled($this->searchClassId)):?> autocomplete searcher:<?=$this->escapeHtmlAttr($this->searchClassId) ?><? endif ?>" type="text" name="lookfor" value="<?=$this->escapeHtmlAttr($this->lookfor)?>"/>
+  <form id="searchForm" class="searchForm navbar-form navbar-left flip" method="get" action="<?=$this->url($basicSearch)?>" name="searchForm" autocomplete="off">
+    <?= $this->context($this)->renderInContext('search/searchTabs', ['searchTabs' => $searchTabs['tabs']]); ?>
+    <? $placeholder = $this->searchbox()->getPlaceholderText(isset($searchTabs['selected']['id']) ? $searchTabs['selected']['id'] : null); ?>
+    <input id="searchForm_lookfor" class="searchForm_lookfor form-control search-query<? if($this->searchbox()->autocompleteEnabled($this->searchClassId)):?> autocomplete searcher:<?=$this->escapeHtmlAttr($this->searchClassId) ?><? endif ?>" type="text" name="lookfor" value="<?=$this->escapeHtmlAttr($this->lookfor)?>"<? if ($placeholder): ?> placeholder="<?=$this->transEsc($placeholder) ?>"<? endif ?> />
     <? if ($handlerCount > 1): ?>
-      <select class="searchForm_type form-control" name="type" data-native-menu="false">
+      <select id="searchForm_type" class="searchForm_type form-control" name="type" data-native-menu="false">
         <? foreach ($handlers as $handler): ?>
           <option value="<?=$this->escapeHtmlAttr($handler['value'])?>"<?=$handler['selected'] ? ' selected="selected"' : ''?>><?=$handler['indent'] ? '-- ' : ''?><?=$this->transEsc($handler['label'])?></option>
         <? endforeach; ?>
@@ -73,8 +75,8 @@
     <? endif; ?>
     <?
       $filterDetails = $this->searchbox()->getFilterDetails(
-          isset($this->filterList) && is_array($this->filterList) ? $this->filterList : array(),
-          isset($this->checkboxFilters) && is_array($this->checkboxFilters) ? $this->checkboxFilters : array()
+          isset($this->filterList) && is_array($this->filterList) ? $this->filterList : [],
+          isset($this->checkboxFilters) && is_array($this->checkboxFilters) ? $this->checkboxFilters : []
       );
     ?>
     <? if ((isset($hasDefaultsApplied) && $hasDefaultsApplied) || !empty($filterDetails)): ?>
@@ -116,5 +118,4 @@
       }
     ?>
   </form>
-  <script type="text/javascript">$(".searchForm_lookfor:visible").focus()</script>
 <? endif; ?>
diff --git a/themes/bootstrap3/templates/summon/advanced.phtml b/themes/bootstrap3/templates/summon/advanced.phtml
index 9b346d8e1c0410f0c5efa5302c1dfbf09da1f224..22a7c0a135dacc6a705dba7d58c7e2b1c6a86c0e 100644
--- a/themes/bootstrap3/templates/summon/advanced.phtml
+++ b/themes/bootstrap3/templates/summon/advanced.phtml
@@ -3,4 +3,4 @@
   // standard advanced search layout:
   $this->extraAdvancedControls = $this->render('search/advanced/summon.phtml');
   echo $this->render('search/advanced/layout.phtml');
-?>
\ No newline at end of file
+?>
diff --git a/themes/bootstrap3/templates/summon/home.phtml b/themes/bootstrap3/templates/summon/home.phtml
index d13d4348c1e39e2222b5f16ce7d65ecd7816ef92..bc5b700660ea8e7baee8cc01de0600b0b4611521 100644
--- a/themes/bootstrap3/templates/summon/home.phtml
+++ b/themes/bootstrap3/templates/summon/home.phtml
@@ -1 +1 @@
-<?=$this->render('search/home.phtml');?>
\ No newline at end of file
+<?=$this->render('search/home.phtml');?>
diff --git a/themes/bootstrap3/templates/summon/search.phtml b/themes/bootstrap3/templates/summon/search.phtml
index c1797c1cd4a1ebb2ccad84718b1e225e51cac6a8..a0c6dd4bbf5077e0b43b335e98733b44bba7b4e6 100644
--- a/themes/bootstrap3/templates/summon/search.phtml
+++ b/themes/bootstrap3/templates/summon/search.phtml
@@ -1,4 +1,4 @@
 <?
     // Load standard settings from the default search results screen:
     echo $this->render('search/results.phtml');
-?>
\ No newline at end of file
+?>
diff --git a/themes/bootstrap3/templates/tag/home.phtml b/themes/bootstrap3/templates/tag/home.phtml
index c1797c1cd4a1ebb2ccad84718b1e225e51cac6a8..a0c6dd4bbf5077e0b43b335e98733b44bba7b4e6 100644
--- a/themes/bootstrap3/templates/tag/home.phtml
+++ b/themes/bootstrap3/templates/tag/home.phtml
@@ -1,4 +1,4 @@
 <?
     // Load standard settings from the default search results screen:
     echo $this->render('search/results.phtml');
-?>
\ No newline at end of file
+?>
diff --git a/themes/bootstrap3/templates/upgrade/error.phtml b/themes/bootstrap3/templates/upgrade/error.phtml
index 565268b0cc9a332234a904f19f1be5b5e029cae2..ef4b9e2b55f263462fb05e02a8a8b1d0e4e215f8 100644
--- a/themes/bootstrap3/templates/upgrade/error.phtml
+++ b/themes/bootstrap3/templates/upgrade/error.phtml
@@ -7,4 +7,4 @@
 ?>
 <h2><?=$this->transEsc('Upgrade VuFind')?></h2>
 <?=$this->flashmessages()?>
-<p><?=$this->transEsc('vufind_upgrade_fail') ?>.  You can try <a href="<?=$this->url('upgrade-reset')?>">starting over</a>.</p>
\ No newline at end of file
+<p><?=$this->transEsc('vufind_upgrade_fail') ?>.  You can try <a href="<?=$this->url('upgrade-reset')?>">starting over</a>.</p>
diff --git a/themes/bootstrap3/templates/upgrade/fixanonymoustags.phtml b/themes/bootstrap3/templates/upgrade/fixanonymoustags.phtml
index e10d93c84098040b3f6a0952b85cd9262b6c152c..9ac6a5a13b8c382dc286f85d4f4c0ff4dc6abe89 100644
--- a/themes/bootstrap3/templates/upgrade/fixanonymoustags.phtml
+++ b/themes/bootstrap3/templates/upgrade/fixanonymoustags.phtml
@@ -23,4 +23,4 @@ an administrator) to associate with old anonymous tags.</p>
 <form method="post" action="<?=$this->url('upgrade-fixanonymoustags')?>">
   <?=$this->transEsc('Username') ?>: <input type="text" name="username" /> <input type="submit" name="submit" value="<?=$this->transEsc('Submit') ?>" /><br /><br />
   <input type="submit" name="skip" value="<?=$this->transEsc('skip_step') ?>." onclick="return confirm('<?=$this->transEsc('skip_confirm') ?>');"/>
-</form>
\ No newline at end of file
+</form>
diff --git a/themes/bootstrap3/templates/upgrade/fixduplicatetags.phtml b/themes/bootstrap3/templates/upgrade/fixduplicatetags.phtml
index c403778a3a4e1905ecfa24eba997e0ff1814f666..e49f008ff915129bf488ba0ed9f24a91d9df4c56 100644
--- a/themes/bootstrap3/templates/upgrade/fixduplicatetags.phtml
+++ b/themes/bootstrap3/templates/upgrade/fixduplicatetags.phtml
@@ -22,4 +22,4 @@ otherwise, it is recommended that you fix these.  Click Submit to proceed.</p>
 <form method="post" action="<?=$this->url('upgrade-fixduplicatetags')?>">
   <input type="submit" name="submit" value="<?=$this->transEsc('Submit') ?>" /><br /><br />
   <input type="submit" name="skip" value="<?=$this->transEsc('skip_step') ?>." onclick="return confirm('<?=$this->transEsc('skip_confirm') ?>');"/>
-</form>
\ No newline at end of file
+</form>
diff --git a/themes/bootstrap3/templates/upgrade/fixmetadata.phtml b/themes/bootstrap3/templates/upgrade/fixmetadata.phtml
index d3dd0d9e89636b95a4c0eb23b319495259aa086b..389dda8bcb5594e0521650ade27c99d4b1780a34 100644
--- a/themes/bootstrap3/templates/upgrade/fixmetadata.phtml
+++ b/themes/bootstrap3/templates/upgrade/fixmetadata.phtml
@@ -16,4 +16,4 @@ but it will improve the user experience by allowing proper sorting of favorites
 <form method="post" action="<?=$this->url('upgrade-fixmetadata')?>">
   <input type="submit" name="submit" value="<?=$this->transEsc('fix_metadata') ?>." /><br /><br />
   <input type="submit" name="skip" value="<?=$this->transEsc('skip_fix_metadata') ?>." onclick="return confirm('<?=$this->transEsc('skip_confirm') ?>');"/>
-</form>
\ No newline at end of file
+</form>
diff --git a/themes/bootstrap3/templates/upgrade/getdbcredentials.phtml b/themes/bootstrap3/templates/upgrade/getdbcredentials.phtml
index e55c5c2bf1c9e62c22f54bbfac2d047a7fc4119b..f13e695155a99df210908f65665c08b3812246f8 100644
--- a/themes/bootstrap3/templates/upgrade/getdbcredentials.phtml
+++ b/themes/bootstrap3/templates/upgrade/getdbcredentials.phtml
@@ -20,4 +20,4 @@ with permission to alter and create tables.</p>
     </tbody>
   </table>
   If you don't have the credentials or you wish to print the SQL out : Click here to <input type="submit" name="printsql" value="Skip" /> credentials.
-</form>
\ No newline at end of file
+</form>
diff --git a/themes/bootstrap3/templates/upgrade/getdbencodingpreference.phtml b/themes/bootstrap3/templates/upgrade/getdbencodingpreference.phtml
index d727a0fc85164a504cadcc29e2c0218baa3977be..d9c735d9c647ef20603edee685f9c0f4d5ec8501 100644
--- a/themes/bootstrap3/templates/upgrade/getdbencodingpreference.phtml
+++ b/themes/bootstrap3/templates/upgrade/getdbencodingpreference.phtml
@@ -23,4 +23,4 @@ upgrade tool later to perform UTF-8 conversion.</p>
 <form method="post" action="<?=$this->url('upgrade-getdbencodingpreference')?>">
   <input type="submit" name="encodingaction" value="Change" /> encoding to UTF-8<br />
   <input type="submit" name="encodingaction" value="Keep" /> Latin-1 encoding
-</form>
\ No newline at end of file
+</form>
diff --git a/themes/bootstrap3/templates/upgrade/getsourcedir.phtml b/themes/bootstrap3/templates/upgrade/getsourcedir.phtml
index 4ac38abb410e09868fe948ab20911aaebe822feb..c7f6b16d7e6f2d89f0e304db025a8754b7094f85 100644
--- a/themes/bootstrap3/templates/upgrade/getsourcedir.phtml
+++ b/themes/bootstrap3/templates/upgrade/getsourcedir.phtml
@@ -10,7 +10,7 @@
 <h3>Option 1: Upgrade from VuFind 1.x</h3>
 <p>Please enter the full path of the directory containing your previous version of VuFind (e.g. /usr/local/vufind):</p>
 <form class="form-inline" method="post" action="<?=$this->url('upgrade-getsourcedir')?>">
-  <input type="text" name="sourcedir" /> <input class="btn btn-default" type="submit" />
+  <input type="text" name="sourcedir" /> <input class="btn btn-primary" type="submit" />
 </form>
 <hr />
 <h3>Option 2: Upgrade from VuFind 2.x or newer</h3>
@@ -25,5 +25,5 @@
     <label for="skip-<?=$this->escapeHtmlAttr($key)?>">Skip <?=$this->escapeHtml($value); ?> Upgrade</label><br />
   <? endforeach; ?>
   </p>
-  <input class="btn btn-default" type="submit" />
+  <input class="btn btn-primary" type="submit" />
 </form>
diff --git a/themes/bootstrap3/templates/upgrade/home.phtml b/themes/bootstrap3/templates/upgrade/home.phtml
index 6ae1aefb829f712b8c95b7654d8419bc58eb3d75..6ceb7eac08d124d570d7ec2c2c6e4d41b6c480f3 100644
--- a/themes/bootstrap3/templates/upgrade/home.phtml
+++ b/themes/bootstrap3/templates/upgrade/home.phtml
@@ -24,4 +24,4 @@
 </ol>
 
 <p>For the latest notes on upgrading, see the <a href="https://vufind.org/wiki/installation:migration_notes">online documentation</a>.</p>
-<p>For help, feel free to use the mailing lists on the <a href="https://vufind.org/support.php">support page</a>.</p>
\ No newline at end of file
+<p>For help, feel free to use the mailing lists on the <a href="https://vufind.org/support.php">support page</a>.</p>
diff --git a/themes/bootstrap3/templates/upgrade/showsql.phtml b/themes/bootstrap3/templates/upgrade/showsql.phtml
index 395bfd381414df6bc65ffd8952106394f29ffb84..094ce028020c7860a8f3aec671f10ec1c775d7f0 100644
--- a/themes/bootstrap3/templates/upgrade/showsql.phtml
+++ b/themes/bootstrap3/templates/upgrade/showsql.phtml
@@ -19,5 +19,5 @@
 <textarea class="pre" rows="20"><?=trim($this->sql) ?></textarea>
 
 <form method="post" action="<?=$this->url('upgrade-showsql')?>">
-  <input class="btn btn-default" type="submit" name="continue" value="Next" />
-</form>
\ No newline at end of file
+  <input class="btn btn-primary" type="submit" name="continue" value="Next" />
+</form>
diff --git a/themes/bootstrap3/templates/web/home.phtml b/themes/bootstrap3/templates/web/home.phtml
index d13d4348c1e39e2222b5f16ce7d65ecd7816ef92..bc5b700660ea8e7baee8cc01de0600b0b4611521 100644
--- a/themes/bootstrap3/templates/web/home.phtml
+++ b/themes/bootstrap3/templates/web/home.phtml
@@ -1 +1 @@
-<?=$this->render('search/home.phtml');?>
\ No newline at end of file
+<?=$this->render('search/home.phtml');?>
diff --git a/themes/bootstrap3/templates/web/results.phtml b/themes/bootstrap3/templates/web/results.phtml
index c1797c1cd4a1ebb2ccad84718b1e225e51cac6a8..a0c6dd4bbf5077e0b43b335e98733b44bba7b4e6 100644
--- a/themes/bootstrap3/templates/web/results.phtml
+++ b/themes/bootstrap3/templates/web/results.phtml
@@ -1,4 +1,4 @@
 <?
     // Load standard settings from the default search results screen:
     echo $this->render('search/results.phtml');
-?>
\ No newline at end of file
+?>
diff --git a/themes/bootstrap3/templates/worldcat/advanced.phtml b/themes/bootstrap3/templates/worldcat/advanced.phtml
index 6a613a7e60856b907244312e3b2c80f0f38a990a..b9aa96af774c943d2ad91ae3f1900ad9d1f5653e 100644
--- a/themes/bootstrap3/templates/worldcat/advanced.phtml
+++ b/themes/bootstrap3/templates/worldcat/advanced.phtml
@@ -2,4 +2,4 @@
   // There are no WorldCat-specific advanced search controls, so just load the
   // standard advanced search layout:
   echo $this->render('search/advanced/layout.phtml');
-?>
\ No newline at end of file
+?>
diff --git a/themes/bootstrap3/templates/worldcat/home.phtml b/themes/bootstrap3/templates/worldcat/home.phtml
index d13d4348c1e39e2222b5f16ce7d65ecd7816ef92..bc5b700660ea8e7baee8cc01de0600b0b4611521 100644
--- a/themes/bootstrap3/templates/worldcat/home.phtml
+++ b/themes/bootstrap3/templates/worldcat/home.phtml
@@ -1 +1 @@
-<?=$this->render('search/home.phtml');?>
\ No newline at end of file
+<?=$this->render('search/home.phtml');?>
diff --git a/themes/bootstrap3/templates/worldcat/search.phtml b/themes/bootstrap3/templates/worldcat/search.phtml
index c1797c1cd4a1ebb2ccad84718b1e225e51cac6a8..a0c6dd4bbf5077e0b43b335e98733b44bba7b4e6 100644
--- a/themes/bootstrap3/templates/worldcat/search.phtml
+++ b/themes/bootstrap3/templates/worldcat/search.phtml
@@ -1,4 +1,4 @@
 <?
     // Load standard settings from the default search results screen:
     echo $this->render('search/results.phtml');
-?>
\ No newline at end of file
+?>
diff --git a/themes/bootstrap3/theme.config.php b/themes/bootstrap3/theme.config.php
index 8ee821b92dbc87e4ab490b053620725ed09bb6a1..446003328841b929a508238b738dd0fbe1dfcb8b 100644
--- a/themes/bootstrap3/theme.config.php
+++ b/themes/bootstrap3/theme.config.php
@@ -8,6 +8,7 @@ return array(
         //'bootstrap-custom.css',
         'compiled.css',
         'print.css:print',
+        'flex-fallback.css:lt IE 10', // flex polyfill
     ),
     'js' => array(
         'vendor/base64.js:lt IE 10', // btoa polyfill
@@ -15,7 +16,8 @@ return array(
         'vendor/bootstrap.min.js',
         'vendor/bootstrap-accessibility.min.js',
         'vendor/validator.min.js',
-        'autocomplete.js',
+        'lib/form-attr-polyfill.js', // input[form] polyfill, cannot load conditionally, since we need all versions of IE
+        'lib/autocomplete.js',
         'common.js',
         'lightbox.js',
     ),
diff --git a/themes/jquerymobile/css/.htaccess b/themes/jquerymobile/css/.htaccess
deleted file mode 100644
index f2e01735bf72b96391f55aca5f20f2c98ed9aef8..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/css/.htaccess
+++ /dev/null
@@ -1,6 +0,0 @@
-<IfModule mod_rewrite.c>
-  RewriteEngine Off
-</IfModule>
-
-RemoveType .css
-AddType text/css .css
\ No newline at end of file
diff --git a/themes/jquerymobile/css/EDS.css b/themes/jquerymobile/css/EDS.css
deleted file mode 100644
index 454ca401bfccf9b2979d5400eb7cd93e2639bddc..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/css/EDS.css
+++ /dev/null
@@ -1,78 +0,0 @@
-/* publication type css */
-
-.pt-icon { width: 70px; float: left; display: inline-block; background-image: url('../images/EDS/PT_Sprite.png'); background-repeat: no-repeat; }
-.pt-serialPeriodical { background-position: -30px -30px; height: 59px; }
-.pt-newspaperArticle { background-position: -140px -30px; height: 51px; }
-.pt-image { background-position: -245px -30px; height: 47px; }
-.pt-videoRecording { background-position: -345px -30px; height: 63px; }
-.pt-score { background-position: -445px -30px; height: 57px; }
-.pt-audio { background-position: -545px -30px; height: 49px; }
-.pt-map { background-position: -35px -120px; height: 45px; }
-.pt-book { background-position: -140px -120px; height: 59px; }
-.pt-kitObject { background-position: -245px -120px; height: 50px; }
-.pt-academicJournal, .pt-unknown { background-position: -345px -120px; height: 57px; }
-.pt-dissertation { background-position: -445px -120px; height: 63px; }
-.pt-literaryMaterial, .pt-authors { background-position: -35px -215px; height: 55px; }
-.pt-tableChart { background-position: -140px -215px; height: 49px; }
-.pt-patent { background-position: -245px -215px; height: 56px; }
-.pt-report { background-position: -345px -215px; height: 63px; }
-.pt-reference, .pt-readersAdvisory { background-position: -445px -215px; height: 52px; }
-.pt-governmentDocument { background-position: -545px -215px; height: 60px; }
-.pt-editorialOpinion { background-position: -35px -305px; height: 47px; }
-.pt-transcript { background-position: -140px -305px; height: 63px; }
-.pt-review { background-position: -245px -305px; height: 48px; }
-.pt-biography { background-position: -345px -305px; height: 53px; }
-.pt-electronicResource { 	background-position: -445px -305px; height: 63px; }
-.pt-recommendedReadsList { background-position: -540px -305px; height: 61px; }
-.pt-pictureBookExtender { background-position: -35px -400px; height: 65px; }
-.pt-grabAndGo { background-position: -140px -400px; height: 51px; }
-.pt-featureArticle { background-position: -245px -400px; height: 65px; }
-.pt-curricularConnection { background-position: -345px -400px; height: 65px; }
-.pt-bookTalk { background-position: -455px -400px; height: 55px; }
-.pt-bookDiscussionGuides { background-position: -545px -400px; height: 55px; }
-.pt-awardWinner { background-position: -34px -500px; height: 70px; }
-.pt-authorReadalike { background-position: -140px -500px; height: 60px; }
-.pt-series { background-position: -245px -495px; height: 75px; }
-.pt-ebook { background-position: -350px -510px; height: 60px; }
-.pt-audiobook { background-position: -440px -510px; height: 60px; }
-.pt-conference { background-position: -545px -505px; height: 70px; }
-.pt-Poem { background-position: -35px -615px; height: 60px; }
-.pt-ShortStory { background-position: -141px -620px; height: 55px; }
-.pt-play{ background-position: -245px -620px; height: 50px; }
-
-/* full text icons */
-/* Icons */
-.icon {
-    background: url("../images/EDS/sprites_32.png") no-repeat top left;
-    height: 32px;
-    line-height: 32px;
-    display: inline-block;
-    padding-left: 36px;
-}
-
-.icon.ebook {
-    background-position: 0 0;
-}
-
-.icon.html {
-    background-position: 0 -42px;
-}
-
-.icon.pdf {
-    background-position: 0 -84px;
-}
-
-.icon13 {
-    background: url("../images/sprites_32.png") no-repeat top left;
-    padding-left: 18px;
-    width: 13px;
-    height: 13px;
-}
-
-.icon13.collapsed {
-    background-position: 0 -126px;
-}
-
-.icon13.expanded {
-    background-position: 0 -149px;
-}
\ No newline at end of file
diff --git a/themes/jquerymobile/css/formats.css b/themes/jquerymobile/css/formats.css
deleted file mode 100644
index dca30d6a6ca67d921aab5729c58495157954c79b..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/css/formats.css
+++ /dev/null
@@ -1,128 +0,0 @@
-/* Icon Classes for item formats */
-
-.cd {
-    background-image:url(../images/silk/cd.png);
-    background-repeat:no-repeat;
-    background-position: left top;
-    padding:0 .5em .5em 20px;
-    margin-right:1em;
-}
-.dvd {
-    background-image:url(../images/silk/dvd.png);
-    background-repeat:no-repeat;
-    background-position: left top;
-    padding:0 .5em .5em 20px;
-    margin-right:1em;
-}
-.electronic {
-    background-image:url(../images/tango/www.png);
-    background-repeat:no-repeat;
-    background-position: left top;
-    padding:0 .5em .5em 20px;
-    margin-right:1em;
-}
-.map {
-    background-image:url(../images/silk/map.png);
-    background-repeat:no-repeat;
-    background-position: left top;
-    padding:0 .5em .5em 20px;
-    margin-right:1em;
-}
-.globe {
-    background-image:url(../images/silk/world.png);
-    background-repeat:no-repeat;
-    background-position: left top;
-    padding:0 .5em .5em 20px;
-    margin-right:1em;
-}
-.microfilm {
-    background-image:url(../images/silk/film.png);
-    background-repeat:no-repeat;
-    background-position: left top;
-    padding:0 .5em .5em 20px;
-    margin-right:1em;
-}
-.photo {
-    background-image:url(../images/silk/picture.png);
-    background-repeat:no-repeat;
-    background-position: left top;
-    padding:0 .5em .5em 20px;
-    margin-right:1em;
-}
-span.slide {
-    background-image:url(../images/silk/picture.png);
-    background-repeat:no-repeat;
-    background-position: left top;
-    padding:0 .5em .5em 20px;
-    margin-right:1em;
-}
-.video {
-    background-image:url(../images/tango/video.png);
-    background-repeat:no-repeat;
-    background-position: left top;
-    padding:0 .5em .5em 20px;
-    margin-right:1em;
-}
-.kit {
-    background-image:url(../images/silk/package.png);
-    background-repeat:no-repeat;
-    background-position: left top;
-    padding:0 .5em .5em 20px;
-    margin-right:1em;
-}
-.musicalscore {
-    background-image:url(../images/silk/music.png);
-    background-repeat:no-repeat;
-    background-position: left top;
-    padding:0 .5em .5em 20px;
-    margin-right:1em;
-}
-.audio {
-    background-image:url(../images/tango/audio-volume-high.png);
-    background-repeat:no-repeat;
-    background-position: left top;
-    padding:0 .5em .5em 20px;
-    margin-right:1em;
-}
-.manuscript {
-    background-image:url(../images/silk/report_edit.png);
-    background-repeat:no-repeat;
-    background-position: left top;
-    padding:0 .5em .5em 20px;
-    margin-right:1em;
-}
-.ebook {
-    background-image:url(../images/ebook.png);
-    background-repeat:no-repeat;
-    background-position: left top;
-    padding:0 .5em .5em 20px;
-    margin-right:1em;
-}
-.book {
-    background-image:url(../images/silk/book.png);
-    background-repeat:no-repeat;
-    background-position: left top;
-    padding:0 .5em .5em 20px;
-    margin-right:1em;
-}
-.journal {
-    background-image:url(../images/silk/report.png);
-    background-repeat:no-repeat;
-    background-position: left top;
-    padding:0 .5em .5em 20px;
-    margin-right:1em;
-}
-.newspaper {
-    background-image:url(../images/silk/newspaper.png);
-    background-repeat:no-repeat;
-    background-position: left top;
-    padding:0 .5em .5em 20px;
-    margin-right:1em;
-}
-.software {
-    background-image:url(../images/silk/disk_multiple.png);
-    background-repeat:no-repeat;
-    background-position: left top;
-    padding:0 .5em .5em 20px;
-    margin-right:1em;
-}
diff --git a/themes/jquerymobile/css/images/Thumbs.db b/themes/jquerymobile/css/images/Thumbs.db
deleted file mode 100644
index 787b9f5cc5ab48d86f38d61b7db758bde042ac40..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/css/images/Thumbs.db and /dev/null differ
diff --git a/themes/jquerymobile/css/images/ajax-loader.png b/themes/jquerymobile/css/images/ajax-loader.png
deleted file mode 100644
index 811a2cdd1b492c47faf85c1206ad6606521eb6e4..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/css/images/ajax-loader.png and /dev/null differ
diff --git a/themes/jquerymobile/css/images/icons-18-black.png b/themes/jquerymobile/css/images/icons-18-black.png
deleted file mode 100644
index 1ecfd26fbcd9708e4bd9d3a583dcd703461c766b..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/css/images/icons-18-black.png and /dev/null differ
diff --git a/themes/jquerymobile/css/images/icons-18-white.png b/themes/jquerymobile/css/images/icons-18-white.png
deleted file mode 100644
index 0c70831ac51a741f570a7c8661b3a83fe459ddd0..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/css/images/icons-18-white.png and /dev/null differ
diff --git a/themes/jquerymobile/css/images/icons-36-black.png b/themes/jquerymobile/css/images/icons-36-black.png
deleted file mode 100644
index 4c72adf1e81039a59ae8ab74cdeb6148c67acfbb..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/css/images/icons-36-black.png and /dev/null differ
diff --git a/themes/jquerymobile/css/images/icons-36-white.png b/themes/jquerymobile/css/images/icons-36-white.png
deleted file mode 100644
index 84ea9fb31ae442d0c60523fbce08ec5f202b7d9c..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/css/images/icons-36-white.png and /dev/null differ
diff --git a/themes/jquerymobile/css/jquery.mobile-1.0rc2.min.css b/themes/jquerymobile/css/jquery.mobile-1.0rc2.min.css
deleted file mode 100644
index 0ebf6e3cffab68342c3bf9e4366fde3ba3b4466c..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/css/jquery.mobile-1.0rc2.min.css
+++ /dev/null
@@ -1,12 +0,0 @@
-/*!
- * jQuery Mobile v1.0rc2
- * http://jquerymobile.com/
- *
- * Copyright 2010, jQuery Project
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *//*!
-* jQuery Mobile Framework
-* Copyright (c) jQuery Project
-* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
-*/.ui-bar-a{border:1px solid #2a2a2a;background:#111;color:#fff;font-weight:bold;text-shadow:0 -1px 1px #000;background-image:-webkit-gradient(linear,left top,left bottom,from(#3c3c3c),to(#111));background-image:-webkit-linear-gradient(top,#3c3c3c,#111);background-image:-moz-linear-gradient(top,#3c3c3c,#111);background-image:-ms-linear-gradient(top,#3c3c3c,#111);background-image:-o-linear-gradient(top,#3c3c3c,#111);background-image:linear-gradient(top,#3c3c3c,#111)}.ui-bar-a,.ui-bar-a input,.ui-bar-a select,.ui-bar-a textarea,.ui-bar-a button{font-family:Helvetica,Arial,sans-serif}.ui-bar-a .ui-link-inherit{color:#fff}.ui-bar-a .ui-link{color:#7cc4e7;font-weight:bold}.ui-bar-a .ui-link:hover{color:#2489ce}.ui-bar-a .ui-link:active{color:#2489ce}.ui-bar-a .ui-link:visited{color:#2489ce}.ui-body-a{border:1px solid #2a2a2a;background:#222;color:#fff;text-shadow:0 1px 0 #000;font-weight:normal;background-image:-webkit-gradient(linear,left top,left bottom,from(#666),to(#222));background-image:-webkit-linear-gradient(top,#666,#222);background-image:-moz-linear-gradient(top,#666,#222);background-image:-ms-linear-gradient(top,#666,#222);background-image:-o-linear-gradient(top,#666,#222);background-image:linear-gradient(top,#666,#222)}.ui-body-a,.ui-body-a input,.ui-body-a select,.ui-body-a textarea,.ui-body-a button{font-family:Helvetica,Arial,sans-serif}.ui-body-a .ui-link-inherit{color:#fff}.ui-body-a .ui-link{color:#2489ce;font-weight:bold}.ui-body-a .ui-link:hover{color:#2489ce}.ui-body-a .ui-link:active{color:#2489ce}.ui-body-a .ui-link:visited{color:#2489ce}.ui-br{border-bottom:#828282;border-bottom:rgba(130,130,130,.3);border-bottom-width:1px;border-bottom-style:solid}.ui-btn-up-a{border:1px solid #222;background:#333;font-weight:bold;color:#fff;text-shadow:0 -1px 1px #000;background-image:-webkit-gradient(linear,left top,left bottom,from(#555),to(#333));background-image:-webkit-linear-gradient(top,#555,#333);background-image:-moz-linear-gradient(top,#555,#333);background-image:-ms-linear-gradient(top,#555,#333);background-image:-o-linear-gradient(top,#555,#333);background-image:linear-gradient(top,#555,#333)}.ui-btn-up-a a.ui-link-inherit{color:#fff}.ui-btn-hover-a{border:1px solid #000;background:#444;font-weight:bold;color:#fff;text-shadow:0 -1px 1px #000;background-image:-webkit-gradient(linear,left top,left bottom,from(#666),to(#444));background-image:-webkit-linear-gradient(top,#666,#444);background-image:-moz-linear-gradient(top,#666,#444);background-image:-ms-linear-gradient(top,#666,#444);background-image:-o-linear-gradient(top,#666,#444);background-image:linear-gradient(top,#666,#444)}.ui-btn-hover-a a.ui-link-inherit{color:#fff}.ui-btn-down-a{border:1px solid #000;background:#3d3d3d;font-weight:bold;color:#fff;text-shadow:0 -1px 1px #000;background-image:-webkit-gradient(linear,left top,left bottom,from(#333),to(#5a5a5a));background-image:-webkit-linear-gradient(top,#333,#5a5a5a);background-image:-moz-linear-gradient(top,#333,#5a5a5a);background-image:-ms-linear-gradient(top,#333,#5a5a5a);background-image:-o-linear-gradient(top,#333,#5a5a5a);background-image:linear-gradient(top,#333,#5a5a5a)}.ui-btn-down-a a.ui-link-inherit{color:#fff}.ui-btn-up-a,.ui-btn-hover-a,.ui-btn-down-a{font-family:Helvetica,Arial,sans-serif;text-decoration:none}.ui-bar-b{border:1px solid #456f9a;background:#5e87b0;color:#fff;font-weight:bold;text-shadow:0 -1px 1px #254f7a;background-image:-webkit-gradient(linear,left top,left bottom,from(#81a8ce),to(#5e87b0));background-image:-webkit-linear-gradient(top,#81a8ce,#5e87b0);background-image:-moz-linear-gradient(top,#81a8ce,#5e87b0);background-image:-ms-linear-gradient(top,#81a8ce,#5e87b0);background-image:-o-linear-gradient(top,#81a8ce,#5e87b0);background-image:linear-gradient(top,#81a8ce,#5e87b0)}.ui-bar-b,.ui-bar-b input,.ui-bar-b select,.ui-bar-b textarea,.ui-bar-b button{font-family:Helvetica,Arial,sans-serif}.ui-bar-b .ui-link-inherit{color:#fff}.ui-bar-b .ui-link{color:#ddf0f8;font-weight:bold}.ui-bar-b .ui-link:hover{color:#ddf0f8}.ui-bar-b .ui-link:active{color:#ddf0f8}.ui-bar-b .ui-link:visited{color:#ddf0f8}.ui-body-b{border:1px solid #c6c6c6;background:#ccc;color:#333;text-shadow:0 1px 0 #fff;font-weight:normal;background-image:-webkit-gradient(linear,left top,left bottom,from(#e6e6e6),to(#ccc));background-image:-webkit-linear-gradient(top,#e6e6e6,#ccc);background-image:-moz-linear-gradient(top,#e6e6e6,#ccc);background-image:-ms-linear-gradient(top,#e6e6e6,#ccc);background-image:-o-linear-gradient(top,#e6e6e6,#ccc);background-image:linear-gradient(top,#e6e6e6,#ccc)}.ui-body-b,.ui-body-b input,.ui-body-b select,.ui-body-b textarea,.ui-body-b button{font-family:Helvetica,Arial,sans-serif}.ui-body-b .ui-link-inherit{color:#333}.ui-body-b .ui-link{color:#2489ce;font-weight:bold}.ui-body-b .ui-link:hover{color:#2489ce}.ui-body-b .ui-link:active{color:#2489ce}.ui-body-b .ui-link:visited{color:#2489ce}.ui-btn-up-b{border:1px solid #145072;background:#2567ab;font-weight:bold;color:#fff;text-shadow:0 -1px 1px #145072;background-image:-webkit-gradient(linear,left top,left bottom,from(#5f9cc5),to(#396b9e));background-image:-webkit-linear-gradient(top,#5f9cc5,#396b9e);background-image:-moz-linear-gradient(top,#5f9cc5,#396b9e);background-image:-ms-linear-gradient(top,#5f9cc5,#396b9e);background-image:-o-linear-gradient(top,#5f9cc5,#396b9e);background-image:linear-gradient(top,#5f9cc5,#396b9e)}.ui-btn-up-b a.ui-link-inherit{color:#fff}.ui-btn-hover-b{border:1px solid #00516e;background:#4b88b6;font-weight:bold;color:#fff;text-shadow:0 -1px 1px #014d68;background-image:-webkit-gradient(linear,left top,left bottom,from(#72b0d4),to(#4b88b6));background-image:-webkit-linear-gradient(top,#72b0d4,#4b88b6);background-image:-moz-linear-gradient(top,#72b0d4,#4b88b6);background-image:-ms-linear-gradient(top,#72b0d4,#4b88b6);background-image:-o-linear-gradient(top,#72b0d4,#4b88b6);background-image:linear-gradient(top,#72b0d4,#4b88b6)}.ui-btn-hover-b a.ui-link-inherit{color:#fff}.ui-btn-down-b{border:1px solid #225377;background:#4e89c5;font-weight:bold;color:#fff;text-shadow:0 -1px 1px #225377;background-image:-webkit-gradient(linear,left top,left bottom,from(#396b9e),to(#4e89c5));background-image:-webkit-linear-gradient(top,#396b9e,#4e89c5);background-image:-moz-linear-gradient(top,#396b9e,#4e89c5);background-image:-ms-linear-gradient(top,#396b9e,#4e89c5);background-image:-o-linear-gradient(top,#396b9e,#4e89c5);background-image:linear-gradient(top,#396b9e,#4e89c5)}.ui-btn-down-b a.ui-link-inherit{color:#fff}.ui-btn-up-b,.ui-btn-hover-b,.ui-btn-down-b{font-family:Helvetica,Arial,sans-serif;text-decoration:none}.ui-bar-c{border:1px solid #b3b3b3;background:#e9eaeb;color:#3e3e3e;font-weight:bold;text-shadow:0 1px 1px #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#f0f0f0),to(#e9eaeb));background-image:-webkit-linear-gradient(top,#f0f0f0,#e9eaeb);background-image:-moz-linear-gradient(top,#f0f0f0,#e9eaeb);background-image:-ms-linear-gradient(top,#f0f0f0,#e9eaeb);background-image:-o-linear-gradient(top,#f0f0f0,#e9eaeb);background-image:linear-gradient(top,#f0f0f0,#e9eaeb)}.ui-bar-c .ui-link-inherit{color:#3e3e3e}.ui-bar-c .ui-link{color:#7cc4e7;font-weight:bold}.ui-bar-c .ui-link:hover{color:#2489ce}.ui-bar-c .ui-link:active{color:#2489ce}.ui-bar-c .ui-link:visited{color:#2489ce}.ui-bar-c,.ui-bar-c input,.ui-bar-c select,.ui-bar-c textarea,.ui-bar-c button{font-family:Helvetica,Arial,sans-serif}.ui-body-c{border:1px solid #b3b3b3;color:#333;text-shadow:0 1px 0 #fff;background:#f0f0f0;background-image:-webkit-gradient(linear,left top,left bottom,from(#eee),to(#ddd));background-image:-webkit-linear-gradient(top,#eee,#ddd);background-image:-moz-linear-gradient(top,#eee,#ddd);background-image:-ms-linear-gradient(top,#eee,#ddd);background-image:-o-linear-gradient(top,#eee,#ddd);background-image:linear-gradient(top,#eee,#ddd)}.ui-body-c,.ui-body-c input,.ui-body-c select,.ui-body-c textarea,.ui-body-c button{font-family:Helvetica,Arial,sans-serif}.ui-body-c .ui-link-inherit{color:#333}.ui-body-c .ui-link{color:#2489ce;font-weight:bold}.ui-body-c .ui-link:hover{color:#2489ce}.ui-body-c .ui-link:active{color:#2489ce}.ui-body-c .ui-link:visited{color:#2489ce}.ui-btn-up-c{border:1px solid #ccc;background:#eee;font-weight:bold;color:#444;text-shadow:0 1px 1px #f6f6f6;background-image:-webkit-gradient(linear,left top,left bottom,from(#fdfdfd),to(#eee));background-image:-webkit-linear-gradient(top,#fdfdfd,#eee);background-image:-moz-linear-gradient(top,#fdfdfd,#eee);background-image:-ms-linear-gradient(top,#fdfdfd,#eee);background-image:-o-linear-gradient(top,#fdfdfd,#eee);background-image:linear-gradient(top,#fdfdfd,#eee)}.ui-btn-up-c a.ui-link-inherit{color:#2f3e46}.ui-btn-hover-c{border:1px solid #bbb;background:#dadada;font-weight:bold;color:#101010;text-shadow:0 1px 1px #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#ededed),to(#dadada));background-image:-webkit-linear-gradient(top,#ededed,#dadada);background-image:-moz-linear-gradient(top,#ededed,#dadada);background-image:-ms-linear-gradient(top,#ededed,#dadada);background-image:-o-linear-gradient(top,#ededed,#dadada);background-image:linear-gradient(top,#ededed,#dadada)}.ui-btn-hover-c a.ui-link-inherit{color:#2f3e46}.ui-btn-down-c{border:1px solid #808080;background:#fdfdfd;font-weight:bold;color:#111;text-shadow:0 1px 1px #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#eee),to(#fdfdfd));background-image:-webkit-linear-gradient(top,#eee,#fdfdfd);background-image:-moz-linear-gradient(top,#eee,#fdfdfd);background-image:-ms-linear-gradient(top,#eee,#fdfdfd);background-image:-o-linear-gradient(top,#eee,#fdfdfd);background-image:linear-gradient(top,#eee,#fdfdfd)}.ui-btn-down-c a.ui-link-inherit{color:#2f3e46}.ui-btn-up-c,.ui-btn-hover-c,.ui-btn-down-c{font-family:Helvetica,Arial,sans-serif;text-decoration:none}.ui-bar-d{border:1px solid #ccc;background:#bbb;color:#333;text-shadow:0 1px 0 #eee;background-image:-webkit-gradient(linear,left top,left bottom,from(#ddd),to(#bbb));background-image:-webkit-linear-gradient(top,#ddd,#bbb);background-image:-moz-linear-gradient(top,#ddd,#bbb);background-image:-ms-linear-gradient(top,#ddd,#bbb);background-image:-o-linear-gradient(top,#ddd,#bbb);background-image:linear-gradient(top,#ddd,#bbb)}.ui-bar-d,.ui-bar-d input,.ui-bar-d select,.ui-bar-d textarea,.ui-bar-d button{font-family:Helvetica,Arial,sans-serif}.ui-bar-d .ui-link-inherit{color:#333}.ui-bar-d .ui-link{color:#2489ce;font-weight:bold}.ui-bar-d .ui-link:hover{color:#2489ce}.ui-bar-d .ui-link:active{color:#2489ce}.ui-bar-d .ui-link:visited{color:#2489ce}.ui-body-d{border:1px solid #ccc;color:#333;text-shadow:0 1px 0 #fff;background:#fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#fff));background-image:-webkit-linear-gradient(top,#fff,#fff);background-image:-moz-linear-gradient(top,#fff,#fff);background-image:-ms-linear-gradient(top,#fff,#fff);background-image:-o-linear-gradient(top,#fff,#fff);background-image:linear-gradient(top,#fff,#fff)}.ui-body-d,.ui-body-d input,.ui-body-d select,.ui-body-d textarea,.ui-body-d button{font-family:Helvetica,Arial,sans-serif}.ui-body-d .ui-link-inherit{color:#333}.ui-body-d .ui-link{color:#2489ce;font-weight:bold}.ui-body-d .ui-link:hover{color:#2489ce}.ui-body-d .ui-link:active{color:#2489ce}.ui-body-d .ui-link:visited{color:#2489ce}.ui-btn-up-d{border:1px solid #ccc;background:#fff;font-weight:bold;color:#444;text-shadow:0 1px 1px #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#fff));background-image:-webkit-linear-gradient(top,#fff,#fff);background-image:-moz-linear-gradient(top,#fff,#fff);background-image:-ms-linear-gradient(top,#fff,#fff);background-image:-o-linear-gradient(top,#fff,#fff);background-image:linear-gradient(top,#fff,#fff)}.ui-btn-up-d a.ui-link-inherit{color:#333}.ui-btn-hover-d{border:1px solid #aaa;background:#eee;font-weight:bold;color:#222;cursor:pointer;text-shadow:0 1px 1px #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#fdfdfd),to(#eee));background-image:-webkit-linear-gradient(top,#fdfdfd,#eee);background-image:-moz-linear-gradient(top,#fdfdfd,#eee);background-image:-ms-linear-gradient(top,#fdfdfd,#eee);background-image:-o-linear-gradient(top,#fdfdfd,#eee);background-image:linear-gradient(top,#fdfdfd,#eee)}.ui-btn-hover-d a.ui-link-inherit{color:#222}.ui-btn-down-d{border:1px solid #aaa;background:#fff;font-weight:bold;color:#111;text-shadow:0 1px 1px #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#eee),to(#fff));background-image:-webkit-linear-gradient(top,#eee,#fff);background-image:-moz-linear-gradient(top,#eee,#fff);background-image:-ms-linear-gradient(top,#eee,#fff);background-image:-o-linear-gradient(top,#eee,#fff);background-image:linear-gradient(top,#eee,#fff)}.ui-btn-down-d a.ui-link-inherit{color:#111}.ui-btn-up-d,.ui-btn-hover-d,.ui-btn-down-d{font-family:Helvetica,Arial,sans-serif;text-decoration:none}.ui-bar-e{border:1px solid #f7c942;background:#fadb4e;color:#333;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#fceda7),to(#fadb4e));background-image:-webkit-linear-gradient(top,#fceda7,#fadb4e);background-image:-moz-linear-gradient(top,#fceda7,#fadb4e);background-image:-ms-linear-gradient(top,#fceda7,#fadb4e);background-image:-o-linear-gradient(top,#fceda7,#fadb4e);background-image:linear-gradient(top,#fceda7,#fadb4e)}.ui-bar-e,.ui-bar-e input,.ui-bar-e select,.ui-bar-e textarea,.ui-bar-e button{font-family:Helvetica,Arial,sans-serif}.ui-bar-e .ui-link-inherit{color:#333}.ui-bar-e .ui-link{color:#2489ce;font-weight:bold}.ui-bar-e .ui-link:hover{color:#2489ce}.ui-bar-e .ui-link:active{color:#2489ce}.ui-bar-e .ui-link:visited{color:#2489ce}.ui-body-e{border:1px solid #f7c942;color:#333;text-shadow:0 1px 0 #fff;background:#faeb9e;background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#faeb9e));background-image:-webkit-linear-gradient(top,#fff,#faeb9e);background-image:-moz-linear-gradient(top,#fff,#faeb9e);background-image:-ms-linear-gradient(top,#fff,#faeb9e);background-image:-o-linear-gradient(top,#fff,#faeb9e);background-image:linear-gradient(top,#fff,#faeb9e)}.ui-body-e,.ui-body-e input,.ui-body-e select,.ui-body-e textarea,.ui-body-e button{font-family:Helvetica,Arial,sans-serif}.ui-body-e .ui-link-inherit{color:#333}.ui-body-e .ui-link{color:#2489ce;font-weight:bold}.ui-body-e .ui-link:hover{color:#2489ce}.ui-body-e .ui-link:active{color:#2489ce}.ui-body-e .ui-link:visited{color:#2489ce}.ui-btn-up-e{border:1px solid #f7c942;background:#fadb4e;font-weight:bold;color:#333;text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#fceda7),to(#fadb4e));background-image:-webkit-linear-gradient(top,#fceda7,#fadb4e);background-image:-moz-linear-gradient(top,#fceda7,#fadb4e);background-image:-ms-linear-gradient(top,#fceda7,#fadb4e);background-image:-o-linear-gradient(top,#fceda7,#fadb4e);background-image:linear-gradient(top,#fceda7,#fadb4e)}.ui-btn-up-e a.ui-link-inherit{color:#333}.ui-btn-hover-e{border:1px solid #e79952;background:#fbe26f;font-weight:bold;color:#111;text-shadow:0 1px 1px #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf0b5),to(#fbe26f));background-image:-webkit-linear-gradient(top,#fcf0b5,#fbe26f);background-image:-moz-linear-gradient(top,#fcf0b5,#fbe26f);background-image:-ms-linear-gradient(top,#fcf0b5,#fbe26f);background-image:-o-linear-gradient(top,#fcf0b5,#fbe26f);background-image:linear-gradient(top,#fcf0b5,#fbe26f)}.ui-btn-hover-e a.ui-link-inherit{color:#333}.ui-btn-down-e{border:1px solid #f7c942;background:#fceda7;font-weight:bold;color:#111;text-shadow:0 1px 1px #fff;background-image:-webkit-gradient(linear,left top,left bottom,from(#fadb4e),to(#fceda7));background-image:-webkit-linear-gradient(top,#fadb4e,#fceda7);background-image:-moz-linear-gradient(top,#fadb4e,#fceda7);background-image:-ms-linear-gradient(top,#fadb4e,#fceda7);background-image:-o-linear-gradient(top,#fadb4e,#fceda7);background-image:linear-gradient(top,#fadb4e,#fceda7)}.ui-btn-down-e a.ui-link-inherit{color:#333}.ui-btn-up-e,.ui-btn-hover-e,.ui-btn-down-e{font-family:Helvetica,Arial,sans-serif;text-decoration:none}a.ui-link-inherit{text-decoration:none!important}.ui-btn-active{border:1px solid #155678;background:#4596ce;font-weight:bold;color:#fff;cursor:pointer;text-shadow:0 -1px 1px #145072;text-decoration:none;background-image:-webkit-gradient(linear,left top,left bottom,from(#85bae4),to(#5393c5));background-image:-webkit-linear-gradient(top,#85bae4,#5393c5);background-image:-moz-linear-gradient(top,#85bae4,#5393c5);background-image:-ms-linear-gradient(top,#85bae4,#5393c5);background-image:-o-linear-gradient(top,#85bae4,#5393c5);background-image:linear-gradient(top,#85bae4,#5393c5);font-family:Helvetica,Arial,sans-serif}.ui-btn-active a.ui-link-inherit{color:#fff}.ui-btn-inner{border-top:1px solid #fff;border-color:rgba(255,255,255,.3)}.ui-corner-tl{-moz-border-radius-topleft:.6em;-webkit-border-top-left-radius:.6em;border-top-left-radius:.6em}.ui-corner-tr{-moz-border-radius-topright:.6em;-webkit-border-top-right-radius:.6em;border-top-right-radius:.6em}.ui-corner-bl{-moz-border-radius-bottomleft:.6em;-webkit-border-bottom-left-radius:.6em;border-bottom-left-radius:.6em}.ui-corner-br{-moz-border-radius-bottomright:.6em;-webkit-border-bottom-right-radius:.6em;border-bottom-right-radius:.6em}.ui-corner-top{-moz-border-radius-topleft:.6em;-webkit-border-top-left-radius:.6em;border-top-left-radius:.6em;-moz-border-radius-topright:.6em;-webkit-border-top-right-radius:.6em;border-top-right-radius:.6em}.ui-corner-bottom{-moz-border-radius-bottomleft:.6em;-webkit-border-bottom-left-radius:.6em;border-bottom-left-radius:.6em;-moz-border-radius-bottomright:.6em;-webkit-border-bottom-right-radius:.6em;border-bottom-right-radius:.6em}.ui-corner-right{-moz-border-radius-topright:.6em;-webkit-border-top-right-radius:.6em;border-top-right-radius:.6em;-moz-border-radius-bottomright:.6em;-webkit-border-bottom-right-radius:.6em;border-bottom-right-radius:.6em}.ui-corner-left{-moz-border-radius-topleft:.6em;-webkit-border-top-left-radius:.6em;border-top-left-radius:.6em;-moz-border-radius-bottomleft:.6em;-webkit-border-bottom-left-radius:.6em;border-bottom-left-radius:.6em}.ui-corner-all{-moz-border-radius:.6em;-webkit-border-radius:.6em;border-radius:.6em}.ui-corner-none{-moz-border-radius:0;-webkit-border-radius:0;border-radius:0}.ui-disabled{opacity:.3}.ui-disabled,.ui-disabled a{pointer-events:none;cursor:default}.ui-icon,.ui-icon-searchfield:after{background:#666;background:rgba(0,0,0,.4);background-image:url(images/icons-18-white.png);background-repeat:no-repeat;-moz-border-radius:9px;-webkit-border-radius:9px;border-radius:9px}.ui-icon-alt{background:#fff;background:rgba(255,255,255,.3);background-image:url(images/icons-18-black.png);background-repeat:no-repeat}@media only screen and (-webkit-min-device-pixel-ratio:1.5),only screen and (min--moz-device-pixel-ratio:1.5),only screen and (min-resolution:240dpi){.ui-icon-plus,.ui-icon-minus,.ui-icon-delete,.ui-icon-arrow-r,.ui-icon-arrow-l,.ui-icon-arrow-u,.ui-icon-arrow-d,.ui-icon-check,.ui-icon-gear,.ui-icon-refresh,.ui-icon-forward,.ui-icon-back,.ui-icon-grid,.ui-icon-star,.ui-icon-alert,.ui-icon-info,.ui-icon-home,.ui-icon-search,.ui-icon-searchfield:after,.ui-icon-checkbox-off,.ui-icon-checkbox-on,.ui-icon-radio-off,.ui-icon-radio-on{background-image:url(images/icons-36-white.png);-moz-background-size:776px 18px;-o-background-size:776px 18px;-webkit-background-size:776px 18px;background-size:776px 18px}.ui-icon-alt{background-image:url(images/icons-36-black.png)}}.ui-icon-plus{background-position:-0 50%}.ui-icon-minus{background-position:-36px 50%}.ui-icon-delete{background-position:-72px 50%}.ui-icon-arrow-r{background-position:-108px 50%}.ui-icon-arrow-l{background-position:-144px 50%}.ui-icon-arrow-u{background-position:-180px 50%}.ui-icon-arrow-d{background-position:-216px 50%}.ui-icon-check{background-position:-252px 50%}.ui-icon-gear{background-position:-288px 50%}.ui-icon-refresh{background-position:-324px 50%}.ui-icon-forward{background-position:-360px 50%}.ui-icon-back{background-position:-396px 50%}.ui-icon-grid{background-position:-432px 50%}.ui-icon-star{background-position:-468px 50%}.ui-icon-alert{background-position:-504px 50%}.ui-icon-info{background-position:-540px 50%}.ui-icon-home{background-position:-576px 50%}.ui-icon-search,.ui-icon-searchfield:after{background-position:-612px 50%}.ui-icon-checkbox-off{background-position:-684px 50%}.ui-icon-checkbox-on{background-position:-648px 50%}.ui-icon-radio-off{background-position:-756px 50%}.ui-icon-radio-on{background-position:-720px 50%}.ui-checkbox .ui-icon{-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px}.ui-icon-checkbox-off,.ui-icon-radio-off{background-color:transparent}.ui-checkbox-on .ui-icon,.ui-radio-on .ui-icon{background-color:#4596ce}.ui-icon-loading{background-image:url(images/ajax-loader.png);width:40px;height:40px;-moz-border-radius:20px;-webkit-border-radius:20px;border-radius:20px;background-size:35px 35px}.ui-btn-corner-tl{-moz-border-radius-topleft:1em;-webkit-border-top-left-radius:1em;border-top-left-radius:1em}.ui-btn-corner-tr{-moz-border-radius-topright:1em;-webkit-border-top-right-radius:1em;border-top-right-radius:1em}.ui-btn-corner-bl{-moz-border-radius-bottomleft:1em;-webkit-border-bottom-left-radius:1em;border-bottom-left-radius:1em}.ui-btn-corner-br{-moz-border-radius-bottomright:1em;-webkit-border-bottom-right-radius:1em;border-bottom-right-radius:1em}.ui-btn-corner-top{-moz-border-radius-topleft:1em;-webkit-border-top-left-radius:1em;border-top-left-radius:1em;-moz-border-radius-topright:1em;-webkit-border-top-right-radius:1em;border-top-right-radius:1em}.ui-btn-corner-bottom{-moz-border-radius-bottomleft:1em;-webkit-border-bottom-left-radius:1em;border-bottom-left-radius:1em;-moz-border-radius-bottomright:1em;-webkit-border-bottom-right-radius:1em;border-bottom-right-radius:1em}.ui-btn-corner-right{-moz-border-radius-topright:1em;-webkit-border-top-right-radius:1em;border-top-right-radius:1em;-moz-border-radius-bottomright:1em;-webkit-border-bottom-right-radius:1em;border-bottom-right-radius:1em}.ui-btn-corner-left{-moz-border-radius-topleft:1em;-webkit-border-top-left-radius:1em;border-top-left-radius:1em;-moz-border-radius-bottomleft:1em;-webkit-border-bottom-left-radius:1em;border-bottom-left-radius:1em}.ui-btn-corner-all{-moz-border-radius:1em;-webkit-border-radius:1em;border-radius:1em}.ui-corner-tl,.ui-corner-tr,.ui-corner-bl,.ui-corner-br,.ui-corner-top,.ui-corner-bottom,.ui-corner-right,.ui-corner-left,.ui-corner-all,.ui-btn-corner-tl,.ui-btn-corner-tr,.ui-btn-corner-bl,.ui-btn-corner-br,.ui-btn-corner-top,.ui-btn-corner-bottom,.ui-btn-corner-right,.ui-btn-corner-left,.ui-btn-corner-all{-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box}.ui-overlay{background:#666;opacity:.5;filter:Alpha(Opacity=50);position:absolute;width:100%;height:100%}.ui-overlay-shadow{-moz-box-shadow:0 0 12px rgba(0,0,0,.6);-webkit-box-shadow:0 0 12px rgba(0,0,0,.6);box-shadow:0 0 12px rgba(0,0,0,.6)}.ui-shadow{-moz-box-shadow:0 1px 4px rgba(0,0,0,.3);-webkit-box-shadow:0 1px 4px rgba(0,0,0,.3);box-shadow:0 1px 4px rgba(0,0,0,.3)}.ui-bar-a .ui-shadow,.ui-bar-b .ui-shadow,.ui-bar-c .ui-shadow{-moz-box-shadow:0 1px 0 rgba(255,255,255,.3);-webkit-box-shadow:0 1px 0 rgba(255,255,255,.3);box-shadow:0 1px 0 rgba(255,255,255,.3)}.ui-shadow-inset{-moz-box-shadow:inset 0 1px 4px rgba(0,0,0,.2);-webkit-box-shadow:inset 0 1px 4px rgba(0,0,0,.2);box-shadow:inset 0 1px 4px rgba(0,0,0,.2)}.ui-icon-shadow{-moz-box-shadow:0 1px 0 rgba(255,255,255,.4);-webkit-box-shadow:0 1px 0 rgba(255,255,255,.4);box-shadow:0 1px 0 rgba(255,255,255,.4)}.ui-focus{-moz-box-shadow:0 0 12px #387bbe;-webkit-box-shadow:0 0 12px #387bbe;box-shadow:0 0 12px #387bbe}.ui-mobile-nosupport-boxshadow *{-moz-box-shadow:none!important;-webkit-box-shadow:none!important;box-shadow:none!important}.ui-mobile-nosupport-boxshadow .ui-focus{outline-width:2px}.ui-mobile,.ui-mobile body{height:100%}.ui-mobile fieldset,.ui-page{padding:0;margin:0}.ui-mobile a img,.ui-mobile fieldset{border:0}.ui-mobile-viewport{margin:0;overflow-x:hidden;-webkit-text-size-adjust:none;-ms-text-size-adjust:none;-webkit-tap-highlight-color:rgba(0,0,0,0)}.ui-mobile [data-role=page],.ui-mobile [data-role=dialog],.ui-page{top:0;left:0;width:100%;min-height:100%;position:absolute;display:none;border:0}.ui-mobile .ui-page-active{display:block;overflow:visible}.ui-page{outline:0}@media screen and (orientation:portrait){.ui-mobile,.ui-mobile .ui-page{min-height:420px}}@media screen and (orientation:landscape){.ui-mobile,.ui-mobile .ui-page{min-height:300px}}.ui-page.ui-mobile-touch-overflow,.ui-mobile-touch-overflow.ui-native-fixed .ui-content{overflow:auto;height:100%;-webkit-overflow-scrolling:touch;-moz-overflow-scrolling:touch;-o-overflow-scrolling:touch;-ms-overflow-scrolling:touch;overflow-scrolling:touch}.ui-page.ui-mobile-touch-overflow,.ui-page.ui-mobile-touch-overflow *{-webkit-transform:rotateY(0)}.ui-page.ui-mobile-pre-transition{display:block}.ui-loading .ui-mobile-viewport{overflow:hidden!important}.ui-loading .ui-loader{display:block}.ui-loading .ui-page{overflow:hidden}.ui-loader{display:none;position:absolute;opacity:.85;z-index:100;left:50%;width:200px;margin-left:-130px;margin-top:-35px;padding:10px 30px}.ui-loader h1{font-size:15px;text-align:center}.ui-loader .ui-icon{position:static;display:block;opacity:.9;margin:0 auto;width:35px;height:35px;background-color:transparent}.ui-mobile-rendering>*{visibility:hidden}.ui-bar,.ui-body{position:relative;padding:.4em 15px;overflow:hidden;display:block;clear:both}.ui-bar{font-size:16px;margin:0}.ui-bar h1,.ui-bar h2,.ui-bar h3,.ui-bar h4,.ui-bar h5,.ui-bar h6{margin:0;padding:0;font-size:16px;display:inline-block}.ui-header,.ui-footer{display:block}.ui-page .ui-header,.ui-page .ui-footer{position:relative}.ui-header .ui-btn-left{position:absolute;left:10px;top:.4em}.ui-header .ui-btn-right{position:absolute;right:10px;top:.4em}.ui-header .ui-title,.ui-footer .ui-title{min-height:1.1em;text-align:center;font-size:16px;display:block;margin:.6em 90px .8em;padding:0;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;outline:0!important}.ui-footer .ui-title{margin:.6em 15px .8em}.ui-content{border-width:0;overflow:visible;overflow-x:hidden;padding:15px}.ui-page-fullscreen .ui-content{padding:0}.ui-mobile-touch-overflow.ui-page.ui-native-fixed,.ui-mobile-touch-overflow.ui-page.ui-native-fullscreen{overflow:visible}.ui-mobile-touch-overflow.ui-native-fixed .ui-header,.ui-mobile-touch-overflow.ui-native-fixed .ui-footer{position:fixed;left:0;right:0;top:0;z-index:200}.ui-mobile-touch-overflow.ui-page.ui-native-fixed .ui-footer{top:auto;bottom:0}.ui-mobile-touch-overflow.ui-native-fixed .ui-content{padding-top:2.5em;padding-bottom:3em;top:0;bottom:0;height:auto;position:absolute}.ui-mobile-touch-overflow.ui-native-fullscreen .ui-content{padding-top:0;padding-bottom:0}.ui-mobile-touch-overflow.ui-native-fullscreen .ui-header,.ui-mobile-touch-overflow.ui-native-fullscreen .ui-footer{opacity:.9}.ui-native-bars-hidden{display:none}.ui-icon{width:18px;height:18px}.ui-fullscreen img{max-width:100%}.ui-nojs{position:absolute;left:-9999px}.ui-hide-label label,.ui-hidden-accessible{position:absolute!important;left:-9999px;clip:rect(1px 1px 1px 1px);clip:rect(1px,1px,1px,1px)}.spin{-webkit-transform:rotate(360deg);-webkit-animation-name:spin;-webkit-animation-duration:1s;-webkit-animation-iteration-count:infinite;-webkit-animation-timing-function:linear}@-webkit-keyframes spin{from{-webkit-transform:rotate(0deg)}to{-webkit-transform:rotate(360deg)}}.in,.out{-webkit-animation-timing-function:ease-in-out;-webkit-animation-duration:350ms}.slide.out{-webkit-transform:translateX(-100%);-webkit-animation-name:slideouttoleft}.slide.in{-webkit-transform:translateX(0);-webkit-animation-name:slideinfromright}.slide.out.reverse{-webkit-transform:translateX(100%);-webkit-animation-name:slideouttoright}.slide.in.reverse{-webkit-transform:translateX(0);-webkit-animation-name:slideinfromleft}.slideup.out{-webkit-animation-name:dontmove;z-index:0}.slideup.in{-webkit-transform:translateY(0);-webkit-animation-name:slideinfrombottom;z-index:10}.slideup.in.reverse{z-index:0;-webkit-animation-name:dontmove}.slideup.out.reverse{-webkit-transform:translateY(100%);z-index:10;-webkit-animation-name:slideouttobottom}.slidedown.out{-webkit-animation-name:dontmove;z-index:0}.slidedown.in{-webkit-transform:translateY(0);-webkit-animation-name:slideinfromtop;z-index:10}.slidedown.in.reverse{z-index:0;-webkit-animation-name:dontmove}.slidedown.out.reverse{-webkit-transform:translateY(-100%);z-index:10;-webkit-animation-name:slideouttotop}@-webkit-keyframes slideinfromright{from{-webkit-transform:translateX(100%)}to{-webkit-transform:translateX(0)}}@-webkit-keyframes slideinfromleft{from{-webkit-transform:translateX(-100%)}to{-webkit-transform:translateX(0)}}@-webkit-keyframes slideouttoleft{from{-webkit-transform:translateX(0)}to{-webkit-transform:translateX(-100%)}}@-webkit-keyframes slideouttoright{from{-webkit-transform:translateX(0)}to{-webkit-transform:translateX(100%)}}@-webkit-keyframes slideinfromtop{from{-webkit-transform:translateY(-100%)}to{-webkit-transform:translateY(0)}}@-webkit-keyframes slideinfrombottom{from{-webkit-transform:translateY(100%)}to{-webkit-transform:translateY(0)}}@-webkit-keyframes slideouttobottom{from{-webkit-transform:translateY(0)}to{-webkit-transform:translateY(100%)}}@-webkit-keyframes slideouttotop{from{-webkit-transform:translateY(0)}to{-webkit-transform:translateY(-100%)}}@-webkit-keyframes fadein{from{opacity:0}to{opacity:1}}@-webkit-keyframes fadeout{from{opacity:1}to{opacity:0}}.fade.out{z-index:0;-webkit-animation-name:fadeout}.fade.in{opacity:1;z-index:10;-webkit-animation-name:fadein}.viewport-flip{-webkit-perspective:1000;position:absolute}.ui-mobile-viewport-transitioning,.ui-mobile-viewport-transitioning .ui-page{width:100%;height:100%;overflow:hidden}.flip{-webkit-animation-duration:.65s;-webkit-backface-visibility:hidden;-webkit-transform:translateX(0)}.flip.out{-webkit-transform:rotateY(-180deg) scale(.8);-webkit-animation-name:flipouttoleft}.flip.in{-webkit-transform:rotateY(0) scale(1);-webkit-animation-name:flipinfromleft}.flip.out.reverse{-webkit-transform:rotateY(180deg) scale(.8);-webkit-animation-name:flipouttoright}.flip.in.reverse{-webkit-transform:rotateY(0) scale(1);-webkit-animation-name:flipinfromright}@-webkit-keyframes flipinfromright{from{-webkit-transform:rotateY(-180deg) scale(.8)}to{-webkit-transform:rotateY(0) scale(1)}}@-webkit-keyframes flipinfromleft{from{-webkit-transform:rotateY(180deg) scale(.8)}to{-webkit-transform:rotateY(0) scale(1)}}@-webkit-keyframes flipouttoleft{from{-webkit-transform:rotateY(0) scale(1)}to{-webkit-transform:rotateY(-180deg) scale(.8)}}@-webkit-keyframes flipouttoright{from{-webkit-transform:rotateY(0) scale(1)}to{-webkit-transform:rotateY(180deg) scale(.8)}}@-webkit-keyframes dontmove{from{opacity:1}to{opacity:1}}.pop{-webkit-transform-origin:50% 50%}.pop.in{-webkit-transform:scale(1);opacity:1;-webkit-animation-name:popin;z-index:10}.pop.in.reverse{z-index:0;-webkit-animation-name:dontmove}.pop.out.reverse{-webkit-transform:scale(.2);opacity:0;-webkit-animation-name:popout;z-index:10}@-webkit-keyframes popin{from{-webkit-transform:scale(.2);opacity:0}to{-webkit-transform:scale(1);opacity:1}}@-webkit-keyframes popout{from{-webkit-transform:scale(1);opacity:1}to{-webkit-transform:scale(.2);opacity:0}}.ui-grid-a,.ui-grid-b,.ui-grid-c,.ui-grid-d{overflow:hidden}.ui-block-a,.ui-block-b,.ui-block-c,.ui-block-d,.ui-block-e{margin:0;padding:0;border:0;float:left;min-height:1px}.ui-grid-solo .ui-block-a{width:100%;float:none}.ui-grid-a .ui-block-a,.ui-grid-a .ui-block-b{width:50%}.ui-grid-a .ui-block-a{clear:left}.ui-grid-b .ui-block-a,.ui-grid-b .ui-block-b,.ui-grid-b .ui-block-c{width:33.333%}.ui-grid-b .ui-block-a{clear:left}.ui-grid-c .ui-block-a,.ui-grid-c .ui-block-b,.ui-grid-c .ui-block-c,.ui-grid-c .ui-block-d{width:25%}.ui-grid-c .ui-block-a{clear:left}.ui-grid-d .ui-block-a,.ui-grid-d .ui-block-b,.ui-grid-d .ui-block-c,.ui-grid-d .ui-block-d,.ui-grid-d .ui-block-e{width:20%}.ui-grid-d .ui-block-a{clear:left}.ui-header,.ui-footer,.ui-page-fullscreen .ui-header,.ui-page-fullscreen .ui-footer{position:absolute;overflow:hidden;width:100%;border-left-width:0;border-right-width:0}.ui-header-fixed,.ui-footer-fixed{z-index:1000;-webkit-transform:translateZ(0)}.ui-footer-duplicate,.ui-page-fullscreen .ui-fixed-inline{display:none}.ui-page-fullscreen .ui-header,.ui-page-fullscreen .ui-footer{opacity:.9}.ui-navbar{overflow:hidden}.ui-navbar ul,.ui-navbar-expanded ul{list-style:none;padding:0;margin:0;position:relative;display:block;border:0}.ui-navbar-collapsed ul{float:left;width:75%;margin-right:-2px}.ui-navbar-collapsed .ui-navbar-toggle{float:left;width:25%}.ui-navbar li.ui-navbar-truncate{position:absolute;left:-9999px;top:-9999px}.ui-navbar li .ui-btn,.ui-navbar .ui-navbar-toggle .ui-btn{display:block;font-size:12px;text-align:center;margin:0;border-right-width:0}.ui-navbar li .ui-btn{margin-right:-1px}.ui-navbar li .ui-btn:last-child{margin-right:0}.ui-header .ui-navbar li .ui-btn,.ui-header .ui-navbar .ui-navbar-toggle .ui-btn,.ui-footer .ui-navbar li .ui-btn,.ui-footer .ui-navbar .ui-navbar-toggle .ui-btn{border-top-width:0;border-bottom-width:0}.ui-navbar .ui-btn-inner{padding-left:2px;padding-right:2px}.ui-navbar-noicons li .ui-btn .ui-btn-inner,.ui-navbar-noicons .ui-navbar-toggle .ui-btn-inner{padding-top:.8em;padding-bottom:.9em}.ui-navbar-expanded .ui-btn{margin:0;font-size:14px}.ui-navbar-expanded .ui-btn-inner{padding-left:5px;padding-right:5px}.ui-navbar-expanded .ui-btn-icon-top .ui-btn-inner{padding:45px 5px 15px;text-align:center}.ui-navbar-expanded .ui-btn-icon-top .ui-icon{top:15px}.ui-navbar-expanded .ui-btn-icon-bottom .ui-btn-inner{padding:15px 5px 45px;text-align:center}.ui-navbar-expanded .ui-btn-icon-bottom .ui-icon{bottom:15px}.ui-navbar-expanded li .ui-btn .ui-btn-inner{min-height:2.5em}.ui-navbar-expanded .ui-navbar-noicons .ui-btn .ui-btn-inner{padding-top:1.8em;padding-bottom:1.9em}.ui-btn{display:block;text-align:center;cursor:pointer;position:relative;margin:.5em 5px;padding:0}.ui-header .ui-btn,.ui-footer .ui-btn,.ui-bar .ui-btn{display:inline-block;font-size:13px;margin:0}.ui-btn-inline{display:inline-block}.ui-btn-inner{padding:.6em 25px;display:block;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;position:relative;zoom:1}.ui-btn input,.ui-btn button{z-index:2}.ui-header .ui-btn-inner,.ui-footer .ui-btn-inner,.ui-bar .ui-btn-inner{padding:.4em 8px .5em}.ui-btn-icon-notext{width:24px;height:24px}.ui-btn-icon-notext .ui-btn-inner{padding:2px 1px 2px 3px}.ui-btn-text{position:relative;z-index:1}.ui-btn-icon-notext .ui-btn-text{position:absolute;left:-9999px}.ui-btn-icon-left .ui-btn-inner{padding-left:33px}.ui-header .ui-btn-icon-left .ui-btn-inner,.ui-footer .ui-btn-icon-left .ui-btn-inner,.ui-bar .ui-btn-icon-left .ui-btn-inner{padding-left:27px}.ui-btn-icon-right .ui-btn-inner{padding-right:33px}.ui-header .ui-btn-icon-right .ui-btn-inner,.ui-footer .ui-btn-icon-right .ui-btn-inner,.ui-bar .ui-btn-icon-right .ui-btn-inner{padding-right:27px}.ui-btn-icon-top .ui-btn-inner{padding-top:33px}.ui-header .ui-btn-icon-top .ui-btn-inner,.ui-footer .ui-btn-icon-top .ui-btn-inner,.ui-bar .ui-btn-icon-top .ui-btn-inner{padding-top:27px}.ui-btn-icon-bottom .ui-btn-inner{padding-bottom:33px}.ui-header .ui-btn-icon-bottom .ui-btn-inner,.ui-footer .ui-btn-icon-bottom .ui-btn-inner,.ui-bar .ui-btn-icon-bottom .ui-btn-inner{padding-bottom:27px}.ui-btn-icon-notext .ui-icon{display:block;z-index:0}.ui-btn-icon-left .ui-icon,.ui-btn-icon-right .ui-icon{position:absolute;top:50%;margin-top:-9px}.ui-btn-icon-top .ui-icon,.ui-btn-icon-bottom .ui-icon{position:absolute;left:50%;margin-left:-9px}.ui-btn-icon-left .ui-icon{left:10px}.ui-btn-icon-right .ui-icon{right:10px}.ui-btn-icon-top .ui-icon{top:10px}.ui-btn-icon-bottom .ui-icon{bottom:10px}.ui-header .ui-btn-icon-left .ui-icon,.ui-footer .ui-btn-icon-left .ui-icon,.ui-bar .ui-btn-icon-left .ui-icon{left:4px}.ui-header .ui-btn-icon-right .ui-icon,.ui-footer .ui-btn-icon-right .ui-icon,.ui-bar .ui-btn-icon-right .ui-icon{right:4px}.ui-header .ui-btn-icon-top .ui-icon,.ui-footer .ui-btn-icon-top .ui-icon,.ui-bar .ui-btn-icon-top .ui-icon{top:4px}.ui-header .ui-btn-icon-bottom .ui-icon,.ui-footer .ui-btn-icon-bottom .ui-icon,.ui-bar .ui-btn-icon-bottom .ui-icon{bottom:4px}.ui-btn-hidden{position:absolute;top:0;left:0;width:100%;height:100%;-webkit-appearance:button;opacity:.1;cursor:pointer;background:transparent;font-size:1px;border:0;line-height:999px}.ui-collapsible{margin:.5em 0}.ui-collapsible-heading{font-size:16px;display:block;margin:0 -8px;padding:0;border-width:0 0 1px 0;position:relative}.ui-collapsible-heading a{text-align:left;margin:0}.ui-collapsible-heading a .ui-btn-inner{padding-left:40px}.ui-collapsible-heading a span.ui-btn{position:absolute;left:6px;top:50%;margin:-12px 0 0 0;width:20px;height:20px;padding:1px 0 1px 2px;text-indent:-9999px}.ui-collapsible-heading a span.ui-btn .ui-btn-inner{padding:10px 0}.ui-collapsible-heading a span.ui-btn .ui-icon{left:0;margin-top:-10px}.ui-collapsible-heading-status{position:fixed;left:-9999px}.ui-collapsible-content{display:block;margin:0 -8px;padding:10px 16px;border-top:0;background-image:none;font-weight:normal}.ui-collapsible-content-collapsed{display:none}.ui-collapsible-set{margin:.5em 0}.ui-collapsible-set .ui-collapsible{margin:-1px 0 0}.ui-controlgroup,fieldset.ui-controlgroup{padding:0;margin:.5em 0 1em}.ui-bar .ui-controlgroup{margin:0 .3em}.ui-controlgroup-label{font-size:16px;line-height:1.4;font-weight:normal;margin:0 0 .3em}.ui-controlgroup-controls{display:block;width:100%}.ui-controlgroup li{list-style:none}.ui-controlgroup-vertical .ui-btn,.ui-controlgroup-vertical .ui-checkbox,.ui-controlgroup-vertical .ui-radio{margin:0;border-bottom-width:0}.ui-controlgroup-controls label.ui-select{position:absolute;left:-9999px}.ui-controlgroup-vertical .ui-controlgroup-last{border-bottom-width:1px}.ui-controlgroup-horizontal{padding:0}.ui-controlgroup-horizontal .ui-btn,.ui-controlgroup-horizontal .ui-select{display:inline-block;margin:0 -5px 0 0}.ui-controlgroup-horizontal .ui-checkbox,.ui-controlgroup-horizontal .ui-radio{float:left;margin:0 -1px 0 0}.ui-controlgroup-horizontal .ui-checkbox .ui-btn,.ui-controlgroup-horizontal .ui-radio .ui-btn,.ui-controlgroup-horizontal .ui-checkbox:last-child,.ui-controlgroup-horizontal .ui-radio:last-child{margin-right:0}.ui-controlgroup-horizontal .ui-controlgroup-last{margin-right:0}.ui-controlgroup .ui-checkbox label,.ui-controlgroup .ui-radio label{font-size:16px}@media all and (min-width:450px){.ui-field-contain .ui-controlgroup-label{vertical-align:top;display:inline-block;width:20%;margin:0 2% 0 0}.ui-field-contain .ui-controlgroup-controls{width:60%;display:inline-block}.ui-field-contain .ui-controlgroup .ui-select{width:100%}.ui-field-contain .ui-controlgroup-horizontal .ui-select{width:auto}}.ui-dialog{min-height:480px}.ui-dialog .ui-header,.ui-dialog .ui-content,.ui-dialog .ui-footer{max-width:500px;margin:10% auto 0 auto;padding:15px;width:85%;position:relative}.ui-dialog .ui-header{padding:0 15px}.ui-dialog .ui-header,.ui-dialog .ui-footer{z-index:10}.ui-dialog .ui-content,.ui-dialog .ui-footer{margin-top:-15px}.ui-checkbox,.ui-radio{position:relative;margin:.2em 0 .5em;z-index:1}.ui-checkbox .ui-btn,.ui-radio .ui-btn{margin:0;text-align:left;z-index:2}.ui-checkbox .ui-btn-inner,.ui-radio .ui-btn-inner{white-space:normal}.ui-checkbox .ui-btn-icon-left .ui-btn-inner,.ui-radio .ui-btn-icon-left .ui-btn-inner{padding-left:45px}.ui-checkbox .ui-btn-icon-right .ui-btn-inner,.ui-radio .ui-btn-icon-right .ui-btn-inner{padding-right:45px}.ui-checkbox .ui-icon,.ui-radio .ui-icon{top:1.1em}.ui-checkbox .ui-btn-icon-left .ui-icon,.ui-radio .ui-btn-icon-left .ui-icon{left:15px}.ui-checkbox .ui-btn-icon-right .ui-icon,.ui-radio .ui-btn-icon-right .ui-icon{right:15px}.ui-checkbox input,.ui-radio input{position:absolute;left:20px;top:50%;width:10px;height:10px;margin:-5px 0 0 0;outline:0!important;z-index:1}.ui-field-contain{padding:1.5em 0;margin:0;border-bottom-width:1px;overflow:visible}.ui-field-contain:first-child{border-top-width:0}@media all and (min-width:450px){.ui-field-contain{border-width:0;padding:0;margin:1em 0}}.ui-select{display:block;position:relative}.ui-select select{position:absolute;left:-9999px;top:-9999px}.ui-select .ui-btn{overflow:hidden}.ui-select .ui-btn select{cursor:pointer;-webkit-appearance:button;left:0;top:0;width:100%;min-height:1.5em;min-height:100%;height:3em;max-height:100%;opacity:0;-ms-filter:"alpha(opacity=0)";filter:alpha(opacity=0);z-index:2}@-moz-document url-prefix(){.ui-select .ui-btn select{opacity:.0001}}.ui-select .ui-btn select.ui-select-nativeonly{opacity:1;text-indent:0}.ui-select .ui-btn-icon-right .ui-btn-inner{padding-right:45px}.ui-select .ui-btn-icon-right .ui-icon{right:15px}label.ui-select{font-size:16px;line-height:1.4;font-weight:normal;margin:0 0 .3em;display:block}.ui-select .ui-btn-text,.ui-selectmenu .ui-btn-text{display:block;min-height:1em;overflow:hidden}.ui-select .ui-btn-text{text-overflow:ellipsis}.ui-selectmenu{position:absolute;padding:0;z-index:100!important;width:80%;max-width:350px;padding:6px}.ui-selectmenu .ui-listview{margin:0}.ui-selectmenu .ui-btn.ui-li-divider{cursor:default}.ui-selectmenu-hidden{top:-9999px;left:-9999px}.ui-selectmenu-screen{position:absolute;top:0;left:0;width:100%;height:100%;z-index:99}.ui-screen-hidden,.ui-selectmenu-list .ui-li .ui-icon{display:none}.ui-selectmenu-list .ui-li .ui-icon{display:block}.ui-li.ui-selectmenu-placeholder{display:none}.ui-selectmenu .ui-header .ui-title{margin:.6em 46px .8em}@media all and (min-width:450px){.ui-field-contain label.ui-select{vertical-align:top;display:inline-block;width:20%;margin:0 2% 0 0}.ui-field-contain .ui-select{width:60%;display:inline-block}}.ui-selectmenu .ui-header h1:after{content:'.';visibility:hidden}label.ui-input-text{font-size:16px;line-height:1.4;display:block;font-weight:normal;margin:0 0 .3em}input.ui-input-text,textarea.ui-input-text{background-image:none;padding:.4em 1.5%;line-height:1.4;font-size:16px;display:block;width:97%}input.ui-input-text{-webkit-appearance:none}textarea.ui-input-text{height:50px;-webkit-transition:height 200ms linear;-moz-transition:height 200ms linear;-o-transition:height 200ms linear;transition:height 200ms linear}.ui-input-search{padding:0 30px;background-image:none;position:relative}.ui-icon-searchfield:after{position:absolute;left:7px;top:50%;margin-top:-9px;content:"";width:18px;height:18px;opacity:.5}.ui-input-search input.ui-input-text{border:0;width:98%;padding:.4em 0;margin:0;display:block;background:transparent none;outline:0!important}.ui-input-search .ui-input-clear{position:absolute;right:0;top:50%;margin-top:-13px}.ui-input-search .ui-input-clear-hidden{display:none}@media all and (min-width:450px){.ui-field-contain label.ui-input-text{vertical-align:top;display:inline-block;width:20%;margin:0 2% 0 0}.ui-field-contain input.ui-input-text,.ui-field-contain textarea.ui-input-text,.ui-field-contain .ui-input-search{width:60%;display:inline-block}.ui-field-contain .ui-input-search{width:50%}.ui-hide-label input.ui-input-text,.ui-hide-label textarea.ui-input-text,.ui-hide-label .ui-input-search{padding:.4em 1.5%;width:97%}.ui-input-search input.ui-input-text{width:98%}}.ui-listview{margin:0;counter-reset:listnumbering}.ui-content .ui-listview{margin:-15px}.ui-content .ui-listview-inset{margin:1em 0}.ui-listview,.ui-li{list-style:none;padding:0}.ui-li,.ui-li.ui-field-contain{display:block;margin:0;position:relative;overflow:visible;text-align:left;border-width:0;border-top-width:1px}.ui-li .ui-btn-text a.ui-link-inherit{text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.ui-li-divider,.ui-li-static{padding:.5em 15px;font-size:14px;font-weight:bold}.ui-li-divider{counter-reset:listnumbering}ol.ui-listview .ui-link-inherit:before,ol.ui-listview .ui-li-static:before,.ui-li-dec{font-size:.8em;display:inline-block;padding-right:.3em;font-weight:normal;counter-increment:listnumbering;content:counter(listnumbering) ". "}ol.ui-listview .ui-li-jsnumbering:before{content:""!important}.ui-listview-inset .ui-li{border-right-width:1px;border-left-width:1px}.ui-li:last-child,.ui-li.ui-field-contain:last-child{border-bottom-width:1px}.ui-li>.ui-btn-inner{display:block;position:relative;padding:0}.ui-li .ui-btn-inner a.ui-link-inherit,.ui-li-static.ui-li{padding:.7em 15px .7em 15px;display:block}.ui-li-has-thumb .ui-btn-inner a.ui-link-inherit,.ui-li-static.ui-li-has-thumb{min-height:60px;padding-left:100px}.ui-li-has-icon .ui-btn-inner a.ui-link-inherit,.ui-li-static.ui-li-has-icon{min-height:20px;padding-left:40px}.ui-li-has-count .ui-btn-inner a.ui-link-inherit,.ui-li-static.ui-li-has-count{padding-right:45px}.ui-li-has-arrow .ui-btn-inner a.ui-link-inherit,.ui-li-static.ui-li-has-arrow{padding-right:30px}.ui-li-has-arrow.ui-li-has-count .ui-btn-inner a.ui-link-inherit,.ui-li-static.ui-li-has-arrow.ui-li-has-count{padding-right:75px}.ui-li-has-count .ui-btn-text{padding-right:15px}.ui-li-heading{font-size:16px;font-weight:bold;display:block;margin:.6em 0;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.ui-li-desc{font-size:12px;font-weight:normal;display:block;margin:-.5em 0 .6em;text-overflow:ellipsis;overflow:hidden;white-space:nowrap}.ui-li-thumb,.ui-li-icon{position:absolute;left:1px;top:0;max-height:80px;max-width:80px}.ui-li-icon{max-height:40px;max-width:40px;left:10px;top:.9em}.ui-li-thumb,.ui-li-icon,.ui-li-content{float:left;margin-right:10px}.ui-li-aside{float:right;width:50%;text-align:right;margin:.3em 0}@media all and (min-width:480px){.ui-li-aside{width:45%}}.ui-li-divider{cursor:default}.ui-li-has-alt .ui-btn-inner a.ui-link-inherit,.ui-li-static.ui-li-has-alt{padding-right:95px}.ui-li-has-count .ui-li-count{position:absolute;font-size:11px;font-weight:bold;padding:.2em .5em;top:50%;margin-top:-.9em;right:38px}.ui-li-divider .ui-li-count,.ui-li-static .ui-li-count{right:10px}.ui-li-has-alt .ui-li-count{right:55px}.ui-li-link-alt{position:absolute;width:40px;height:100%;border-width:0;border-left-width:1px;top:0;right:0;margin:0;padding:0;z-index:2}.ui-li-link-alt .ui-btn{overflow:hidden;position:absolute;right:8px;top:50%;margin:-11px 0 0 0;border-bottom-width:1px;z-index:-1}.ui-li-link-alt .ui-btn-inner{padding:0;height:100%;position:absolute;width:100%;top:0;left:0}.ui-li-link-alt .ui-btn .ui-icon{right:50%;margin-right:-9px}.ui-listview * .ui-btn-inner>.ui-btn>.ui-btn-inner{border-top:0}.ui-listview-filter{border-width:0;overflow:hidden;margin:-15px -15px 15px -15px}.ui-listview-filter .ui-input-search{margin:5px;width:auto;display:block}.ui-listview-filter-inset{margin:-15px -5px -15px -5px;background:transparent}.ui-li.ui-screen-hidden{display:none}@media only screen and (min-device-width:768px) and (max-device-width:1024px){.ui-li .ui-btn-text{overflow:visible}}label.ui-slider{font-size:16px;line-height:1.4;font-weight:normal;margin:0 0 .3em;display:block}input.ui-slider-input,.ui-field-contain input.ui-slider-input{display:inline-block;width:50px}select.ui-slider-switch{display:none}div.ui-slider{position:relative;display:inline-block;overflow:visible;height:15px;padding:0;margin:0 2% 0 20px;top:4px;width:66%}div.ui-slider-switch{width:99.8%}a.ui-slider-handle{position:absolute;z-index:10;top:50%;width:28px;height:28px;margin-top:-15px;margin-left:-15px}a.ui-slider-handle .ui-btn-inner{padding-left:0;padding-right:0}@media all and (min-width:480px){.ui-field-contain label.ui-slider{vertical-align:top;display:inline-block;width:20%;margin:0 2% 0 0}.ui-field-contain div.ui-slider{width:43%}}div.ui-slider-switch{height:32px;overflow:hidden;margin-left:0}div.ui-slider-inneroffset{margin-left:50%;position:absolute;top:1px;height:100%;width:50%}a.ui-slider-handle-snapping{-webkit-transition:left 100ms linear}div.ui-slider-labelbg{position:absolute;top:0;margin:0;border-width:0}div.ui-slider-switch div.ui-slider-labelbg-a{width:60%;height:100%;left:0}div.ui-slider-switch div.ui-slider-labelbg-b{width:60%;height:100%;right:0}.ui-slider-switch-a div.ui-slider-labelbg-a,.ui-slider-switch-b div.ui-slider-labelbg-b{z-index:-1}.ui-slider-switch-a div.ui-slider-labelbg-b,.ui-slider-switch-b div.ui-slider-labelbg-a{z-index:0}div.ui-slider-switch a.ui-slider-handle{z-index:20;width:101%;height:32px;margin-top:-18px;margin-left:-101%}span.ui-slider-label{width:100%;position:absolute;height:32px;font-size:16px;text-align:center;line-height:2;background:0;border-color:transparent}span.ui-slider-label-a{left:-100%;margin-right:-1px}span.ui-slider-label-b{right:-100%;margin-left:-1px}
\ No newline at end of file
diff --git a/themes/jquerymobile/css/slick/ajax-loader.gif b/themes/jquerymobile/css/slick/ajax-loader.gif
deleted file mode 100644
index e0e6e9760bc04861cc4771e327f22ed7962e0858..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/css/slick/ajax-loader.gif and /dev/null differ
diff --git a/themes/jquerymobile/css/slick/fonts/slick.eot b/themes/jquerymobile/css/slick/fonts/slick.eot
deleted file mode 100644
index 2cbab9ca97723bc24c50315a0a9bd155db4e0aa5..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/css/slick/fonts/slick.eot and /dev/null differ
diff --git a/themes/jquerymobile/css/slick/fonts/slick.svg b/themes/jquerymobile/css/slick/fonts/slick.svg
deleted file mode 100644
index b36a66a6c454fb901133b8bce089a5ff7f74f871..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/css/slick/fonts/slick.svg
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" standalone="no"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg xmlns="http://www.w3.org/2000/svg">
-<metadata>Generated by Fontastic.me</metadata>
-<defs>
-<font id="slick" horiz-adv-x="512">
-<font-face font-family="slick" units-per-em="512" ascent="480" descent="-32"/>
-<missing-glyph horiz-adv-x="512" />
-
-<glyph unicode="&#8594;" d="M241 113l130 130c4 4 6 8 6 13 0 5-2 9-6 13l-130 130c-3 3-7 5-12 5-5 0-10-2-13-5l-29-30c-4-3-6-7-6-12 0-5 2-10 6-13l87-88-87-88c-4-3-6-8-6-13 0-5 2-9 6-12l29-30c3-3 8-5 13-5 5 0 9 2 12 5z m234 143c0-40-9-77-29-110-20-34-46-60-80-80-33-20-70-29-110-29-40 0-77 9-110 29-34 20-60 46-80 80-20 33-29 70-29 110 0 40 9 77 29 110 20 34 46 60 80 80 33 20 70 29 110 29 40 0 77-9 110-29 34-20 60-46 80-80 20-33 29-70 29-110z"/>
-<glyph unicode="&#8592;" d="M296 113l29 30c4 3 6 7 6 12 0 5-2 10-6 13l-87 88 87 88c4 3 6 8 6 13 0 5-2 9-6 12l-29 30c-3 3-8 5-13 5-5 0-9-2-12-5l-130-130c-4-4-6-8-6-13 0-5 2-9 6-13l130-130c3-3 7-5 12-5 5 0 10 2 13 5z m179 143c0-40-9-77-29-110-20-34-46-60-80-80-33-20-70-29-110-29-40 0-77 9-110 29-34 20-60 46-80 80-20 33-29 70-29 110 0 40 9 77 29 110 20 34 46 60 80 80 33 20 70 29 110 29 40 0 77-9 110-29 34-20 60-46 80-80 20-33 29-70 29-110z"/>
-<glyph unicode="&#8226;" d="M475 256c0-40-9-77-29-110-20-34-46-60-80-80-33-20-70-29-110-29-40 0-77 9-110 29-34 20-60 46-80 80-20 33-29 70-29 110 0 40 9 77 29 110 20 34 46 60 80 80 33 20 70 29 110 29 40 0 77-9 110-29 34-20 60-46 80-80 20-33 29-70 29-110z"/>
-<glyph unicode="&#97;" d="M475 439l0-128c0-5-1-9-5-13-4-4-8-5-13-5l-128 0c-8 0-13 3-17 11-3 7-2 14 4 20l40 39c-28 26-62 39-100 39-20 0-39-4-57-11-18-8-33-18-46-32-14-13-24-28-32-46-7-18-11-37-11-57 0-20 4-39 11-57 8-18 18-33 32-46 13-14 28-24 46-32 18-7 37-11 57-11 23 0 44 5 64 15 20 9 38 23 51 42 2 1 4 3 7 3 3 0 5-1 7-3l39-39c2-2 3-3 3-6 0-2-1-4-2-6-21-25-46-45-76-59-29-14-60-20-93-20-30 0-58 5-85 17-27 12-51 27-70 47-20 19-35 43-47 70-12 27-17 55-17 85 0 30 5 58 17 85 12 27 27 51 47 70 19 20 43 35 70 47 27 12 55 17 85 17 28 0 55-5 81-15 26-11 50-26 70-45l37 37c6 6 12 7 20 4 8-4 11-9 11-17z"/>
-</font></defs></svg>
diff --git a/themes/jquerymobile/css/slick/fonts/slick.ttf b/themes/jquerymobile/css/slick/fonts/slick.ttf
deleted file mode 100644
index 9d03461b653373f7cda3b4af104c6bca07f9892b..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/css/slick/fonts/slick.ttf and /dev/null differ
diff --git a/themes/jquerymobile/css/slick/fonts/slick.woff b/themes/jquerymobile/css/slick/fonts/slick.woff
deleted file mode 100644
index 8ee99721bb81b59a5e1ceee1d3256b15f907d96b..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/css/slick/fonts/slick.woff and /dev/null differ
diff --git a/themes/jquerymobile/css/slick/slick.css b/themes/jquerymobile/css/slick/slick.css
deleted file mode 100644
index 27f0525b8e3946bb7e2112790c14d083bdbb17cb..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/css/slick/slick.css
+++ /dev/null
@@ -1,57 +0,0 @@
-@charset "UTF-8";
-/* Slider */
-.slick-slider { position: relative; display: block; box-sizing: border-box; -moz-box-sizing: border-box; -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; -ms-touch-action: pan-y; touch-action: pan-y; -webkit-tap-highlight-color: transparent; width:90%; margin:auto;}
-
-.slick-list { position: relative; overflow: hidden; display: block; margin: 0; padding: 0; }
-.slick-list:focus { outline: none; }
-.slick-loading .slick-list { background: #fff url("./ajax-loader.gif") center center no-repeat; }
-.slick-list.dragging { cursor: pointer; cursor: hand; }
-
-.slick-slider .slick-track { -webkit-transform: translate3d(0, 0, 0); -moz-transform: translate3d(0, 0, 0); -ms-transform: translate3d(0, 0, 0); -o-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); }
-
-.slick-track { position: relative; left: 0; top: 0; display: block; }
-.slick-track:before, .slick-track:after { content: ""; display: table; }
-.slick-track:after { clear: both; }
-.slick-loading .slick-track { visibility: hidden; }
-
-.slick-slide { float: left; height: 100%; min-height: 1px; display: none; text-align:center; }
-[dir="rtl"] .slick-slide { float: right; }
-.slick-slide img { display: block; margin: auto; }
-.slick-slide.slick-loading img { display: none; }
-.slick-slide.dragging img { pointer-events: none; }
-.slick-initialized .slick-slide { display: block; }
-.slick-loading .slick-slide { visibility: hidden; }
-.slick-vertical .slick-slide { display: block; height: auto; border: 1px solid transparent; }
-
-/* Icons */
-@font-face { font-family: "slick"; src: url("./fonts/slick.eot"); src: url("./fonts/slick.eot?#iefix") format("embedded-opentype"), url("./fonts/slick.woff") format("woff"), url("./fonts/slick.ttf") format("truetype"), url("./fonts/slick.svg#slick") format("svg"); font-weight: normal; font-style: normal; }
-/* Arrows */
-.slick-prev, .slick-next { position: absolute; display: block; height: 20px; width: 20px; line-height: 0; font-size: 0; cursor: pointer; background: transparent; color: transparent; top: 50%; margin-top: -10px; padding: 0; border: none; outline: none; }
-.slick-prev:hover, .slick-prev:focus, .slick-next:hover, .slick-next:focus { outline: none; background: transparent; color: transparent; }
-.slick-prev:hover:before, .slick-prev:focus:before, .slick-next:hover:before, .slick-next:focus:before { opacity: 1; }
-.slick-prev.slick-disabled:before, .slick-next.slick-disabled:before { opacity: 0.25; }
-
-.slick-prev:before, .slick-next:before { font-family: "slick"; font-size: 20px; line-height: 1; color: black; opacity: 0.75; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }
-
-.slick-prev { left: -25px; }
-[dir="rtl"] .slick-prev { left: auto; right: -25px; }
-.slick-prev:before { content: "←"; }
-[dir="rtl"] .slick-prev:before { content: "→"; }
-
-.slick-next { right: -25px; }
-[dir="rtl"] .slick-next { left: -25px; right: auto; }
-.slick-next:before { content: "→"; }
-[dir="rtl"] .slick-next:before { content: "←"; }
-
-/* Dots */
-.slick-slider { margin-bottom: 30px; }
-
-.slick-dots { position: absolute; bottom: -45px; list-style: none; display: block; text-align: center; padding: 0; width: 100%; }
-.slick-dots li { position: relative; display: inline-block; height: 20px; width: 20px; margin: 0 5px; padding: 0; cursor: pointer; }
-.slick-dots li button { border: 0; background: transparent; display: block; height: 20px; width: 20px; outline: none; line-height: 0; font-size: 0; color: transparent; padding: 5px; cursor: pointer; }
-.slick-dots li button:hover, .slick-dots li button:focus { outline: none; }
-.slick-dots li button:hover:before, .slick-dots li button:focus:before { opacity: 1; }
-.slick-dots li button:before { position: absolute; top: 0; left: 0; content: "•"; width: 20px; height: 20px; font-family: "slick"; font-size: 6px; line-height: 20px; text-align: center; color: black; opacity: 0.25; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }
-.slick-dots li.slick-active button:before { color: black; opacity: 0.75; }
-
-/*# sourceMappingURL=slick.css.map */
\ No newline at end of file
diff --git a/themes/jquerymobile/css/slick/slick.css.map b/themes/jquerymobile/css/slick/slick.css.map
deleted file mode 100644
index 9f0499ad5e665741b7a9ae429f624969947a58f7..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/css/slick/slick.css.map
+++ /dev/null
@@ -1,7 +0,0 @@
-{
-"version": 3,
-"mappings": ";;AAuCA,aAAc,GACV,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,KAAK,EACd,UAAU,EAAE,UAAU,EACtB,eAAe,EAAE,UAAU,EAC3B,qBAAqB,EAAE,IAAI,EAC3B,mBAAmB,EAAE,IAAI,EACzB,kBAAkB,EAAE,IAAI,EACxB,gBAAgB,EAAE,IAAI,EACtB,eAAe,EAAE,IAAI,EACrB,WAAW,EAAE,IAAI,EACjB,gBAAgB,EAAE,KAAK,EACvB,YAAY,EAAE,KAAK,EACnB,2BAA2B,EAAE,WAAW;;AAE5C,WAAY,GACR,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,KAAK,EACd,MAAM,EAAE,CAAC,EACT,OAAO,EAAE,CAAC;AAEV,iBAAQ,GACJ,OAAO,EAAE,IAAI;AAGjB,0BAAiB,GACb,UAAU,EAAE,qDAA+D;AAG/E,oBAAW,GACP,MAAM,EAAE,OAAO,EACf,MAAM,EAAE,IAAI;;AAGpB,0BAA2B,GACvB,iBAAiB,EAAE,oBAAoB,EACvC,cAAc,EAAE,oBAAoB,EACpC,aAAa,EAAE,oBAAoB,EACnC,YAAY,EAAE,oBAAoB,EAClC,SAAS,EAAE,oBAAoB;;AAGnC,YAAa,GACT,QAAQ,EAAE,QAAQ,EAClB,IAAI,EAAE,CAAC,EACP,GAAG,EAAE,CAAC,EACN,OAAO,EAAE,KAAK;AAEd,uCACQ,GACJ,OAAO,EAAE,EAAE,EACX,OAAO,EAAE,KAAK;AAGlB,kBAAQ,GACJ,KAAK,EAAE,IAAI;AAGf,2BAAiB,GACb,UAAU,EAAE,MAAM;;AAG1B,YAAa,GACT,KAAK,EAAE,IAAI,EACX,MAAM,EAAE,IAAI,EACZ,UAAU,EAAE,GAAG,EAWf,OAAO,EAAE,IAAI;AAVb,wBAAc,GACV,KAAK,EAAE,KAAK;AAEhB,gBAAI,GACA,OAAO,EAAE,KAAK;AAElB,8BAAoB,GAChB,OAAO,EAAE,IAAI;AAKjB,yBAAe,GACX,cAAc,EAAE,IAAI;AAGxB,+BAAqB,GACjB,OAAO,EAAE,KAAK;AAGlB,2BAAiB,GACb,UAAU,EAAE,MAAM;AAGtB,4BAAkB,GACd,OAAO,EAAE,KAAK,EACd,MAAM,EAAE,IAAI,EACZ,MAAM,EAAE,qBAAqB;;;AAMnC,UASC,GARG,WAAW,EAAC,OAAO,EACnB,GAAG,EAAK,wBAA2B,EACnC,GAAG,EAAK,gMAA8D,EAItE,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM;;AAMxB,wBACY,GACR,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,KAAK,EACd,MAAM,EAAE,IAAI,EACZ,KAAK,EAAE,IAAI,EACX,WAAW,EAAE,CAAC,EACd,SAAS,EAAE,CAAC,EACZ,MAAM,EAAE,OAAO,EACf,UAAU,EAAE,WAAW,EACvB,KAAK,EAAE,WAAW,EAClB,GAAG,EAAE,GAAG,EACR,UAAU,EAAE,KAAK,EACjB,OAAO,EAAE,CAAC,EACV,MAAM,EAAE,IAAI,EACZ,OAAO,EAAE,IAAI;AACb,0EAAiB,GACf,OAAO,EAAE,IAAI,EACb,UAAU,EAAE,WAAW,EACvB,KAAK,EAAE,WAAW;AAClB,sGAAS,GACP,OAAO,EA/JI,CAAC;AAkKhB,oEAAwB,GACpB,OAAO,EAlKM,IAAG;;AAqKxB,sCAAuC,GACnC,WAAW,EAjLK,OAAO,EAkLvB,SAAS,EAAE,IAAI,EACf,WAAW,EAAE,CAAC,EACd,KAAK,EAlLW,KAAK,EAmLrB,OAAO,EA5KO,IAAG,EA6KjB,sBAAsB,EAAE,WAAW,EACnC,uBAAuB,EAAE,SAAS;;AAEtC,WAAY,GACR,IAAI,EAAE,KAAK;AACX,uBAAc,GACV,IAAI,EAAG,IAAI,EACX,KAAK,EAAE,KAAK;AAEhB,kBAAS,GACL,OAAO,EA3LQ,GAAO;AA4LtB,8BAAc,GACV,OAAO,EA5LI,GAAO;;AAgM9B,WAAY,GACR,KAAK,EAAE,KAAK;AACZ,uBAAc,GACV,IAAI,EAAG,KAAK,EACZ,KAAK,EAAE,IAAI;AAEf,kBAAS,GACL,OAAO,EAvMQ,GAAO;AAwMtB,8BAAc,GACV,OAAO,EA1MI,GAAO;;;AAiN9B,aAAc,GACV,aAAa,EAAE,IAAI;;AAEvB,WAAY,GACR,QAAQ,EAAE,QAAQ,EAClB,MAAM,EAAE,KAAK,EACb,UAAU,EAAE,IAAI,EAChB,OAAO,EAAE,KAAK,EACd,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,CAAC,EACV,KAAK,EAAE,IAAI;AAEX,cAAG,GACC,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,YAAY,EACrB,MAAM,EAAE,IAAI,EACZ,KAAK,EAAE,IAAI,EACX,MAAM,EAAE,KAAK,EACb,OAAO,EAAE,CAAC,EACV,MAAM,EAAE,OAAO;AAEf,qBAAO,GACH,MAAM,EAAE,CAAC,EACT,UAAU,EAAE,WAAW,EACvB,OAAO,EAAE,KAAK,EACd,MAAM,EAAE,IAAI,EACZ,KAAK,EAAE,IAAI,EACX,OAAO,EAAE,IAAI,EACb,WAAW,EAAE,CAAC,EACd,SAAS,EAAE,CAAC,EACZ,KAAK,EAAE,WAAW,EAClB,OAAO,EAAE,GAAG,EACZ,MAAM,EAAE,OAAO;AACf,wDAAiB,GACb,OAAO,EAAE,IAAI;AACb,sEAAS,GACP,OAAO,EAhPN,CAAC;AAoPR,4BAAS,GACL,QAAQ,EAAE,QAAQ,EAClB,GAAG,EAAE,CAAC,EACN,IAAI,EAAE,CAAC,EACP,OAAO,EA3PD,GAAO,EA4Pb,KAAK,EAAE,IAAI,EACX,MAAM,EAAE,IAAI,EACZ,WAAW,EArQP,OAAO,EAsQX,SAAS,EA9PR,GAAG,EA+PJ,WAAW,EAAE,IAAI,EACjB,UAAU,EAAE,MAAM,EAClB,KAAK,EArQI,KAAgB,EAsQzB,OAAO,EA/PF,IAAG,EAgQR,sBAAsB,EAAE,WAAW,EACnC,uBAAuB,EAAE,SAAS;AAK1C,yCAA6B,GACzB,KAAK,EA9QQ,KAAgB,EA+Q7B,OAAO,EA1QD,IAAG",
-"sources": ["slick.scss"],
-"names": [],
-"file": "slick.css"
-}
diff --git a/themes/jquerymobile/css/styles.css b/themes/jquerymobile/css/styles.css
deleted file mode 100644
index 1ceebec3224856b0520ca35547d8e79f8b877936..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/css/styles.css
+++ /dev/null
@@ -1,313 +0,0 @@
-ul.results,ul.filters,ul.mylists,ul.comments,ul.history,ul.bookbag {
-    margin-bottom: 10px !important;
-    margin-top: 10px !important;
-}
-ul.results .ui-icon-check {
-    background-color: green;
-}
-ul.results .ui-icon-plus {
-    background-color: white;
-}
-ul.results .ui-li-aside {
-    width: 40px;
-    font-size: 12px;
-}
-ul.results .ui-li .ui-btn-inner a.ui-link-inherit {
-    padding-right: 45px;
-}
-ul.mylists a {
-    font-size: 12px !important;
-    white-space: normal !important;
-}
-ul.filters a {
-    font-size: 12px !important;
-    white-space: normal !important;
-}
-ul.filters .ui-icon-minus {
-    background-color: #cc0000;
-}
-ul.bookbag .ui-icon-minus {
-    background-color: #cc0000;
-}
-ul.mylist .ui-icon-minus {
-    background-color: #cc0000;
-}
-ul.narrow .ui-icon-check {
-    background-color: green;
-}
-ul.narrow li.checked a {
-    color: green !important;
-}
-ul.narrow li.checked .ui-li-count {
-    color: green;
-}
-ul.comments .ui-icon-minus {
-    background-color: #cc0000;
-}
-ul.comments .ui-li-aside {
-    width: 60px;
-    font-size: 10px;
-}
-ul.comments p {
-    white-space: normal;
-    margin-top: .3em;
-    font-size: 14px;
-}
-ul.comments p.posted-by {
-    font-size: 12px;
-}
-ul.history .ui-icon-minus {
-    background-color: #cc0000;
-}
-ul.history .ui-icon-plus {
-    background-color: green;
-}
-ul.history p {
-    white-space: normal;
-    font-size: 12px;
-}
-.result {
-    white-space: normal !important;
-}
-.result p {
-    white-space: normal !important;
-}
-.result h3 {
-    font-size: 14px;
-    font-weight: normal;
-    white-space: normal;
-    color: #0066CC !important;
-}
-.narrow-search a.ui-link-inherit {
-    font-size: 14px;
-}
-.narrow-search .ui-listview-inset {
-    margin: 0;
-}
-.narrow-search .ui-collapsible-content {
-    padding: 5px 0;
-}
-.highlight {
-    font-weight: bold;
-}
-.hide {
-    display: none;
-}
-/** class to make stuff "invisible" but still readable by screen readers */
-.offscreen {
-    position:absolute;
-    left:-10000px;
-    top:auto;
-    width:1px;
-    height:1px;
-    overflow:hidden;
-    display:inline;
-}
-.iconlabel {
-    line-height: 20px;
-    font-size: 12px;
-}
-h3 {
-    font-size: 16px;
-    margin-top: 0.5em;
-    margin-bottom: 0.5em;
-}
-h4 {
-    font-size: 14px;
-    margin-top: 0.5em;
-    margin-bottom: 0.5em;
-}
-p {
-    font-size: 14px;
-    margin-top: .5em;
-    margin-bottom: .5em;
-}
-.record .iconlabel {
-    font-size: 14px;
-}
-dl.biblio dt {
-    font-size: 14px;
-    font-weight: bold;
-    margin: 0.5em 0 0.5em;
-}
-dl.biblio dd {
-    font-size: 14px;
-    margin-left: 1em;
-}
-div.recordcover {
-    text-align:center;
-}
-table.holdings th {
-    font-size: 14px;
-    font-weight: bold;
-    vertical-align: top;
-    text-align: right;
-}
-table.holdings td {
-    font-size: 14px;
-}
-label,legend,.ui-controlgroup-label {
-    font-size: 14px !important;
-    font-weight: bold !important;
-}
-div.footer-text {
-    font-size: 14px;
-    margin-bottom: 20px;
-    text-align: center;
-}
-.available {
-    background-image:url(../images/silk/bullet_green.png);
-    background-repeat:no-repeat;
-    color:#009900;
-    padding-left:18px
-}
-.checkedout {
-    background-image:url(../images/silk/bullet_red.png);
-    background-repeat:no-repeat;
-    color:#cc0000;
-    padding-left:18px
-}
-
-.holdPlace {
-    background-image:url(../images/fugue/holdPlace.png);
-    background-repeat:no-repeat;
-    background-position: left;
-    padding-left:18px
-}
-.holdCancel {
-    background-image:url(../images/fugue/holdCancel.png);
-    background-repeat:no-repeat;
-    background-position: left;
-    padding-left:18px
-}
-.holdCancelAll {
-    background-image:url(../images/fugue/holdCancelAll.png);
-    background-repeat:no-repeat;
-    background-position: left;
-    padding-left:18px
-}
-.renew {
-    background-image:url(../images/fugue/renew.png);
-    background-repeat:no-repeat;
-    background-position: left;
-    padding-left:18px
-}
-.renewAll {
-    background-image:url(../images/fugue/renewAll.png);
-    background-repeat:no-repeat;
-    background-position: left;
-    padding-left:18px
-}
-.unknown {
-    background-image:url(../images/silk/bullet_orange.png);
-    background-repeat:no-repeat;
-    color:#ff890f;
-    padding-left:18px
-}
-.ajax_hold_request_loading {
-    background: url(../images/loading.gif) no-repeat left top;
-    padding:0 .5em .5em 20px;
-}
-
-.error, .alert, .info, .success {
-  text-align:center;
-  padding:10px 0;
-  box-shadow:0 1px 0 #AAA,0 -1px 0 #FFF;
-}
-.error, .alert {
-  color:#8a1f11;
-  background:#FDE;
-  border:1px solid #811;
-}
-.notice {color:#514721;}
-.success {
-  color:#264409;
-  background:#e6efc2;
-  border:1px solid #c6d880;
-}
-.info {
-  color:#205791;
-  background:#DEF;
-  border:1px solid #259;
-}
-.error a, .alert a {color:#8a1f11;}
-.notice a {color:#514721;}
-.success a {color:#264409;}
-.info a {color:#205791;}
-
-
-.sysInfo {
-    margin: 0 auto;
-    padding: 1em;
-    background-color: #FFEF8F;
-    border: 2px solid #F9DD34;
-    border-radius: 5px 5px 5px 5px;
-}
-
-/** Citation **/
-
-p.citationText {
-    padding-left:25px;
-    text-indent:-25px;
-}
-
-#hierarchyTree ul {
-    list-style-type: none;
-    margin: 0;
-    padding: 0;
-}
-
-#hierarchyTree #treeList li {
-    background-image:url(../images/fugue/treeItem.png);
-    background-repeat: no-repeat;
-    padding: 0.25em 0 0 23px;
-    background-position: 0 0.25em;
-}
-
-#hierarchyTree #treeList li.currentRecord {
-    background-image:url(../images/fugue/treeItemCurrent.png);
-    background-repeat: no-repeat;
-    padding: 0.25em 0 0 23px;
-    background-position: 0 0.25em;
-}
-
-#hierarchyTree #treeList li.hierarchy {
-    background-image:url(../images/fugue/collection.png);
-    background-repeat: no-repeat;
-    padding: 0.25em 0 0 23px;
-    background-position: 0 0.25em;
-}
-
-#hierarchyTree #treeList li.currentHierarchy {
-    background-image:url(../images/fugue/collectionCurrent.png);
-    background-repeat: no-repeat;
-    padding: 0.25em 0 0 23px;
-    background-position: 0 0.25em;
-}
-
-#hierarchyTree #treeList li.currentHierarchy > a, #hierarchyTree #treeList li.currentRecord > a {
-    color: #000;
-    font-weight: bold;
-}
-
-#tagList .tag.ui-btn-up-b a {color: #FFF;}
-#tagList .tag .text {
-  padding: 1em;
-  padding-right: 0;
-  vertical-align: super;
-}
-#tagList .tag .tag-form {display: inline;}
-
-span[class^="services-"], span[class*=" services-"] span:first-of-type::before {
-    content: "";
-}
-span[class^="services-"], span[class*=" services-"] span::before {
-    content: ", ";
-}
-
-.marc-row-LEADER,
-.marc-row-006,
-.marc-row-007,
-.marc-row-008 {
-  white-space: pre-wrap;
-}
diff --git a/themes/jquerymobile/css/vudl.css b/themes/jquerymobile/css/vudl.css
deleted file mode 100644
index 23cad5a77ba170bfdca26f5c217bd519035dd548..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/css/vudl.css
+++ /dev/null
@@ -1,30 +0,0 @@
-.thumbnail {
-  text-align:center;
-  height:180px;
-}
-.label {
-  display:block;
-  margin-bottom:5px;
-}
-a.pdf,a.doc {
-  display:block;
-  margin:0 auto;
-}
-a.pdf {
-  background:url('../images/small/pdf.png');
-  width:70px;
-  height:87px;
-}
-a.doc {
-  background:url('../images/small/doc.png');
-  width:116px;
-  height:85px;
-}
-
-.content {
-  padding-top:0;
-}
-.preview {
-  display:block;
-  text-align:center;
-}
\ No newline at end of file
diff --git a/themes/jquerymobile/images/.htaccess b/themes/jquerymobile/images/.htaccess
deleted file mode 100644
index d96fae1a2e794096294f36bf3e2b5ee9090f0bf1..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/images/.htaccess
+++ /dev/null
@@ -1,3 +0,0 @@
-<IfModule mod_rewrite.c>
-  RewriteEngine Off
-</IfModule>
diff --git a/themes/jquerymobile/images/EDS/PT_Sprite.png b/themes/jquerymobile/images/EDS/PT_Sprite.png
deleted file mode 100644
index 64225908ea429e97bf01b89c6e77cbfe2b0840e2..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/EDS/PT_Sprite.png and /dev/null differ
diff --git a/themes/jquerymobile/images/EDS/sprites_32.png b/themes/jquerymobile/images/EDS/sprites_32.png
deleted file mode 100644
index 1ac5486a8216e8262069cd08d1ba6fad8a04cd30..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/EDS/sprites_32.png and /dev/null differ
diff --git a/themes/jquerymobile/images/ebook.png b/themes/jquerymobile/images/ebook.png
deleted file mode 100644
index 6535ad8e5a2cb3591f5657e65d85d9f8fb8a8fe9..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/ebook.png and /dev/null differ
diff --git a/themes/jquerymobile/images/fugue/bookbag.png b/themes/jquerymobile/images/fugue/bookbag.png
deleted file mode 100644
index 223e889eb13ca5f03cea33109a3fa8547c6c5e48..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/fugue/bookbag.png and /dev/null differ
diff --git a/themes/jquerymobile/images/fugue/bookbagAdd.png b/themes/jquerymobile/images/fugue/bookbagAdd.png
deleted file mode 100644
index 2398cd9d3ebe89b63c330f05cf4b996bfe912e0e..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/fugue/bookbagAdd.png and /dev/null differ
diff --git a/themes/jquerymobile/images/fugue/bookbagDelete.png b/themes/jquerymobile/images/fugue/bookbagDelete.png
deleted file mode 100644
index 21a2243339bb524403053cd06489c63a141cb7f4..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/fugue/bookbagDelete.png and /dev/null differ
diff --git a/themes/jquerymobile/images/fugue/bookbagEmpty.png b/themes/jquerymobile/images/fugue/bookbagEmpty.png
deleted file mode 100644
index 65c2fc83fd9444816694c5c31bad10920c03603b..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/fugue/bookbagEmpty.png and /dev/null differ
diff --git a/themes/jquerymobile/images/fugue/collection.png b/themes/jquerymobile/images/fugue/collection.png
deleted file mode 100644
index 320e701ae15d052d22907794f55b3ed15f07a0a7..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/fugue/collection.png and /dev/null differ
diff --git a/themes/jquerymobile/images/fugue/collectionCurrent.png b/themes/jquerymobile/images/fugue/collectionCurrent.png
deleted file mode 100644
index 9732669670328e6952326f9a4e30ba8b34664362..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/fugue/collectionCurrent.png and /dev/null differ
diff --git a/themes/jquerymobile/images/fugue/cross-small.png b/themes/jquerymobile/images/fugue/cross-small.png
deleted file mode 100644
index 53c3a71b25917651d5294126cbaa30f33d18d971..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/fugue/cross-small.png and /dev/null differ
diff --git a/themes/jquerymobile/images/fugue/holdCancel.png b/themes/jquerymobile/images/fugue/holdCancel.png
deleted file mode 100644
index 38558b29b4b0b879351581f62ce79f04b7bf0878..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/fugue/holdCancel.png and /dev/null differ
diff --git a/themes/jquerymobile/images/fugue/holdCancelAll.png b/themes/jquerymobile/images/fugue/holdCancelAll.png
deleted file mode 100644
index 3f93371db6b30a338f935655f91e2d8dbbc536df..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/fugue/holdCancelAll.png and /dev/null differ
diff --git a/themes/jquerymobile/images/fugue/holdPlace.png b/themes/jquerymobile/images/fugue/holdPlace.png
deleted file mode 100644
index b001bb7358621cf970eae192abfd5b24e2863e40..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/fugue/holdPlace.png and /dev/null differ
diff --git a/themes/jquerymobile/images/fugue/renew.png b/themes/jquerymobile/images/fugue/renew.png
deleted file mode 100644
index a502793fb1ca15f1f5099eca161cc42cc60e4e5f..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/fugue/renew.png and /dev/null differ
diff --git a/themes/jquerymobile/images/fugue/renewAll.png b/themes/jquerymobile/images/fugue/renewAll.png
deleted file mode 100644
index 92506b6cc2366c16242824ac226c1085931f66ba..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/fugue/renewAll.png and /dev/null differ
diff --git a/themes/jquerymobile/images/fugue/tick-small.png b/themes/jquerymobile/images/fugue/tick-small.png
deleted file mode 100644
index a110aef9330c6e9089dfb18544d1a46d65d9fa92..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/fugue/tick-small.png and /dev/null differ
diff --git a/themes/jquerymobile/images/fugue/tree.png b/themes/jquerymobile/images/fugue/tree.png
deleted file mode 100644
index d0b534db872347ebc238a87e9dd8b889778086ed..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/fugue/tree.png and /dev/null differ
diff --git a/themes/jquerymobile/images/fugue/treeCurrent.png b/themes/jquerymobile/images/fugue/treeCurrent.png
deleted file mode 100644
index dc4d5008d17afb112dfe6dc60b6527f724e0c455..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/fugue/treeCurrent.png and /dev/null differ
diff --git a/themes/jquerymobile/images/fugue/treeItem.png b/themes/jquerymobile/images/fugue/treeItem.png
deleted file mode 100644
index 13cb0a63c697eadd1985cbaa7e8aee40ac7a76a8..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/fugue/treeItem.png and /dev/null differ
diff --git a/themes/jquerymobile/images/fugue/treeItemCurrent.png b/themes/jquerymobile/images/fugue/treeItemCurrent.png
deleted file mode 100644
index 78918c872c4b7062d11cac03e52557fba1dc14b7..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/fugue/treeItemCurrent.png and /dev/null differ
diff --git a/themes/jquerymobile/images/loading.gif b/themes/jquerymobile/images/loading.gif
deleted file mode 100644
index 471c1a4f93f2cabf0b3a85c3ff8e0a8aadefc548..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/loading.gif and /dev/null differ
diff --git a/themes/jquerymobile/images/silk/add.png b/themes/jquerymobile/images/silk/add.png
deleted file mode 100644
index 6332fefea4be19eeadf211b0b202b272e8564898..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/silk/add.png and /dev/null differ
diff --git a/themes/jquerymobile/images/silk/application_add.png b/themes/jquerymobile/images/silk/application_add.png
deleted file mode 100644
index 2e945076cf7686b3b408d6eb2cf913992100da15..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/silk/application_add.png and /dev/null differ
diff --git a/themes/jquerymobile/images/silk/bin.png b/themes/jquerymobile/images/silk/bin.png
deleted file mode 100644
index ebad933c8b3729a9b27dc34c5a111600b8d46fdb..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/silk/bin.png and /dev/null differ
diff --git a/themes/jquerymobile/images/silk/book.png b/themes/jquerymobile/images/silk/book.png
deleted file mode 100644
index b0f4dd7928cc5714e002fd2a6e8f2faac0073f00..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/silk/book.png and /dev/null differ
diff --git a/themes/jquerymobile/images/silk/book_link.png b/themes/jquerymobile/images/silk/book_link.png
deleted file mode 100644
index dd0820e86d0ae7484a9d1fea509ce168ad44699a..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/silk/book_link.png and /dev/null differ
diff --git a/themes/jquerymobile/images/silk/book_open.png b/themes/jquerymobile/images/silk/book_open.png
deleted file mode 100644
index 7d863f949741ff83fd8373a77c0d95a3d95e441f..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/silk/book_open.png and /dev/null differ
diff --git a/themes/jquerymobile/images/silk/box.png b/themes/jquerymobile/images/silk/box.png
deleted file mode 100644
index 8443c23eb944cf8ef49c9d13cd496502f46f1885..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/silk/box.png and /dev/null differ
diff --git a/themes/jquerymobile/images/silk/bullet_green.png b/themes/jquerymobile/images/silk/bullet_green.png
deleted file mode 100644
index 058ad261f520490be9d3fc2e322392fdedfd1cbd..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/silk/bullet_green.png and /dev/null differ
diff --git a/themes/jquerymobile/images/silk/bullet_orange.png b/themes/jquerymobile/images/silk/bullet_orange.png
deleted file mode 100644
index fa63024e55bdde1851f2067dee1a6cad2e9115ea..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/silk/bullet_orange.png and /dev/null differ
diff --git a/themes/jquerymobile/images/silk/bullet_red.png b/themes/jquerymobile/images/silk/bullet_red.png
deleted file mode 100644
index 0cd803115831933aa171497cfe9c1af983035f86..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/silk/bullet_red.png and /dev/null differ
diff --git a/themes/jquerymobile/images/silk/cart.png b/themes/jquerymobile/images/silk/cart.png
deleted file mode 100644
index 1baf7b9fde1195da75a09a4ac8a7cdcc11542c3a..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/silk/cart.png and /dev/null differ
diff --git a/themes/jquerymobile/images/silk/cart_delete.png b/themes/jquerymobile/images/silk/cart_delete.png
deleted file mode 100644
index ac5bce5c8862ff091d89763a9c0ed19a70e639a5..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/silk/cart_delete.png and /dev/null differ
diff --git a/themes/jquerymobile/images/silk/cart_go.png b/themes/jquerymobile/images/silk/cart_go.png
deleted file mode 100644
index 20ee0584f61fbc7a4759ccda9a3d805460bc70c8..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/silk/cart_go.png and /dev/null differ
diff --git a/themes/jquerymobile/images/silk/cart_put.png b/themes/jquerymobile/images/silk/cart_put.png
deleted file mode 100644
index 3aec353e03f6b750e7e5ecce6118a0827df168ae..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/silk/cart_put.png and /dev/null differ
diff --git a/themes/jquerymobile/images/silk/cart_remove.png b/themes/jquerymobile/images/silk/cart_remove.png
deleted file mode 100644
index 360217b526d10a3a39e0acfbc4f4a41bbf986734..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/silk/cart_remove.png and /dev/null differ
diff --git a/themes/jquerymobile/images/silk/cd.png b/themes/jquerymobile/images/silk/cd.png
deleted file mode 100644
index ef4322357cbc34e0b5eeed34f9fdf553a1de2ee7..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/silk/cd.png and /dev/null differ
diff --git a/themes/jquerymobile/images/silk/delete.png b/themes/jquerymobile/images/silk/delete.png
deleted file mode 100644
index 08f249365afd29594b51210c6e21ba253897505d..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/silk/delete.png and /dev/null differ
diff --git a/themes/jquerymobile/images/silk/disk-black.png b/themes/jquerymobile/images/silk/disk-black.png
deleted file mode 100644
index 8d1a21e35d099667a716d90c84c1d7790bf2fe83..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/silk/disk-black.png and /dev/null differ
diff --git a/themes/jquerymobile/images/silk/disk_multiple.png b/themes/jquerymobile/images/silk/disk_multiple.png
deleted file mode 100644
index fc5a52f5e4a7e8eb54bcd59728e88a2db5f046ed..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/silk/disk_multiple.png and /dev/null differ
diff --git a/themes/jquerymobile/images/silk/door_in.png b/themes/jquerymobile/images/silk/door_in.png
deleted file mode 100644
index 41676a0a5be0f026fb136315fafb6c4566522d7a..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/silk/door_in.png and /dev/null differ
diff --git a/themes/jquerymobile/images/silk/door_out.png b/themes/jquerymobile/images/silk/door_out.png
deleted file mode 100644
index 2541d2bcbc218b194f79fd99f67d33de1873c6c4..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/silk/door_out.png and /dev/null differ
diff --git a/themes/jquerymobile/images/silk/dvd.png b/themes/jquerymobile/images/silk/dvd.png
deleted file mode 100644
index 9d94de5df00c518c84b400de7176f15843af7f4b..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/silk/dvd.png and /dev/null differ
diff --git a/themes/jquerymobile/images/silk/edit.png b/themes/jquerymobile/images/silk/edit.png
deleted file mode 100644
index 0bfecd50ee9f5bc5828f0c0745aa3e0effcbe250..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/silk/edit.png and /dev/null differ
diff --git a/themes/jquerymobile/images/silk/email.png b/themes/jquerymobile/images/silk/email.png
deleted file mode 100644
index 7348aed77fe6a64c2210a202f12c6eccae7fcf24..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/silk/email.png and /dev/null differ
diff --git a/themes/jquerymobile/images/silk/error.png b/themes/jquerymobile/images/silk/error.png
deleted file mode 100644
index 628cf2dae3d419ae220c8928ac71393b480745a3..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/silk/error.png and /dev/null differ
diff --git a/themes/jquerymobile/images/silk/feed.png b/themes/jquerymobile/images/silk/feed.png
deleted file mode 100644
index 315c4f4fa62cb720326ba3f54259666ba3999e42..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/silk/feed.png and /dev/null differ
diff --git a/themes/jquerymobile/images/silk/film.png b/themes/jquerymobile/images/silk/film.png
deleted file mode 100644
index b0ce7bb198a3b268bd634d2b26e9b710f3797d37..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/silk/film.png and /dev/null differ
diff --git a/themes/jquerymobile/images/silk/heart.png b/themes/jquerymobile/images/silk/heart.png
deleted file mode 100644
index d9ee53e590a68a95a9fa9483f0ebd14f3f25bb72..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/silk/heart.png and /dev/null differ
diff --git a/themes/jquerymobile/images/silk/help.png b/themes/jquerymobile/images/silk/help.png
deleted file mode 100644
index 5c870176d4dea68aab9e51166cc3d7a582f326d6..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/silk/help.png and /dev/null differ
diff --git a/themes/jquerymobile/images/silk/house.png b/themes/jquerymobile/images/silk/house.png
deleted file mode 100644
index fed62219f57cdfb854782dbadf5123c44d056bd4..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/silk/house.png and /dev/null differ
diff --git a/themes/jquerymobile/images/silk/list.png b/themes/jquerymobile/images/silk/list.png
deleted file mode 100644
index 244e6ca045c50a130086ac388b560a12761544b4..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/silk/list.png and /dev/null differ
diff --git a/themes/jquerymobile/images/silk/map.png b/themes/jquerymobile/images/silk/map.png
deleted file mode 100644
index f90ef25ec7f1cb0fdae38d9fe2d9edeee9928ef1..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/silk/map.png and /dev/null differ
diff --git a/themes/jquerymobile/images/silk/music.png b/themes/jquerymobile/images/silk/music.png
deleted file mode 100644
index a8b3ede3df956f8d505543b190bc8d1b5b4dce75..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/silk/music.png and /dev/null differ
diff --git a/themes/jquerymobile/images/silk/newspaper.png b/themes/jquerymobile/images/silk/newspaper.png
deleted file mode 100644
index 6a2ecce1b85eaa9084b427ee2c5226e2296eaeb8..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/silk/newspaper.png and /dev/null differ
diff --git a/themes/jquerymobile/images/silk/package.png b/themes/jquerymobile/images/silk/package.png
deleted file mode 100644
index da3c2a2d74bab159ba0f65d7db601768258afcb2..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/silk/package.png and /dev/null differ
diff --git a/themes/jquerymobile/images/silk/phone.png b/themes/jquerymobile/images/silk/phone.png
deleted file mode 100644
index c39f162f854a7c412fab9b6ff38fffdc61754a58..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/silk/phone.png and /dev/null differ
diff --git a/themes/jquerymobile/images/silk/photo.png b/themes/jquerymobile/images/silk/photo.png
deleted file mode 100644
index 6c2aaaaaf33ec07184ae0f5824ef24c82c41106f..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/silk/photo.png and /dev/null differ
diff --git a/themes/jquerymobile/images/silk/picture.png b/themes/jquerymobile/images/silk/picture.png
deleted file mode 100644
index 4a158fef7e0da8fd19525f574f2c4966443866cf..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/silk/picture.png and /dev/null differ
diff --git a/themes/jquerymobile/images/silk/printer.png b/themes/jquerymobile/images/silk/printer.png
deleted file mode 100644
index a350d1871536eb28fe2949936de1c79c1c26269d..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/silk/printer.png and /dev/null differ
diff --git a/themes/jquerymobile/images/silk/readme.txt b/themes/jquerymobile/images/silk/readme.txt
deleted file mode 100644
index 2cf67dcaff69312455f374df0901fa912c451a13..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/images/silk/readme.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-Silk icon set 1.3
-
-_________________________________________
-Mark James
-http://www.famfamfam.com/lab/icons/silk/
-_________________________________________
-
-This work is licensed under a
-Creative Commons Attribution 2.5 License.
-[ http://creativecommons.org/licenses/by/2.5/ ]
-
-This means you may use it for any purpose,
-and make any changes you like.
-All I ask is that you include a link back
-to this page in your credits.
-
-Are you using this icon set? Send me an email
-(including a link or picture if available) to
-mjames@gmail.com
-
-Any other questions about this icon set please
-contact mjames@gmail.com
\ No newline at end of file
diff --git a/themes/jquerymobile/images/silk/report.png b/themes/jquerymobile/images/silk/report.png
deleted file mode 100644
index 779ad58efc5776825ef81064a042eceba274a928..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/silk/report.png and /dev/null differ
diff --git a/themes/jquerymobile/images/silk/report_edit.png b/themes/jquerymobile/images/silk/report_edit.png
deleted file mode 100644
index c61a6d847795a2c6c9f0d8e6c69d3f72cec5e77d..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/silk/report_edit.png and /dev/null differ
diff --git a/themes/jquerymobile/images/silk/report_picture.png b/themes/jquerymobile/images/silk/report_picture.png
deleted file mode 100644
index 3a9a7e5eb91319a532f1c796740c70692b8335eb..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/silk/report_picture.png and /dev/null differ
diff --git a/themes/jquerymobile/images/silk/script.png b/themes/jquerymobile/images/silk/script.png
deleted file mode 100644
index 0f9ed4d48301ffdce04cdb17dbf8acbad8372d11..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/silk/script.png and /dev/null differ
diff --git a/themes/jquerymobile/images/silk/script_edit.png b/themes/jquerymobile/images/silk/script_edit.png
deleted file mode 100644
index b4d31ce282f378e5b94cd40680d283842229e491..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/silk/script_edit.png and /dev/null differ
diff --git a/themes/jquerymobile/images/silk/sound.png b/themes/jquerymobile/images/silk/sound.png
deleted file mode 100644
index 6056d234a9818d248987389d4a621e5c83ce0851..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/silk/sound.png and /dev/null differ
diff --git a/themes/jquerymobile/images/silk/tag_blue.png b/themes/jquerymobile/images/silk/tag_blue.png
deleted file mode 100644
index 9757fc6ed6597438eb8e5a70a1ab2402cdebd5d1..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/silk/tag_blue.png and /dev/null differ
diff --git a/themes/jquerymobile/images/silk/tag_yellow.png b/themes/jquerymobile/images/silk/tag_yellow.png
deleted file mode 100644
index 83d12924ff3847904f13ce02fe7d96ee1a6012c7..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/silk/tag_yellow.png and /dev/null differ
diff --git a/themes/jquerymobile/images/silk/user.png b/themes/jquerymobile/images/silk/user.png
deleted file mode 100644
index 79f35ccbdad44489dbf07d1bf688c411aa3b612c..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/silk/user.png and /dev/null differ
diff --git a/themes/jquerymobile/images/silk/user_add.png b/themes/jquerymobile/images/silk/user_add.png
deleted file mode 100644
index deae99bcff9815d8530a920e754d743700ddd5fb..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/silk/user_add.png and /dev/null differ
diff --git a/themes/jquerymobile/images/silk/user_comment.png b/themes/jquerymobile/images/silk/user_comment.png
deleted file mode 100644
index e54ebebafb5072fabac9a0f3d8a79fcee3265f9f..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/silk/user_comment.png and /dev/null differ
diff --git a/themes/jquerymobile/images/silk/user_delete.png b/themes/jquerymobile/images/silk/user_delete.png
deleted file mode 100644
index acbb5630e51a12a1cd30ea799d659b309e7041cd..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/silk/user_delete.png and /dev/null differ
diff --git a/themes/jquerymobile/images/silk/user_edit.png b/themes/jquerymobile/images/silk/user_edit.png
deleted file mode 100644
index c1974cda745278a404b9e29fa91e0503a84accb1..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/silk/user_edit.png and /dev/null differ
diff --git a/themes/jquerymobile/images/silk/user_gray.png b/themes/jquerymobile/images/silk/user_gray.png
deleted file mode 100644
index 8fd539e9cb04111e950ac9b0cce82676f12f67d4..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/silk/user_gray.png and /dev/null differ
diff --git a/themes/jquerymobile/images/silk/user_green.png b/themes/jquerymobile/images/silk/user_green.png
deleted file mode 100644
index 30383c2de517fd22945a87b0528d2821ec4d49ce..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/silk/user_green.png and /dev/null differ
diff --git a/themes/jquerymobile/images/silk/user_orange.png b/themes/jquerymobile/images/silk/user_orange.png
deleted file mode 100644
index b818127df6d064b71838c377063c2c61517ffa01..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/silk/user_orange.png and /dev/null differ
diff --git a/themes/jquerymobile/images/silk/user_red.png b/themes/jquerymobile/images/silk/user_red.png
deleted file mode 100644
index c6f66e8b300750826b214e38e7cf3365fa637878..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/silk/user_red.png and /dev/null differ
diff --git a/themes/jquerymobile/images/silk/user_suit.png b/themes/jquerymobile/images/silk/user_suit.png
deleted file mode 100644
index b3454e15fb60fe8704a574b0ac35c4d0c902d738..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/silk/user_suit.png and /dev/null differ
diff --git a/themes/jquerymobile/images/silk/world.png b/themes/jquerymobile/images/silk/world.png
deleted file mode 100644
index 68f21d30116710e48a8bf462cb32441e51fad5f6..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/silk/world.png and /dev/null differ
diff --git a/themes/jquerymobile/images/tango/audio-volume-high.png b/themes/jquerymobile/images/tango/audio-volume-high.png
deleted file mode 100644
index ec8f00b4ad0c6138d17957a9ba6d8616bb39a6a7..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/tango/audio-volume-high.png and /dev/null differ
diff --git a/themes/jquerymobile/images/tango/bookmark_add.png b/themes/jquerymobile/images/tango/bookmark_add.png
deleted file mode 100644
index 6cf6443a296cd908ac3e6dba8861b3955a919e20..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/tango/bookmark_add.png and /dev/null differ
diff --git a/themes/jquerymobile/images/tango/email.png b/themes/jquerymobile/images/tango/email.png
deleted file mode 100644
index 859251fe0fcdbdf20de5040a802825ce977c1a24..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/tango/email.png and /dev/null differ
diff --git a/themes/jquerymobile/images/tango/film.png b/themes/jquerymobile/images/tango/film.png
deleted file mode 100644
index 4a71b1d66e152a7a07932ffeda2986d25dd596fe..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/tango/film.png and /dev/null differ
diff --git a/themes/jquerymobile/images/tango/find.png b/themes/jquerymobile/images/tango/find.png
deleted file mode 100644
index d072d3cbe2dadb1494f77e950952123813613677..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/tango/find.png and /dev/null differ
diff --git a/themes/jquerymobile/images/tango/gnome-help.png b/themes/jquerymobile/images/tango/gnome-help.png
deleted file mode 100644
index f25fc3fbf106af60de59581bf2e6fba58d489bf8..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/tango/gnome-help.png and /dev/null differ
diff --git a/themes/jquerymobile/images/tango/video.png b/themes/jquerymobile/images/tango/video.png
deleted file mode 100644
index 5dacbb231ad6e13b216c398c8383b80b51fd92e7..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/tango/video.png and /dev/null differ
diff --git a/themes/jquerymobile/images/tango/www.png b/themes/jquerymobile/images/tango/www.png
deleted file mode 100644
index 53014ab153f17a68c5b107a7b0f1d153d956afbb..0000000000000000000000000000000000000000
Binary files a/themes/jquerymobile/images/tango/www.png and /dev/null differ
diff --git a/themes/jquerymobile/js/.htaccess b/themes/jquerymobile/js/.htaccess
deleted file mode 100644
index a00c90e011ab940bae2c5bf8c9bff11b583787c4..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/js/.htaccess
+++ /dev/null
@@ -1,6 +0,0 @@
-<IfModule mod_rewrite.c>
-  RewriteEngine Off
-</IfModule>
-
-RemoveType .js
-AddType text/javascript .js
\ No newline at end of file
diff --git a/themes/jquerymobile/js/check_item_statuses.js b/themes/jquerymobile/js/check_item_statuses.js
deleted file mode 100644
index 158e94419bbbeae6a61b82a6a7330fedc5757cc9..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/js/check_item_statuses.js
+++ /dev/null
@@ -1,61 +0,0 @@
-/*global path*/
-function linkCallnumbers(callnumber, callnumber_handler) {
-  if (callnumber_handler) {
-    var cns = callnumber.split(',\t');
-    for (var i = 0; i < cns.length; i++) {
-      cns[i] = '<a href="' + path + '/Alphabrowse/Home?source=' + encodeURI(callnumber_handler) + '&amp;from=' + encodeURI(cns[i]) + '">' + cns[i] + '</a>';
-    }
-    return cns.join(',\t');
-  }
-  return callnumber;
-}
-
-function checkItemStatuses() {
-    var id = $.map($('.ajaxItemId'), function(i) {
-        return $(i).find('.hiddenId')[0].value;
-    });
-    if (id.length) {
-        $(".ajax_availability").show();
-        $.post(
-            path + '/AJAX/JSON?method=getItemStatuses',
-            {id:id},
-            function(response) {
-                if (response.status == 'OK') {
-                    $.each(response.data, function(i, result) {
-                        var item = $($('.ajaxItemId')[result.record_number]);
-
-                        item.find('.status').empty().append(result.availability_message);
-                        if (typeof(result.missing_data) != 'undefined'
-                            && result.missing_data
-                        ) {
-                            // No data is available -- hide the entire status area:
-                            item.find('.callnumAndLocation').hide();
-                            item.find('.status').hide();
-                        } else if (result.locationList) {
-                            // Not supported in this theme:
-                            item.find('.callnumAndLocation').hide();
-                            item.find('.status').hide();
-                        } else {
-                            // Default case -- load call number and location into appropriate containers:
-                            item.find('.callnumber').empty().append(linkCallnumbers(result.callnumber, result.callnumber_handler));
-                            item.find('.location').empty().append(
-                                result.reserve == 'true'
-                                ? result.reserve_message
-                                : result.location
-                            );
-                        }
-                    });
-                } else {
-                    // display the error message on each of the ajax status place holder
-                    $(".ajax_availability").empty().append(response.data);
-                }
-                $(".ajax_availability").removeClass('ajax_availability');
-            },
-            'json'
-        );
-    }
-}
-
-$('.results-page').live('pageshow', function() {
-    checkItemStatuses();
-});
diff --git a/themes/jquerymobile/js/common.js b/themes/jquerymobile/js/common.js
deleted file mode 100644
index 10e6f964be2da44ba02bb93be7f036956814513f..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/js/common.js
+++ /dev/null
@@ -1,34 +0,0 @@
-//$.ajaxSetup({cache: false});
-
-$(document).bind('mobileinit', function(){
-    $.mobile.selectmenu.prototype.options.nativeMenu = false;
-});
-
-$('[data-role="page"]').live('pageshow',function() {
-    var url = location.hash;
-    if (url.length > 0) {
-        url = url.substr(1);
-    } else {
-        url = location.href;
-    }
-    // update the language form action URL
-    $('#langForm').attr('action', url);
-    
-    // update the "Go to Standard View" href
-    var match = url.match(/([&?]?ui=[^&]+)/);
-    if (match) {
-        var replace = ((match[1].indexOf('?') != -1) ? '?' : '&') + 'ui=standard';
-        url = url.replace(match[1], replace);
-    } else {
-        url += ((url.indexOf('?') == -1) ? '?' : '&') + 'ui=standard';
-    }
-    url = url.replace('&ui-state=dialog', '');
-    $('a.standard-view').each(function() {
-        $(this).attr('href', url); 
-    });
-});
-
-// mostly lifted from http://docs.jquery.com/Frequently_Asked_Questions#How_do_I_select_an_element_by_an_ID_that_has_characters_used_in_CSS_notation.3F
-function jqEscape(myid) {
-    return String(myid).replace(/(:|\.)/g,'\\$1');
-}
diff --git a/themes/jquerymobile/js/hold.js b/themes/jquerymobile/js/hold.js
deleted file mode 100644
index 4b2baeedb5eda5ffe50acdbe808fcf6f61092c7b..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/js/hold.js
+++ /dev/null
@@ -1,45 +0,0 @@
-/*global path */
-function setUpHoldRequestForm(recordId) {
-  $('#requestGroupId').change(function() {
-    var $emptyOption = $("#pickUpLocation option[value='']");
-    $("#pickUpLocation option[value!='']").remove();
-    try {
-        $("#pickUpLocation").selectmenu("refresh", true);
-    } catch (e) {}
-    if ($('#requestGroupId').val() === '') {
-        return;
-    }
-    $('#pickUpLocationLabel').addClass("ajax_hold_request_loading");
-    var params = {
-      method: 'getRequestGroupPickupLocations',
-      id: recordId,
-      requestGroupId: $('#requestGroupId').val()
-    };
-    $.ajax({
-      data: params,
-      dataType: 'json',
-      cache: false,
-      url: path + '/AJAX/JSON',
-      success: function(response) {
-        if (response.status == 'OK') {
-          var defaultValue = $('#pickUpLocation').data('default');
-          $.each(response.data.locations, function() {
-            var option = $('<option></option>').attr('value', this.locationID).text(this.locationDisplay);
-            if (this.locationID == defaultValue || (defaultValue == '' && this.isDefault && $emptyOption.length == 0)) {
-              option.attr('selected', 'selected');
-            }
-            $('#pickUpLocation').append(option);
-          });
-          try {
-              $("#pickUpLocation").selectmenu("refresh", true);
-          } catch (e) {}
-        }
-        $('#pickUpLocationLabel').removeClass("ajax_hold_request_loading");
-      },
-      fail: function() {
-        $('#pickUpLocationLabel').removeClass("ajax_hold_request_loading");
-      }
-    });
-  });
-  $('#requestGroupId').change();
-}
diff --git a/themes/jquerymobile/js/jquery-1.6.4.min.js b/themes/jquerymobile/js/jquery-1.6.4.min.js
deleted file mode 100644
index 628ed9b31604ed868f70c7a593441cfcdced1723..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/js/jquery-1.6.4.min.js
+++ /dev/null
@@ -1,4 +0,0 @@
-/*! jQuery v1.6.4 http://jquery.com/ | http://jquery.org/license */
-(function(a,b){function cu(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cr(a){if(!cg[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){ch||(ch=c.createElement("iframe"),ch.frameBorder=ch.width=ch.height=0),b.appendChild(ch);if(!ci||!ch.createElement)ci=(ch.contentWindow||ch.contentDocument).document,ci.write((c.compatMode==="CSS1Compat"?"<!doctype html>":"")+"<html><body>"),ci.close();d=ci.createElement(a),ci.body.appendChild(d),e=f.css(d,"display"),b.removeChild(ch)}cg[a]=e}return cg[a]}function cq(a,b){var c={};f.each(cm.concat.apply([],cm.slice(0,b)),function(){c[this]=a});return c}function cp(){cn=b}function co(){setTimeout(cp,0);return cn=f.now()}function cf(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ce(){try{return new a.XMLHttpRequest}catch(b){}}function b$(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g<i;g++){if(g===1)for(h in a.converters)typeof h=="string"&&(e[h.toLowerCase()]=a.converters[h]);l=k,k=d[g];if(k==="*")k=l;else if(l!=="*"&&l!==k){m=l+" "+k,n=e[m]||e["* "+k];if(!n){p=b;for(o in e){j=o.split(" ");if(j[0]===l||j[0]==="*"){p=e[j[1]+" "+k];if(p){o=e[o],o===!0?n=p:p===!0&&(n=o);break}}}}!n&&!p&&f.error("No conversion from "+m.replace(" "," to ")),n!==!0&&(c=n?n(c):p(o(c)))}}return c}function bZ(a,c,d){var e=a.contents,f=a.dataTypes,g=a.responseFields,h,i,j,k;for(i in g)i in d&&(c[g[i]]=d[i]);while(f[0]==="*")f.shift(),h===b&&(h=a.mimeType||c.getResponseHeader("content-type"));if(h)for(i in e)if(e[i]&&e[i].test(h)){f.unshift(i);break}if(f[0]in d)j=f[0];else{for(i in d){if(!f[0]||a.converters[i+" "+f[0]]){j=i;break}k||(k=i)}j=j||k}if(j){j!==f[0]&&f.unshift(j);return d[j]}}function bY(a,b,c,d){if(f.isArray(b))f.each(b,function(b,e){c||bA.test(a)?d(a,e):bY(a+"["+(typeof e=="object"||f.isArray(e)?b:"")+"]",e,c,d)});else if(!c&&b!=null&&typeof b=="object")for(var e in b)bY(a+"["+e+"]",b[e],c,d);else d(a,b)}function bX(a,c){var d,e,g=f.ajaxSettings.flatOptions||{};for(d in c)c[d]!==b&&((g[d]?a:e||(e={}))[d]=c[d]);e&&f.extend(!0,a,e)}function bW(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h=a[f],i=0,j=h?h.length:0,k=a===bP,l;for(;i<j&&(k||!l);i++)l=h[i](c,d,e),typeof l=="string"&&(!k||g[l]?l=b:(c.dataTypes.unshift(l),l=bW(a,c,d,e,l,g)));(k||!l)&&!g["*"]&&(l=bW(a,c,d,e,"*",g));return l}function bV(a){return function(b,c){typeof b!="string"&&(c=b,b="*");if(f.isFunction(c)){var d=b.toLowerCase().split(bL),e=0,g=d.length,h,i,j;for(;e<g;e++)h=d[e],j=/^\+/.test(h),j&&(h=h.substr(1)||"*"),i=a[h]=a[h]||[],i[j?"unshift":"push"](c)}}}function by(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=b==="width"?bt:bu;if(d>0){c!=="border"&&f.each(e,function(){c||(d-=parseFloat(f.css(a,"padding"+this))||0),c==="margin"?d+=parseFloat(f.css(a,c+this))||0:d-=parseFloat(f.css(a,"border"+this+"Width"))||0});return d+"px"}d=bv(a,b,b);if(d<0||d==null)d=a.style[b]||0;d=parseFloat(d)||0,c&&f.each(e,function(){d+=parseFloat(f.css(a,"padding"+this))||0,c!=="padding"&&(d+=parseFloat(f.css(a,"border"+this+"Width"))||0),c==="margin"&&(d+=parseFloat(f.css(a,c+this))||0)});return d+"px"}function bl(a,b){b.src?f.ajax({url:b.src,async:!1,dataType:"script"}):f.globalEval((b.text||b.textContent||b.innerHTML||"").replace(bd,"/*$0*/")),b.parentNode&&b.parentNode.removeChild(b)}function bk(a){f.nodeName(a,"input")?bj(a):"getElementsByTagName"in a&&f.grep(a.getElementsByTagName("input"),bj)}function bj(a){if(a.type==="checkbox"||a.type==="radio")a.defaultChecked=a.checked}function bi(a){return"getElementsByTagName"in a?a.getElementsByTagName("*"):"querySelectorAll"in a?a.querySelectorAll("*"):[]}function bh(a,b){var c;if(b.nodeType===1){b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase();if(c==="object")b.outerHTML=a.outerHTML;else if(c!=="input"||a.type!=="checkbox"&&a.type!=="radio"){if(c==="option")b.selected=a.defaultSelected;else if(c==="input"||c==="textarea")b.defaultValue=a.defaultValue}else a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value);b.removeAttribute(f.expando)}}function bg(a,b){if(b.nodeType===1&&!!f.hasData(a)){var c=f.expando,d=f.data(a),e=f.data(b,d);if(d=d[c]){var g=d.events;e=e[c]=f.extend({},d);if(g){delete e.handle,e.events={};for(var h in g)for(var i=0,j=g[h].length;i<j;i++)f.event.add(b,h+(g[h][i].namespace?".":"")+g[h][i].namespace,g[h][i],g[h][i].data)}}}}function bf(a,b){return f.nodeName(a,"table")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function V(a,b,c){b=b||0;if(f.isFunction(b))return f.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return f.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=f.grep(a,function(a){return a.nodeType===1});if(Q.test(b))return f.filter(b,d,!c);b=f.filter(b,d)}return f.grep(a,function(a,d){return f.inArray(a,b)>=0===c})}function U(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function M(a,b){return(a&&a!=="*"?a+".":"")+b.replace(y,"`").replace(z,"&")}function L(a){var b,c,d,e,g,h,i,j,k,l,m,n,o,p=[],q=[],r=f._data(this,"events");if(!(a.liveFired===this||!r||!r.live||a.target.disabled||a.button&&a.type==="click")){a.namespace&&(n=new RegExp("(^|\\.)"+a.namespace.split(".").join("\\.(?:.*\\.)?")+"(\\.|$)")),a.liveFired=this;var s=r.live.slice(0);for(i=0;i<s.length;i++)g=s[i],g.origType.replace(w,"")===a.type?q.push(g.selector):s.splice(i--,1);e=f(a.target).closest(q,a.currentTarget);for(j=0,k=e.length;j<k;j++){m=e[j];for(i=0;i<s.length;i++){g=s[i];if(m.selector===g.selector&&(!n||n.test(g.namespace))&&!m.elem.disabled){h=m.elem,d=null;if(g.preType==="mouseenter"||g.preType==="mouseleave")a.type=g.preType,d=f(a.relatedTarget).closest(g.selector)[0],d&&f.contains(h,d)&&(d=h);(!d||d!==h)&&p.push({elem:h,handleObj:g,level:m.level})}}}for(j=0,k=p.length;j<k;j++){e=p[j];if(c&&e.level>c)break;a.currentTarget=e.elem,a.data=e.handleObj.data,a.handleObj=e.handleObj,o=e.handleObj.origHandler.apply(e.elem,arguments);if(o===!1||a.isPropagationStopped()){c=e.level,o===!1&&(b=!1);if(a.isImmediatePropagationStopped())break}}return b}}function J(a,c,d){var e=f.extend({},d[0]);e.type=a,e.originalEvent={},e.liveFired=b,f.event.handle.call(c,e),e.isDefaultPrevented()&&d[0].preventDefault()}function D(){return!0}function C(){return!1}function m(a,c,d){var e=c+"defer",g=c+"queue",h=c+"mark",i=f.data(a,e,b,!0);i&&(d==="queue"||!f.data(a,g,b,!0))&&(d==="mark"||!f.data(a,h,b,!0))&&setTimeout(function(){!f.data(a,g,b,!0)&&!f.data(a,h,b,!0)&&(f.removeData(a,e,!0),i.resolve())},0)}function l(a){for(var b in a)if(b!=="toJSON")return!1;return!0}function k(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(j,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNaN(d)?i.test(d)?f.parseJSON(d):d:parseFloat(d)}catch(g){}f.data(a,c,d)}else d=b}return d}var c=a.document,d=a.navigator,e=a.location,f=function(){function K(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(K,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/\d/,n=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,o=/^[\],:{}\s]*$/,p=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,q=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,r=/(?:^|:|,)(?:\s*\[)+/g,s=/(webkit)[ \/]([\w.]+)/,t=/(opera)(?:.*version)?[ \/]([\w.]+)/,u=/(msie) ([\w.]+)/,v=/(mozilla)(?:.*? rv:([\w.]+))?/,w=/-([a-z]|[0-9])/ig,x=/^-ms-/,y=function(a,b){return(b+"").toUpperCase()},z=d.userAgent,A,B,C,D=Object.prototype.toString,E=Object.prototype.hasOwnProperty,F=Array.prototype.push,G=Array.prototype.slice,H=String.prototype.trim,I=Array.prototype.indexOf,J={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=n.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.6.4",length:0,size:function(){return this.length},toArray:function(){return G.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?F.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),B.done(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(G.apply(this,arguments),"slice",G.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:F,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j<k;j++)if((a=arguments[j])!=null)for(c in a){d=i[c],f=a[c];if(i===f)continue;l&&f&&(e.isPlainObject(f)||(g=e.isArray(f)))?(g?(g=!1,h=d&&e.isArray(d)?d:[]):h=d&&e.isPlainObject(d)?d:{},i[c]=e.extend(l,h,f)):f!==b&&(i[c]=f)}return i},e.extend({noConflict:function(b){a.$===e&&(a.$=g),b&&a.jQuery===e&&(a.jQuery=f);return e},isReady:!1,readyWait:1,holdReady:function(a){a?e.readyWait++:e.ready(!0)},ready:function(a){if(a===!0&&!--e.readyWait||a!==!0&&!e.isReady){if(!c.body)return setTimeout(e.ready,1);e.isReady=!0;if(a!==!0&&--e.readyWait>0)return;B.resolveWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").unbind("ready")}},bindReady:function(){if(!B){B=e._Deferred();if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",C,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",C),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&K()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a&&typeof a=="object"&&"setInterval"in a},isNaN:function(a){return a==null||!m.test(a)||isNaN(a)},type:function(a){return a==null?String(a):J[D.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!E.call(a,"constructor")&&!E.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||E.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw a},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(o.test(b.replace(p,"@").replace(q,"]").replace(r,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(x,"ms-").replace(w,y)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g<h;)if(c.apply(a[g++],d)===!1)break}else if(i){for(f in a)if(c.call(a[f],f,a[f])===!1)break}else for(;g<h;)if(c.call(a[g],g,a[g++])===!1)break;return a},trim:H?function(a){return a==null?"":H.call(a)}:function(a){return a==null?"":(a+"").replace(k,"").replace(l,"")},makeArray:function(a,b){var c=b||[];if(a!=null){var d=e.type(a);a.length==null||d==="string"||d==="function"||d==="regexp"||e.isWindow(a)?F.call(c,a):e.merge(c,a)}return c},inArray:function(a,b){if(!b)return-1;if(I)return I.call(b,a);for(var c=0,d=b.length;c<d;c++)if(b[c]===a)return c;return-1},merge:function(a,c){var d=a.length,e=0;if(typeof c.length=="number")for(var f=c.length;e<f;e++)a[d++]=c[e];else while(c[e]!==b)a[d++]=c[e++];a.length=d;return a},grep:function(a,b,c){var d=[],e;c=!!c;for(var f=0,g=a.length;f<g;f++)e=!!b(a[f],f),c!==e&&d.push(a[f]);return d},map:function(a,c,d){var f,g,h=[],i=0,j=a.length,k=a instanceof e||j!==b&&typeof j=="number"&&(j>0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i<j;i++)f=c(a[i],i,d),f!=null&&(h[h.length]=f);else for(g in a)f=c(a[g],g,d),f!=null&&(h[h.length]=f);return h.concat.apply([],h)},guid:1,proxy:function(a,c){if(typeof c=="string"){var d=a[c];c=a,a=d}if(!e.isFunction(a))return b;var f=G.call(arguments,2),g=function(){return a.apply(c,f.concat(G.call(arguments)))};g.guid=a.guid=a.guid||g.guid||e.guid++;return g},access:function(a,c,d,f,g,h){var i=a.length;if(typeof c=="object"){for(var j in c)e.access(a,j,c[j],f,g,d);return a}if(d!==b){f=!h&&f&&e.isFunction(d);for(var k=0;k<i;k++)g(a[k],c,f?d.call(a[k],k,g(a[k],c)):d,h);return a}return i?g(a[0],c):b},now:function(){return(new Date).getTime()},uaMatch:function(a){a=a.toLowerCase();var b=s.exec(a)||t.exec(a)||u.exec(a)||a.indexOf("compatible")<0&&v.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},sub:function(){function a(b,c){return new a.fn.init(b,c)}e.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function(d,f){f&&f instanceof e&&!(f instanceof a)&&(f=a(f));return e.fn.init.call(this,d,f,b)},a.fn.init.prototype=a.fn;var b=a(c);return a},browser:{}}),e.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){J["[object "+b+"]"]=b.toLowerCase()}),A=e.uaMatch(z),A.browser&&(e.browser[A.browser]=!0,e.browser.version=A.version),e.browser.webkit&&(e.browser.safari=!0),j.test(" ")&&(k=/^[\s\xA0]+/,l=/[\s\xA0]+$/),h=e(c),c.addEventListener?C=function(){c.removeEventListener("DOMContentLoaded",C,!1),e.ready()}:c.attachEvent&&(C=function(){c.readyState==="complete"&&(c.detachEvent("onreadystatechange",C),e.ready())});return e}(),g="done fail isResolved isRejected promise then always pipe".split(" "),h=[].slice;f.extend({_Deferred:function(){var a=[],b,c,d,e={done:function(){if(!d){var c=arguments,g,h,i,j,k;b&&(k=b,b=0);for(g=0,h=c.length;g<h;g++)i=c[g],j=f.type(i),j==="array"?e.done.apply(e,i):j==="function"&&a.push(i);k&&e.resolveWith(k[0],k[1])}return this},resolveWith:function(e,f){if(!d&&!b&&!c){f=f||[],c=1;try{while(a[0])a.shift().apply(e,f)}finally{b=[e,f],c=0}}return this},resolve:function(){e.resolveWith(this,arguments);return this},isResolved:function(){return!!c||!!b},cancel:function(){d=1,a=[];return this}};return e},Deferred:function(a){var b=f._Deferred(),c=f._Deferred(),d;f.extend(b,{then:function(a,c){b.done(a).fail(c);return this},always:function(){return b.done.apply(b,arguments).fail.apply(this,arguments)},fail:c.done,rejectWith:c.resolveWith,reject:c.resolve,isRejected:c.isResolved,pipe:function(a,c){return f.Deferred(function(d){f.each({done:[a,"resolve"],fail:[c,"reject"]},function(a,c){var e=c[0],g=c[1],h;f.isFunction(e)?b[a](function(){h=e.apply(this,arguments),h&&f.isFunction(h.promise)?h.promise().then(d.resolve,d.reject):d[g+"With"](this===b?d:this,[h])}):b[a](d[g])})}).promise()},promise:function(a){if(a==null){if(d)return d;d=a={}}var c=g.length;while(c--)a[g[c]]=b[g[c]];return a}}),b.done(c.cancel).fail(b.cancel),delete b.cancel,a&&a.call(b,b);return b},when:function(a){function i(a){return function(c){b[a]=arguments.length>1?h.call(arguments,0):c,--e||g.resolveWith(g,h.call(b,0))}}var b=arguments,c=0,d=b.length,e=d,g=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred();if(d>1){for(;c<d;c++)b[c]&&f.isFunction(b[c].promise)?b[c].promise().then(i(c),g.reject):--e;e||g.resolveWith(g,b)}else g!==a&&g.resolveWith(g,d?[a]:[]);return g.promise()}}),f.support=function(){var a=c.createElement("div"),b=c.documentElement,d,e,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u;a.setAttribute("className","t"),a.innerHTML="   <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>",d=a.getElementsByTagName("*"),e=a.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=a.getElementsByTagName("input")[0],k={leadingWhitespace:a.firstChild.nodeType===3,tbody:!a.getElementsByTagName("tbody").length,htmlSerialize:!!a.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55$/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:a.className!=="t",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},i.checked=!0,k.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,k.optDisabled=!h.disabled;try{delete a.test}catch(v){k.deleteExpando=!1}!a.addEventListener&&a.attachEvent&&a.fireEvent&&(a.attachEvent("onclick",function(){k.noCloneEvent=!1}),a.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),k.radioValue=i.value==="t",i.setAttribute("checked","checked"),a.appendChild(i),l=c.createDocumentFragment(),l.appendChild(a.firstChild),k.checkClone=l.cloneNode(!0).cloneNode(!0).lastChild.checked,a.innerHTML="",a.style.width=a.style.paddingLeft="1px",m=c.getElementsByTagName("body")[0],o=c.createElement(m?"div":"body"),p={visibility:"hidden",width:0,height:0,border:0,margin:0,background:"none"},m&&f.extend(p,{position:"absolute",left:"-1000px",top:"-1000px"});for(t in p)o.style[t]=p[t];o.appendChild(a),n=m||b,n.insertBefore(o,n.firstChild),k.appendChecked=i.checked,k.boxModel=a.offsetWidth===2,"zoom"in a.style&&(a.style.display="inline",a.style.zoom=1,k.inlineBlockNeedsLayout=a.offsetWidth===2,a.style.display="",a.innerHTML="<div style='width:4px;'></div>",k.shrinkWrapBlocks=a.offsetWidth!==2),a.innerHTML="<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>",q=a.getElementsByTagName("td"),u=q[0].offsetHeight===0,q[0].style.display="",q[1].style.display="none",k.reliableHiddenOffsets=u&&q[0].offsetHeight===0,a.innerHTML="",c.defaultView&&c.defaultView.getComputedStyle&&(j=c.createElement("div"),j.style.width="0",j.style.marginRight="0",a.appendChild(j),k.reliableMarginRight=(parseInt((c.defaultView.getComputedStyle(j,null)||{marginRight:0}).marginRight,10)||0)===0),o.innerHTML="",n.removeChild(o);if(a.attachEvent)for(t in{submit:1,change:1,focusin:1})s="on"+t,u=s in a,u||(a.setAttribute(s,"return;"),u=typeof a[s]=="function"),k[t+"Bubbles"]=u;o=l=g=h=m=j=a=i=null;return k}(),f.boxModel=f.support.boxModel;var i=/^(?:\{.*\}|\[.*\])$/,j=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!l(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i=f.expando,j=typeof c=="string",k=a.nodeType,l=k?f.cache:a,m=k?a[f.expando]:a[f.expando]&&f.expando;if((!m||e&&m&&l[m]&&!l[m][i])&&j&&d===b)return;m||(k?a[f.expando]=m=++f.uuid:m=f.expando),l[m]||(l[m]={},k||(l[m].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?l[m][i]=f.extend(l[m][i],c):l[m]=f.extend(l[m],c);g=l[m],e&&(g[i]||(g[i]={}),g=g[i]),d!==b&&(g[f.camelCase(c)]=d);if(c==="events"&&!g[c])return g[i]&&g[i].events;j?(h=g[c],h==null&&(h=g[f.camelCase(c)])):h=g;return h}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e=f.expando,g=a.nodeType,h=g?f.cache:a,i=g?a[f.expando]:f.expando;if(!h[i])return;if(b){d=c?h[i][e]:h[i];if(d){d[b]||(b=f.camelCase(b)),delete d[b];if(!l(d))return}}if(c){delete h[i][e];if(!l(h[i]))return}var j=h[i][e];f.support.deleteExpando||!h.setInterval?delete h[i]:h[i]=null,j?(h[i]={},g||(h[i].toJSON=f.noop),h[i][e]=j):g&&(f.support.deleteExpando?delete a[f.expando]:a.removeAttribute?a.removeAttribute(f.expando):a[f.expando]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d=null;if(typeof a=="undefined"){if(this.length){d=f.data(this[0]);if(this[0].nodeType===1){var e=this[0].attributes,g;for(var h=0,i=e.length;h<i;h++)g=e[h].name,g.indexOf("data-")===0&&(g=f.camelCase(g.substring(5)),k(this[0],g,d[g]))}}return d}if(typeof a=="object")return this.each(function(){f.data(this,a)});var j=a.split(".");j[1]=j[1]?"."+j[1]:"";if(c===b){d=this.triggerHandler("getData"+j[1]+"!",[j[0]]),d===b&&this.length&&(d=f.data(this[0],a),d=k(this[0],a,d));return d===b&&j[1]?this.data(j[0]):d}return this.each(function(){var b=f(this),d=[j[0],c];b.triggerHandler("setData"+j[1]+"!",d),f.data(this,a,c),b.triggerHandler("changeData"+j[1]+"!",d)})},removeData:function(a){return this.each(function(){f.removeData(this,a)})}}),f.extend({_mark:function(a,c){a&&(c=(c||"fx")+"mark",f.data(a,c,(f.data(a,c,b,!0)||0)+1,!0))},_unmark:function(a,c,d){a!==!0&&(d=c,c=a,a=!1);if(c){d=d||"fx";var e=d+"mark",g=a?0:(f.data(c,e,b,!0)||1)-1;g?f.data(c,e,g,!0):(f.removeData(c,e,!0),m(c,d,"mark"))}},queue:function(a,c,d){if(a){c=(c||"fx")+"queue";var e=f.data(a,c,b,!0);d&&(!e||f.isArray(d)?e=f.data(a,c,f.makeArray(d),!0):e.push(d));return e||[]}},dequeue:function(a,b){b=b||"fx";var c=f.queue(a,b),d=c.shift(),e;d==="inprogress"&&(d=c.shift()),d&&(b==="fx"&&c.unshift("inprogress"),d.call(a,function(){f.dequeue(a,b)})),c.length||(f.removeData(a,b+"queue",!0),m(a,b,"queue"))}}),f.fn.extend({queue:function(a,c){typeof a!="string"&&(c=a,a="fx");if(c===b)return f.queue(this[0],a);return this.each(function(){var b=f.queue(this,a,c);a==="fx"&&b[0]!=="inprogress"&&f.dequeue(this,a)})},dequeue:function(a){return this.each(function(){f.dequeue(this,a)})},delay:function(a,b){a=f.fx?f.fx.speeds[a]||a:a,b=b||"fx";return this.queue(b,function(){var c=this;setTimeout(function(){f.dequeue(c,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){function m(){--h||d.resolveWith(e,[e])}typeof a!="string"&&(c=a,a=b),a=a||"fx";var d=f.Deferred(),e=this,g=e.length,h=1,i=a+"defer",j=a+"queue",k=a+"mark",l;while(g--)if(l=f.data(e[g],i,b,!0)||(f.data(e[g],j,b,!0)||f.data(e[g],k,b,!0))&&f.data(e[g],i,f._Deferred(),!0))h++,l.done(m);m();return d.promise()}});var n=/[\n\t\r]/g,o=/\s+/,p=/\r/g,q=/^(?:button|input)$/i,r=/^(?:button|input|object|select|textarea)$/i,s=/^a(?:rea)?$/i,t=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,u,v;f.fn.extend({attr:function(a,b){return f.access(this,a,b,!0,f.attr)},removeAttr:function(a){return this.each(function(){f.removeAttr(this,a)})},prop:function(a,b){return f.access(this,a,b,!0,f.prop)},removeProp:function(a){a=f.propFix[a]||a;return this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,g,h,i;if(f.isFunction(a))return this.each(function(b){f(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(o);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{g=" "+e.className+" ";for(h=0,i=b.length;h<i;h++)~g.indexOf(" "+b[h]+" ")||(g+=b[h]+" ");e.className=f.trim(g)}}}return this},removeClass:function(a){var c,d,e,g,h,i,j;if(f.isFunction(a))return this.each(function(b){f(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a=="string"||a===b){c=(a||"").split(o);for(d=0,e=this.length;d<e;d++){g=this[d];if(g.nodeType===1&&g.className)if(a){h=(" "+g.className+" ").replace(n," ");for(i=0,j=c.length;i<j;i++)h=h.replace(" "+c[i]+" "," ");g.className=f.trim(h)}else g.className=""}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";if(f.isFunction(a))return this.each(function(c){f(this).toggleClass(a.call(this,c,this.className,b),b)});return this.each(function(){if(c==="string"){var e,g=0,h=f(this),i=b,j=a.split(o);while(e=j[g++])i=d?i:!h.hasClass(e),h[i?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&f._data(this,"__className__",this.className),this.className=this.className||a===!1?"":f._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ";for(var c=0,d=this.length;c<d;c++)if(this[c].nodeType===1&&(" "+this[c].className+" ").replace(n," ").indexOf(b)>-1)return!0;return!1},val:function(a){var c,d,e=this[0];if(!arguments.length){if(e){c=f.valHooks[e.nodeName.toLowerCase()]||f.valHooks[e.type];if(c&&"get"in c&&(d=c.get(e,"value"))!==b)return d;d=e.value;return typeof d=="string"?d.replace(p,""):d==null?"":d}return b}var g=f.isFunction(a);return this.each(function(d){var e=f(this),h;if(this.nodeType===1){g?h=a.call(this,d,e.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.nodeName.toLowerCase()]||f.valHooks[this.type];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c=a.selectedIndex,d=[],e=a.options,g=a.type==="select-one";if(c<0)return null;for(var h=g?c:0,i=g?c+1:e.length;h<i;h++){var j=e[h];if(j.selected&&(f.support.optDisabled?!j.disabled:j.getAttribute("disabled")===null)&&(!j.parentNode.disabled||!f.nodeName(j.parentNode,"optgroup"))){b=f(j).val();if(g)return b;d.push(b)}}if(g&&!d.length&&e.length)return f(e[c]).val();return d},set:function(a,b){var c=f.makeArray(b);f(a).find("option").each(function(){this.selected=f.inArray(f(this).val(),c)>=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attrFix:{tabindex:"tabIndex"},attr:function(a,c,d,e){var g=a.nodeType;if(!a||g===3||g===8||g===2)return b;if(e&&c in f.attrFn)return f(a)[c](d);if(!("getAttribute"in a))return f.prop(a,c,d);var h,i,j=g!==1||!f.isXMLDoc(a);j&&(c=f.attrFix[c]||c,i=f.attrHooks[c],i||(t.test(c)?i=v:u&&(i=u)));if(d!==b){if(d===null){f.removeAttr(a,c);return b}if(i&&"set"in i&&j&&(h=i.set(a,d,c))!==b)return h;a.setAttribute(c,""+d);return d}if(i&&"get"in i&&j&&(h=i.get(a,c))!==null)return h;h=a.getAttribute(c);return h===null?b:h},removeAttr:function(a,b){var c;a.nodeType===1&&(b=f.attrFix[b]||b,f.attr(a,b,""),a.removeAttribute(b),t.test(b)&&(c=f.propFix[b]||b)in a&&(a[c]=!1))},attrHooks:{type:{set:function(a,b){if(q.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.value;a.setAttribute("type",b),c&&(a.value=c);return b}}},value:{get:function(a,b){if(u&&f.nodeName(a,"button"))return u.get(a,b);return b in a?a.value:null},set:function(a,b,c){if(u&&f.nodeName(a,"button"))return u.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e=a.nodeType;if(!a||e===3||e===8||e===2)return b;var g,h,i=e!==1||!f.isXMLDoc(a);i&&(c=f.propFix[c]||c,h=f.propHooks[c]);return d!==b?h&&"set"in h&&(g=h.set(a,d,c))!==b?g:a[c]=d:h&&"get"in h&&(g=h.get(a,c))!==null?g:a[c]},propHooks:{tabIndex:{get:function(a){var c=a.getAttributeNode("tabindex");return c&&c.specified?parseInt(c.value,10):r.test(a.nodeName)||s.test(a.nodeName)&&a.href?0:b}}}}),f.attrHooks.tabIndex=f.propHooks.tabIndex,v={get:function(a,c){var d;return f.prop(a,c)===!0||(d=a.getAttributeNode(c))&&d.nodeValue!==!1?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a,c):(d=f.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase()));return c}},f.support.getSetAttribute||(u=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&d.nodeValue!==""?d.nodeValue:b},set:function(a,b,d){var e=a.getAttributeNode(d);e||(e=c.createAttribute(d),a.setAttributeNode(e));return e.nodeValue=b+""}},f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})})),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex);return null}})),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var w=/\.(.*)$/,x=/^(?:textarea|input|select)$/i,y=/\./g,z=/ /g,A=/[^\w\s.|`]/g,B=function(a){return a.replace(A,"\\$&")};f.event={add:function(a,c,d,e){if(a.nodeType!==3&&a.nodeType!==8){if(d===!1)d=C;else if(!d)return;var g,h;d.handler&&(g=d,d=g.handler),d.guid||(d.guid=f.guid++);var i=f._data(a);if(!i)return;var j=i.events,k=i.handle;j||(i.events=j={}),k||(i.handle=k=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.handle.apply(k.elem,arguments):b}),k.elem=a,c=c.split(" ");var l,m=0,n;while(l=c[m++]){h=g?f.extend({},g):{handler:d,data:e},l.indexOf(".")>-1?(n=l.split("."),l=n.shift(),h.namespace=n.slice(0).sort().join(".")):(n=[],h.namespace=""),h.type=l,h.guid||(h.guid=d.guid);var o=j[l],p=f.event.special[l]||{};if(!o){o=j[l]=[];if(!p.setup||p.setup.call(a,e,n,k)===!1)a.addEventListener?a.addEventListener(l,k,!1):a.attachEvent&&a.attachEvent("on"+l,k)}p.add&&(p.add.call(a,h),h.handler.guid||(h.handler.guid=d.guid)),o.push(h),f.event.global[l]=!0}a=null}},global:{},remove:function(a,c,d,e){if(a.nodeType!==3&&a.nodeType!==8){d===!1&&(d=C);var g,h,i,j,k=0,l,m,n,o,p,q,r,s=f.hasData(a)&&f._data(a),t=s&&s.events;if(!s||!t)return;c&&c.type&&(d=c.handler,c=c.type);if(!c||typeof c=="string"&&c.charAt(0)==="."){c=c||"";for(h in t)f.event.remove(a,h+c);return}c=c.split(" ");while(h=c[k++]){r=h,q=null,l=h.indexOf(".")<0,m=[],l||(m=h.split("."),h=m.shift(),n=new RegExp("(^|\\.)"+f.map(m.slice(0).sort(),B).join("\\.(?:.*\\.)?")+"(\\.|$)")),p=t[h];if(!p)continue;if(!d){for(j=0;j<p.length;j++){q=p[j];if(l||n.test(q.namespace))f.event.remove(a,r,q.handler,j),p.splice(j--,1)}continue}o=f.event.special[h]||{};for(j=e||0;j<p.length;j++){q=p[j];if(d.guid===q.guid){if(l||n.test(q.namespace))e==null&&p.splice(j--,1),o.remove&&o.remove.call(a,q);if(e!=null)break}}if(p.length===0||e!=null&&p.length===1)(!o.teardown||o.teardown.call(a,m)===!1)&&f.removeEvent(a,h,s.handle),g=null,delete 
-t[h]}if(f.isEmptyObject(t)){var u=s.handle;u&&(u.elem=null),delete s.events,delete s.handle,f.isEmptyObject(s)&&f.removeData(a,b,!0)}}},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,e,g){var h=c.type||c,i=[],j;h.indexOf("!")>=0&&(h=h.slice(0,-1),j=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if(!!e&&!f.event.customEvent[h]||!!f.event.global[h]){c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.exclusive=j,c.namespace=i.join("."),c.namespace_re=new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)");if(g||!e)c.preventDefault(),c.stopPropagation();if(!e){f.each(f.cache,function(){var a=f.expando,b=this[a];b&&b.events&&b.events[h]&&f.event.trigger(c,d,b.handle.elem)});return}if(e.nodeType===3||e.nodeType===8)return;c.result=b,c.target=e,d=d!=null?f.makeArray(d):[],d.unshift(c);var k=e,l=h.indexOf(":")<0?"on"+h:"";do{var m=f._data(k,"handle");c.currentTarget=k,m&&m.apply(k,d),l&&f.acceptData(k)&&k[l]&&k[l].apply(k,d)===!1&&(c.result=!1,c.preventDefault()),k=k.parentNode||k.ownerDocument||k===c.target.ownerDocument&&a}while(k&&!c.isPropagationStopped());if(!c.isDefaultPrevented()){var n,o=f.event.special[h]||{};if((!o._default||o._default.call(e.ownerDocument,c)===!1)&&(h!=="click"||!f.nodeName(e,"a"))&&f.acceptData(e)){try{l&&e[h]&&(n=e[l],n&&(e[l]=null),f.event.triggered=h,e[h]())}catch(p){}n&&(e[l]=n),f.event.triggered=b}}return c.result}},handle:function(c){c=f.event.fix(c||a.event);var d=((f._data(this,"events")||{})[c.type]||[]).slice(0),e=!c.exclusive&&!c.namespace,g=Array.prototype.slice.call(arguments,0);g[0]=c,c.currentTarget=this;for(var h=0,i=d.length;h<i;h++){var j=d[h];if(e||c.namespace_re.test(j.namespace)){c.handler=j.handler,c.data=j.data,c.handleObj=j;var k=j.handler.apply(this,g);k!==b&&(c.result=k,k===!1&&(c.preventDefault(),c.stopPropagation()));if(c.isImmediatePropagationStopped())break}}return c.result},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),fix:function(a){if(a[f.expando])return a;var d=a;a=f.Event(d);for(var e=this.props.length,g;e;)g=this.props[--e],a[g]=d[g];a.target||(a.target=a.srcElement||c),a.target.nodeType===3&&(a.target=a.target.parentNode),!a.relatedTarget&&a.fromElement&&(a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement);if(a.pageX==null&&a.clientX!=null){var h=a.target.ownerDocument||c,i=h.documentElement,j=h.body;a.pageX=a.clientX+(i&&i.scrollLeft||j&&j.scrollLeft||0)-(i&&i.clientLeft||j&&j.clientLeft||0),a.pageY=a.clientY+(i&&i.scrollTop||j&&j.scrollTop||0)-(i&&i.clientTop||j&&j.clientTop||0)}a.which==null&&(a.charCode!=null||a.keyCode!=null)&&(a.which=a.charCode!=null?a.charCode:a.keyCode),!a.metaKey&&a.ctrlKey&&(a.metaKey=a.ctrlKey),!a.which&&a.button!==b&&(a.which=a.button&1?1:a.button&2?3:a.button&4?2:0);return a},guid:1e8,proxy:f.proxy,special:{ready:{setup:f.bindReady,teardown:f.noop},live:{add:function(a){f.event.add(this,M(a.origType,a.selector),f.extend({},a,{handler:L,guid:a.handler.guid}))},remove:function(a){f.event.remove(this,M(a.origType,a.selector),a)}},beforeunload:{setup:function(a,b,c){f.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}}},f.removeEvent=c.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){a.detachEvent&&a.detachEvent("on"+b,c)},f.Event=function(a,b){if(!this.preventDefault)return new f.Event(a,b);a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?D:C):this.type=a,b&&f.extend(this,b),this.timeStamp=f.now(),this[f.expando]=!0},f.Event.prototype={preventDefault:function(){this.isDefaultPrevented=D;var a=this.originalEvent;!a||(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){this.isPropagationStopped=D;var a=this.originalEvent;!a||(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=D,this.stopPropagation()},isDefaultPrevented:C,isPropagationStopped:C,isImmediatePropagationStopped:C};var E=function(a){var b=a.relatedTarget,c=!1,d=a.type;a.type=a.data,b!==this&&(b&&(c=f.contains(this,b)),c||(f.event.handle.apply(this,arguments),a.type=d))},F=function(a){a.type=a.data,f.event.handle.apply(this,arguments)};f.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){f.event.special[a]={setup:function(c){f.event.add(this,b,c&&c.selector?F:E,a)},teardown:function(a){f.event.remove(this,b,a&&a.selector?F:E)}}}),f.support.submitBubbles||(f.event.special.submit={setup:function(a,b){if(!f.nodeName(this,"form"))f.event.add(this,"click.specialSubmit",function(a){var b=a.target,c=f.nodeName(b,"input")||f.nodeName(b,"button")?b.type:"";(c==="submit"||c==="image")&&f(b).closest("form").length&&J("submit",this,arguments)}),f.event.add(this,"keypress.specialSubmit",function(a){var b=a.target,c=f.nodeName(b,"input")||f.nodeName(b,"button")?b.type:"";(c==="text"||c==="password")&&f(b).closest("form").length&&a.keyCode===13&&J("submit",this,arguments)});else return!1},teardown:function(a){f.event.remove(this,".specialSubmit")}});if(!f.support.changeBubbles){var G,H=function(a){var b=f.nodeName(a,"input")?a.type:"",c=a.value;b==="radio"||b==="checkbox"?c=a.checked:b==="select-multiple"?c=a.selectedIndex>-1?f.map(a.options,function(a){return a.selected}).join("-"):"":f.nodeName(a,"select")&&(c=a.selectedIndex);return c},I=function(c){var d=c.target,e,g;if(!!x.test(d.nodeName)&&!d.readOnly){e=f._data(d,"_change_data"),g=H(d),(c.type!=="focusout"||d.type!=="radio")&&f._data(d,"_change_data",g);if(e===b||g===e)return;if(e!=null||g)c.type="change",c.liveFired=b,f.event.trigger(c,arguments[1],d)}};f.event.special.change={filters:{focusout:I,beforedeactivate:I,click:function(a){var b=a.target,c=f.nodeName(b,"input")?b.type:"";(c==="radio"||c==="checkbox"||f.nodeName(b,"select"))&&I.call(this,a)},keydown:function(a){var b=a.target,c=f.nodeName(b,"input")?b.type:"";(a.keyCode===13&&!f.nodeName(b,"textarea")||a.keyCode===32&&(c==="checkbox"||c==="radio")||c==="select-multiple")&&I.call(this,a)},beforeactivate:function(a){var b=a.target;f._data(b,"_change_data",H(b))}},setup:function(a,b){if(this.type==="file")return!1;for(var c in G)f.event.add(this,c+".specialChange",G[c]);return x.test(this.nodeName)},teardown:function(a){f.event.remove(this,".specialChange");return x.test(this.nodeName)}},G=f.event.special.change.filters,G.focus=G.beforeactivate}f.support.focusinBubbles||f.each({focus:"focusin",blur:"focusout"},function(a,b){function e(a){var c=f.event.fix(a);c.type=b,c.originalEvent={},f.event.trigger(c,null,c.target),c.isDefaultPrevented()&&a.preventDefault()}var d=0;f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.each(["bind","one"],function(a,c){f.fn[c]=function(a,d,e){var g;if(typeof a=="object"){for(var h in a)this[c](h,d,a[h],e);return this}if(arguments.length===2||d===!1)e=d,d=b;c==="one"?(g=function(a){f(this).unbind(a,g);return e.apply(this,arguments)},g.guid=e.guid||f.guid++):g=e;if(a==="unload"&&c!=="one")this.one(a,d,e);else for(var i=0,j=this.length;i<j;i++)f.event.add(this[i],a,g,d);return this}}),f.fn.extend({unbind:function(a,b){if(typeof a=="object"&&!a.preventDefault)for(var c in a)this.unbind(c,a[c]);else for(var d=0,e=this.length;d<e;d++)f.event.remove(this[d],a,b);return this},delegate:function(a,b,c,d){return this.live(b,c,d,a)},undelegate:function(a,b,c){return arguments.length===0?this.unbind("live"):this.die(b,null,c,a)},trigger:function(a,b){return this.each(function(){f.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return f.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||f.guid++,d=0,e=function(c){var e=(f.data(this,"lastToggle"+a.guid)||0)%d;f.data(this,"lastToggle"+a.guid,e+1),c.preventDefault();return b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});var K={focus:"focusin",blur:"focusout",mouseenter:"mouseover",mouseleave:"mouseout"};f.each(["live","die"],function(a,c){f.fn[c]=function(a,d,e,g){var h,i=0,j,k,l,m=g||this.selector,n=g?this:f(this.context);if(typeof a=="object"&&!a.preventDefault){for(var o in a)n[c](o,d,a[o],m);return this}if(c==="die"&&!a&&g&&g.charAt(0)==="."){n.unbind(g);return this}if(d===!1||f.isFunction(d))e=d||C,d=b;a=(a||"").split(" ");while((h=a[i++])!=null){j=w.exec(h),k="",j&&(k=j[0],h=h.replace(w,""));if(h==="hover"){a.push("mouseenter"+k,"mouseleave"+k);continue}l=h,K[h]?(a.push(K[h]+k),h=h+k):h=(K[h]||h)+k;if(c==="live")for(var p=0,q=n.length;p<q;p++)f.event.add(n[p],"live."+M(h,m),{data:d,selector:m,handler:e,origType:h,origHandler:e,preType:l});else n.unbind("live."+M(h,m),e)}return this}}),f.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error".split(" "),function(a,b){f.fn[b]=function(a,c){c==null&&(c=a,a=null);return arguments.length>0?this.bind(b,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0)}),function(){function u(a,b,c,d,e,f){for(var g=0,h=d.length;g<h;g++){var i=d[g];if(i){var j=!1;i=i[a];while(i){if(i.sizcache===c){j=d[i.sizset];break}if(i.nodeType===1){f||(i.sizcache=c,i.sizset=g);if(typeof b!="string"){if(i===b){j=!0;break}}else if(k.filter(b,[i]).length>0){j=i;break}}i=i[a]}d[g]=j}}}function t(a,b,c,d,e,f){for(var g=0,h=d.length;g<h;g++){var i=d[g];if(i){var j=!1;i=i[a];while(i){if(i.sizcache===c){j=d[i.sizset];break}i.nodeType===1&&!f&&(i.sizcache=c,i.sizset=g);if(i.nodeName.toLowerCase()===b){j=i;break}i=i[a]}d[g]=j}}}var a=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d=0,e=Object.prototype.toString,g=!1,h=!0,i=/\\/g,j=/\W/;[0,0].sort(function(){h=!1;return 0});var k=function(b,d,f,g){f=f||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return f;var i,j,n,o,q,r,s,t,u=!0,w=k.isXML(d),x=[],y=b;do{a.exec(""),i=a.exec(y);if(i){y=i[3],x.push(i[1]);if(i[2]){o=i[3];break}}}while(i);if(x.length>1&&m.exec(b))if(x.length===2&&l.relative[x[0]])j=v(x[0]+x[1],d);else{j=l.relative[x[0]]?[d]:k(x.shift(),d);while(x.length)b=x.shift(),l.relative[b]&&(b+=x.shift()),j=v(b,j)}else{!g&&x.length>1&&d.nodeType===9&&!w&&l.match.ID.test(x[0])&&!l.match.ID.test(x[x.length-1])&&(q=k.find(x.shift(),d,w),d=q.expr?k.filter(q.expr,q.set)[0]:q.set[0]);if(d){q=g?{expr:x.pop(),set:p(g)}:k.find(x.pop(),x.length===1&&(x[0]==="~"||x[0]==="+")&&d.parentNode?d.parentNode:d,w),j=q.expr?k.filter(q.expr,q.set):q.set,x.length>0?n=p(j):u=!1;while(x.length)r=x.pop(),s=r,l.relative[r]?s=x.pop():r="",s==null&&(s=d),l.relative[r](n,s,w)}else n=x=[]}n||(n=j),n||k.error(r||b);if(e.call(n)==="[object Array]")if(!u)f.push.apply(f,n);else if(d&&d.nodeType===1)for(t=0;n[t]!=null;t++)n[t]&&(n[t]===!0||n[t].nodeType===1&&k.contains(d,n[t]))&&f.push(j[t]);else for(t=0;n[t]!=null;t++)n[t]&&n[t].nodeType===1&&f.push(j[t]);else p(n,f);o&&(k(o,h,f,g),k.uniqueSort(f));return f};k.uniqueSort=function(a){if(r){g=h,a.sort(r);if(g)for(var b=1;b<a.length;b++)a[b]===a[b-1]&&a.splice(b--,1)}return a},k.matches=function(a,b){return k(a,null,null,b)},k.matchesSelector=function(a,b){return k(b,null,null,[a]).length>0},k.find=function(a,b,c){var d;if(!a)return[];for(var e=0,f=l.order.length;e<f;e++){var g,h=l.order[e];if(g=l.leftMatch[h].exec(a)){var j=g[1];g.splice(1,1);if(j.substr(j.length-1)!=="\\"){g[1]=(g[1]||"").replace(i,""),d=l.find[h](g,b,c);if(d!=null){a=a.replace(l.match[h],"");break}}}}d||(d=typeof b.getElementsByTagName!="undefined"?b.getElementsByTagName("*"):[]);return{set:d,expr:a}},k.filter=function(a,c,d,e){var f,g,h=a,i=[],j=c,m=c&&c[0]&&k.isXML(c[0]);while(a&&c.length){for(var n in l.filter)if((f=l.leftMatch[n].exec(a))!=null&&f[2]){var o,p,q=l.filter[n],r=f[1];g=!1,f.splice(1,1);if(r.substr(r.length-1)==="\\")continue;j===i&&(i=[]);if(l.preFilter[n]){f=l.preFilter[n](f,j,d,i,e,m);if(!f)g=o=!0;else if(f===!0)continue}if(f)for(var s=0;(p=j[s])!=null;s++)if(p){o=q(p,f,s,j);var t=e^!!o;d&&o!=null?t?g=!0:j[s]=!1:t&&(i.push(p),g=!0)}if(o!==b){d||(j=i),a=a.replace(l.match[n],"");if(!g)return[];break}}if(a===h)if(g==null)k.error(a);else break;h=a}return j},k.error=function(a){throw"Syntax error, unrecognized expression: "+a};var l=k.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(a){return a.getAttribute("href")},type:function(a){return a.getAttribute("type")}},relative:{"+":function(a,b){var c=typeof b=="string",d=c&&!j.test(b),e=c&&!d;d&&(b=b.toLowerCase());for(var f=0,g=a.length,h;f<g;f++)if(h=a[f]){while((h=h.previousSibling)&&h.nodeType!==1);a[f]=e||h&&h.nodeName.toLowerCase()===b?h||!1:h===b}e&&k.filter(b,a,!0)},">":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!j.test(b)){b=b.toLowerCase();for(;e<f;e++){c=a[e];if(c){var g=c.parentNode;a[e]=g.nodeName.toLowerCase()===b?g:!1}}}else{for(;e<f;e++)c=a[e],c&&(a[e]=d?c.parentNode:c.parentNode===b);d&&k.filter(b,a,!0)}},"":function(a,b,c){var e,f=d++,g=u;typeof b=="string"&&!j.test(b)&&(b=b.toLowerCase(),e=b,g=t),g("parentNode",b,f,a,e,c)},"~":function(a,b,c){var e,f=d++,g=u;typeof b=="string"&&!j.test(b)&&(b=b.toLowerCase(),e=b,g=t),g("previousSibling",b,f,a,e,c)}},find:{ID:function(a,b,c){if(typeof b.getElementById!="undefined"&&!c){var d=b.getElementById(a[1]);return d&&d.parentNode?[d]:[]}},NAME:function(a,b){if(typeof b.getElementsByName!="undefined"){var c=[],d=b.getElementsByName(a[1]);for(var e=0,f=d.length;e<f;e++)d[e].getAttribute("name")===a[1]&&c.push(d[e]);return c.length===0?null:c}},TAG:function(a,b){if(typeof b.getElementsByTagName!="undefined")return b.getElementsByTagName(a[1])}},preFilter:{CLASS:function(a,b,c,d,e,f){a=" "+a[1].replace(i,"")+" ";if(f)return a;for(var g=0,h;(h=b[g])!=null;g++)h&&(e^(h.className&&(" "+h.className+" ").replace(/[\t\n\r]/g," ").indexOf(a)>=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(i,"")},TAG:function(a,b){return a[1].replace(i,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||k.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&k.error(a[0]);a[0]=d++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(i,"");!f&&l.attrMap[g]&&(a[1]=l.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(i,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=k(b[3],null,null,c);else{var g=k.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(l.match.POS.test(b[0])||l.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!k(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return b<c[3]-0},gt:function(a,b,c){return b>c[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=l.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||k.getText([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h<i;h++)if(g[h]===a)return!1;return!0}k.error(e)},CHILD:function(a,b){var c=b[1],d=a;switch(c){case"only":case"first":while(d=d.previousSibling)if(d.nodeType===1)return!1;if(c==="first")return!0;d=a;case"last":while(d=d.nextSibling)if(d.nodeType===1)return!1;return!0;case"nth":var e=b[2],f=b[3];if(e===1&&f===0)return!0;var g=b[0],h=a.parentNode;if(h&&(h.sizcache!==g||!a.nodeIndex)){var i=0;for(d=h.firstChild;d;d=d.nextSibling)d.nodeType===1&&(d.nodeIndex=++i);h.sizcache=g}var j=a.nodeIndex-f;return e===0?j===0:j%e===0&&j/e>=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=l.attrHandle[c]?l.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=l.setFilters[e];if(f)return f(a,c,b,d)}}},m=l.match.POS,n=function(a,b){return"\\"+(b-0+1)};for(var o in l.match)l.match[o]=new RegExp(l.match[o].source+/(?![^\[]*\])(?![^\(]*\))/.source),l.leftMatch[o]=new RegExp(/(^(?:.|\r|\n)*?)/.source+l.match[o].source.replace(/\\(\d+)/g,n));var p=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(q){p=function(a,b){var c=0,d=b||[];if(e.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var f=a.length;c<f;c++)d.push(a[c]);else for(;a[c];c++)d.push(a[c]);return d}}var r,s;c.documentElement.compareDocumentPosition?r=function(a,b){if(a===b){g=!0;return 0}if(!a.compareDocumentPosition||!b.compareDocumentPosition)return a.compareDocumentPosition?-1:1;return a.compareDocumentPosition(b)&4?-1:1}:(r=function(a,b){if(a===b){g=!0;return 0}if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],f=[],h=a.parentNode,i=b.parentNode,j=h;if(h===i)return s(a,b);if(!h)return-1;if(!i)return 1;while(j)e.unshift(j),j=j.parentNode;j=i;while(j)f.unshift(j),j=j.parentNode;c=e.length,d=f.length;for(var k=0;k<c&&k<d;k++)if(e[k]!==f[k])return s(e[k],f[k]);return k===c?s(a,f[k],-1):s(e[k],b,1)},s=function(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}),k.getText=function(a){var b="",c;for(var d=0;a[d];d++)c=a[d],c.nodeType===3||c.nodeType===4?b+=c.nodeValue:c.nodeType!==8&&(b+=k.getText(c.childNodes));return b},function(){var a=c.createElement("div"),d="script"+(new Date).getTime(),e=c.documentElement;a.innerHTML="<a name='"+d+"'/>",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(l.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},l.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(l.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(l.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=k,b=c.createElement("div"),d="__sizzle__";b.innerHTML="<p class='TEST'></p>";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){k=function(b,e,f,g){e=e||c;if(!g&&!k.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return p(e.getElementsByTagName(b),f);if(h[2]&&l.find.CLASS&&e.getElementsByClassName)return p(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return p([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return p([],f);if(i.id===h[3])return p([i],f)}try{return p(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var m=e,n=e.getAttribute("id"),o=n||d,q=e.parentNode,r=/^\s*[+~]/.test(b);n?o=o.replace(/'/g,"\\$&"):e.setAttribute("id",o),r&&q&&(e=e.parentNode);try{if(!r||q)return p(e.querySelectorAll("[id='"+o+"'] "+b),f)}catch(s){}finally{n||m.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)k[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}k.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!k.isXML(a))try{if(e||!l.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return k(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="<div class='test e'></div><div class='test'></div>";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;l.order.splice(1,0,"CLASS"),l.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?k.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?k.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:k.contains=function(){return!1},k.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var v=function(a,b){var c,d=[],e="",f=b.nodeType?[b]:b;while(c=l.match.PSEUDO.exec(a))e+=c[0],a=a.replace(l.match.PSEUDO,"");a=l.relative[a]?a+"*":a;for(var g=0,h=f.length;g<h;g++)k(a,f[g],d);return k.filter(e,d)};f.find=k,f.expr=k.selectors,f.expr[":"]=f.expr.filters,f.unique=k.uniqueSort,f.text=k.getText,f.isXMLDoc=k.isXML,f.contains=k.contains}();var N=/Until$/,O=/^(?:parents|prevUntil|prevAll)/,P=/,/,Q=/^.[^:#\[\.,]*$/,R=Array.prototype.slice,S=f.expr.match.POS,T={children:!0,contents:!0,next:!0,prev:!0};f.fn.extend({find:function(a){var b=this,c,d;if(typeof a!="string")return f(a).filter(function(){for(c=0,d=b.length;c<d;c++)if(f.contains(b[c],this))return!0});var e=this.pushStack("","find",a),g,h,i;for(c=0,d=this.length;c<d;c++){g=e.length,f.find(a,this[c],e);if(c>0)for(h=g;h<e.length;h++)for(i=0;i<g;i++)if(e[i]===e[h]){e.splice(h--,1);break}}return e},has:function(a){var b=f(a);return this.filter(function(){for(var a=0,c=b.length;a<c;a++)if(f.contains(this,b[a]))return!0})},not:function(a){return this.pushStack(V(this,a,!1),"not",a)},filter:function(a){return this.pushStack(V(this,a,!0),"filter",a)},is:function(a){return!!a&&(typeof a=="string"?f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h,i,j={},k=1;if(g&&a.length){for(d=0,e=a.length;d<e;d++)i=a[d],j[i]||(j[i]=S.test(i)?f(i,b||this.context):i);while(g&&g.ownerDocument&&g!==b){for(i in j)h=j[i],(h.jquery?h.index(g)>-1:f(g).is(h))&&c.push({selector:i,elem:g,level:k});g=g.parentNode,k++}}return c}var l=S.test(a)||typeof a!="string"?f(a,b||this.context):0;for(d=0,e=this.length;d<e;d++){g=this[d];while(g){if(l?l.index(g)>-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a)return this[0]&&this[0].parentNode?this.prevAll().length:-1;if(typeof a=="string")return f.inArray(this[0],f(a));return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(U(c[0])||U(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling(a.parentNode.firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c),g=R.call(arguments);N.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!T[a]?f.unique(e):e,(this.length>1||P.test(d))&&O.test(a)&&(e=e.reverse());return this.pushStack(e,a,g.join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var W=/ jQuery\d+="(?:\d+|null)"/g,X=/^\s+/,Y=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Z=/<([\w:]+)/,$=/<tbody/i,_=/<|&#?\w+;/,ba=/<(?:script|object|embed|option|style)/i,bb=/checked\s*(?:[^=]|=\s*.checked.)/i,bc=/\/(java|ecma)script/i,bd=/^\s*<!(?:\[CDATA\[|\-\-)/,be={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]};be.optgroup=be.option,be.tbody=be.tfoot=be.colgroup=be.caption=be.thead,be.th=be.td,f.support.htmlSerialize||(be._default=[1,"div<div>","</div>"]),f.fn.extend({text:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.text(a.call(this,b,c.text()))});if(typeof a!="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return f.text(this)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){f(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f(arguments[0]).toArray());return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(W,""):null;if(typeof a=="string"&&!ba.test(a)&&(f.support.leadingWhitespace||!X.test(a))&&!be[(Z.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Y,"<$1></$2>");try{for(var c=0,d=this.length;c<d;c++)this[c].nodeType===1&&(f.cleanData(this[c].getElementsByTagName("*")),this[c].innerHTML=a)}catch(e){this.empty().append(a)}}else f.isFunction(a)?this.each(function(b){var c=f(this);c.html(a.call(this,b,c.html()))}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(f.isFunction(a))return this.each(function(b){var c=f(this),d=c.html();c.replaceWith(a.call(this,b,d))});typeof a!="string"&&(a=f(a).detach());return this.each(function(){var b=this.nextSibling,c=this.parentNode;f(this).remove(),b?f(b).before(a):f(c).append(a)})}return this.length?this.pushStack(f(f.isFunction(a)?a():a),"replaceWith",a):this},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){var e,g,h,i,j=a[0],k=[];if(!f.support.checkClone&&arguments.length===3&&typeof j=="string"&&bb.test(j))return this.each(function(){f(this).domManip(a,c,d,!0)});if(f.isFunction(j))return this.each(function(e){var g=f(this);a[0]=j.call(this,e,c?g.html():b),g.domManip(a,c,d)});if(this[0]){i=j&&j.parentNode,f.support.parentNode&&i&&i.nodeType===11&&i.childNodes.length===this.length?e={fragment:i}:e=f.buildFragment(a,this,k),h=e.fragment,h.childNodes.length===1?g=h=h.firstChild:g=h.firstChild;if(g){c=c&&f.nodeName(g,"tr");for(var l=0,m=this.length,n=m-1;l<m;l++)d.call(c?bf(this[l],g):this[l],e.cacheable||m>1&&l<n?f.clone(h,!0,!0):h)}k.length&&f.each(k,bl)}return this}}),f.buildFragment=function(a,b,d){var e,g,h,i;b&&b[0]&&(i=b[0].ownerDocument||b[0]),i.createDocumentFragment||(i=c),a.length===1&&typeof a[0]=="string"&&a[0].length<512&&i===c&&a[0].charAt(0)==="<"&&!ba.test(a[0])&&(f.support.checkClone||!bb.test(a[0]))&&(g=!0,h=f.fragments[a[0]],h&&h!==1&&(e=h)),e||(e=i.createDocumentFragment(),f.clean
-(a,i,e,d)),g&&(f.fragments[a[0]]=h?e:1);return{fragment:e,cacheable:g}},f.fragments={},f.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){f.fn[a]=function(c){var d=[],e=f(c),g=this.length===1&&this[0].parentNode;if(g&&g.nodeType===11&&g.childNodes.length===1&&e.length===1){e[b](this[0]);return this}for(var h=0,i=e.length;h<i;h++){var j=(h>0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d=a.cloneNode(!0),e,g,h;if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bh(a,d),e=bi(a),g=bi(d);for(h=0;e[h];++h)g[h]&&bh(e[h],g[h])}if(b){bg(a,d);if(c){e=bi(a),g=bi(d);for(h=0;e[h];++h)bg(e[h],g[h])}}e=g=null;return d},clean:function(a,b,d,e){var g;b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var h=[],i;for(var j=0,k;(k=a[j])!=null;j++){typeof k=="number"&&(k+="");if(!k)continue;if(typeof k=="string")if(!_.test(k))k=b.createTextNode(k);else{k=k.replace(Y,"<$1></$2>");var l=(Z.exec(k)||["",""])[1].toLowerCase(),m=be[l]||be._default,n=m[0],o=b.createElement("div");o.innerHTML=m[1]+k+m[2];while(n--)o=o.lastChild;if(!f.support.tbody){var p=$.test(k),q=l==="table"&&!p?o.firstChild&&o.firstChild.childNodes:m[1]==="<table>"&&!p?o.childNodes:[];for(i=q.length-1;i>=0;--i)f.nodeName(q[i],"tbody")&&!q[i].childNodes.length&&q[i].parentNode.removeChild(q[i])}!f.support.leadingWhitespace&&X.test(k)&&o.insertBefore(b.createTextNode(X.exec(k)[0]),o.firstChild),k=o.childNodes}var r;if(!f.support.appendChecked)if(k[0]&&typeof (r=k.length)=="number")for(i=0;i<r;i++)bk(k[i]);else bk(k);k.nodeType?h.push(k):h=f.merge(h,k)}if(d){g=function(a){return!a.type||bc.test(a.type)};for(j=0;h[j];j++)if(e&&f.nodeName(h[j],"script")&&(!h[j].type||h[j].type.toLowerCase()==="text/javascript"))e.push(h[j].parentNode?h[j].parentNode.removeChild(h[j]):h[j]);else{if(h[j].nodeType===1){var s=f.grep(h[j].getElementsByTagName("script"),g);h.splice.apply(h,[j+1,0].concat(s))}d.appendChild(h[j])}}return h},cleanData:function(a){var b,c,d=f.cache,e=f.expando,g=f.event.special,h=f.support.deleteExpando;for(var i=0,j;(j=a[i])!=null;i++){if(j.nodeName&&f.noData[j.nodeName.toLowerCase()])continue;c=j[f.expando];if(c){b=d[c]&&d[c][e];if(b&&b.events){for(var k in b.events)g[k]?f.event.remove(j,k):f.removeEvent(j,k,b.handle);b.handle&&(b.handle.elem=null)}h?delete j[f.expando]:j.removeAttribute&&j.removeAttribute(f.expando),delete d[c]}}}});var bm=/alpha\([^)]*\)/i,bn=/opacity=([^)]*)/,bo=/([A-Z]|^ms)/g,bp=/^-?\d+(?:px)?$/i,bq=/^-?\d/,br=/^([\-+])=([\-+.\de]+)/,bs={position:"absolute",visibility:"hidden",display:"block"},bt=["Left","Right"],bu=["Top","Bottom"],bv,bw,bx;f.fn.css=function(a,c){if(arguments.length===2&&c===b)return this;return f.access(this,a,c,!0,function(a,c,d){return d!==b?f.style(a,c,d):f.css(a,c)})},f.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bv(a,"opacity","opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":f.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!!a&&a.nodeType!==3&&a.nodeType!==8&&!!a.style){var g,h,i=f.camelCase(c),j=a.style,k=f.cssHooks[i];c=f.cssProps[i]||i;if(d===b){if(k&&"get"in k&&(g=k.get(a,!1,e))!==b)return g;return j[c]}h=typeof d,h==="string"&&(g=br.exec(d))&&(d=+(g[1]+1)*+g[2]+parseFloat(f.css(a,c)),h="number");if(d==null||h==="number"&&isNaN(d))return;h==="number"&&!f.cssNumber[i]&&(d+="px");if(!k||!("set"in k)||(d=k.set(a,d))!==b)try{j[c]=d}catch(l){}}},css:function(a,c,d){var e,g;c=f.camelCase(c),g=f.cssHooks[c],c=f.cssProps[c]||c,c==="cssFloat"&&(c="float");if(g&&"get"in g&&(e=g.get(a,!0,d))!==b)return e;if(bv)return bv(a,c)},swap:function(a,b,c){var d={};for(var e in b)d[e]=a.style[e],a.style[e]=b[e];c.call(a);for(e in b)a.style[e]=d[e]}}),f.curCSS=f.css,f.each(["height","width"],function(a,b){f.cssHooks[b]={get:function(a,c,d){var e;if(c){if(a.offsetWidth!==0)return by(a,b,d);f.swap(a,bs,function(){e=by(a,b,d)});return e}},set:function(a,b){if(!bp.test(b))return b;b=parseFloat(b);if(b>=0)return b+"px"}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return bn.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNaN(b)?"":"alpha(opacity="+b*100+")",g=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&f.trim(g.replace(bm,""))===""){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bm.test(g)?g.replace(bm,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){var c;f.swap(a,{display:"inline-block"},function(){b?c=bv(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(bw=function(a,c){var d,e,g;c=c.replace(bo,"-$1").toLowerCase();if(!(e=a.ownerDocument.defaultView))return b;if(g=e.getComputedStyle(a,null))d=g.getPropertyValue(c),d===""&&!f.contains(a.ownerDocument.documentElement,a)&&(d=f.style(a,c));return d}),c.documentElement.currentStyle&&(bx=function(a,b){var c,d=a.currentStyle&&a.currentStyle[b],e=a.runtimeStyle&&a.runtimeStyle[b],f=a.style;!bp.test(d)&&bq.test(d)&&(c=f.left,e&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":d||0,d=f.pixelLeft+"px",f.left=c,e&&(a.runtimeStyle.left=e));return d===""?"auto":d}),bv=bw||bx,f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)});var bz=/%20/g,bA=/\[\]$/,bB=/\r?\n/g,bC=/#.*$/,bD=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bE=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bF=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,bG=/^(?:GET|HEAD)$/,bH=/^\/\//,bI=/\?/,bJ=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,bK=/^(?:select|textarea)/i,bL=/\s+/,bM=/([?&])_=[^&]*/,bN=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bO=f.fn.load,bP={},bQ={},bR,bS,bT=["*/"]+["*"];try{bR=e.href}catch(bU){bR=c.createElement("a"),bR.href="",bR=bR.href}bS=bN.exec(bR.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bO)return bO.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("<div>").append(c.replace(bJ,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bK.test(this.nodeName)||bE.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bB,"\r\n")}}):{name:b.name,value:c.replace(bB,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.bind(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?bX(a,f.ajaxSettings):(b=a,a=f.ajaxSettings),bX(a,b);return a},ajaxSettings:{url:bR,isLocal:bF.test(bS[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":bT},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:bV(bP),ajaxTransport:bV(bQ),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a>0?4:0;var o,r,u,w=c,x=l?bZ(d,v,l):b,y,z;if(a>=200&&a<300||a===304){if(d.ifModified){if(y=v.getResponseHeader("Last-Modified"))f.lastModified[k]=y;if(z=v.getResponseHeader("Etag"))f.etag[k]=z}if(a===304)w="notmodified",o=!0;else try{r=b$(d,x),w="success",o=!0}catch(A){w="parsererror",u=A}}else{u=w;if(!w||a)w="error",a<0&&(a=0)}v.status=a,v.statusText=""+(c||w),o?h.resolveWith(e,[r,w,v]):h.rejectWith(e,[v,w,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.resolveWith(e,[v,w]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f._Deferred(),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bD.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.done,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bC,"").replace(bH,bS[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bL),d.crossDomain==null&&(r=bN.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bS[1]&&r[2]==bS[2]&&(r[3]||(r[1]==="http:"?80:443))==(bS[3]||(bS[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),bW(bP,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bG.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bI.test(d.url)?"&":"?")+d.data,delete d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bM,"$1_="+x);d.url=y+(y===d.url?(bI.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", "+bT+"; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=bW(bQ,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){s<2?w(-1,z):f.error(z)}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)bY(g,a[g],c,e);return d.join("&").replace(bz,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var b_=f.now(),ca=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+b_++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=b.contentType==="application/x-www-form-urlencoded"&&typeof b.data=="string";if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(ca.test(b.url)||e&&ca.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(ca,l),b.url===j&&(e&&(k=k.replace(ca,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var cb=a.ActiveXObject?function(){for(var a in cd)cd[a](0,1)}:!1,cc=0,cd;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ce()||cf()}:ce,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,cb&&delete cd[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n),m.text=h.responseText;try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cc,cb&&(cd||(cd={},f(a).unload(cb)),cd[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var cg={},ch,ci,cj=/^(?:toggle|show|hide)$/,ck=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,cl,cm=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cn;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(cq("show",3),a,b,c);for(var g=0,h=this.length;g<h;g++)d=this[g],d.style&&(e=d.style.display,!f._data(d,"olddisplay")&&e==="none"&&(e=d.style.display=""),e===""&&f.css(d,"display")==="none"&&f._data(d,"olddisplay",cr(d.nodeName)));for(g=0;g<h;g++){d=this[g];if(d.style){e=d.style.display;if(e===""||e==="none")d.style.display=f._data(d,"olddisplay")||""}}return this},hide:function(a,b,c){if(a||a===0)return this.animate(cq("hide",3),a,b,c);for(var d=0,e=this.length;d<e;d++)if(this[d].style){var g=f.css(this[d],"display");g!=="none"&&!f._data(this[d],"olddisplay")&&f._data(this[d],"olddisplay",g)}for(d=0;d<e;d++)this[d].style&&(this[d].style.display="none");return this},_toggle:f.fn.toggle,toggle:function(a,b,c){var d=typeof a=="boolean";f.isFunction(a)&&f.isFunction(b)?this._toggle.apply(this,arguments):a==null||d?this.each(function(){var b=d?a:f(this).is(":hidden");f(this)[b?"show":"hide"]()}):this.animate(cq("toggle",3),a,b,c);return this},fadeTo:function(a,b,c,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=f.speed(b,c,d);if(f.isEmptyObject(a))return this.each(e.complete,[!1]);a=f.extend({},a);return this[e.queue===!1?"each":"queue"](function(){e.queue===!1&&f._mark(this);var b=f.extend({},e),c=this.nodeType===1,d=c&&f(this).is(":hidden"),g,h,i,j,k,l,m,n,o;b.animatedProperties={};for(i in a){g=f.camelCase(i),i!==g&&(a[g]=a[i],delete a[i]),h=a[g],f.isArray(h)?(b.animatedProperties[g]=h[1],h=a[g]=h[0]):b.animatedProperties[g]=b.specialEasing&&b.specialEasing[g]||b.easing||"swing";if(h==="hide"&&d||h==="show"&&!d)return b.complete.call(this);c&&(g==="height"||g==="width")&&(b.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY],f.css(this,"display")==="inline"&&f.css(this,"float")==="none"&&(f.support.inlineBlockNeedsLayout?(j=cr(this.nodeName),j==="inline"?this.style.display="inline-block":(this.style.display="inline",this.style.zoom=1)):this.style.display="inline-block"))}b.overflow!=null&&(this.style.overflow="hidden");for(i in a)k=new f.fx(this,b,i),h=a[i],cj.test(h)?k[h==="toggle"?d?"show":"hide":h]():(l=ck.exec(h),m=k.cur(),l?(n=parseFloat(l[2]),o=l[3]||(f.cssNumber[i]?"":"px"),o!=="px"&&(f.style(this,i,(n||1)+o),m=(n||1)/k.cur()*m,f.style(this,i,m+o)),l[1]&&(n=(l[1]==="-="?-1:1)*n+m),k.custom(m,n,o)):k.custom(m,h,""));return!0})},stop:function(a,b){a&&this.queue([]),this.each(function(){var a=f.timers,c=a.length;b||f._unmark(!0,this);while(c--)a[c].elem===this&&(b&&a[c](!0),a.splice(c,1))}),b||this.dequeue();return this}}),f.each({slideDown:cq("show",1),slideUp:cq("hide",1),slideToggle:cq("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){f.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),f.extend({speed:function(a,b,c){var d=a&&typeof a=="object"?f.extend({},a):{complete:c||!c&&b||f.isFunction(a)&&a,duration:a,easing:c&&b||b&&!f.isFunction(b)&&b};d.duration=f.fx.off?0:typeof d.duration=="number"?d.duration:d.duration in f.fx.speeds?f.fx.speeds[d.duration]:f.fx.speeds._default,d.old=d.complete,d.complete=function(a){f.isFunction(d.old)&&d.old.call(this),d.queue!==!1?f.dequeue(this):a!==!1&&f._unmark(this)};return d},easing:{linear:function(a,b,c,d){return c+d*a},swing:function(a,b,c,d){return(-Math.cos(a*Math.PI)/2+.5)*d+c}},timers:[],fx:function(a,b,c){this.options=b,this.elem=a,this.prop=c,b.orig=b.orig||{}}}),f.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this),(f.fx.step[this.prop]||f.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a,b=f.css(this.elem,this.prop);return isNaN(a=parseFloat(b))?!b||b==="auto"?0:b:a},custom:function(a,b,c){function g(a){return d.step(a)}var d=this,e=f.fx;this.startTime=cn||co(),this.start=a,this.end=b,this.unit=c||this.unit||(f.cssNumber[this.prop]?"":"px"),this.now=this.start,this.pos=this.state=0,g.elem=this.elem,g()&&f.timers.push(g)&&!cl&&(cl=setInterval(e.tick,e.interval))},show:function(){this.options.orig[this.prop]=f.style(this.elem,this.prop),this.options.show=!0,this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur()),f(this.elem).show()},hide:function(){this.options.orig[this.prop]=f.style(this.elem,this.prop),this.options.hide=!0,this.custom(this.cur(),0)},step:function(a){var b=cn||co(),c=!0,d=this.elem,e=this.options,g,h;if(a||b>=e.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),e.animatedProperties[this.prop]=!0;for(g in e.animatedProperties)e.animatedProperties[g]!==!0&&(c=!1);if(c){e.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){d.style["overflow"+b]=e.overflow[a]}),e.hide&&f(d).hide();if(e.hide||e.show)for(var i in e.animatedProperties)f.style(d,i,e.orig[i]);e.complete.call(d)}return!1}e.duration==Infinity?this.now=b:(h=b-this.startTime,this.state=h/e.duration,this.pos=f.easing[e.animatedProperties[this.prop]](this.state,h,0,1,e.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){for(var a=f.timers,b=0;b<a.length;++b)a[b]()||a.splice(b--,1);a.length||f.fx.stop()},interval:13,stop:function(){clearInterval(cl),cl=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){f.style(a.elem,"opacity",a.now)},_default:function(a){a.elem.style&&a.elem.style[a.prop]!=null?a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit:a.elem[a.prop]=a.now}}}),f.expr&&f.expr.filters&&(f.expr.filters.animated=function(a){return f.grep(f.timers,function(b){return a===b.elem}).length});var cs=/^t(?:able|d|h)$/i,ct=/^(?:body|html)$/i;"getBoundingClientRect"in c.documentElement?f.fn.offset=function(a){var b=this[0],c;if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);try{c=b.getBoundingClientRect()}catch(d){}var e=b.ownerDocument,g=e.documentElement;if(!c||!f.contains(g,b))return c?{top:c.top,left:c.left}:{top:0,left:0};var h=e.body,i=cu(e),j=g.clientTop||h.clientTop||0,k=g.clientLeft||h.clientLeft||0,l=i.pageYOffset||f.support.boxModel&&g.scrollTop||h.scrollTop,m=i.pageXOffset||f.support.boxModel&&g.scrollLeft||h.scrollLeft,n=c.top+l-j,o=c.left+m-k;return{top:n,left:o}}:f.fn.offset=function(a){var b=this[0];if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);f.offset.initialize();var c,d=b.offsetParent,e=b,g=b.ownerDocument,h=g.documentElement,i=g.body,j=g.defaultView,k=j?j.getComputedStyle(b,null):b.currentStyle,l=b.offsetTop,m=b.offsetLeft;while((b=b.parentNode)&&b!==i&&b!==h){if(f.offset.supportsFixedPosition&&k.position==="fixed")break;c=j?j.getComputedStyle(b,null):b.currentStyle,l-=b.scrollTop,m-=b.scrollLeft,b===d&&(l+=b.offsetTop,m+=b.offsetLeft,f.offset.doesNotAddBorder&&(!f.offset.doesAddBorderForTableAndCells||!cs.test(b.nodeName))&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),e=d,d=b.offsetParent),f.offset.subtractsBorderForOverflowNotVisible&&c.overflow!=="visible"&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),k=c}if(k.position==="relative"||k.position==="static")l+=i.offsetTop,m+=i.offsetLeft;f.offset.supportsFixedPosition&&k.position==="fixed"&&(l+=Math.max(h.scrollTop,i.scrollTop),m+=Math.max(h.scrollLeft,i.scrollLeft));return{top:l,left:m}},f.offset={initialize:function(){var a=c.body,b=c.createElement("div"),d,e,g,h,i=parseFloat(f.css(a,"marginTop"))||0,j="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";f.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"}),b.innerHTML=j,a.insertBefore(b,a.firstChild),d=b.firstChild,e=d.firstChild,h=d.nextSibling.firstChild.firstChild,this.doesNotAddBorder=e.offsetTop!==5,this.doesAddBorderForTableAndCells=h.offsetTop===5,e.style.position="fixed",e.style.top="20px",this.supportsFixedPosition=e.offsetTop===20||e.offsetTop===15,e.style.position=e.style.top="",d.style.overflow="hidden",d.style.position="relative",this.subtractsBorderForOverflowNotVisible=e.offsetTop===-5,this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==i,a.removeChild(b),f.offset.initialize=f.noop},bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.offset.initialize(),f.offset.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,"marginTop"))||0,c+=parseFloat(f.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,"position");d==="static"&&(a.style.position="relative");var e=f(a),g=e.offset(),h=f.css(a,"top"),i=f.css(a,"left"),j=(d==="absolute"||d==="fixed")&&f.inArray("auto",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=ct.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!ct.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each(["Left","Top"],function(a,c){var d="scroll"+c;f.fn[d]=function(c){var e,g;if(c===b){e=this[0];if(!e)return null;g=cu(e);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:f.support.boxModel&&g.document.documentElement[d]||g.document.body[d]:e[d]}return this.each(function(){g=cu(this),g?g.scrollTo(a?f(g).scrollLeft():c,a?c:f(g).scrollTop()):this[d]=c})}}),f.each(["Height","Width"],function(a,c){var d=c.toLowerCase();f.fn["inner"+c]=function(){var a=this[0];return a&&a.style?parseFloat(f.css(a,d,"padding")):null},f.fn["outer"+c]=function(a){var b=this[0];return b&&b.style?parseFloat(f.css(b,d,a?"margin":"border")):null},f.fn[d]=function(a){var e=this[0];if(!e)return a==null?null:this;if(f.isFunction(a))return this.each(function(b){var c=f(this);c[d](a.call(this,b,c[d]()))});if(f.isWindow(e)){var g=e.document.documentElement["client"+c],h=e.document.body;return e.document.compatMode==="CSS1Compat"&&g||h&&h["client"+c]||g}if(e.nodeType===9)return Math.max(e.documentElement["client"+c],e.body["scroll"+c],e.documentElement["scroll"+c],e.body["offset"+c],e.documentElement["offset"+c]);if(a===b){var i=f.css(e,d),j=parseFloat(i);return f.isNaN(j)?i:j}return this.css(d,typeof a=="string"?a:a+"px")}}),a.jQuery=a.$=f})(window);
\ No newline at end of file
diff --git a/themes/jquerymobile/js/jquery.cookie.js b/themes/jquerymobile/js/jquery.cookie.js
deleted file mode 100644
index 6df1faca25fccd58bea8641b7a32b4df55ec6249..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/js/jquery.cookie.js
+++ /dev/null
@@ -1,96 +0,0 @@
-/**
- * Cookie plugin
- *
- * Copyright (c) 2006 Klaus Hartl (stilbuero.de)
- * Dual licensed under the MIT and GPL licenses:
- * http://www.opensource.org/licenses/mit-license.php
- * http://www.gnu.org/licenses/gpl.html
- *
- */
-
-/**
- * Create a cookie with the given name and value and other optional parameters.
- *
- * @example $.cookie('the_cookie', 'the_value');
- * @desc Set the value of a cookie.
- * @example $.cookie('the_cookie', 'the_value', { expires: 7, path: '/', domain: 'jquery.com', secure: true });
- * @desc Create a cookie with all available options.
- * @example $.cookie('the_cookie', 'the_value');
- * @desc Create a session cookie.
- * @example $.cookie('the_cookie', null);
- * @desc Delete a cookie by passing null as value. Keep in mind that you have to use the same path and domain
- *       used when the cookie was set.
- *
- * @param String name The name of the cookie.
- * @param String value The value of the cookie.
- * @param Object options An object literal containing key/value pairs to provide optional cookie attributes.
- * @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object.
- *                             If a negative value is specified (e.g. a date in the past), the cookie will be deleted.
- *                             If set to null or omitted, the cookie will be a session cookie and will not be retained
- *                             when the the browser exits.
- * @option String path The value of the path atribute of the cookie (default: path of page that created the cookie).
- * @option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie).
- * @option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will
- *                        require a secure protocol (like HTTPS).
- * @type undefined
- *
- * @name $.cookie
- * @cat Plugins/Cookie
- * @author Klaus Hartl/klaus.hartl@stilbuero.de
- */
-
-/**
- * Get the value of a cookie with the given name.
- *
- * @example $.cookie('the_cookie');
- * @desc Get the value of a cookie.
- *
- * @param String name The name of the cookie.
- * @return The value of the cookie.
- * @type String
- *
- * @name $.cookie
- * @cat Plugins/Cookie
- * @author Klaus Hartl/klaus.hartl@stilbuero.de
- */
-jQuery.cookie = function(name, value, options) {
-    if (typeof value != 'undefined') { // name and value given, set cookie
-        options = options || {};
-        if (value === null) {
-            value = '';
-            options.expires = -1;
-        }
-        var expires = '';
-        if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) {
-            var date;
-            if (typeof options.expires == 'number') {
-                date = new Date();
-                date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));
-            } else {
-                date = options.expires;
-            }
-            expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE
-        }
-        // CAUTION: Needed to parenthesize options.path and options.domain
-        // in the following expressions, otherwise they evaluate to undefined
-        // in the packed version for some reason...
-        var path = options.path ? '; path=' + (options.path) : '';
-        var domain = options.domain ? '; domain=' + (options.domain) : '';
-        var secure = options.secure ? '; secure' : '';
-        document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');
-    } else { // only name given, get cookie
-        var cookieValue = null;
-        if (document.cookie && document.cookie != '') {
-            var cookies = document.cookie.split(';');
-            for (var i = 0; i < cookies.length; i++) {
-                var cookie = jQuery.trim(cookies[i]);
-                // Does this cookie string begin with the name we want?
-                if (cookie.substring(0, name.length + 1) == (name + '=')) {
-                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
-                    break;
-                }
-            }
-        }
-        return cookieValue;
-    }
-};
\ No newline at end of file
diff --git a/themes/jquerymobile/js/jquery.mobile-1.0rc2.min.js b/themes/jquerymobile/js/jquery.mobile-1.0rc2.min.js
deleted file mode 100644
index a99df1903557614b19583297f2ba28fbe30cf91f..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/js/jquery.mobile-1.0rc2.min.js
+++ /dev/null
@@ -1,175 +0,0 @@
-/*!
- * jQuery Mobile v1.0rc2
- * http://jquerymobile.com/
- *
- * Copyright 2010, jQuery Project
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- */
-(function(a,d){if(a.cleanData){var b=a.cleanData;a.cleanData=function(c){for(var e=0,d;(d=c[e])!=null;e++)a(d).triggerHandler("remove");b(c)}}else{var c=a.fn.remove;a.fn.remove=function(b,e){return this.each(function(){e||(!b||a.filter(b,[this]).length)&&a("*",this).add([this]).each(function(){a(this).triggerHandler("remove")});return c.call(a(this),b,e)})}}a.widget=function(c,b,d){var h=c.split(".")[0],i,c=c.split(".")[1];i=h+"-"+c;if(!d)d=b,b=a.Widget;a.expr[":"][i]=function(b){return!!a.data(b,
-c)};a[h]=a[h]||{};a[h][c]=function(a,c){arguments.length&&this._createWidget(a,c)};b=new b;b.options=a.extend(true,{},b.options);a[h][c].prototype=a.extend(true,b,{namespace:h,widgetName:c,widgetEventPrefix:a[h][c].prototype.widgetEventPrefix||c,widgetBaseClass:i},d);a.widget.bridge(c,a[h][c])};a.widget.bridge=function(c,b){a.fn[c]=function(g){var h=typeof g==="string",i=Array.prototype.slice.call(arguments,1),k=this,g=!h&&i.length?a.extend.apply(null,[true,g].concat(i)):g;if(h&&g.charAt(0)==="_")return k;
-h?this.each(function(){var b=a.data(this,c);if(!b)throw"cannot call methods on "+c+" prior to initialization; attempted to call method '"+g+"'";if(!a.isFunction(b[g]))throw"no such method '"+g+"' for "+c+" widget instance";var e=b[g].apply(b,i);if(e!==b&&e!==d)return k=e,false}):this.each(function(){var d=a.data(this,c);d?d.option(g||{})._init():a.data(this,c,new b(g,this))});return k}};a.Widget=function(a,c){arguments.length&&this._createWidget(a,c)};a.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",
-options:{disabled:false},_createWidget:function(c,b){a.data(b,this.widgetName,this);this.element=a(b);this.options=a.extend(true,{},this.options,this._getCreateOptions(),c);var d=this;this.element.bind("remove."+this.widgetName,function(){d.destroy()});this._create();this._trigger("create");this._init()},_getCreateOptions:function(){var c={};a.metadata&&(c=a.metadata.get(element)[this.widgetName]);return c},_create:function(){},_init:function(){},destroy:function(){this.element.unbind("."+this.widgetName).removeData(this.widgetName);
-this.widget().unbind("."+this.widgetName).removeAttr("aria-disabled").removeClass(this.widgetBaseClass+"-disabled ui-state-disabled")},widget:function(){return this.element},option:function(c,b){var g=c;if(arguments.length===0)return a.extend({},this.options);if(typeof c==="string"){if(b===d)return this.options[c];g={};g[c]=b}this._setOptions(g);return this},_setOptions:function(c){var b=this;a.each(c,function(a,c){b._setOption(a,c)});return this},_setOption:function(a,c){this.options[a]=c;a==="disabled"&&
-this.widget()[c?"addClass":"removeClass"](this.widgetBaseClass+"-disabled ui-state-disabled").attr("aria-disabled",c);return this},enable:function(){return this._setOption("disabled",false)},disable:function(){return this._setOption("disabled",true)},_trigger:function(c,b,d){var h=this.options[c],b=a.Event(b);b.type=(c===this.widgetEventPrefix?c:this.widgetEventPrefix+c).toLowerCase();d=d||{};if(b.originalEvent)for(var c=a.event.props.length,i;c;)i=a.event.props[--c],b[i]=b.originalEvent[i];this.element.trigger(b,
-d);return!(a.isFunction(h)&&h.call(this.element[0],b,d)===false||b.isDefaultPrevented())}}})(jQuery);
-(function(a,d){a.widget("mobile.widget",{_createWidget:function(){a.Widget.prototype._createWidget.apply(this,arguments);this._trigger("init")},_getCreateOptions:function(){var b=this.element,c={};a.each(this.options,function(a){var e=b.jqmData(a.replace(/[A-Z]/g,function(a){return"-"+a.toLowerCase()}));e!==d&&(c[a]=e)});return c},enhanceWithin:function(b){var c=a(b).data("page"),c=c&&c.keepNativeSelector();a(this.options.initSelector,b).not(c||"")[this.widgetName]()}})})(jQuery);
-(function(a){a(window);var d=a("html");a.mobile.media=function(){var b={},c=a("<div id='jquery-mediatest'>"),f=a("<body>").append(c);return function(a){if(!(a in b)){var g=document.createElement("style"),h="@media "+a+" { #jquery-mediatest { position:absolute; } }";g.type="text/css";g.styleSheet?g.styleSheet.cssText=h:g.appendChild(document.createTextNode(h));d.prepend(f).prepend(g);b[a]=c.css("position")==="absolute";f.add(g).remove()}return b[a]}}()})(jQuery);
-(function(a,d){function b(a){var c=a.charAt(0).toUpperCase()+a.substr(1),a=(a+" "+e.join(c+" ")+c).split(" "),b;for(b in a)if(f[a[b]]!==d)return true}var c=a("<body>").prependTo("html"),f=c[0].style,e=["Webkit","Moz","O"],g="palmGetResource"in window,h=window.blackberry;a.mobile.browser={};a.mobile.browser.ie=function(){for(var a=3,c=document.createElement("div"),b=c.all||[];c.innerHTML="<\!--[if gt IE "+ ++a+"]><br><![endif]--\>",b[0];);return a>4?a:!a}();a.extend(a.support,{orientation:"orientation"in
-window&&"onorientationchange"in window,touch:"ontouchend"in document,cssTransitions:"WebKitTransitionEvent"in window,pushState:"pushState"in history&&"replaceState"in history,mediaquery:a.mobile.media("only all"),cssPseudoElement:!!b("content"),touchOverflow:!!b("overflowScrolling"),boxShadow:!!b("boxShadow")&&!h,scrollTop:("pageXOffset"in window||"scrollTop"in document.documentElement||"scrollTop"in c[0])&&!g,dynamicBaseTag:function(){var b=location.protocol+"//"+location.host+location.pathname+
-"ui-dir/",f=a("head base"),e=null,d="",g;f.length?d=f.attr("href"):f=e=a("<base>",{href:b}).appendTo("head");g=a("<a href='testurl' />").prependTo(c)[0].href;f[0].href=d||location.pathname;e&&e.remove();return g.indexOf(b)===0}()});c.remove();g=function(){var a=window.navigator.userAgent;return a.indexOf("Nokia")>-1&&(a.indexOf("Symbian/3")>-1||a.indexOf("Series60/5")>-1)&&a.indexOf("AppleWebKit")>-1&&a.match(/(BrowserNG|NokiaBrowser)\/7\.[0-3]/)}();a.mobile.ajaxBlacklist=window.blackberry&&!window.WebKitPoint||
-window.operamini&&Object.prototype.toString.call(window.operamini)==="[object OperaMini]"||g;g&&a(function(){a("head link[rel='stylesheet']").attr("rel","alternate stylesheet").attr("rel","stylesheet")});a.support.boxShadow||a("html").addClass("ui-mobile-nosupport-boxshadow")})(jQuery);
-(function(a,d,b,c){function f(a){for(;a&&typeof a.originalEvent!=="undefined";)a=a.originalEvent;return a}function e(c){for(var b={},f,u;c;){f=a.data(c,l);for(u in f)if(f[u])b[u]=b.hasVirtualBinding=true;c=c.parentNode}return b}function g(){s&&(clearTimeout(s),s=0);s=setTimeout(function(){E=s=0;v.length=0;D=false;y=true},a.vmouse.resetTimerDuration)}function h(b,u,e){var d,g;if(!(g=e&&e[b])){if(e=!e)a:{for(e=u.target;e;){if((g=a.data(e,l))&&(!b||g[b]))break a;e=e.parentNode}e=null}g=e}if(g){d=u;var e=
-d.type,j,h;d=a.Event(d);d.type=b;g=d.originalEvent;j=a.event.props;if(g)for(h=j.length;h;)b=j[--h],d[b]=g[b];if(e.search(/mouse(down|up)|click/)>-1&&!d.which)d.which=1;if(e.search(/^touch/)!==-1&&(b=f(g),e=b.touches,b=b.changedTouches,e=e&&e.length?e[0]:b&&b.length?b[0]:c))for(g=0,len=z.length;g<len;g++)b=z[g],d[b]=e[b];a(u.target).trigger(d)}return d}function i(c){var b=a.data(c.target,A);if(!D&&(!E||E!==b))if(b=h("v"+c.type,c))b.isDefaultPrevented()&&c.preventDefault(),b.isPropagationStopped()&&
-c.stopPropagation(),b.isImmediatePropagationStopped()&&c.stopImmediatePropagation()}function k(c){var b=f(c).touches,d;if(b&&b.length===1&&(d=c.target,b=e(d),b.hasVirtualBinding))E=u++,a.data(d,A,E),s&&(clearTimeout(s),s=0),x=y=false,d=f(c).touches[0],w=d.pageX,t=d.pageY,h("vmouseover",c,b),h("vmousedown",c,b)}function n(a){y||(x||h("vmousecancel",a,e(a.target)),x=true,g())}function o(c){if(!y){var b=f(c).touches[0],d=x,u=a.vmouse.moveDistanceThreshold;x=x||Math.abs(b.pageX-w)>u||Math.abs(b.pageY-
-t)>u;flags=e(c.target);x&&!d&&h("vmousecancel",c,flags);h("vmousemove",c,flags);g()}}function q(a){if(!y){y=true;var c=e(a.target),b;h("vmouseup",a,c);if(!x&&(b=h("vclick",a,c))&&b.isDefaultPrevented())b=f(a).changedTouches[0],v.push({touchID:E,x:b.clientX,y:b.clientY}),D=true;h("vmouseout",a,c);x=false;g()}}function m(c){var c=a.data(c,l),b;if(c)for(b in c)if(c[b])return true;return false}function j(){}function p(c){var b=c.substr(1);return{setup:function(){m(this)||a.data(this,l,{});a.data(this,
-l)[c]=true;r[c]=(r[c]||0)+1;r[c]===1&&B.bind(b,i);a(this).bind(b,j);if(C)r.touchstart=(r.touchstart||0)+1,r.touchstart===1&&B.bind("touchstart",k).bind("touchend",q).bind("touchmove",o).bind("scroll",n)},teardown:function(){--r[c];r[c]||B.unbind(b,i);C&&(--r.touchstart,r.touchstart||B.unbind("touchstart",k).unbind("touchmove",o).unbind("touchend",q).unbind("scroll",n));var f=a(this),e=a.data(this,l);e&&(e[c]=false);f.unbind(b,j);m(this)||f.removeData(l)}}}var l="virtualMouseBindings",A="virtualTouchID",
-d="vmouseover vmousedown vmousemove vmouseup vclick vmouseout vmousecancel".split(" "),z="clientX clientY pageX pageY screenX screenY".split(" "),r={},s=0,w=0,t=0,x=false,v=[],D=false,y=false,C="addEventListener"in b,B=a(b),u=1,E=0;a.vmouse={moveDistanceThreshold:10,clickDistanceThreshold:10,resetTimerDuration:1500};for(var F=0;F<d.length;F++)a.event.special[d[F]]=p(d[F]);C&&b.addEventListener("click",function(c){var b=v.length,f=c.target,e,d,u,g,j;if(b){e=c.clientX;d=c.clientY;threshold=a.vmouse.clickDistanceThreshold;
-for(u=f;u;){for(g=0;g<b;g++)if(j=v[g],u===f&&Math.abs(j.x-e)<threshold&&Math.abs(j.y-d)<threshold||a.data(u,A)===j.touchID){c.preventDefault();c.stopPropagation();return}u=u.parentNode}}},true)})(jQuery,window,document);
-(function(a,d,b){function c(c,b,f){var e=f.type;f.type=b;a.event.handle.call(c,f);f.type=e}a.each("touchstart touchmove touchend orientationchange throttledresize tap taphold swipe swipeleft swiperight scrollstart scrollstop".split(" "),function(c,b){a.fn[b]=function(a){return a?this.bind(b,a):this.trigger(b)};a.attrFn[b]=true});var f=a.support.touch,e=f?"touchstart":"mousedown",g=f?"touchend":"mouseup",h=f?"touchmove":"mousemove";a.event.special.scrollstart={enabled:true,setup:function(){function b(a,
-d){e=d;c(f,e?"scrollstart":"scrollstop",a)}var f=this,e,d;a(f).bind("touchmove scroll",function(c){a.event.special.scrollstart.enabled&&(e||b(c,true),clearTimeout(d),d=setTimeout(function(){b(c,false)},50))})}};a.event.special.tap={setup:function(){var b=this,f=a(b);f.bind("vmousedown",function(e){function d(){clearTimeout(p)}function g(){d();f.unbind("vclick",h).unbind("vmouseup",d).unbind("vmousecancel",g)}function h(a){g();j==a.target&&c(b,"tap",a)}if(e.which&&e.which!==1)return false;var j=e.target,
-p;f.bind("vmousecancel",g).bind("vmouseup",d).bind("vclick",h);p=setTimeout(function(){c(b,"taphold",a.Event("taphold"))},750)})}};a.event.special.swipe={scrollSupressionThreshold:10,durationThreshold:1E3,horizontalDistanceThreshold:30,verticalDistanceThreshold:75,setup:function(){var c=a(this);c.bind(e,function(f){function e(c){if(q){var b=c.originalEvent.touches?c.originalEvent.touches[0]:c;m={time:(new Date).getTime(),coords:[b.pageX,b.pageY]};Math.abs(q.coords[0]-m.coords[0])>a.event.special.swipe.scrollSupressionThreshold&&
-c.preventDefault()}}var d=f.originalEvent.touches?f.originalEvent.touches[0]:f,q={time:(new Date).getTime(),coords:[d.pageX,d.pageY],origin:a(f.target)},m;c.bind(h,e).one(g,function(){c.unbind(h,e);q&&m&&m.time-q.time<a.event.special.swipe.durationThreshold&&Math.abs(q.coords[0]-m.coords[0])>a.event.special.swipe.horizontalDistanceThreshold&&Math.abs(q.coords[1]-m.coords[1])<a.event.special.swipe.verticalDistanceThreshold&&q.origin.trigger("swipe").trigger(q.coords[0]>m.coords[0]?"swipeleft":"swiperight");
-q=m=b})})}};(function(a,c){function b(){var a=e();a!==d&&(d=a,f.trigger("orientationchange"))}var f=a(c),e,d;a.event.special.orientationchange={setup:function(){if(a.support.orientation&&a.mobile.orientationChangeEnabled)return false;d=e();f.bind("throttledresize",b)},teardown:function(){if(a.support.orientation&&a.mobile.orientationChangeEnabled)return false;f.unbind("throttledresize",b)},add:function(a){var c=a.handler;a.handler=function(a){a.orientation=e();return c.apply(this,arguments)}}};a.event.special.orientationchange.orientation=
-e=function(){var b=true,b=document.documentElement;return(b=a.support.orientation?c.orientation%180==0:b&&b.clientWidth/b.clientHeight<1.1)?"portrait":"landscape"}})(jQuery,d);(function(){a.event.special.throttledresize={setup:function(){a(this).bind("resize",c)},teardown:function(){a(this).unbind("resize",c)}};var c=function(){e=(new Date).getTime();d=e-b;d>=250?(b=e,a(this).trigger("throttledresize")):(f&&clearTimeout(f),f=setTimeout(c,250-d))},b=0,f,e,d})();a.each({scrollstop:"scrollstart",taphold:"tap",
-swipeleft:"swipe",swiperight:"swipe"},function(c,b){a.event.special[c]={setup:function(){a(this).bind(b,a.noop)}}})})(jQuery,this);
-(function(a,d,b){function c(a){a=a||location.href;return"#"+a.replace(/^[^#]*#?(.*)$/,"$1")}var f="hashchange",e=document,g,h=a.event.special,i=e.documentMode,k="on"+f in d&&(i===b||i>7);a.fn[f]=function(a){return a?this.bind(f,a):this.trigger(f)};a.fn[f].delay=50;h[f]=a.extend(h[f],{setup:function(){if(k)return false;a(g.start)},teardown:function(){if(k)return false;a(g.stop)}});g=function(){function g(){var b=c(),e=l(m);if(b!==m)p(m=b,e),a(d).trigger(f);else if(e!==m)location.href=location.href.replace(/#.*/,
-"")+e;i=setTimeout(g,a.fn[f].delay)}var h={},i,m=c(),j=function(a){return a},p=j,l=j;h.start=function(){i||g()};h.stop=function(){i&&clearTimeout(i);i=b};a.browser.msie&&!k&&function(){var b,d;h.start=function(){if(!b)d=(d=a.fn[f].src)&&d+c(),b=a('<iframe tabindex="-1" title="empty"/>').hide().one("load",function(){d||p(c());g()}).attr("src",d||"javascript:0").insertAfter("body")[0].contentWindow,e.onpropertychange=function(){try{if(event.propertyName==="title")b.document.title=e.title}catch(a){}}};
-h.stop=j;l=function(){return c(b.location.href)};p=function(c,d){var g=b.document,h=a.fn[f].domain;if(c!==d)g.title=e.title,g.open(),h&&g.write('<script>document.domain="'+h+'"<\/script>'),g.close(),b.location.hash=c}}();return h}()})(jQuery,this);
-(function(a){a.widget("mobile.page",a.mobile.widget,{options:{theme:"c",domCache:false,keepNativeDefault:":jqmData(role='none'), :jqmData(role='nojs')"},_create:function(){this._trigger("beforecreate");this.element.attr("tabindex","0").addClass("ui-page ui-body-"+this.options.theme)},keepNativeSelector:function(){var d=this.options;return d.keepNative&&a.trim(d.keepNative)&&d.keepNative!==d.keepNativeDefault?[d.keepNative,d.keepNativeDefault].join(", "):d.keepNativeDefault}})})(jQuery);
-(function(a,d){a.extend(a.mobile,{ns:"",subPageUrlKey:"ui-page",activePageClass:"ui-page-active",activeBtnClass:"ui-btn-active",ajaxEnabled:true,hashListeningEnabled:true,defaultPageTransition:"slide",minScrollBack:250,defaultDialogTransition:"pop",loadingMessage:"loading",pageLoadErrorMessage:"Error Loading Page",autoInitializePage:true,pushStateEnabled:true,orientationChangeEnabled:true,gradeA:function(){return a.support.mediaquery||a.mobile.browser.ie&&a.mobile.browser.ie>=7},keyCode:{ALT:18,BACKSPACE:8,
-CAPS_LOCK:20,COMMA:188,COMMAND:91,COMMAND_LEFT:91,COMMAND_RIGHT:93,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,MENU:93,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38,WINDOWS:91},silentScroll:function(c){if(a.type(c)!=="number")c=a.mobile.defaultHomeScroll;a.event.special.scrollstart.enabled=false;setTimeout(function(){d.scrollTo(0,
-c);a(document).trigger("silentscroll",{x:0,y:c})},20);setTimeout(function(){a.event.special.scrollstart.enabled=true},150)},nsNormalize:function(c){return!c?void 0:a.camelCase(a.mobile.ns+c)},getInheritedTheme:function(a,b){var e=a.closest("[class*='ui-bar-'],[class*='ui-body-']");return e.length&&/ui-(bar|body)-([a-z])\b/.exec(e.attr("class"))[2]||""||""||b||"a"}});a.fn.jqmData=function(b,f){var e;typeof b!="undefined"&&(e=this.data(b?a.mobile.nsNormalize(b):b,f));return e};a.jqmData=function(b,
-f,e){var d;typeof f!="undefined"&&(d=a.data(b,f?a.mobile.nsNormalize(f):f,e));return d};a.fn.jqmRemoveData=function(b){return this.removeData(a.mobile.nsNormalize(b))};a.jqmRemoveData=function(b,f){return a.removeData(b,a.mobile.nsNormalize(f))};a.fn.removeWithDependents=function(){a.removeWithDependents(this)};a.removeWithDependents=function(b){b=a(b);(b.jqmData("dependents")||a()).remove();b.remove()};a.fn.addDependents=function(b){a.addDependents(a(this),b)};a.addDependents=function(b,f){var e=
-a(b).jqmData("dependents")||a();a(b).jqmData("dependents",a.merge(e,f))};a.fn.getEncodedText=function(){return a("<div/>").text(a(this).text()).html()};var b=a.find;a.find=function(c,f,e,d){c=c.replace(/:jqmData\(([^)]*)\)/g,"[data-"+(a.mobile.ns||"")+"$1]");return b.call(this,c,f,e,d)};a.extend(a.find,b);a.find.matches=function(b,d){return a.find(b,null,null,d)};a.find.matchesSelector=function(b,d){return a.find(d,null,null,[b]).length>0}})(jQuery,this);
-(function(a,d){function b(a){var b=a.find(".ui-title:eq(0)");b.length?b.focus():a.focus()}function c(b){p&&(!p.closest(".ui-page-active").length||b)&&p.removeClass(a.mobile.activeBtnClass);p=null}function f(){z=false;A.length>0&&a.mobile.changePage.apply(null,A.pop())}function e(c,d,e,f){var h=a.mobile.urlHistory.getActive(),j=a.support.touchOverflow&&a.mobile.touchOverflowEnabled,i=h.lastScroll||(j?0:a.mobile.defaultHomeScroll),h=g();window.scrollTo(0,a.mobile.defaultHomeScroll);d&&d.data("page")._trigger("beforehide",
-null,{nextPage:c});j||c.height(h+i);c.data("page")._trigger("beforeshow",null,{prevPage:d||a("")});a.mobile.hidePageLoadingMsg();j&&i&&(c.addClass("ui-mobile-pre-transition"),b(c),c.is(".ui-native-fixed")?c.find(".ui-content").scrollTop(i):c.scrollTop(i));e=(a.mobile.transitionHandlers[e||"none"]||a.mobile.defaultTransitionHandler)(e,f,c,d);e.done(function(){j||(c.height(""),b(c));j||a.mobile.silentScroll(i);d&&(j||d.height(""),d.data("page")._trigger("hide",null,{nextPage:c}));c.data("page")._trigger("show",
-null,{prevPage:d||a("")})});return e}function g(){var b=jQuery.event.special.orientationchange.orientation()==="portrait",c=b?screen.availHeight:screen.availWidth,b=Math.max(b?480:320,a(window).height());return Math.min(c,b)}function h(){(!a.support.touchOverflow||!a.mobile.touchOverflowEnabled)&&a("."+a.mobile.activePageClass).css("min-height",g())}function i(b,c){c&&b.attr("data-"+a.mobile.ns+"role",c);b.page()}function k(a){for(;a;){if(a.nodeName.toLowerCase()=="a")break;a=a.parentNode}return a}
-function n(b){var b=a(b).closest(".ui-page").jqmData("url"),c=t.hrefNoHash;if(!b||!j.isPath(b))b=c;return j.makeUrlAbsolute(b,c)}var o=a(window),q=a("html"),m=a("head"),j={urlParseRE:/^(((([^:\/#\?]+:)?(?:(\/\/)((?:(([^:@\/#\?]+)(?:\:([^:@\/#\?]+))?)@)?(([^:\/#\?\]\[]+|\[[^\/\]@#?]+\])(?:\:([0-9]+))?))?)?)?((\/?(?:[^\/\?#]+\/+)*)([^\?#]*)))?(\?[^#]+)?)(#.*)?/,parseUrl:function(b){if(a.type(b)==="object")return b;b=j.urlParseRE.exec(b||"")||[];return{href:b[0]||"",hrefNoHash:b[1]||"",hrefNoSearch:b[2]||
-"",domain:b[3]||"",protocol:b[4]||"",doubleSlash:b[5]||"",authority:b[6]||"",username:b[8]||"",password:b[9]||"",host:b[10]||"",hostname:b[11]||"",port:b[12]||"",pathname:b[13]||"",directory:b[14]||"",filename:b[15]||"",search:b[16]||"",hash:b[17]||""}},makePathAbsolute:function(a,b){if(a&&a.charAt(0)==="/")return a;for(var a=a||"",c=(b=b?b.replace(/^\/|(\/[^\/]*|[^\/]+)$/g,""):"")?b.split("/"):[],d=a.split("/"),e=0;e<d.length;e++){var f=d[e];switch(f){case ".":break;case "..":c.length&&c.pop();break;
-default:c.push(f)}}return"/"+c.join("/")},isSameDomain:function(a,b){return j.parseUrl(a).domain===j.parseUrl(b).domain},isRelativeUrl:function(a){return j.parseUrl(a).protocol===""},isAbsoluteUrl:function(a){return j.parseUrl(a).protocol!==""},makeUrlAbsolute:function(a,b){if(!j.isRelativeUrl(a))return a;var c=j.parseUrl(a),d=j.parseUrl(b),e=c.protocol||d.protocol,f=c.protocol?c.doubleSlash:c.doubleSlash||d.doubleSlash,g=c.authority||d.authority,h=c.pathname!=="",i=j.makePathAbsolute(c.pathname||
-d.filename,d.pathname);return e+f+g+i+(c.search||!h&&d.search||"")+c.hash},addSearchParams:function(b,c){var d=j.parseUrl(b),e=typeof c==="object"?a.param(c):c,f=d.search||"?";return d.hrefNoSearch+f+(f.charAt(f.length-1)!=="?"?"&":"")+e+(d.hash||"")},convertUrlToDataUrl:function(a){var b=j.parseUrl(a);if(j.isEmbeddedPage(b))return b.hash.split(r)[0].replace(/^#/,"");else if(j.isSameDomain(b,t))return b.hrefNoHash.replace(t.domain,"");return a},get:function(a){if(a===d)a=location.hash;return j.stripHash(a).replace(/[^\/]*\.[^\/*]+$/,
-"")},getFilePath:function(b){var c="&"+a.mobile.subPageUrlKey;return b&&b.split(c)[0].split(r)[0]},set:function(a){location.hash=a},isPath:function(a){return/\//.test(a)},clean:function(a){return a.replace(t.domain,"")},stripHash:function(a){return a.replace(/^#/,"")},cleanHash:function(a){return j.stripHash(a.replace(/\?.*$/,"").replace(r,""))},isExternal:function(a){a=j.parseUrl(a);return a.protocol&&a.domain!==w.domain?true:false},hasProtocol:function(a){return/^(:?\w+:)/.test(a)},isFirstPageUrl:function(b){var b=
-j.parseUrl(j.makeUrlAbsolute(b,t)),c=a.mobile.firstPage,c=c&&c[0]?c[0].id:d;return(b.hrefNoHash===w.hrefNoHash||x&&b.hrefNoHash===t.hrefNoHash)&&(!b.hash||b.hash==="#"||c&&b.hash.replace(/^#/,"")===c)},isEmbeddedPage:function(a){a=j.parseUrl(a);return a.protocol!==""?a.hash&&(a.hrefNoHash===w.hrefNoHash||x&&a.hrefNoHash===t.hrefNoHash):/^#/.test(a.href)}},p=null,l={stack:[],activeIndex:0,getActive:function(){return l.stack[l.activeIndex]},getPrev:function(){return l.stack[l.activeIndex-1]},getNext:function(){return l.stack[l.activeIndex+
-1]},addNew:function(a,b,c,d,e){l.getNext()&&l.clearForward();l.stack.push({url:a,transition:b,title:c,pageUrl:d,role:e});l.activeIndex=l.stack.length-1},clearForward:function(){l.stack=l.stack.slice(0,l.activeIndex+1)},directHashChange:function(b){var c,e,f;this.getActive();a.each(l.stack,function(a,d){b.currentUrl===d.url&&(c=a<l.activeIndex,e=!c,f=a)});this.activeIndex=f!==d?f:this.activeIndex;c?(b.either||b.isBack)(true):e&&(b.either||b.isForward)(false)},ignoreNextHashChange:false},A=[],z=false,
-r="&ui-state=dialog",s=m.children("base"),w=j.parseUrl(location.href),t=s.length?j.parseUrl(j.makeUrlAbsolute(s.attr("href"),w.href)):w,x=w.hrefNoHash!==t.hrefNoHash,v=a.support.dynamicBaseTag?{element:s.length?s:a("<base>",{href:t.hrefNoHash}).prependTo(m),set:function(a){v.element.attr("href",j.makeUrlAbsolute(a,t))},reset:function(){v.element.attr("href",t.hrefNoHash)}}:d,D=true,y,C,B;y=function(){var b=o;a.support.touchOverflow&&a.mobile.touchOverflowEnabled&&(b=a(".ui-page-active"),b=b.is(".ui-native-fixed")?
-b.find(".ui-content"):b);return b};C=function(b){if(D){var c=a.mobile.urlHistory.getActive();if(c)b=b&&b.scrollTop(),c.lastScroll=b<a.mobile.minScrollBack?a.mobile.defaultHomeScroll:b}};B=function(){setTimeout(C,100,a(this))};o.bind(a.support.pushState?"popstate":"hashchange",function(){D=false});o.one(a.support.pushState?"popstate":"hashchange",function(){D=true});o.one("pagecontainercreate",function(){a.mobile.pageContainer.bind("pagechange",function(){var a=y();D=true;a.unbind("scrollstop",B);
-a.bind("scrollstop",B)})});y().bind("scrollstop",B);a.mobile.getScreenHeight=g;a.fn.animationComplete=function(b){return a.support.cssTransitions?a(this).one("webkitAnimationEnd",b):(setTimeout(b,0),a(this))};a.mobile.path=j;a.mobile.base=v;a.mobile.urlHistory=l;a.mobile.dialogHashKey=r;a.mobile.noneTransitionHandler=function(b,c,d,e){e&&e.removeClass(a.mobile.activePageClass);d.addClass(a.mobile.activePageClass);return a.Deferred().resolve(b,c,d,e).promise()};a.mobile.defaultTransitionHandler=a.mobile.noneTransitionHandler;
-a.mobile.transitionHandlers={none:a.mobile.defaultTransitionHandler};a.mobile.allowCrossDomainPages=false;a.mobile.getDocumentUrl=function(b){return b?a.extend({},w):w.href};a.mobile.getDocumentBase=function(b){return b?a.extend({},t):t.href};a.mobile._bindPageRemove=function(){var b=a(this);!b.data("page").options.domCache&&b.is(":jqmData(external-page='true')")&&b.bind("pagehide.remove",function(){var b=a(this),c=new a.Event("pageremove");b.trigger(c);c.isDefaultPrevented()||b.removeWithDependents()})};
-a.mobile.loadPage=function(b,c){var e=a.Deferred(),f=a.extend({},a.mobile.loadPage.defaults,c),g=null,h=null,r=j.makeUrlAbsolute(b,a.mobile.activePage&&n(a.mobile.activePage)||t.hrefNoHash);if(f.data&&f.type==="get")r=j.addSearchParams(r,f.data),f.data=d;if(f.data&&f.type==="post")f.reloadPage=true;var m=j.getFilePath(r),l=j.convertUrlToDataUrl(r);f.pageContainer=f.pageContainer||a.mobile.pageContainer;g=f.pageContainer.children(":jqmData(url='"+l+"')");g.length===0&&l&&!j.isPath(l)&&(g=f.pageContainer.children("#"+
-l).attr("data-"+a.mobile.ns+"url",l));g.length===0&&a.mobile.firstPage&&j.isFirstPageUrl(m)&&(g=a(a.mobile.firstPage));v&&v.reset();if(g.length){if(!f.reloadPage)return i(g,f.role),e.resolve(r,c,g),e.promise();h=g}var q=f.pageContainer,k=new a.Event("pagebeforeload"),p={url:b,absUrl:r,dataUrl:l,deferred:e,options:f};q.trigger(k,p);if(k.isDefaultPrevented())return e.promise();if(f.showLoadMsg)var s=setTimeout(function(){a.mobile.showPageLoadingMsg()},f.loadMsgDelay);!a.mobile.allowCrossDomainPages&&
-!j.isSameDomain(w,r)?e.reject(r,c):a.ajax({url:m,type:f.type,data:f.data,dataType:"html",success:function(d){var q=a("<div></div>"),k=d.match(/<title[^>]*>([^<]*)/)&&RegExp.$1,t=RegExp("\\bdata-"+a.mobile.ns+"url=[\"']?([^\"'>]*)[\"']?");RegExp("(<[^>]+\\bdata-"+a.mobile.ns+"role=[\"']?page[\"']?[^>]*>)").test(d)&&RegExp.$1&&t.test(RegExp.$1)&&RegExp.$1&&(b=m=j.getFilePath(RegExp.$1));v&&v.set(m);q.get(0).innerHTML=d;g=q.find(":jqmData(role='page'), :jqmData(role='dialog')").first();g.length||(g=
-a("<div data-"+a.mobile.ns+"role='page'>"+d.split(/<\/?body[^>]*>/gmi)[1]+"</div>"));k&&!g.jqmData("title")&&g.jqmData("title",k);if(!a.support.dynamicBaseTag){var n=j.get(m);g.find("[src], link[href], a[rel='external'], :jqmData(ajax='false'), a[target]").each(function(){var b=a(this).is("[href]")?"href":a(this).is("[src]")?"src":"action",c=a(this).attr(b),c=c.replace(location.protocol+"//"+location.host+location.pathname,"");/^(\w+:|#|\/)/.test(c)||a(this).attr(b,n+c)})}g.attr("data-"+a.mobile.ns+
-"url",j.convertUrlToDataUrl(m)).attr("data-"+a.mobile.ns+"external-page",true).appendTo(f.pageContainer);g.one("pagecreate",a.mobile._bindPageRemove);i(g,f.role);r.indexOf("&"+a.mobile.subPageUrlKey)>-1&&(g=f.pageContainer.children(":jqmData(url='"+l+"')"));f.showLoadMsg&&(clearTimeout(s),a.mobile.hidePageLoadingMsg());p.page=g;f.pageContainer.trigger("pageload",p);e.resolve(r,c,g,h)},error:function(){v&&v.set(j.get());var b=new a.Event("pageloadfailed");f.pageContainer.trigger(b,p);b.isDefaultPrevented()||
-(f.showLoadMsg&&(clearTimeout(s),a.mobile.hidePageLoadingMsg(),a("<div class='ui-loader ui-overlay-shadow ui-body-e ui-corner-all'><h1>"+a.mobile.pageLoadErrorMessage+"</h1></div>").css({display:"block",opacity:0.96,top:o.scrollTop()+100}).appendTo(f.pageContainer).delay(800).fadeOut(400,function(){a(this).remove()})),e.reject(r,c))}});return e.promise()};a.mobile.loadPage.defaults={type:"get",data:d,reloadPage:false,role:d,showLoadMsg:false,pageContainer:d,loadMsgDelay:50};a.mobile.changePage=function(b,
-g){if(z)A.unshift(arguments);else{var h=a.extend({},a.mobile.changePage.defaults,g);h.pageContainer=h.pageContainer||a.mobile.pageContainer;h.fromPage=h.fromPage||a.mobile.activePage;var m=h.pageContainer,k=new a.Event("pagebeforechange"),p={toPage:b,options:h};m.trigger(k,p);if(!k.isDefaultPrevented())if(b=p.toPage,z=true,typeof b=="string")a.mobile.loadPage(b,h).done(function(b,c,d,f){z=false;c.duplicateCachedPage=f;a.mobile.changePage(d,c)}).fail(function(){z=false;c(true);f();h.pageContainer.trigger("pagechangefailed",
-p)});else{if(b[0]===a.mobile.firstPage[0]&&!h.dataUrl)h.dataUrl=w.hrefNoHash;var k=h.fromPage,s=h.dataUrl&&j.convertUrlToDataUrl(h.dataUrl)||b.jqmData("url"),t=s;j.getFilePath(s);var n=l.getActive(),x=l.activeIndex===0,o=0,v=document.title,y=h.role==="dialog"||b.jqmData("role")==="dialog";if(k&&k[0]===b[0]&&!h.allowSamePageTransition)z=false,m.trigger("pagechange",p);else{i(b,h.role);h.fromHashChange&&l.directHashChange({currentUrl:s,isBack:function(){o=-1},isForward:function(){o=1}});try{a(document.activeElement||
-"").add("input:focus, textarea:focus, select:focus").blur()}catch(B){}y&&n&&(s=(n.url||"")+r);if(h.changeHash!==false&&s)l.ignoreNextHashChange=true,j.set(s);var C=b.jqmData("title")||b.children(":jqmData(role='header')").find(".ui-title").getEncodedText();C&&v==document.title&&(v=C);h.transition=h.transition||(o&&!x?n.transition:d)||(y?a.mobile.defaultDialogTransition:a.mobile.defaultPageTransition);o||l.addNew(s,h.transition,v,t,h.role);document.title=l.getActive().title;a.mobile.activePage=b;h.reverse=
-h.reverse||o<0;e(b,k,h.transition,h.reverse).done(function(){c();h.duplicateCachedPage&&h.duplicateCachedPage.remove();q.removeClass("ui-mobile-rendering");f();m.trigger("pagechange",p)})}}}};a.mobile.changePage.defaults={transition:d,reverse:false,changeHash:true,fromHashChange:false,role:d,duplicateCachedPage:d,pageContainer:d,showLoadMsg:true,dataUrl:d,fromPage:d,allowSamePageTransition:false};a.mobile._registerInternalEvents=function(){a("form").live("submit",function(b){var c=a(this);if(a.mobile.ajaxEnabled&&
-!c.is(":jqmData(ajax='false')")){var d=c.attr("method"),f=c.attr("target"),e=c.attr("action");if(!e&&(e=n(c),e===t.hrefNoHash))e=w.hrefNoSearch;e=j.makeUrlAbsolute(e,n(c));!j.isExternal(e)&&!f&&(a.mobile.changePage(e,{type:d&&d.length&&d.toLowerCase()||"get",data:c.serialize(),transition:c.jqmData("transition"),direction:c.jqmData("direction"),reloadPage:true}),b.preventDefault())}});a(document).bind("vclick",function(b){if(!(b.which>1)&&(b=k(b.target))&&j.parseUrl(b.getAttribute("href")||"#").hash!==
-"#")c(true),p=a(b).closest(".ui-btn").not(".ui-disabled"),p.addClass(a.mobile.activeBtnClass),a("."+a.mobile.activePageClass+" .ui-btn").not(b).blur()});a(document).bind("click",function(b){var f=k(b.target);if(f&&!(b.which>1)){var e=a(f),g=function(){window.setTimeout(function(){c(true)},200)};if(e.is(":jqmData(rel='back')"))return window.history.back(),false;var h=n(e),f=j.makeUrlAbsolute(e.attr("href")||"#",h);if(!a.mobile.ajaxEnabled&&!j.isEmbeddedPage(f))g();else{if(f.search("#")!=-1)if(f=f.replace(/[^#]*#/,
-""))f=j.isPath(f)?j.makeUrlAbsolute(f,h):j.makeUrlAbsolute("#"+f,w.hrefNoHash);else{b.preventDefault();return}var h=e.is("[rel='external']")||e.is(":jqmData(ajax='false')")||e.is("[target]"),i=a.mobile.allowCrossDomainPages&&w.protocol==="file:"&&f.search(/^https?:/)!=-1;h||j.isExternal(f)&&!i?g():(g=e.jqmData("transition"),h=(h=e.jqmData("direction"))&&h==="reverse"||e.jqmData("back"),e=e.attr("data-"+a.mobile.ns+"rel")||d,a.mobile.changePage(f,{transition:g,reverse:h,role:e}),b.preventDefault())}}});
-a(".ui-page").live("pageshow.prefetch",function(){var b=[];a(this).find("a:jqmData(prefetch)").each(function(){var c=a(this),f=c.attr("href");f&&a.inArray(f,b)===-1&&(b.push(f),a.mobile.loadPage(f,{role:c.attr("data-"+a.mobile.ns+"rel")}))})});a.mobile._handleHashChange=function(b){var c=j.stripHash(b),f={transition:a.mobile.urlHistory.stack.length===0?"none":d,changeHash:false,fromHashChange:true};if(!a.mobile.hashListeningEnabled||l.ignoreNextHashChange)l.ignoreNextHashChange=false;else{if(l.stack.length>
-1&&c.indexOf(r)>-1)if(a.mobile.activePage.is(".ui-dialog"))l.directHashChange({currentUrl:c,either:function(b){var e=a.mobile.urlHistory.getActive();c=e.pageUrl;a.extend(f,{role:e.role,transition:e.transition,reverse:b})}});else{l.directHashChange({currentUrl:c,isBack:function(){window.history.back()},isForward:function(){window.history.forward()}});return}c?(c=typeof c==="string"&&!j.isPath(c)?j.makeUrlAbsolute("#"+c,t):c,a.mobile.changePage(c,f)):a.mobile.changePage(a.mobile.firstPage,f)}};o.bind("hashchange",
-function(){a.mobile._handleHashChange(location.hash)});a(document).bind("pageshow",h);a(window).bind("throttledresize",h)}})(jQuery);
-(function(a,d){var b={},c=a(d),f=a.mobile.path.parseUrl(location.href);a.extend(b,{initialFilePath:f.pathname+f.search,initialHref:f.hrefNoHash,hashchangeFired:false,state:function(){return{hash:location.hash||"#"+b.initialFilePath,title:document.title,initialHref:b.initialHref}},resetUIKeys:function(b){var c="&"+a.mobile.subPageUrlKey,f=b.indexOf(a.mobile.dialogHashKey);f>-1?b=b.slice(0,f)+"#"+b.slice(f):b.indexOf(c)>-1&&(b=b.split(c).join("#"+c));return b},nextHashChangePrevented:function(c){a.mobile.urlHistory.ignoreNextHashChange=
-c;b.onHashChangeDisabled=c},onHashChange:function(){if(!b.onHashChangeDisabled){var c,f;c=location.hash;var d=a.mobile.path.isPath(c),i=d?location.href:a.mobile.getDocumentUrl();c=d?c.replace("#",""):c;f=b.state();c=a.mobile.path.makeUrlAbsolute(c,i);d&&(c=b.resetUIKeys(c));history.replaceState(f,document.title,c)}},onPopState:function(c){var f=c.originalEvent.state;f&&(b.nextHashChangePrevented(true),setTimeout(function(){b.nextHashChangePrevented(false);a.mobile._handleHashChange(f.hash)},100))},
-init:function(){c.bind("hashchange",b.onHashChange);c.bind("popstate",b.onPopState);location.hash===""&&history.replaceState(b.state(),document.title,location.href)}});a(function(){a.mobile.pushStateEnabled&&a.support.pushState&&b.init()})})(jQuery,this);
-(function(a){function d(b,c,f,d){var g=new a.Deferred,h=c?" reverse":"",i="ui-mobile-viewport-transitioning viewport-"+b;f.animationComplete(function(){f.add(d).removeClass("out in reverse "+b);d&&d[0]!==f[0]&&d.removeClass(a.mobile.activePageClass);f.parent().removeClass(i);g.resolve(b,c,f,d)});f.parent().addClass(i);d&&d.addClass(b+" out"+h);f.addClass(a.mobile.activePageClass+" "+b+" in"+h);return g.promise()}a.mobile.css3TransitionHandler=d;if(a.mobile.defaultTransitionHandler===a.mobile.noneTransitionHandler)a.mobile.defaultTransitionHandler=
-d})(jQuery,this);
-(function(a){a.mobile.page.prototype.options.degradeInputs={color:false,date:false,datetime:false,"datetime-local":false,email:false,month:false,number:false,range:"number",search:"text",tel:false,time:false,url:false,week:false};a(document).bind("pagecreate create",function(d){var b=a(d.target).closest(':jqmData(role="page")').data("page"),c;if(b)c=b.options,a(d.target).find("input").not(b.keepNativeSelector()).each(function(){var b=a(this),d=this.getAttribute("type"),g=c.degradeInputs[d]||"text";
-if(c.degradeInputs[d]){var h=a("<div>").html(b.clone()).html(),i=h.indexOf(" type=")>-1;b.replaceWith(h.replace(i?/\s+type=["']?\w+['"]?/:/\/?>/,' type="'+g+'" data-'+a.mobile.ns+'type="'+d+'"'+(i?"":">")))}})})})(jQuery);
-(function(a,d){a.widget("mobile.dialog",a.mobile.widget,{options:{closeBtnText:"Close",theme:"a",initSelector:":jqmData(role='dialog')"},_create:function(){var b=this,c=this.element,f=c.attr("class").match(/ui-body-[a-z]/),d=a("<a href='#' data-"+a.mobile.ns+"icon='delete' data-"+a.mobile.ns+"iconpos='notext'>"+this.options.closeBtnText+"</a>");f.length&&c.removeClass(f[0]);c.addClass("ui-body-"+this.options.theme);c.attr("role","dialog").addClass("ui-dialog").find(":jqmData(role='header')").addClass("ui-corner-top ui-overlay-shadow").prepend(d).end().find(":jqmData(role='content'),:jqmData(role='footer')").last().addClass("ui-corner-bottom ui-overlay-shadow");
-d.bind("vclick",function(){b.close()});c.bind("vclick submit",function(b){var b=a(b.target).closest(b.type==="vclick"?"a":"form"),c;b.length&&!b.jqmData("transition")&&(c=a.mobile.urlHistory.getActive()||{},b.attr("data-"+a.mobile.ns+"transition",c.transition||a.mobile.defaultDialogTransition).attr("data-"+a.mobile.ns+"direction","reverse"))}).bind("pagehide",function(){a(this).find("."+a.mobile.activeBtnClass).removeClass(a.mobile.activeBtnClass)})},close:function(){d.history.back()}});a(a.mobile.dialog.prototype.options.initSelector).live("pagecreate",
-function(){a(this).dialog()})})(jQuery,this);
-(function(a){a.mobile.page.prototype.options.backBtnText="Back";a.mobile.page.prototype.options.addBackBtn=false;a.mobile.page.prototype.options.backBtnTheme=null;a.mobile.page.prototype.options.headerTheme="a";a.mobile.page.prototype.options.footerTheme="a";a.mobile.page.prototype.options.contentTheme=null;a(":jqmData(role='page'), :jqmData(role='dialog')").live("pagecreate",function(){var d=a(this).data("page").options,b=d.theme;a(":jqmData(role='header'), :jqmData(role='footer'), :jqmData(role='content')",this).each(function(){var c=
-a(this),f=c.jqmData("role"),e=c.jqmData("theme"),g,h;c.addClass("ui-"+f);if(f==="header"||f==="footer"){var i=e||(f==="header"?d.headerTheme:d.footerTheme)||b;c.addClass("ui-bar-"+i).attr("role",f==="header"?"banner":"contentinfo");e=c.children("a");g=e.hasClass("ui-btn-left");h=e.hasClass("ui-btn-right");g=g||e.eq(0).not(".ui-btn-right").addClass("ui-btn-left").length;h||e.eq(1).addClass("ui-btn-right");d.addBackBtn&&f==="header"&&a(".ui-page").length>1&&c.jqmData("url")!==a.mobile.path.stripHash(location.hash)&&
-!g&&a("<a href='#' class='ui-btn-left' data-"+a.mobile.ns+"rel='back' data-"+a.mobile.ns+"icon='arrow-l'>"+d.backBtnText+"</a>").attr("data-"+a.mobile.ns+"theme",d.backBtnTheme||i).prependTo(c);c.children("h1, h2, h3, h4, h5, h6").addClass("ui-title").attr({tabindex:"0",role:"heading","aria-level":"1"})}else if(f==="content"){if(e||d.contentTheme)c.addClass("ui-body-"+(e||d.contentTheme));c.attr("role","main")}})})})(jQuery);
-(function(a){a.widget("mobile.collapsible",a.mobile.widget,{options:{expandCueText:" click to expand contents",collapseCueText:" click to collapse contents",collapsed:true,heading:">:header,>legend",theme:null,contentTheme:null,iconTheme:"d",initSelector:":jqmData(role='collapsible')"},_create:function(){var d=this.element,b=this.options,c=d.addClass("ui-collapsible"),f=d.find(b.heading).eq(0),e=c.wrapInner("<div class='ui-collapsible-content'></div>").find(".ui-collapsible-content"),g=d.closest(":jqmData(role='collapsible-set')").addClass("ui-collapsible-set"),
-d=g.children(":jqmData(role='collapsible')");f.is("legend")&&(f=a("<div role='heading'>"+f.html()+"</div>").insertBefore(f),f.next().remove());if(g.length){if(!b.theme)b.theme=g.jqmData("theme");if(!b.contentTheme)b.contentTheme=g.jqmData("content-theme")}e.addClass(b.contentTheme?"ui-body-"+b.contentTheme:"");f.insertBefore(e).addClass("ui-collapsible-heading").append("<span class='ui-collapsible-heading-status'></span>").wrapInner("<a href='#' class='ui-collapsible-heading-toggle'></a>").find("a:eq(0)").buttonMarkup({shadow:false,
-corners:false,iconPos:"left",icon:"plus",theme:b.theme});g.length?(g.jqmData("collapsiblebound")||g.jqmData("collapsiblebound",true).bind("expand",function(b){a(b.target).closest(".ui-collapsible").siblings(".ui-collapsible").trigger("collapse")}),d.first().find("a:eq(0)").addClass("ui-corner-top").find(".ui-btn-inner").addClass("ui-corner-top"),d.last().jqmData("collapsible-last",true).find("a:eq(0)").addClass("ui-corner-bottom").find(".ui-btn-inner").addClass("ui-corner-bottom"),c.jqmData("collapsible-last")&&
-f.find("a:eq(0), .ui-btn-inner").addClass("ui-corner-bottom")):f.find("a:eq(0), .ui-btn-inner").addClass("ui-corner-top ui-corner-bottom");c.bind("expand collapse",function(d){if(!d.isDefaultPrevented()){d.preventDefault();var i=a(this),d=d.type==="collapse",k=b.contentTheme;f.toggleClass("ui-collapsible-heading-collapsed",d).find(".ui-collapsible-heading-status").text(d?b.expandCueText:b.collapseCueText).end().find(".ui-icon").toggleClass("ui-icon-minus",!d).toggleClass("ui-icon-plus",d);i.toggleClass("ui-collapsible-collapsed",
-d);e.toggleClass("ui-collapsible-content-collapsed",d).attr("aria-hidden",d);if(k&&(!g.length||c.jqmData("collapsible-last")))f.find("a:eq(0), .ui-btn-inner").toggleClass("ui-corner-bottom",d),e.toggleClass("ui-corner-bottom",!d);e.trigger("updatelayout")}}).trigger(b.collapsed?"collapse":"expand");f.bind("click",function(a){var b=f.is(".ui-collapsible-heading-collapsed")?"expand":"collapse";c.trigger(b);a.preventDefault()})}});a(document).bind("pagecreate create",function(d){a(a.mobile.collapsible.prototype.options.initSelector,
-d.target).collapsible()})})(jQuery);(function(a){a.fn.fieldcontain=function(){return this.addClass("ui-field-contain ui-body ui-br")};a(document).bind("pagecreate create",function(d){a(":jqmData(role='fieldcontain')",d.target).fieldcontain()})})(jQuery);
-(function(a){a.fn.grid=function(d){return this.each(function(){var b=a(this),c=a.extend({grid:null},d),f=b.children(),e={solo:1,a:2,b:3,c:4,d:5},c=c.grid;if(!c)if(f.length<=5)for(var g in e)e[g]===f.length&&(c=g);else c="a";e=e[c];b.addClass("ui-grid-"+c);f.filter(":nth-child("+e+"n+1)").addClass("ui-block-a");e>1&&f.filter(":nth-child("+e+"n+2)").addClass("ui-block-b");e>2&&f.filter(":nth-child(3n+3)").addClass("ui-block-c");e>3&&f.filter(":nth-child(4n+4)").addClass("ui-block-d");e>4&&f.filter(":nth-child(5n+5)").addClass("ui-block-e")})}})(jQuery);
-(function(a,d){a.widget("mobile.navbar",a.mobile.widget,{options:{iconpos:"top",grid:null,initSelector:":jqmData(role='navbar')"},_create:function(){var b=this.element,c=b.find("a"),f=c.filter(":jqmData(icon)").length?this.options.iconpos:d;b.addClass("ui-navbar").attr("role","navigation").find("ul").grid({grid:this.options.grid});f||b.addClass("ui-navbar-noicons");c.buttonMarkup({corners:false,shadow:false,iconpos:f});b.delegate("a","vclick",function(){c.not(".ui-state-persist").removeClass(a.mobile.activeBtnClass);
-a(this).addClass(a.mobile.activeBtnClass)})}});a(document).bind("pagecreate create",function(b){a(a.mobile.navbar.prototype.options.initSelector,b.target).navbar()})})(jQuery);
-(function(a){var d={};a.widget("mobile.listview",a.mobile.widget,{options:{theme:"c",countTheme:"c",headerTheme:"b",dividerTheme:"b",splitIcon:"arrow-r",splitTheme:"b",inset:false,initSelector:":jqmData(role='listview')"},_create:function(){var a=this;a.element.addClass(function(c,d){return d+" ui-listview "+(a.options.inset?" ui-listview-inset ui-corner-all ui-shadow ":"")});a.refresh(true)},_itemApply:function(b,c){var d=c.find(".ui-li-count");d.length&&c.addClass("ui-li-has-count");d.addClass("ui-btn-up-"+
-(b.jqmData("counttheme")||this.options.countTheme)+" ui-btn-corner-all");c.find("h1, h2, h3, h4, h5, h6").addClass("ui-li-heading").end().find("p, dl").addClass("ui-li-desc").end().find(">img:eq(0), .ui-link-inherit>img:eq(0)").addClass("ui-li-thumb").each(function(){c.addClass(a(this).is(".ui-li-icon")?"ui-li-has-icon":"ui-li-has-thumb")}).end().find(".ui-li-aside").each(function(){var b=a(this);b.prependTo(b.parent())})},_removeCorners:function(a,c){a=a.add(a.find(".ui-btn-inner, .ui-li-link-alt, .ui-li-thumb"));
-c==="top"?a.removeClass("ui-corner-top ui-corner-tr ui-corner-tl"):c==="bottom"?a.removeClass("ui-corner-bottom ui-corner-br ui-corner-bl"):a.removeClass("ui-corner-top ui-corner-tr ui-corner-tl ui-corner-bottom ui-corner-br ui-corner-bl")},_refreshCorners:function(a){var c,d;this.options.inset&&(c=this.element.children("li"),d=a?c.not(".ui-screen-hidden"):c.filter(":visible"),this._removeCorners(c),c=d.first().addClass("ui-corner-top"),c.add(c.find(".ui-btn-inner")).find(".ui-li-link-alt").addClass("ui-corner-tr").end().find(".ui-li-thumb").not(".ui-li-icon").addClass("ui-corner-tl"),
-d=d.last().addClass("ui-corner-bottom"),d.add(d.find(".ui-btn-inner")).find(".ui-li-link-alt").addClass("ui-corner-br").end().find(".ui-li-thumb").not(".ui-li-icon").addClass("ui-corner-bl"));a||this.element.trigger("updatelayout")},refresh:function(b){this.parentPage=this.element.closest(".ui-page");this._createSubPages();var c=this.options,d=this.element,e=d.jqmData("dividertheme")||c.dividerTheme,g=d.jqmData("splittheme"),h=d.jqmData("spliticon"),i=d.children("li"),k=a.support.cssPseudoElement||
-!a.nodeName(d[0],"ol")?0:1,n,o,q,m,j;k&&d.find(".ui-li-dec").remove();for(var p=0,l=i.length;p<l;p++){n=i.eq(p);o="ui-li";if(b||!n.hasClass("ui-li"))q=n.jqmData("theme")||c.theme,m=n.children("a"),m.length?(j=n.jqmData("icon"),n.buttonMarkup({wrapperEls:"div",shadow:false,corners:false,iconpos:"right",icon:m.length>1||j===false?false:j||"arrow-r",theme:q}),j!=false&&m.length==1&&n.addClass("ui-li-has-arrow"),m.first().addClass("ui-link-inherit"),m.length>1&&(o+=" ui-li-has-alt",m=m.last(),j=g||m.jqmData("theme")||
-c.splitTheme,m.appendTo(n).attr("title",m.getEncodedText()).addClass("ui-li-link-alt").empty().buttonMarkup({shadow:false,corners:false,theme:q,icon:false,iconpos:false}).find(".ui-btn-inner").append(a("<span />").buttonMarkup({shadow:true,corners:true,theme:j,iconpos:"notext",icon:h||m.jqmData("icon")||c.splitIcon})))):n.jqmData("role")==="list-divider"?(o+=" ui-li-divider ui-btn ui-bar-"+e,n.attr("role","heading"),k&&(k=1)):o+=" ui-li-static ui-body-"+q;k&&o.indexOf("ui-li-divider")<0&&(q=n.is(".ui-li-static:first")?
-n:n.find(".ui-link-inherit"),q.addClass("ui-li-jsnumbering").prepend("<span class='ui-li-dec'>"+k++ +". </span>"));n.add(n.children(".ui-btn-inner")).addClass(o);this._itemApply(d,n)}this._refreshCorners(b)},_idStringEscape:function(a){return a.replace(/[^a-zA-Z0-9]/g,"-")},_createSubPages:function(){var b=this.element,c=b.closest(".ui-page"),f=c.jqmData("url"),e=f||c[0][a.expando],g=b.attr("id"),h=this.options,i="data-"+a.mobile.ns,k=this,n=c.find(":jqmData(role='footer')").jqmData("id"),o;typeof d[e]===
-"undefined"&&(d[e]=-1);g=g||++d[e];a(b.find("li>ul, li>ol").toArray().reverse()).each(function(c){var d=a(this),e=d.attr("id")||g+"-"+c,c=d.parent(),k=a(d.prevAll().toArray().reverse()),k=k.length?k:a("<span>"+a.trim(c.contents()[0].nodeValue)+"</span>"),l=k.first().getEncodedText(),e=(f||"")+"&"+a.mobile.subPageUrlKey+"="+e,A=d.jqmData("theme")||h.theme,z=d.jqmData("counttheme")||b.jqmData("counttheme")||h.countTheme;o=true;d.detach().wrap("<div "+i+"role='page' "+i+"url='"+e+"' "+i+"theme='"+A+
-"' "+i+"count-theme='"+z+"'><div "+i+"role='content'></div></div>").parent().before("<div "+i+"role='header' "+i+"theme='"+h.headerTheme+"'><div class='ui-title'>"+l+"</div></div>").after(n?a("<div "+i+"role='footer' "+i+"id='"+n+"'>"):"").parent().appendTo(a.mobile.pageContainer).page();d=c.find("a:first");d.length||(d=a("<a/>").html(k||l).prependTo(c.empty()));d.attr("href","#"+e)}).listview();o&&c.is(":jqmData(external-page='true')")&&c.data("page").options.domCache===false&&c.unbind("pagehide.remove").bind("pagehide.remove",
-function(b,d){var e=d.nextPage;d.nextPage&&(e=e.jqmData("url"),e.indexOf(f+"&"+a.mobile.subPageUrlKey)!==0&&(k.childPages().remove(),c.remove()))})},childPages:function(){var b=this.parentPage.jqmData("url");return a(":jqmData(url^='"+b+"&"+a.mobile.subPageUrlKey+"')")}});a(document).bind("pagecreate create",function(b){a(a.mobile.listview.prototype.options.initSelector,b.target).listview()})})(jQuery);
-(function(a){a.mobile.listview.prototype.options.filter=false;a.mobile.listview.prototype.options.filterPlaceholder="Filter items...";a.mobile.listview.prototype.options.filterTheme="c";a.mobile.listview.prototype.options.filterCallback=function(a,b){return a.toLowerCase().indexOf(b)===-1};a(":jqmData(role='listview')").live("listviewcreate",function(){var d=a(this),b=d.data("listview");if(b.options.filter){var c=a("<form>",{"class":"ui-listview-filter ui-bar-"+b.options.filterTheme,role:"search"});
-a("<input>",{placeholder:b.options.filterPlaceholder}).attr("data-"+a.mobile.ns+"type","search").jqmData("lastval","").bind("keyup change",function(){var c=a(this),e=this.value.toLowerCase(),g=null,g=c.jqmData("lastval")+"",h=false,i="";c.jqmData("lastval",e);i=e.replace(RegExp("^"+g),"");g=e.length<g.length||i.length!=e.length-g.length?d.children():d.children(":not(.ui-screen-hidden)");if(e){for(var k=g.length-1;k>=0;k--)c=a(g[k]),i=c.jqmData("filtertext")||c.text(),c.is("li:jqmData(role=list-divider)")?
-(c.toggleClass("ui-filter-hidequeue",!h),h=false):b.options.filterCallback(i,e)?c.toggleClass("ui-filter-hidequeue",true):h=true;g.filter(":not(.ui-filter-hidequeue)").toggleClass("ui-screen-hidden",false);g.filter(".ui-filter-hidequeue").toggleClass("ui-screen-hidden",true).toggleClass("ui-filter-hidequeue",false)}else g.toggleClass("ui-screen-hidden",false);b._refreshCorners()}).appendTo(c).textinput();a(this).jqmData("inset")&&c.addClass("ui-listview-filter-inset");c.bind("submit",function(){return false}).insertBefore(d)}})})(jQuery);
-(function(a){a(document).bind("pagecreate create",function(d){a(":jqmData(role='nojs')",d.target).addClass("ui-nojs")})})(jQuery);
-(function(a,d){a.widget("mobile.checkboxradio",a.mobile.widget,{options:{theme:null,initSelector:"input[type='checkbox'],input[type='radio']"},_create:function(){var b=this,c=this.element,f=c.closest("form,fieldset,:jqmData(role='page')").find("label").filter("[for='"+c[0].id+"']"),e=c.attr("type"),g=e+"-on",h=e+"-off",i=c.parents(":jqmData(type='horizontal')").length?d:h;if(!(e!=="checkbox"&&e!=="radio")){a.extend(this,{label:f,inputtype:e,checkedClass:"ui-"+g+(i?"":" "+a.mobile.activeBtnClass),
-uncheckedClass:"ui-"+h,checkedicon:"ui-icon-"+g,uncheckedicon:"ui-icon-"+h});if(!this.options.theme)this.options.theme=this.element.jqmData("theme");f.buttonMarkup({theme:this.options.theme,icon:i,shadow:false});c.add(f).wrapAll("<div class='ui-"+e+"'></div>");f.bind({vmouseover:function(b){a(this).parent().is(".ui-disabled")&&b.stopPropagation()},vclick:function(a){if(c.is(":disabled"))a.preventDefault();else return b._cacheVals(),c.prop("checked",e==="radio"&&true||!c.prop("checked")),b._getInputSet().not(c).prop("checked",
-false),b._updateAll(),false}});c.bind({vmousedown:function(){this._cacheVals()},vclick:function(){var c=a(this);c.is(":checked")?(c.prop("checked",true),b._getInputSet().not(c).prop("checked",false)):c.prop("checked",false);b._updateAll()},focus:function(){f.addClass("ui-focus")},blur:function(){f.removeClass("ui-focus")}});this.refresh()}},_cacheVals:function(){this._getInputSet().each(function(){var b=a(this);b.jqmData("cacheVal",b.is(":checked"))})},_getInputSet:function(){return this.inputtype==
-"checkbox"?this.element:this.element.closest("form,fieldset,:jqmData(role='page')").find("input[name='"+this.element.attr("name")+"'][type='"+this.inputtype+"']")},_updateAll:function(){var b=this;this._getInputSet().each(function(){var c=a(this);(c.is(":checked")||b.inputtype==="checkbox")&&c.trigger("change")}).checkboxradio("refresh")},refresh:function(){var b=this.element,c=this.label,d=c.find(".ui-icon");a(b[0]).prop("checked")?(c.addClass(this.checkedClass).removeClass(this.uncheckedClass),
-d.addClass(this.checkedicon).removeClass(this.uncheckedicon)):(c.removeClass(this.checkedClass).addClass(this.uncheckedClass),d.removeClass(this.checkedicon).addClass(this.uncheckedicon));b.is(":disabled")?this.disable():this.enable()},disable:function(){this.element.prop("disabled",true).parent().addClass("ui-disabled")},enable:function(){this.element.prop("disabled",false).parent().removeClass("ui-disabled")}});a(document).bind("pagecreate create",function(b){a.mobile.checkboxradio.prototype.enhanceWithin(b.target)})})(jQuery);
-(function(a,d){a.widget("mobile.button",a.mobile.widget,{options:{theme:null,icon:null,iconpos:null,inline:null,corners:true,shadow:true,iconshadow:true,initSelector:"button, [type='button'], [type='submit'], [type='reset'], [type='image']"},_create:function(){var b=this.element,c=this.options,f,e;this.button=a("<div></div>").text(b.text()||b.val()).insertBefore(b).buttonMarkup({theme:c.theme,icon:c.icon,iconpos:c.iconpos,inline:c.inline,corners:c.corners,shadow:c.shadow,iconshadow:c.iconshadow}).append(b.addClass("ui-btn-hidden"));
-c=b.attr("type");f=b.attr("name");c!=="button"&&c!=="reset"&&f&&b.bind("vclick",function(){e===d&&(e=a("<input>",{type:"hidden",name:b.attr("name"),value:b.attr("value")}).insertBefore(b),a(document).submit(function(){e.remove()}))});this.refresh()},enable:function(){this.element.attr("disabled",false);this.button.removeClass("ui-disabled").attr("aria-disabled",false);return this._setOption("disabled",false)},disable:function(){this.element.attr("disabled",true);this.button.addClass("ui-disabled").attr("aria-disabled",
-true);return this._setOption("disabled",true)},refresh:function(){this.element.attr("disabled")?this.disable():this.enable()}});a(document).bind("pagecreate create",function(b){a.mobile.button.prototype.enhanceWithin(b.target)})})(jQuery);
-(function(a,d){a.widget("mobile.slider",a.mobile.widget,{options:{theme:null,trackTheme:null,disabled:false,initSelector:"input[type='range'], :jqmData(type='range'), :jqmData(role='slider')"},_create:function(){var b=this,c=this.element,f=a.mobile.getInheritedTheme(c,"c"),e=this.options.theme||f,g=this.options.trackTheme||f,h=c[0].nodeName.toLowerCase(),f=h=="select"?"ui-slider-switch":"",i=c.attr("id"),k=i+"-label",i=a("[for='"+i+"']").attr("id",k),n=function(){return h=="input"?parseFloat(c.val()):
-c[0].selectedIndex},o=h=="input"?parseFloat(c.attr("min")):0,q=h=="input"?parseFloat(c.attr("max")):c.find("option").length-1,m=window.parseFloat(c.attr("step")||1),j=a("<div class='ui-slider "+f+" ui-btn-down-"+g+" ui-btn-corner-all' role='application'></div>"),p=a("<a href='#' class='ui-slider-handle'></a>").appendTo(j).buttonMarkup({corners:true,theme:e,shadow:true}).attr({role:"slider","aria-valuemin":o,"aria-valuemax":q,"aria-valuenow":n(),"aria-valuetext":n(),title:n(),"aria-labelledby":k});
-a.extend(this,{slider:j,handle:p,dragging:false,beforeStart:null,userModified:false});h=="select"&&(j.wrapInner("<div class='ui-slider-inneroffset'></div>"),c.find("option"),c.find("option").each(function(b){var c=!b?"b":"a",d=!b?"right":"left",b=!b?" ui-btn-down-"+g:" "+a.mobile.activeBtnClass;a("<div class='ui-slider-labelbg ui-slider-labelbg-"+c+b+" ui-btn-corner-"+d+"'></div>").prependTo(j);a("<span class='ui-slider-label ui-slider-label-"+c+b+" ui-btn-corner-"+d+"' role='img'>"+a(this).getEncodedText()+
-"</span>").prependTo(p)}));i.addClass("ui-slider");c.addClass(h==="input"?"ui-slider-input":"ui-slider-switch").change(function(){b.refresh(n(),true)}).keyup(function(){b.refresh(n(),true,true)}).blur(function(){b.refresh(n(),true)});a(document).bind("vmousemove",function(a){if(b.dragging)return b.refresh(a),b.userModified=b.userModified||b.beforeStart!==c[0].selectedIndex,false});j.bind("vmousedown",function(a){b.dragging=true;b.userModified=false;if(h==="select")b.beforeStart=c[0].selectedIndex;
-b.refresh(a);return false});j.add(document).bind("vmouseup",function(){if(b.dragging)return b.dragging=false,h==="select"&&!b.userModified&&(p.addClass("ui-slider-handle-snapping"),b.refresh(!b.beforeStart?1:0)),false});j.insertAfter(c);this.handle.bind("vmousedown",function(){a(this).focus()}).bind("vclick",false);this.handle.bind("keydown",function(c){var d=n();if(!b.options.disabled){switch(c.keyCode){case a.mobile.keyCode.HOME:case a.mobile.keyCode.END:case a.mobile.keyCode.PAGE_UP:case a.mobile.keyCode.PAGE_DOWN:case a.mobile.keyCode.UP:case a.mobile.keyCode.RIGHT:case a.mobile.keyCode.DOWN:case a.mobile.keyCode.LEFT:if(c.preventDefault(),
-!b._keySliding)b._keySliding=true,a(this).addClass("ui-state-active")}switch(c.keyCode){case a.mobile.keyCode.HOME:b.refresh(o);break;case a.mobile.keyCode.END:b.refresh(q);break;case a.mobile.keyCode.PAGE_UP:case a.mobile.keyCode.UP:case a.mobile.keyCode.RIGHT:b.refresh(d+m);break;case a.mobile.keyCode.PAGE_DOWN:case a.mobile.keyCode.DOWN:case a.mobile.keyCode.LEFT:b.refresh(d-m)}}}).keyup(function(){if(b._keySliding)b._keySliding=false,a(this).removeClass("ui-state-active")});this.refresh(d,d,true)},
-refresh:function(a,c,d){if(this.options.disabled||this.element.attr("disabled"))this.slider.addClass("ui-disabled");else{var e=this.element,g,h=e[0].nodeName.toLowerCase(),i=h==="input"?parseFloat(e.attr("min")):0,k=h==="input"?parseFloat(e.attr("max")):e.find("option").length-1;if(typeof a==="object"){if(!this.dragging||a.pageX<this.slider.offset().left-8||a.pageX>this.slider.offset().left+this.slider.width()+8)return;g=Math.round((a.pageX-this.slider.offset().left)/this.slider.width()*100)}else a==
-null&&(a=h==="input"?parseFloat(e.val()):e[0].selectedIndex),g=(parseFloat(a)-i)/(k-i)*100;if(!isNaN(g)&&(g<0&&(g=0),g>100&&(g=100),a=Math.round(g/100*(k-i))+i,a<i&&(a=i),a>k&&(a=k),this.handle.css("left",g+"%"),this.handle.attr({"aria-valuenow":h==="input"?a:e.find("option").eq(a).attr("value"),"aria-valuetext":h==="input"?a:e.find("option").eq(a).getEncodedText(),title:a}),h==="select"&&(a===0?this.slider.addClass("ui-slider-switch-a").removeClass("ui-slider-switch-b"):this.slider.addClass("ui-slider-switch-b").removeClass("ui-slider-switch-a")),
-!d))d=false,h==="input"?(d=e.val()!==a,e.val(a)):(d=e[0].selectedIndex!==a,e[0].selectedIndex=a),!c&&d&&e.trigger("change")}},enable:function(){this.element.attr("disabled",false);this.slider.removeClass("ui-disabled").attr("aria-disabled",false);return this._setOption("disabled",false)},disable:function(){this.element.attr("disabled",true);this.slider.addClass("ui-disabled").attr("aria-disabled",true);return this._setOption("disabled",true)}});a(document).bind("pagecreate create",function(b){a.mobile.slider.prototype.enhanceWithin(b.target)})})(jQuery);
-(function(a){a.widget("mobile.textinput",a.mobile.widget,{options:{theme:null,initSelector:"input[type='text'], input[type='search'], :jqmData(type='search'), input[type='number'], :jqmData(type='number'), input[type='password'], input[type='email'], input[type='url'], input[type='tel'], textarea, input[type='time'], input[type='date'], input[type='month'], input[type='week'], input[type='datetime'], input[type='datetime-local'], input[type='color'], input:not([type])"},_create:function(){var d=this.element,
-b=this.options.theme,c,f,e;b||(b=a.mobile.getInheritedTheme(this.element,"c"));c=" ui-body-"+b;a("label[for='"+d.attr("id")+"']").addClass("ui-input-text");d.addClass("ui-input-text ui-body-"+b);f=d;typeof d[0].autocorrect!=="undefined"&&!a.support.touchOverflow&&(d[0].setAttribute("autocorrect","off"),d[0].setAttribute("autocomplete","off"));d.is("[type='search'],:jqmData(type='search')")?(f=d.wrap("<div class='ui-input-search ui-shadow-inset ui-btn-corner-all ui-btn-shadow ui-icon-searchfield"+
-c+"'></div>").parent(),e=a("<a href='#' class='ui-input-clear' title='clear text'>clear text</a>").tap(function(a){d.val("").focus();d.trigger("change");e.addClass("ui-input-clear-hidden");a.preventDefault()}).appendTo(f).buttonMarkup({icon:"delete",iconpos:"notext",corners:true,shadow:true}),b=function(){d.val()?e.removeClass("ui-input-clear-hidden"):e.addClass("ui-input-clear-hidden")},b(),d.keyup(b).focus(b)):d.addClass("ui-corner-all ui-shadow-inset"+c);d.focus(function(){f.addClass("ui-focus")}).blur(function(){f.removeClass("ui-focus")});
-if(d.is("textarea")){var g=function(){var a=d[0].scrollHeight;d[0].clientHeight<a&&d.css({height:a+15})},h;d.keyup(function(){clearTimeout(h);h=setTimeout(g,100)});a.trim(d.text())&&a(g)}},disable:function(){(this.element.attr("disabled",true).is("[type='search'],:jqmData(type='search')")?this.element.parent():this.element).addClass("ui-disabled")},enable:function(){(this.element.attr("disabled",false).is("[type='search'],:jqmData(type='search')")?this.element.parent():this.element).removeClass("ui-disabled")}});
-a(document).bind("pagecreate create",function(d){a.mobile.textinput.prototype.enhanceWithin(d.target)})})(jQuery);
-(function(a){var d=function(b){var c=b.selectID,d=b.label,e=b.select.closest(".ui-page"),g=a("<div>",{"class":"ui-selectmenu-screen ui-screen-hidden"}).appendTo(e),h=b._selectOptions(),i=b.isMultiple=b.select[0].multiple,k=c+"-button",n=c+"-menu",o=a("<div data-"+a.mobile.ns+"role='dialog' data-"+a.mobile.ns+"theme='"+b.options.menuPageTheme+"'><div data-"+a.mobile.ns+"role='header'><div class='ui-title'>"+d.getEncodedText()+"</div></div><div data-"+a.mobile.ns+"role='content'></div></div>").appendTo(a.mobile.pageContainer).page(),
-q=a("<div>",{"class":"ui-selectmenu ui-selectmenu-hidden ui-overlay-shadow ui-corner-all ui-body-"+b.options.overlayTheme+" "+a.mobile.defaultDialogTransition}).insertAfter(g),m=a("<ul>",{"class":"ui-selectmenu-list",id:n,role:"listbox","aria-labelledby":k}).attr("data-"+a.mobile.ns+"theme",b.options.theme).appendTo(q),j=a("<div>",{"class":"ui-header ui-bar-"+b.options.theme}).prependTo(q),p=a("<h1>",{"class":"ui-title"}).appendTo(j),l=a("<a>",{text:b.options.closeText,href:"#","class":"ui-btn-left"}).attr("data-"+
-a.mobile.ns+"iconpos","notext").attr("data-"+a.mobile.ns+"icon","delete").appendTo(j).buttonMarkup(),A=o.find(".ui-content"),z=o.find(".ui-header a");a.extend(b,{select:b.select,selectID:c,buttonId:k,menuId:n,thisPage:e,menuPage:o,label:d,screen:g,selectOptions:h,isMultiple:i,theme:b.options.theme,listbox:q,list:m,header:j,headerTitle:p,headerClose:l,menuPageContent:A,menuPageClose:z,placeholder:"",build:function(){var b=this;b.refresh();b.select.attr("tabindex","-1").focus(function(){a(this).blur();
-b.button.focus()});b.button.bind("vclick keydown",function(c){if(c.type=="vclick"||c.keyCode&&(c.keyCode===a.mobile.keyCode.ENTER||c.keyCode===a.mobile.keyCode.SPACE))b.open(),c.preventDefault()});b.list.attr("role","listbox").delegate(".ui-li>a","focusin",function(){a(this).attr("tabindex","0")}).delegate(".ui-li>a","focusout",function(){a(this).attr("tabindex","-1")}).delegate("li:not(.ui-disabled, .ui-li-divider)","click",function(c){var d=b.select[0].selectedIndex,f=b.list.find("li:not(.ui-li-divider)").index(this),
-e=b._selectOptions().eq(f)[0];e.selected=b.isMultiple?!e.selected:true;b.isMultiple&&a(this).find(".ui-icon").toggleClass("ui-icon-checkbox-on",e.selected).toggleClass("ui-icon-checkbox-off",!e.selected);(b.isMultiple||d!==f)&&b.select.trigger("change");b.isMultiple||b.close();c.preventDefault()}).keydown(function(b){var c=a(b.target),d=c.closest("li");switch(b.keyCode){case 38:return b=d.prev(),b.length&&(c.blur().attr("tabindex","-1"),b.find("a").first().focus()),false;case 40:return b=d.next(),
-b.length&&(c.blur().attr("tabindex","-1"),b.find("a").first().focus()),false;case 13:case 32:return c.trigger("click"),false}});b.menuPage.bind("pagehide",function(){b.list.appendTo(b.listbox);b._focusButton();a.mobile._bindPageRemove.call(b.thisPage)});b.screen.bind("vclick",function(){b.close()});b.headerClose.click(function(){if(b.menuType=="overlay")return b.close(),false});b.thisPage.addDependents(this.menuPage)},_isRebuildRequired:function(){var a=this.list.find("li");return this._selectOptions().text()!==
-a.text()},refresh:function(b){var c=this;this._selectOptions();this.selected();var d=this.selectedIndices();(b||this._isRebuildRequired())&&c._buildList();c.setButtonText();c.setButtonCount();c.list.find("li:not(.ui-li-divider)").removeClass(a.mobile.activeBtnClass).attr("aria-selected",false).each(function(b){a.inArray(b,d)>-1&&(b=a(this),b.attr("aria-selected",true),c.isMultiple?b.find(".ui-icon").removeClass("ui-icon-checkbox-off").addClass("ui-icon-checkbox-on"):b.addClass(a.mobile.activeBtnClass))})},
-close:function(){if(!this.options.disabled&&this.isOpen)this.menuType=="page"?window.history.back():(this.screen.addClass("ui-screen-hidden"),this.listbox.addClass("ui-selectmenu-hidden").removeAttr("style").removeClass("in"),this.list.appendTo(this.listbox),this._focusButton()),this.isOpen=false},open:function(){if(!this.options.disabled){var b=this,c=b.list.parent().outerHeight(),d=b.list.parent().outerWidth(),f=a(".ui-page-active"),e=a.support.touchOverflow&&a.mobile.touchOverflowEnabled,f=f.is(".ui-native-fixed")?
-f.find(".ui-content"):f;scrollTop=e?f.scrollTop():a(window).scrollTop();btnOffset=b.button.offset().top;screenHeight=window.innerHeight;screenWidth=window.innerWidth;b.button.addClass(a.mobile.activeBtnClass);setTimeout(function(){b.button.removeClass(a.mobile.activeBtnClass)},300);if(c>screenHeight-80||!a.support.scrollTop){b.thisPage.unbind("pagehide.remove");if(scrollTop==0&&btnOffset>screenHeight)b.thisPage.one("pagehide",function(){a(this).jqmData("lastScroll",btnOffset)});b.menuPage.one("pageshow",
-function(){a(window).one("silentscroll",function(){b.list.find(a.mobile.activeBtnClass).focus()});b.isOpen=true});b.menuType="page";b.menuPageContent.append(b.list);b.menuPage.find("div .ui-title").text(b.label.text());a.mobile.changePage(b.menuPage,{transition:a.mobile.defaultDialogTransition})}else{b.menuType="overlay";b.screen.height(a(document).height()).removeClass("ui-screen-hidden");var f=btnOffset-scrollTop,g=scrollTop+screenHeight-btnOffset,h=c/2,e=parseFloat(b.list.parent().css("max-width")),
-c=f>c/2&&g>c/2?btnOffset+b.button.outerHeight()/2-h:f>g?scrollTop+screenHeight-c-30:scrollTop+30;d<e?e=(screenWidth-d)/2:(e=b.button.offset().left+b.button.outerWidth()/2-d/2,e<30?e=30:e+d>screenWidth&&(e=screenWidth-d-30));b.listbox.append(b.list).removeClass("ui-selectmenu-hidden").css({top:c,left:e}).addClass("in");b.list.find(a.mobile.activeBtnClass).focus();b.isOpen=true}}},_buildList:function(){var b=this,c=this.options,d=this.placeholder,f=[],e=[],g=b.isMultiple?"checkbox-off":"false";b.list.empty().filter(".ui-listview").listview("destroy");
-b.select.find("option").each(function(h){var j=a(this),i=j.parent(),m=j.getEncodedText(),q="<a href='#'>"+m+"</a>",l=[],k=[];i.is("optgroup")&&(i=i.attr("label"),a.inArray(i,f)===-1&&(e.push("<li data-"+a.mobile.ns+"role='list-divider'>"+i+"</li>"),f.push(i)));if(!this.getAttribute("value")||m.length==0||j.jqmData("placeholder"))c.hidePlaceholderMenuItems&&l.push("ui-selectmenu-placeholder"),d=b.placeholder=m;this.disabled&&(l.push("ui-disabled"),k.push("aria-disabled='true'"));e.push("<li data-"+
-a.mobile.ns+"option-index='"+h+"' data-"+a.mobile.ns+"icon='"+g+"' class='"+l.join(" ")+"' "+k.join(" ")+">"+q+"</li>")});b.list.html(e.join(" "));b.list.find("li").attr({role:"option",tabindex:"-1"}).first().attr("tabindex","0");this.isMultiple||this.headerClose.hide();!this.isMultiple&&!d.length?this.header.hide():this.headerTitle.text(this.placeholder);b.list.listview()},_button:function(){return a("<a>",{href:"#",role:"button",id:this.buttonId,"aria-haspopup":"true","aria-owns":this.menuId})}})};
-a("select").live("selectmenubeforecreate",function(){var b=a(this).data("selectmenu");b.options.nativeMenu||d(b)})})(jQuery);
-(function(a){a.widget("mobile.selectmenu",a.mobile.widget,{options:{theme:null,disabled:false,icon:"arrow-d",iconpos:"right",inline:null,corners:true,shadow:true,iconshadow:true,menuPageTheme:"b",overlayTheme:"a",hidePlaceholderMenuItems:true,closeText:"Close",nativeMenu:true,initSelector:"select:not(:jqmData(role='slider'))"},_button:function(){return a("<div/>")},_setDisabled:function(a){this.element.attr("disabled",a);this.button.attr("aria-disabled",a);return this._setOption("disabled",a)},_focusButton:function(){var a=
-this;setTimeout(function(){a.button.focus()},40)},_selectOptions:function(){return this.select.find("option")},_preExtension:function(){this.select=this.element.wrap("<div class='ui-select'>");this.selectID=this.select.attr("id");this.label=a("label[for='"+this.selectID+"']").addClass("ui-select");this.isMultiple=this.select[0].multiple;if(!this.options.theme)this.options.theme=a.mobile.getInheritedTheme(this.select,"c")},_create:function(){this._preExtension();this._trigger("beforeCreate");this.button=
-this._button();var d=this,b=this.options,c=this.button.text(a(this.select[0].options.item(this.select[0].selectedIndex==-1?0:this.select[0].selectedIndex)).text()).insertBefore(this.select).buttonMarkup({theme:b.theme,icon:b.icon,iconpos:b.iconpos,inline:b.inline,corners:b.corners,shadow:b.shadow,iconshadow:b.iconshadow});b.nativeMenu&&window.opera&&window.opera.version&&this.select.addClass("ui-select-nativeonly");if(this.isMultiple)this.buttonCount=a("<span>").addClass("ui-li-count ui-btn-up-c ui-btn-corner-all").hide().appendTo(c.addClass("ui-li-has-count"));
-(b.disabled||this.element.attr("disabled"))&&this.disable();this.select.change(function(){d.refresh()});this.build()},build:function(){var d=this;this.select.appendTo(d.button).bind("vmousedown",function(){d.button.addClass(a.mobile.activeBtnClass)}).bind("focus vmouseover",function(){d.button.trigger("vmouseover")}).bind("vmousemove",function(){d.button.removeClass(a.mobile.activeBtnClass)}).bind("change blur vmouseout",function(){d.button.trigger("vmouseout").removeClass(a.mobile.activeBtnClass)}).bind("change blur",
-function(){d.button.removeClass("ui-btn-down-"+d.options.theme)})},selected:function(){return this._selectOptions().filter(":selected")},selectedIndices:function(){var a=this;return this.selected().map(function(){return a._selectOptions().index(this)}).get()},setButtonText:function(){var d=this,b=this.selected();this.button.find(".ui-btn-text").text(function(){return!d.isMultiple?b.text():b.length?b.map(function(){return a(this).text()}).get().join(", "):d.placeholder})},setButtonCount:function(){var a=
-this.selected();this.isMultiple&&this.buttonCount[a.length>1?"show":"hide"]().text(a.length)},refresh:function(){this.setButtonText();this.setButtonCount()},open:a.noop,close:a.noop,disable:function(){this._setDisabled(true);this.button.addClass("ui-disabled")},enable:function(){this._setDisabled(false);this.button.removeClass("ui-disabled")}});a(document).bind("pagecreate create",function(d){a.mobile.selectmenu.prototype.enhanceWithin(d.target)})})(jQuery);
-(function(a){function d(b){for(;b;){var d=a(b);if(d.hasClass("ui-btn")&&!d.hasClass("ui-disabled"))break;b=b.parentNode}return b}a.fn.buttonMarkup=function(c){return this.each(function(){var d=a(this),e=a.extend({},a.fn.buttonMarkup.defaults,{icon:d.jqmData("icon"),iconpos:d.jqmData("iconpos"),theme:d.jqmData("theme"),inline:d.jqmData("inline"),shadow:d.jqmData("shadow"),corners:d.jqmData("corners"),iconshadow:d.jqmData("iconshadow")},c),g="ui-btn-inner",h,i;b&&b();if(!e.theme)e.theme=a.mobile.getInheritedTheme(d,
-"c");h="ui-btn ui-btn-up-"+e.theme;e.inline&&(h+=" ui-btn-inline");if(e.icon)e.icon="ui-icon-"+e.icon,e.iconpos=e.iconpos||"left",i="ui-icon "+e.icon,e.iconshadow&&(i+=" ui-icon-shadow");e.iconpos&&(h+=" ui-btn-icon-"+e.iconpos,e.iconpos=="notext"&&!d.attr("title")&&d.attr("title",d.getEncodedText()));e.corners&&(h+=" ui-btn-corner-all",g+=" ui-btn-corner-all");e.shadow&&(h+=" ui-shadow");d.attr("data-"+a.mobile.ns+"theme",e.theme).addClass(h);e=("<D class='"+g+"' aria-hidden='true'><D class='ui-btn-text'></D>"+
-(e.icon?"<span class='"+i+"'></span>":"")+"</D>").replace(/D/g,e.wrapperEls);d.wrapInner(e)})};a.fn.buttonMarkup.defaults={corners:true,shadow:true,iconshadow:true,inline:false,wrapperEls:"span"};var b=function(){a(document).bind({vmousedown:function(b){var b=d(b.target),f;b&&(b=a(b),f=b.attr("data-"+a.mobile.ns+"theme"),b.removeClass("ui-btn-up-"+f).addClass("ui-btn-down-"+f))},"vmousecancel vmouseup":function(b){var b=d(b.target),f;b&&(b=a(b),f=b.attr("data-"+a.mobile.ns+"theme"),b.removeClass("ui-btn-down-"+
-f).addClass("ui-btn-up-"+f))},"vmouseover focus":function(b){var b=d(b.target),f;b&&(b=a(b),f=b.attr("data-"+a.mobile.ns+"theme"),b.removeClass("ui-btn-up-"+f).addClass("ui-btn-hover-"+f))},"vmouseout blur":function(b){var b=d(b.target),f;b&&(b=a(b),f=b.attr("data-"+a.mobile.ns+"theme"),b.removeClass("ui-btn-hover-"+f).addClass("ui-btn-up-"+f))}});b=null};a(document).bind("pagecreate create",function(b){a(":jqmData(role='button'), .ui-bar > a, .ui-header > a, .ui-footer > a, .ui-bar > :jqmData(role='controlgroup') > a",
-b.target).not(".ui-btn, :jqmData(role='none'), :jqmData(role='nojs')").buttonMarkup()})})(jQuery);
-(function(a){a.fn.controlgroup=function(d){return this.each(function(){function b(a){a.removeClass("ui-btn-corner-all ui-shadow").eq(0).addClass(g[0]).end().filter(":last").addClass(g[1]).addClass("ui-controlgroup-last")}var c=a(this),f=a.extend({direction:c.jqmData("type")||"vertical",shadow:false,excludeInvisible:true},d),e=c.find(">legend"),g=f.direction=="horizontal"?["ui-corner-left","ui-corner-right"]:["ui-corner-top","ui-corner-bottom"];c.find("input:eq(0)").attr("type");e.length&&(c.wrapInner("<div class='ui-controlgroup-controls'></div>"),
-a("<div role='heading' class='ui-controlgroup-label'>"+e.html()+"</div>").insertBefore(c.children(0)),e.remove());c.addClass("ui-corner-all ui-controlgroup ui-controlgroup-"+f.direction);b(c.find(".ui-btn"+(f.excludeInvisible?":visible":"")));b(c.find(".ui-btn-inner"));f.shadow&&c.addClass("ui-shadow")})};a(document).bind("pagecreate create",function(d){a(":jqmData(role='controlgroup')",d.target).controlgroup({excludeInvisible:false})})})(jQuery);
-(function(a){a(document).bind("pagecreate create",function(d){a(d.target).find("a").not(".ui-btn, .ui-link-inherit, :jqmData(role='none'), :jqmData(role='nojs')").addClass("ui-link")})})(jQuery);
-(function(a,d){a.fn.fixHeaderFooter=function(){return!a.support.scrollTop||a.support.touchOverflow&&a.mobile.touchOverflowEnabled?this:this.each(function(){var b=a(this);b.jqmData("fullscreen")&&b.addClass("ui-page-fullscreen");b.find(".ui-header:jqmData(position='fixed')").addClass("ui-header-fixed ui-fixed-inline fade");b.find(".ui-footer:jqmData(position='fixed')").addClass("ui-footer-fixed ui-fixed-inline fade")})};a.mobile.fixedToolbars=function(){function b(){!i&&h==="overlay"&&(g||a.mobile.fixedToolbars.hide(true),
-a.mobile.fixedToolbars.startShowTimer())}function c(a){var b=0,c,d;if(a){d=document.body;c=a.offsetParent;for(b=a.offsetTop;a&&a!=d;){b+=a.scrollTop||0;if(a==c)b+=c.offsetTop,c=a.offsetParent;a=a.parentNode}}return b}function f(b){var d=a(window).scrollTop(),e=c(b[0]),f=b.css("top")=="auto"?0:parseFloat(b.css("top")),g=window.innerHeight,h=b.outerHeight(),i=b.parents(".ui-page:not(.ui-page-fullscreen)").length;return b.is(".ui-header-fixed")?(f=d-e+f,f<e&&(f=0),b.css("top",i?f:d)):b.css("top",i?d+
-g-h-(e-f):d+g-h)}if(a.support.scrollTop&&(!a.support.touchOverflow||!a.mobile.touchOverflowEnabled)){var e,g,h="inline",i=false,k=null,n=false,o=true;a(function(){var c=a(document),d=a(window);c.bind("vmousedown",function(){o&&(k=h)}).bind("vclick",function(b){o&&!a(b.target).closest("a,input,textarea,select,button,label,.ui-header-fixed,.ui-footer-fixed").length&&!n&&(a.mobile.fixedToolbars.toggle(k),k=null)}).bind("silentscroll",b);(c.scrollTop()===0?d:c).bind("scrollstart",function(){n=true;k===
-null&&(k=h);var b=k=="overlay";if(i=b||!!g)a.mobile.fixedToolbars.clearShowTimer(),b&&a.mobile.fixedToolbars.hide(true)}).bind("scrollstop",function(b){a(b.target).closest("a,input,textarea,select,button,label,.ui-header-fixed,.ui-footer-fixed").length||(n=false,i&&(a.mobile.fixedToolbars.startShowTimer(),i=false),k=null)});d.bind("resize updatelayout",b)});a(".ui-page").live("pagebeforeshow",function(b,c){var d=a(b.target).find(":jqmData(role='footer')"),g=d.data("id"),h=c.prevPage,h=h&&h.find(":jqmData(role='footer')"),
-h=h.length&&h.jqmData("id")===g;g&&h&&(e=d,f(e.removeClass("fade in out").appendTo(a.mobile.pageContainer)))}).live("pageshow",function(){var b=a(this);e&&e.length&&setTimeout(function(){f(e.appendTo(b).addClass("fade"));e=null},500);a.mobile.fixedToolbars.show(true,this)});a(".ui-collapsible-contain").live("collapse expand",b);return{show:function(b,d){a.mobile.fixedToolbars.clearShowTimer();h="overlay";return(d?a(d):a.mobile.activePage?a.mobile.activePage:a(".ui-page-active")).children(".ui-header-fixed:first, .ui-footer-fixed:not(.ui-footer-duplicate):last").each(function(){var d=
-a(this),e=a(window).scrollTop(),g=c(d[0]),h=window.innerHeight,i=d.outerHeight(),e=d.is(".ui-header-fixed")&&e<=g+i||d.is(".ui-footer-fixed")&&g<=e+h;d.addClass("ui-fixed-overlay").removeClass("ui-fixed-inline");!e&&!b&&d.animationComplete(function(){d.removeClass("in")}).addClass("in");f(d)})},hide:function(b){h="inline";return(a.mobile.activePage?a.mobile.activePage:a(".ui-page-active")).children(".ui-header-fixed:first, .ui-footer-fixed:not(.ui-footer-duplicate):last").each(function(){var c=a(this),
-d=c.css("top"),d=d=="auto"?0:parseFloat(d);c.addClass("ui-fixed-inline").removeClass("ui-fixed-overlay");if(d<0||c.is(".ui-header-fixed")&&d!==0)b?c.css("top",0):c.css("top")!=="auto"&&parseFloat(c.css("top"))!==0&&c.animationComplete(function(){c.removeClass("out reverse").css("top",0)}).addClass("out reverse")})},startShowTimer:function(){a.mobile.fixedToolbars.clearShowTimer();var b=[].slice.call(arguments);g=setTimeout(function(){g=d;a.mobile.fixedToolbars.show.apply(null,b)},100)},clearShowTimer:function(){g&&
-clearTimeout(g);g=d},toggle:function(b){b&&(h=b);return h==="overlay"?a.mobile.fixedToolbars.hide():a.mobile.fixedToolbars.show()},setTouchToggleEnabled:function(a){o=a}}}}();a(document).bind("pagecreate create",function(b){a(":jqmData(position='fixed')",b.target).length&&a(b.target).each(function(){if(!a.support.scrollTop||a.support.touchOverflow&&a.mobile.touchOverflowEnabled)return this;var b=a(this);b.jqmData("fullscreen")&&b.addClass("ui-page-fullscreen");b.find(".ui-header:jqmData(position='fixed')").addClass("ui-header-fixed ui-fixed-inline fade");
-b.find(".ui-footer:jqmData(position='fixed')").addClass("ui-footer-fixed ui-fixed-inline fade")})})})(jQuery);
-(function(a){a.mobile.touchOverflowEnabled=false;a.mobile.touchOverflowZoomEnabled=false;a(document).bind("pagecreate",function(d){a.support.touchOverflow&&a.mobile.touchOverflowEnabled&&(d=a(d.target),d.is(":jqmData(role='page')")&&d.each(function(){var b=a(this),c=b.find(":jqmData(role='header'), :jqmData(role='footer')").filter(":jqmData(position='fixed')"),d=b.jqmData("fullscreen"),e=c.length?b.find(".ui-content"):b;b.addClass("ui-mobile-touch-overflow");e.bind("scrollstop",function(){e.scrollTop()>
-0&&window.scrollTo(0,a.mobile.defaultHomeScroll)});c.length&&(b.addClass("ui-native-fixed"),d&&(b.addClass("ui-native-fullscreen"),c.addClass("fade in"),a(document).bind("vclick",function(){c.removeClass("ui-native-bars-hidden").toggleClass("in out").animationComplete(function(){a(this).not(".in").addClass("ui-native-bars-hidden")})})))}))})})(jQuery);
-(function(a,d){function b(){var b=a("meta[name='viewport']");b.length?b.attr("content",b.attr("content")+", user-scalable=no"):a("head").prepend("<meta>",{name:"viewport",content:"user-scalable=no"})}var c=a("html");a("head");var f=a(d);a(d.document).trigger("mobileinit");if(a.mobile.gradeA()){if(a.mobile.ajaxBlacklist)a.mobile.ajaxEnabled=false;c.addClass("ui-mobile ui-mobile-rendering");var e=a("<div class='ui-loader ui-body-a ui-corner-all'><span class='ui-icon ui-icon-loading spin'></span><h1></h1></div>");
-a.extend(a.mobile,{showPageLoadingMsg:function(){if(a.mobile.loadingMessage){var b=a("."+a.mobile.activeBtnClass).first();e.find("h1").text(a.mobile.loadingMessage).end().appendTo(a.mobile.pageContainer).css({top:a.support.scrollTop&&f.scrollTop()+f.height()/2||b.length&&b.offset().top||100})}c.addClass("ui-loading")},hidePageLoadingMsg:function(){c.removeClass("ui-loading")},initializePage:function(){var b=a(":jqmData(role='page')");b.length||(b=a("body").wrapInner("<div data-"+a.mobile.ns+"role='page'></div>").children(0));
-b.add(":jqmData(role='dialog')").each(function(){var b=a(this);b.jqmData("url")||b.attr("data-"+a.mobile.ns+"url",b.attr("id")||location.pathname+location.search)});a.mobile.firstPage=b.first();a.mobile.pageContainer=b.first().parent().addClass("ui-mobile-viewport");f.trigger("pagecontainercreate");a.mobile.showPageLoadingMsg();!a.mobile.hashListeningEnabled||!a.mobile.path.stripHash(location.hash)?a.mobile.changePage(a.mobile.firstPage,{transition:"none",reverse:true,changeHash:false,fromHashChange:true}):
-f.trigger("hashchange",[true])}});a.support.touchOverflow&&a.mobile.touchOverflowEnabled&&!a.mobile.touchOverflowZoomEnabled&&b();a.mobile._registerInternalEvents();a(function(){d.scrollTo(0,1);a.mobile.defaultHomeScroll=!a.support.scrollTop||a(d).scrollTop()===1?0:1;a.mobile.autoInitializePage&&a.mobile.initializePage();f.load(a.mobile.silentScroll)})}})(jQuery,this);
diff --git a/themes/jquerymobile/js/keep_alive.js b/themes/jquerymobile/js/keep_alive.js
deleted file mode 100644
index 5556008d6762ef7d2ebe940bba359c7196057d1d..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/js/keep_alive.js
+++ /dev/null
@@ -1,7 +0,0 @@
-/*global path, keepAliveInterval */
-
-$(document).ready(function() {
-  window.setInterval(function() {
-    $.getJSON(path + '/AJAX/JSON', {method: 'keepAlive'});
-  }, keepAliveInterval * 1000);
-});
diff --git a/themes/jquerymobile/js/recaptcha_ajax.js b/themes/jquerymobile/js/recaptcha_ajax.js
deleted file mode 100644
index 34ca67409589cc3ce6bb3a3d28d0491a5f7c794e..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/js/recaptcha_ajax.js
+++ /dev/null
@@ -1,182 +0,0 @@
-(function(){var h,aa=aa||{},l=this,ba=function(a){a=a.split(".");for(var b=l,c;c=a.shift();)if(null!=b[c])b=b[c];else return null;return b},ca=function(){},da=function(a){var b=typeof a;if("object"==b)if(a){if(a instanceof Array)return"array";if(a instanceof Object)return b;var c=Object.prototype.toString.call(a);if("[object Window]"==c)return"object";if("[object Array]"==c||"number"==typeof a.length&&"undefined"!=typeof a.splice&&"undefined"!=typeof a.propertyIsEnumerable&&!a.propertyIsEnumerable("splice"))return"array";
-if("[object Function]"==c||"undefined"!=typeof a.call&&"undefined"!=typeof a.propertyIsEnumerable&&!a.propertyIsEnumerable("call"))return"function"}else return"null";else if("function"==b&&"undefined"==typeof a.call)return"object";return b},m=function(a){return"array"==da(a)},ea=function(a){var b=da(a);return"array"==b||"object"==b&&"number"==typeof a.length},n=function(a){return"string"==typeof a},fa=function(a){return"function"==da(a)},ga=function(a){var b=typeof a;return"object"==b&&null!=a||"function"==
-b},ha=function(a,b,c){return a.call.apply(a.bind,arguments)},ia=function(a,b,c){if(!a)throw Error();if(2<arguments.length){var d=Array.prototype.slice.call(arguments,2);return function(){var c=Array.prototype.slice.call(arguments);Array.prototype.unshift.apply(c,d);return a.apply(b,c)}}return function(){return a.apply(b,arguments)}},p=function(a,b,c){p=Function.prototype.bind&&-1!=Function.prototype.bind.toString().indexOf("native code")?ha:ia;return p.apply(null,arguments)},ja=Date.now||function(){return+new Date},
-q=function(a,b){var c=a.split("."),d=l;c[0]in d||!d.execScript||d.execScript("var "+c[0]);for(var e;c.length&&(e=c.shift());)c.length||void 0===b?d=d[e]?d[e]:d[e]={}:d[e]=b},r=function(a,b){function c(){}c.prototype=b.prototype;a.superClass_=b.prototype;a.prototype=new c;a.base=function(a,c,g){return b.prototype[c].apply(a,Array.prototype.slice.call(arguments,2))}};
-Function.prototype.bind=Function.prototype.bind||function(a,b){if(1<arguments.length){var c=Array.prototype.slice.call(arguments,1);c.unshift(this,a);return p.apply(null,c)}return p(this,a)};var s={};q("RecaptchaTemplates",s);s.VertHtml='<table id="recaptcha_table" class="recaptchatable" > <tr> <td colspan="6" class=\'recaptcha_r1_c1\'></td> </tr> <tr> <td class=\'recaptcha_r2_c1\'></td> <td colspan="4" class=\'recaptcha_image_cell\'><center><div id="recaptcha_image"></div></center></td> <td class=\'recaptcha_r2_c2\'></td> </tr> <tr> <td rowspan="6" class=\'recaptcha_r3_c1\'></td> <td colspan="4" class=\'recaptcha_r3_c2\'></td> <td rowspan="6" class=\'recaptcha_r3_c3\'></td> </tr> <tr> <td rowspan="3" class=\'recaptcha_r4_c1\' height="49"> <div class="recaptcha_input_area"> <input name="recaptcha_response_field" id="recaptcha_response_field" type="text" autocorrect="off" autocapitalize="off" placeholder="" /> <span id="recaptcha_privacy" class="recaptcha_only_if_privacy"></span> </div> </td> <td rowspan="4" class=\'recaptcha_r4_c2\'></td> <td><a id=\'recaptcha_reload_btn\'><img id=\'recaptcha_reload\' width="25" height="17" /></a></td> <td rowspan="4" class=\'recaptcha_r4_c4\'></td> </tr> <tr> <td><a id=\'recaptcha_switch_audio_btn\' class="recaptcha_only_if_image"><img id=\'recaptcha_switch_audio\' width="25" height="16" alt="" /></a><a id=\'recaptcha_switch_img_btn\' class="recaptcha_only_if_audio"><img id=\'recaptcha_switch_img\' width="25" height="16" alt=""/></a></td> </tr> <tr> <td><a id=\'recaptcha_whatsthis_btn\'><img id=\'recaptcha_whatsthis\' width="25" height="16" /></a></td> </tr> <tr> <td class=\'recaptcha_r7_c1\'></td> <td class=\'recaptcha_r8_c1\'></td> </tr> </table> ';s.CleanCss=".recaptchatable td img{display:block}.recaptchatable .recaptcha_image_cell center img{height:57px}.recaptchatable .recaptcha_image_cell center{height:57px}.recaptchatable .recaptcha_image_cell{background-color:white;height:57px;padding:7px!important}.recaptchatable,#recaptcha_area tr,#recaptcha_area td,#recaptcha_area th{margin:0!important;border:0!important;border-collapse:collapse!important;vertical-align:middle!important}.recaptchatable *{margin:0;padding:0;border:0;color:black;position:static;top:auto;left:auto;right:auto;bottom:auto}.recaptchatable #recaptcha_image{position:relative;margin:auto;border:1px solid #dfdfdf!important}.recaptchatable #recaptcha_image #recaptcha_challenge_image{display:block}.recaptchatable #recaptcha_image #recaptcha_ad_image{display:block;position:absolute;top:0}.recaptchatable a img{border:0}.recaptchatable a,.recaptchatable a:hover{cursor:pointer;outline:none;border:0!important;padding:0!important;text-decoration:none;color:blue;background:none!important;font-weight:normal}.recaptcha_input_area{position:relative!important;background:none!important}.recaptchatable label.recaptcha_input_area_text{border:1px solid #dfdfdf!important;margin:0!important;padding:0!important;position:static!important;top:auto!important;left:auto!important;right:auto!important;bottom:auto!important}.recaptcha_theme_red label.recaptcha_input_area_text,.recaptcha_theme_white label.recaptcha_input_area_text{color:black!important}.recaptcha_theme_blackglass label.recaptcha_input_area_text{color:white!important}.recaptchatable #recaptcha_response_field{font-size:11pt}.recaptcha_theme_blackglass #recaptcha_response_field,.recaptcha_theme_white #recaptcha_response_field{border:1px solid gray}.recaptcha_theme_red #recaptcha_response_field{border:1px solid #cca940}.recaptcha_audio_cant_hear_link{font-size:7pt;color:black}.recaptchatable{line-height:1em;border:1px solid #dfdfdf!important}.recaptcha_error_text{color:red}.recaptcha_only_if_privacy{float:right;text-align:right;margin-right:7px}#recaptcha-ad-choices{position:absolute;height:15px;top:0;right:0}#recaptcha-ad-choices img{height:15px}.recaptcha-ad-choices-collapsed{width:15px;height:15px;display:block}.recaptcha-ad-choices-expanded{width:75px;height:15px;display:none}#recaptcha-ad-choices:hover .recaptcha-ad-choices-collapsed{display:none}#recaptcha-ad-choices:hover .recaptcha-ad-choices-expanded{display:block}";s.CleanHtml='<table id="recaptcha_table" class="recaptchatable"> <tr height="73"> <td class=\'recaptcha_image_cell\' width="302"><center><div id="recaptcha_image"></div></center></td> <td style="padding: 10px 7px 7px 7px;"> <a id=\'recaptcha_reload_btn\'><img id=\'recaptcha_reload\' width="25" height="18" alt="" /></a> <a id=\'recaptcha_switch_audio_btn\' class="recaptcha_only_if_image"><img id=\'recaptcha_switch_audio\' width="25" height="15" alt="" /></a><a id=\'recaptcha_switch_img_btn\' class="recaptcha_only_if_audio"><img id=\'recaptcha_switch_img\' width="25" height="15" alt=""/></a> <a id=\'recaptcha_whatsthis_btn\'><img id=\'recaptcha_whatsthis\' width="25" height="16" /></a> </td> <td style="padding: 18px 7px 18px 7px;"> <img id=\'recaptcha_logo\' alt="" width="71" height="36" /> </td> </tr> <tr> <td style="padding-left: 7px;"> <div class="recaptcha_input_area" style="padding-top: 2px; padding-bottom: 7px;"> <input style="border: 1px solid #3c3c3c; width: 302px;" name="recaptcha_response_field" id="recaptcha_response_field" type="text" /> </div> </td> <td colspan=2><span id="recaptcha_privacy" class="recaptcha_only_if_privacy"></span></td> </tr> </table> ';s.VertCss=".recaptchatable td img{display:block}.recaptchatable .recaptcha_r1_c1{background:url('IMGROOT/sprite.png') 0 -63px no-repeat;width:318px;height:9px}.recaptchatable .recaptcha_r2_c1{background:url('IMGROOT/sprite.png') -18px 0 no-repeat;width:9px;height:57px}.recaptchatable .recaptcha_r2_c2{background:url('IMGROOT/sprite.png') -27px 0 no-repeat;width:9px;height:57px}.recaptchatable .recaptcha_r3_c1{background:url('IMGROOT/sprite.png') 0 0 no-repeat;width:9px;height:63px}.recaptchatable .recaptcha_r3_c2{background:url('IMGROOT/sprite.png') -18px -57px no-repeat;width:300px;height:6px}.recaptchatable .recaptcha_r3_c3{background:url('IMGROOT/sprite.png') -9px 0 no-repeat;width:9px;height:63px}.recaptchatable .recaptcha_r4_c1{background:url('IMGROOT/sprite.png') -43px 0 no-repeat;width:171px;height:49px}.recaptchatable .recaptcha_r4_c2{background:url('IMGROOT/sprite.png') -36px 0 no-repeat;width:7px;height:57px}.recaptchatable .recaptcha_r4_c4{background:url('IMGROOT/sprite.png') -214px 0 no-repeat;width:97px;height:57px}.recaptchatable .recaptcha_r7_c1{background:url('IMGROOT/sprite.png') -43px -49px no-repeat;width:171px;height:8px}.recaptchatable .recaptcha_r8_c1{background:url('IMGROOT/sprite.png') -43px -49px no-repeat;width:25px;height:8px}.recaptchatable .recaptcha_image_cell center img{height:57px}.recaptchatable .recaptcha_image_cell center{height:57px}.recaptchatable .recaptcha_image_cell{background-color:white;height:57px}#recaptcha_area,#recaptcha_table{width:318px!important}.recaptchatable,#recaptcha_area tr,#recaptcha_area td,#recaptcha_area th{margin:0!important;border:0!important;padding:0!important;border-collapse:collapse!important;vertical-align:middle!important}.recaptchatable *{margin:0;padding:0;border:0;font-family:helvetica,sans-serif;font-size:8pt;color:black;position:static;top:auto;left:auto;right:auto;bottom:auto}.recaptchatable #recaptcha_image{position:relative;margin:auto}.recaptchatable #recaptcha_image #recaptcha_challenge_image{display:block}.recaptchatable #recaptcha_image #recaptcha_ad_image{display:block;position:absolute;top:0}.recaptchatable img{border:0!important;margin:0!important;padding:0!important}.recaptchatable a,.recaptchatable a:hover{cursor:pointer;outline:none;border:0!important;padding:0!important;text-decoration:none;color:blue;background:none!important;font-weight:normal}.recaptcha_input_area{position:relative!important;width:153px!important;height:45px!important;margin-left:7px!important;margin-right:7px!important;background:none!important}.recaptchatable label.recaptcha_input_area_text{margin:0!important;padding:0!important;position:static!important;top:auto!important;left:auto!important;right:auto!important;bottom:auto!important;background:none!important;height:auto!important;width:auto!important}.recaptcha_theme_red label.recaptcha_input_area_text,.recaptcha_theme_white label.recaptcha_input_area_text{color:black!important}.recaptcha_theme_blackglass label.recaptcha_input_area_text{color:white!important}.recaptchatable #recaptcha_response_field{width:153px!important;position:relative!important;bottom:7px!important;padding:0!important;margin:15px 0 0 0!important;font-size:10pt}.recaptcha_theme_blackglass #recaptcha_response_field,.recaptcha_theme_white #recaptcha_response_field{border:1px solid gray}.recaptcha_theme_red #recaptcha_response_field{border:1px solid #cca940}.recaptcha_audio_cant_hear_link{font-size:7pt;color:black}.recaptchatable{line-height:1!important}#recaptcha_instructions_error{color:red!important}.recaptcha_only_if_privacy{float:right;text-align:right}#recaptcha-ad-choices{position:absolute;height:15px;top:0;right:0}#recaptcha-ad-choices img{height:15px}.recaptcha-ad-choices-collapsed{width:15px;height:15px;display:block}.recaptcha-ad-choices-expanded{width:75px;height:15px;display:none}#recaptcha-ad-choices:hover .recaptcha-ad-choices-collapsed{display:none}#recaptcha-ad-choices:hover .recaptcha-ad-choices-expanded{display:block}";var t={visual_challenge:"Get a visual challenge",audio_challenge:"Get an audio challenge",refresh_btn:"Get a new challenge",instructions_visual:"Type the text:",instructions_audio:"Type what you hear:",help_btn:"Help",play_again:"Play sound again",cant_hear_this:"Download sound as MP3",incorrect_try_again:"Incorrect. Try again.",image_alt_text:"reCAPTCHA challenge image",privacy_and_terms:"Privacy & Terms"},ka={visual_challenge:"\u0627\u0644\u062d\u0635\u0648\u0644 \u0639\u0644\u0649 \u062a\u062d\u062f\u064d \u0645\u0631\u0626\u064a",
-audio_challenge:"\u0627\u0644\u062d\u0635\u0648\u0644 \u0639\u0644\u0649 \u062a\u062d\u062f\u064d \u0635\u0648\u062a\u064a",refresh_btn:"\u0627\u0644\u062d\u0635\u0648\u0644 \u0639\u0644\u0649 \u062a\u062d\u062f\u064d \u062c\u062f\u064a\u062f",instructions_visual:"\u064a\u0631\u062c\u0649 \u0643\u062a\u0627\u0628\u0629 \u0627\u0644\u0646\u0635:",instructions_audio:"\u0627\u0643\u062a\u0628 \u0645\u0627 \u062a\u0633\u0645\u0639\u0647:",help_btn:"\u0645\u0633\u0627\u0639\u062f\u0629",play_again:"\u062a\u0634\u063a\u064a\u0644 \u0627\u0644\u0635\u0648\u062a \u0645\u0631\u0629 \u0623\u062e\u0631\u0649",
-cant_hear_this:"\u062a\u0646\u0632\u064a\u0644 \u0627\u0644\u0635\u0648\u062a \u0628\u062a\u0646\u0633\u064a\u0642 MP3",incorrect_try_again:"\u063a\u064a\u0631 \u0635\u062d\u064a\u062d. \u0623\u0639\u062f \u0627\u0644\u0645\u062d\u0627\u0648\u0644\u0629.",image_alt_text:"\u0635\u0648\u0631\u0629 \u0627\u0644\u062a\u062d\u062f\u064a \u0645\u0646 reCAPTCHA",privacy_and_terms:"\u0627\u0644\u062e\u0635\u0648\u0635\u064a\u0629 \u0648\u0627\u0644\u0628\u0646\u0648\u062f"},la={visual_challenge:"Obtener una pista visual",
-audio_challenge:"Obtener una pista sonora",refresh_btn:"Obtener una pista nueva",instructions_visual:"Introduzca el texto:",instructions_audio:"Escribe lo que oigas:",help_btn:"Ayuda",play_again:"Volver a reproducir el sonido",cant_hear_this:"Descargar el sonido en MP3",incorrect_try_again:"Incorrecto. Vu\u00e9lvelo a intentar.",image_alt_text:"Pista de imagen reCAPTCHA",privacy_and_terms:"Privacidad y condiciones"},ma={visual_challenge:"Kumuha ng pagsubok na visual",audio_challenge:"Kumuha ng pagsubok na audio",
-refresh_btn:"Kumuha ng bagong pagsubok",instructions_visual:"I-type ang teksto:",instructions_audio:"I-type ang iyong narinig",help_btn:"Tulong",play_again:"I-play muli ang tunog",cant_hear_this:"I-download ang tunog bilang MP3",incorrect_try_again:"Hindi wasto. Muling subukan.",image_alt_text:"larawang panghamon ng reCAPTCHA",privacy_and_terms:"Privacy at Mga Tuntunin"},na={visual_challenge:"Test visuel",audio_challenge:"Test audio",refresh_btn:"Nouveau test",instructions_visual:"Saisissez le texte\u00a0:",
-instructions_audio:"Qu'entendez-vous ?",help_btn:"Aide",play_again:"R\u00e9\u00e9couter",cant_hear_this:"T\u00e9l\u00e9charger l'audio au format MP3",incorrect_try_again:"Incorrect. Veuillez r\u00e9essayer.",image_alt_text:"Image reCAPTCHA",privacy_and_terms:"Confidentialit\u00e9 et conditions d'utilisation"},oa={visual_challenge:"Dapatkan kata pengujian berbentuk visual",audio_challenge:"Dapatkan kata pengujian berbentuk audio",refresh_btn:"Dapatkan kata pengujian baru",instructions_visual:"Ketik teks:",
-instructions_audio:"Ketik yang Anda dengar:",help_btn:"Bantuan",play_again:"Putar suara sekali lagi",cant_hear_this:"Unduh suara sebagai MP3",incorrect_try_again:"Salah. Coba lagi.",image_alt_text:"Gambar tantangan reCAPTCHA",privacy_and_terms:"Privasi & Persyaratan"},pa={visual_challenge:"\u05e7\u05d1\u05dc \u05d0\u05ea\u05d2\u05e8 \u05d7\u05d6\u05d5\u05ea\u05d9",audio_challenge:"\u05e7\u05d1\u05dc \u05d0\u05ea\u05d2\u05e8 \u05e9\u05de\u05e2",refresh_btn:"\u05e7\u05d1\u05dc \u05d0\u05ea\u05d2\u05e8 \u05d7\u05d3\u05e9",
-instructions_visual:"\u05d4\u05e7\u05dc\u05d3 \u05d0\u05ea \u05d4\u05d8\u05e7\u05e1\u05d8:",instructions_audio:"\u05d4\u05e7\u05dc\u05d3 \u05d0\u05ea \u05de\u05d4 \u05e9\u05d0\u05ea\u05d4 \u05e9\u05d5\u05de\u05e2:",help_btn:"\u05e2\u05d6\u05e8\u05d4",play_again:"\u05d4\u05e4\u05e2\u05dc \u05e9\u05d5\u05d1 \u05d0\u05ea \u05d4\u05e9\u05de\u05e2",cant_hear_this:"\u05d4\u05d5\u05e8\u05d3 \u05e9\u05de\u05e2 \u05db-3MP",incorrect_try_again:"\u05e9\u05d2\u05d5\u05d9. \u05e0\u05e1\u05d4 \u05e9\u05d5\u05d1.",
-image_alt_text:"\u05ea\u05de\u05d5\u05e0\u05ea \u05d0\u05ea\u05d2\u05e8 \u05e9\u05dc reCAPTCHA",privacy_and_terms:"\u05e4\u05e8\u05d8\u05d9\u05d5\u05ea \u05d5\u05ea\u05e0\u05d0\u05d9\u05dd"},qa={visual_challenge:"Obter um desafio visual",audio_challenge:"Obter um desafio de \u00e1udio",refresh_btn:"Obter um novo desafio",instructions_visual:"Digite o texto:",instructions_audio:"Digite o que voc\u00ea ouve:",help_btn:"Ajuda",play_again:"Reproduzir som novamente",cant_hear_this:"Fazer download do som no formato MP3",
-incorrect_try_again:"Incorreto. Tente novamente.",image_alt_text:"Imagem de desafio reCAPTCHA",privacy_and_terms:"Privacidade e Termos"},ra={visual_challenge:"Ob\u0163ine\u0163i un cod captcha vizual",audio_challenge:"Ob\u0163ine\u0163i un cod captcha audio",refresh_btn:"Ob\u0163ine\u0163i un nou cod captcha",instructions_visual:"Introduce\u021bi textul:",instructions_audio:"Introduce\u0163i ceea ce auzi\u0163i:",help_btn:"Ajutor",play_again:"Reda\u0163i sunetul din nou",cant_hear_this:"Desc\u0103rca\u0163i fi\u015fierul audio ca MP3",
-incorrect_try_again:"Incorect. \u00cencerca\u0163i din nou.",image_alt_text:"Imagine de verificare reCAPTCHA",privacy_and_terms:"Confiden\u0163ialitate \u015fi termeni"},sa={visual_challenge:"\u6536\u5230\u4e00\u4e2a\u89c6\u9891\u9080\u8bf7",audio_challenge:"\u6362\u4e00\u7ec4\u97f3\u9891\u9a8c\u8bc1\u7801",refresh_btn:"\u6362\u4e00\u7ec4\u9a8c\u8bc1\u7801",instructions_visual:"\u8f93\u5165\u6587\u5b57\uff1a",instructions_audio:"\u8bf7\u952e\u5165\u60a8\u542c\u5230\u7684\u5185\u5bb9\uff1a",help_btn:"\u5e2e\u52a9",
-play_again:"\u91cd\u65b0\u64ad\u653e",cant_hear_this:"\u4ee5 MP3 \u683c\u5f0f\u4e0b\u8f7d\u58f0\u97f3",incorrect_try_again:"\u4e0d\u6b63\u786e\uff0c\u8bf7\u91cd\u8bd5\u3002",image_alt_text:"reCAPTCHA \u9a8c\u8bc1\u56fe\u7247",privacy_and_terms:"\u9690\u79c1\u6743\u548c\u4f7f\u7528\u6761\u6b3e"},ta={en:t,af:{visual_challenge:"Kry 'n visuele verifi\u00ebring",audio_challenge:"Kry 'n klankverifi\u00ebring",refresh_btn:"Kry 'n nuwe verifi\u00ebring",instructions_visual:"",instructions_audio:"Tik wat jy hoor:",
-help_btn:"Hulp",play_again:"Speel geluid weer",cant_hear_this:"Laai die klank af as MP3",incorrect_try_again:"Verkeerd. Probeer weer.",image_alt_text:"reCAPTCHA-uitdagingprent",privacy_and_terms:"Privaatheid en bepalings"},am:{visual_challenge:"\u12e8\u12a5\u12ed\u1273 \u1270\u130b\u1323\u121a \u12a0\u130d\u129d",audio_challenge:"\u120c\u120b \u12a0\u12f2\u1235 \u12e8\u12f5\u121d\u133d \u1325\u12eb\u1244 \u12ed\u1245\u1228\u1265",refresh_btn:"\u120c\u120b \u12a0\u12f2\u1235 \u1325\u12eb\u1244 \u12ed\u1245\u1228\u1265",
-instructions_visual:"",instructions_audio:"\u12e8\u121d\u1275\u1230\u121b\u12cd\u1295 \u1270\u12ed\u1265\u1361-",help_btn:"\u12a5\u1308\u12db",play_again:"\u12f5\u121d\u1339\u1295 \u12a5\u1295\u12f0\u1308\u1293 \u12a0\u132b\u12cd\u1275",cant_hear_this:"\u12f5\u121d\u1339\u1295 \u1260MP3 \u1245\u122d\u133d \u12a0\u12cd\u122d\u12f5",incorrect_try_again:"\u1275\u12ad\u12ad\u120d \u12a0\u12ed\u12f0\u1208\u121d\u1362 \u12a5\u1295\u12f0\u1308\u1293 \u121e\u12ad\u122d\u1362",image_alt_text:"reCAPTCHA \u121d\u1235\u120d \u130d\u1320\u121d",
-privacy_and_terms:"\u130d\u120b\u12ca\u1290\u1275 \u12a5\u1293 \u12cd\u120d"},ar:ka,"ar-EG":ka,bg:{visual_challenge:"\u041f\u043e\u043b\u0443\u0447\u0430\u0432\u0430\u043d\u0435 \u043d\u0430 \u0432\u0438\u0437\u0443\u0430\u043b\u043d\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430",audio_challenge:"\u0417\u0430\u0440\u0435\u0436\u0434\u0430\u043d\u0435 \u043d\u0430 \u0430\u0443\u0434\u0438\u043e\u0442\u0435\u0441\u0442",refresh_btn:"\u0417\u0430\u0440\u0435\u0436\u0434\u0430\u043d\u0435 \u043d\u0430 \u043d\u043e\u0432 \u0442\u0435\u0441\u0442",
-instructions_visual:"\u0412\u044a\u0432\u0435\u0434\u0435\u0442\u0435 \u0442\u0435\u043a\u0441\u0442\u0430:",instructions_audio:"\u0412\u044a\u0432\u0435\u0434\u0435\u0442\u0435 \u0447\u0443\u0442\u043e\u0442\u043e:",help_btn:"\u041f\u043e\u043c\u043e\u0449",play_again:"\u041f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u043f\u0443\u0441\u043a\u0430\u043d\u0435 \u043d\u0430 \u0437\u0432\u0443\u043a\u0430",cant_hear_this:"\u0418\u0437\u0442\u0435\u0433\u043b\u044f\u043d\u0435 \u043d\u0430 \u0437\u0432\u0443\u043a\u0430 \u0432\u044a\u0432 \u0444\u043e\u0440\u043c\u0430\u0442 MP3",
-incorrect_try_again:"\u041d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u043d\u043e. \u041e\u043f\u0438\u0442\u0430\u0439\u0442\u0435 \u043e\u0442\u043d\u043e\u0432\u043e.",image_alt_text:"\u0418\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u043d\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430\u0442\u0430 \u0441 reCAPTCHA",privacy_and_terms:"\u041f\u043e\u0432\u0435\u0440\u0438\u0442\u0435\u043b\u043d\u043e\u0441\u0442 \u0438 \u041e\u0431\u0449\u0438 \u0443\u0441\u043b\u043e\u0432\u0438\u044f"},
-bn:{visual_challenge:"\u098f\u0995\u099f\u09bf \u09a6\u09c3\u09b6\u09cd\u09af\u09ae\u09be\u09a8 \u09aa\u09cd\u09b0\u09a4\u09bf\u09a6\u09cd\u09ac\u09a8\u09cd\u09a6\u09cd\u09ac\u09bf\u09a4\u09be \u09aa\u09be\u09a8",audio_challenge:"\u098f\u0995\u099f\u09bf \u0985\u09a1\u09bf\u0993 \u09aa\u09cd\u09b0\u09a4\u09bf\u09a6\u09cd\u09ac\u09a8\u09cd\u09a6\u09cd\u09ac\u09bf\u09a4\u09be  \u09aa\u09be\u09a8",refresh_btn:"\u098f\u0995\u099f\u09bf \u09a8\u09a4\u09c1\u09a8 \u09aa\u09cd\u09b0\u09a4\u09bf\u09a6\u09cd\u09ac\u09a8\u09cd\u09a6\u09cd\u09ac\u09bf\u09a4\u09be  \u09aa\u09be\u09a8",
-instructions_visual:"",instructions_audio:"\u0986\u09aa\u09a8\u09bf \u09af\u09be \u09b6\u09c1\u09a8\u099b\u09c7\u09a8 \u09a4\u09be \u09b2\u09bf\u0996\u09c1\u09a8:",help_btn:"\u09b8\u09b9\u09be\u09df\u09a4\u09be",play_again:"\u0986\u09ac\u09be\u09b0 \u09b8\u09be\u0989\u09a8\u09cd\u09a1 \u09aa\u09cd\u09b2\u09c7 \u0995\u09b0\u09c1\u09a8",cant_hear_this:"MP3 \u09b0\u09c2\u09aa\u09c7 \u09b6\u09ac\u09cd\u09a6 \u09a1\u09be\u0989\u09a8\u09b2\u09cb\u09a1 \u0995\u09b0\u09c1\u09a8",incorrect_try_again:"\u09ac\u09c7\u09a0\u09bf\u0995\u09f7 \u0986\u09ac\u09be\u09b0 \u099a\u09c7\u09b7\u09cd\u099f\u09be \u0995\u09b0\u09c1\u09a8\u09f7",
-image_alt_text:"reCAPTCHA \u099a\u09cd\u09af\u09be\u09b2\u09c7\u099e\u09cd\u099c \u099a\u09bf\u09a4\u09cd\u09b0",privacy_and_terms:"\u0997\u09cb\u09aa\u09a8\u09c0\u09af\u09bc\u09a4\u09be \u0993 \u09b6\u09b0\u09cd\u09a4\u09be\u09ac\u09b2\u09c0"},ca:{visual_challenge:"Obt\u00e9n un repte visual",audio_challenge:"Obteniu una pista sonora",refresh_btn:"Obteniu una pista nova",instructions_visual:"Escriviu el text:",instructions_audio:"Escriviu el que escolteu:",help_btn:"Ajuda",play_again:"Torna a reproduir el so",
-cant_hear_this:"Baixa el so com a MP3",incorrect_try_again:"No \u00e9s correcte. Torna-ho a provar.",image_alt_text:"Imatge del repte de reCAPTCHA",privacy_and_terms:"Privadesa i condicions"},cs:{visual_challenge:"Zobrazit vizu\u00e1ln\u00ed podobu v\u00fdrazu",audio_challenge:"P\u0159ehr\u00e1t zvukovou podobu v\u00fdrazu",refresh_btn:"Zobrazit nov\u00fd v\u00fdraz",instructions_visual:"Zadejte text:",instructions_audio:"Napi\u0161te, co jste sly\u0161eli:",help_btn:"N\u00e1pov\u011bda",play_again:"Znovu p\u0159ehr\u00e1t zvuk",
-cant_hear_this:"St\u00e1hnout zvuk ve form\u00e1tu MP3",incorrect_try_again:"\u0160patn\u011b. Zkuste to znovu.",image_alt_text:"Obr\u00e1zek reCAPTCHA",privacy_and_terms:"Ochrana soukrom\u00ed a smluvn\u00ed podm\u00ednky"},da:{visual_challenge:"Hent en visuel udfordring",audio_challenge:"Hent en lydudfordring",refresh_btn:"Hent en ny udfordring",instructions_visual:"Indtast teksten:",instructions_audio:"Indtast det, du h\u00f8rer:",help_btn:"Hj\u00e6lp",play_again:"Afspil lyden igen",cant_hear_this:"Download lyd som MP3",
-incorrect_try_again:"Forkert. Pr\u00f8v igen.",image_alt_text:"reCAPTCHA-udfordringsbillede",privacy_and_terms:"Privatliv og vilk\u00e5r"},de:{visual_challenge:"Captcha abrufen",audio_challenge:"Audio-Captcha abrufen",refresh_btn:"Neues Captcha abrufen",instructions_visual:"Geben Sie den angezeigten Text ein:",instructions_audio:"Geben Sie das Geh\u00f6rte ein:",help_btn:"Hilfe",play_again:"Wort erneut abspielen",cant_hear_this:"Wort als MP3 herunterladen",incorrect_try_again:"Falsch. Bitte versuchen Sie es erneut.",
-image_alt_text:"reCAPTCHA-Bild",privacy_and_terms:"Datenschutzerkl\u00e4rung & Nutzungsbedingungen"},el:{visual_challenge:"\u039f\u03c0\u03c4\u03b9\u03ba\u03ae \u03c0\u03c1\u03cc\u03ba\u03bb\u03b7\u03c3\u03b7",audio_challenge:"\u0397\u03c7\u03b7\u03c4\u03b9\u03ba\u03ae \u03c0\u03c1\u03cc\u03ba\u03bb\u03b7\u03c3\u03b7",refresh_btn:"\u039d\u03ad\u03b1 \u03c0\u03c1\u03cc\u03ba\u03bb\u03b7\u03c3\u03b7",instructions_visual:"\u03a0\u03bb\u03b7\u03ba\u03c4\u03c1\u03bf\u03bb\u03bf\u03b3\u03ae\u03c3\u03c4\u03b5 \u03c4\u03bf \u03ba\u03b5\u03af\u03bc\u03b5\u03bd\u03bf:",
-instructions_audio:"\u03a0\u03bb\u03b7\u03ba\u03c4\u03c1\u03bf\u03bb\u03bf\u03b3\u03ae\u03c3\u03c4\u03b5 \u03cc\u03c4\u03b9 \u03b1\u03ba\u03bf\u03cd\u03c4\u03b5:",help_btn:"\u0392\u03bf\u03ae\u03b8\u03b5\u03b9\u03b1",play_again:"\u0391\u03bd\u03b1\u03c0\u03b1\u03c1\u03b1\u03b3\u03c9\u03b3\u03ae \u03ae\u03c7\u03bf\u03c5 \u03be\u03b1\u03bd\u03ac",cant_hear_this:"\u039b\u03ae\u03c8\u03b7 \u03ae\u03c7\u03bf\u03c5 \u03c9\u03c2 \u039c\u03a13",incorrect_try_again:"\u039b\u03ac\u03b8\u03bf\u03c2. \u0394\u03bf\u03ba\u03b9\u03bc\u03ac\u03c3\u03c4\u03b5 \u03be\u03b1\u03bd\u03ac.",
-image_alt_text:"\u0395\u03b9\u03ba\u03cc\u03bd\u03b1 \u03c0\u03c1\u03cc\u03ba\u03bb\u03b7\u03c3\u03b7\u03c2 reCAPTCHA",privacy_and_terms:"\u0391\u03c0\u03cc\u03c1\u03c1\u03b7\u03c4\u03bf \u03ba\u03b1\u03b9 \u03cc\u03c1\u03bf\u03b9"},"en-GB":t,"en-US":t,es:la,"es-419":{visual_challenge:"Enfrentar un desaf\u00edo visual",audio_challenge:"Enfrentar un desaf\u00edo de audio",refresh_btn:"Enfrentar un nuevo desaf\u00edo",instructions_visual:"Escriba el texto:",instructions_audio:"Escribe lo que escuchas:",
-help_btn:"Ayuda",play_again:"Reproducir sonido de nuevo",cant_hear_this:"Descargar sonido en formato MP3",incorrect_try_again:"Incorrecto. Vuelve a intentarlo.",image_alt_text:"Imagen del desaf\u00edo de la reCAPTCHA",privacy_and_terms:"Privacidad y condiciones"},"es-ES":la,et:{visual_challenge:"Kuva kuvap\u00f5hine robotil\u00f5ks",audio_challenge:"Kuva helip\u00f5hine robotil\u00f5ks",refresh_btn:"Kuva uus robotil\u00f5ks",instructions_visual:"Tippige tekst:",instructions_audio:"Tippige, mida kuulete.",
-help_btn:"Abi",play_again:"Esita heli uuesti",cant_hear_this:"Laadi heli alla MP3-vormingus",incorrect_try_again:"Vale. Proovige uuesti.",image_alt_text:"reCAPTCHA robotil\u00f5ksu kujutis",privacy_and_terms:"Privaatsus ja tingimused"},eu:{visual_challenge:"Eskuratu ikusizko erronka",audio_challenge:"Eskuratu audio-erronka",refresh_btn:"Eskuratu erronka berria",instructions_visual:"",instructions_audio:"Idatzi entzuten duzuna:",help_btn:"Laguntza",play_again:"Erreproduzitu soinua berriro",cant_hear_this:"Deskargatu soinua MP3 gisa",
-incorrect_try_again:"Ez da zuzena. Saiatu berriro.",image_alt_text:"reCAPTCHA erronkaren irudia",privacy_and_terms:"Pribatutasuna eta baldintzak"},fa:{visual_challenge:"\u062f\u0631\u06cc\u0627\u0641\u062a \u06cc\u06a9 \u0645\u0639\u0645\u0627\u06cc \u062f\u06cc\u062f\u0627\u0631\u06cc",audio_challenge:"\u062f\u0631\u06cc\u0627\u0641\u062a \u06cc\u06a9 \u0645\u0639\u0645\u0627\u06cc \u0635\u0648\u062a\u06cc",refresh_btn:"\u062f\u0631\u06cc\u0627\u0641\u062a \u06cc\u06a9 \u0645\u0639\u0645\u0627\u06cc \u062c\u062f\u06cc\u062f",
-instructions_visual:"",instructions_audio:"\u0622\u0646\u0686\u0647 \u0631\u0627 \u06a9\u0647 \u0645\u06cc\u200c\u0634\u0646\u0648\u06cc\u062f \u062a\u0627\u06cc\u067e \u06a9\u0646\u06cc\u062f:",help_btn:"\u0631\u0627\u0647\u0646\u0645\u0627\u06cc\u06cc",play_again:"\u067e\u062e\u0634 \u0645\u062c\u062f\u062f \u0635\u062f\u0627",cant_hear_this:"\u062f\u0627\u0646\u0644\u0648\u062f \u0635\u062f\u0627 \u0628\u0647 \u0635\u0648\u0631\u062a MP3",incorrect_try_again:"\u0646\u0627\u062f\u0631\u0633\u062a. \u062f\u0648\u0628\u0627\u0631\u0647 \u0627\u0645\u062a\u062d\u0627\u0646 \u06a9\u0646\u06cc\u062f.",
-image_alt_text:"\u062a\u0635\u0648\u06cc\u0631 \u0686\u0627\u0644\u0634\u06cc reCAPTCHA",privacy_and_terms:"\u062d\u0631\u06cc\u0645 \u062e\u0635\u0648\u0635\u06cc \u0648 \u0634\u0631\u0627\u06cc\u0637"},fi:{visual_challenge:"Kuvavahvistus",audio_challenge:"\u00c4\u00e4nivahvistus",refresh_btn:"Uusi kuva",instructions_visual:"Kirjoita teksti:",instructions_audio:"Kirjoita kuulemasi:",help_btn:"Ohje",play_again:"Toista \u00e4\u00e4ni uudelleen",cant_hear_this:"Lataa \u00e4\u00e4ni MP3-tiedostona",
-incorrect_try_again:"V\u00e4\u00e4rin. Yrit\u00e4 uudelleen.",image_alt_text:"reCAPTCHA-kuva",privacy_and_terms:"Tietosuoja ja k\u00e4ytt\u00f6ehdot"},fil:ma,fr:na,"fr-CA":{visual_challenge:"Obtenir un test visuel",audio_challenge:"Obtenir un test audio",refresh_btn:"Obtenir un nouveau test",instructions_visual:"Saisissez le texte\u00a0:",instructions_audio:"Tapez ce que vous entendez\u00a0:",help_btn:"Aide",play_again:"Jouer le son de nouveau",cant_hear_this:"T\u00e9l\u00e9charger le son en format MP3",
-incorrect_try_again:"Erreur, essayez \u00e0 nouveau",image_alt_text:"Image reCAPTCHA",privacy_and_terms:"Confidentialit\u00e9 et conditions d'utilisation"},"fr-FR":na,gl:{visual_challenge:"Obter unha proba visual",audio_challenge:"Obter unha proba de audio",refresh_btn:"Obter unha proba nova",instructions_visual:"",instructions_audio:"Escribe o que escoitas:",help_btn:"Axuda",play_again:"Reproducir o son de novo",cant_hear_this:"Descargar son como MP3",incorrect_try_again:"Incorrecto. T\u00e9ntao de novo.",
-image_alt_text:"Imaxe de proba de reCAPTCHA",privacy_and_terms:"Privacidade e condici\u00f3ns"},gu:{visual_challenge:"\u0a8f\u0a95 \u0aa6\u0ac3\u0ab6\u0acd\u0aaf\u0abe\u0aa4\u0acd\u0aae\u0a95 \u0aaa\u0aa1\u0a95\u0abe\u0ab0 \u0aae\u0ac7\u0ab3\u0ab5\u0acb",audio_challenge:"\u0a8f\u0a95 \u0a91\u0aa1\u0abf\u0a93 \u0aaa\u0aa1\u0a95\u0abe\u0ab0 \u0aae\u0ac7\u0ab3\u0ab5\u0acb",refresh_btn:"\u0a8f\u0a95 \u0aa8\u0ab5\u0acb \u0aaa\u0aa1\u0a95\u0abe\u0ab0 \u0aae\u0ac7\u0ab3\u0ab5\u0acb",instructions_visual:"",
-instructions_audio:"\u0aa4\u0aae\u0ac7 \u0a9c\u0ac7 \u0ab8\u0abe\u0a82\u0aad\u0ab3\u0acb \u0a9b\u0acb \u0aa4\u0ac7 \u0ab2\u0a96\u0acb:",help_btn:"\u0ab8\u0ab9\u0abe\u0aaf",play_again:"\u0aa7\u0acd\u0ab5\u0aa8\u0abf \u0aab\u0ab0\u0ac0\u0aa5\u0ac0 \u0a9a\u0ab2\u0abe\u0ab5\u0acb",cant_hear_this:"MP3 \u0aa4\u0ab0\u0ac0\u0a95\u0ac7 \u0aa7\u0acd\u0ab5\u0aa8\u0abf\u0aa8\u0ac7 \u0aa1\u0abe\u0a89\u0aa8\u0ab2\u0acb\u0aa1 \u0a95\u0ab0\u0acb",incorrect_try_again:"\u0a96\u0acb\u0a9f\u0ac1\u0a82. \u0aab\u0ab0\u0ac0 \u0aaa\u0acd\u0ab0\u0aaf\u0abe\u0ab8 \u0a95\u0ab0\u0acb.",
-image_alt_text:"reCAPTCHA \u0aaa\u0aa1\u0a95\u0abe\u0ab0 \u0a9b\u0aac\u0ac0",privacy_and_terms:"\u0a97\u0acb\u0aaa\u0aa8\u0ac0\u0aaf\u0aa4\u0abe \u0a85\u0aa8\u0ac7 \u0ab6\u0ab0\u0aa4\u0acb"},hi:{visual_challenge:"\u0915\u094b\u0908 \u0935\u093f\u091c\u0941\u0905\u0932 \u091a\u0941\u0928\u094c\u0924\u0940 \u0932\u0947\u0902",audio_challenge:"\u0915\u094b\u0908 \u0911\u0921\u093f\u092f\u094b \u091a\u0941\u0928\u094c\u0924\u0940 \u0932\u0947\u0902",refresh_btn:"\u0915\u094b\u0908 \u0928\u0908 \u091a\u0941\u0928\u094c\u0924\u0940 \u0932\u0947\u0902",
-instructions_visual:"\u091f\u0947\u0915\u094d\u0938\u094d\u091f \u091f\u093e\u0907\u092a \u0915\u0930\u0947\u0902:",instructions_audio:"\u091c\u094b \u0906\u092a \u0938\u0941\u0928 \u0930\u0939\u0947 \u0939\u0948\u0902 \u0909\u0938\u0947 \u0932\u093f\u0916\u0947\u0902:",help_btn:"\u0938\u0939\u093e\u092f\u0924\u093e",play_again:"\u0927\u094d\u200d\u0935\u0928\u093f \u092a\u0941\u0928: \u091a\u0932\u093e\u090f\u0902",cant_hear_this:"\u0927\u094d\u200d\u0935\u0928\u093f \u0915\u094b MP3 \u0915\u0947 \u0930\u0942\u092a \u092e\u0947\u0902 \u0921\u093e\u0909\u0928\u0932\u094b\u0921 \u0915\u0930\u0947\u0902",
-incorrect_try_again:"\u0917\u0932\u0924. \u092a\u0941\u0928: \u092a\u094d\u0930\u092f\u093e\u0938 \u0915\u0930\u0947\u0902.",image_alt_text:"reCAPTCHA \u091a\u0941\u0928\u094c\u0924\u0940 \u091a\u093f\u0924\u094d\u0930",privacy_and_terms:"\u0917\u094b\u092a\u0928\u0940\u092f\u0924\u093e \u0914\u0930 \u0936\u0930\u094d\u0924\u0947\u0902"},hr:{visual_challenge:"Dohvati vizualni upit",audio_challenge:"Dohvati zvu\u010dni upit",refresh_btn:"Dohvati novi upit",instructions_visual:"Unesite tekst:",instructions_audio:"Upi\u0161ite \u0161to \u010dujete:",
-help_btn:"Pomo\u0107",play_again:"Ponovi zvuk",cant_hear_this:"Preuzmi zvuk u MP3 formatu",incorrect_try_again:"Nije to\u010dno. Poku\u0161ajte ponovno.",image_alt_text:"Slikovni izazov reCAPTCHA",privacy_and_terms:"Privatnost i odredbe"},hu:{visual_challenge:"Vizu\u00e1lis kih\u00edv\u00e1s k\u00e9r\u00e9se",audio_challenge:"Hangkih\u00edv\u00e1s k\u00e9r\u00e9se",refresh_btn:"\u00daj kih\u00edv\u00e1s k\u00e9r\u00e9se",instructions_visual:"\u00cdrja be a sz\u00f6veget:",instructions_audio:"\u00cdrja le, amit hall:",
-help_btn:"S\u00fag\u00f3",play_again:"Hang ism\u00e9telt lej\u00e1tsz\u00e1sa",cant_hear_this:"Hang let\u00f6lt\u00e9se MP3 form\u00e1tumban",incorrect_try_again:"Hib\u00e1s. Pr\u00f3b\u00e1lkozzon \u00fajra.",image_alt_text:"reCAPTCHA ellen\u0151rz\u0151 k\u00e9p",privacy_and_terms:"Adatv\u00e9delem \u00e9s Szerz\u0151d\u00e9si Felt\u00e9telek"},hy:{visual_challenge:"\u054d\u057f\u0561\u0576\u0561\u056c \u057f\u0565\u057d\u0578\u0572\u0561\u056f\u0561\u0576 \u056d\u0576\u0564\u056b\u0580",audio_challenge:"\u054d\u057f\u0561\u0576\u0561\u056c \u0571\u0561\u0575\u0576\u0561\u0575\u056b\u0576 \u056d\u0576\u0564\u056b\u0580",
-refresh_btn:"\u054d\u057f\u0561\u0576\u0561\u056c \u0576\u0578\u0580 \u056d\u0576\u0564\u056b\u0580",instructions_visual:"\u0544\u0578\u0582\u057f\u0584\u0561\u0563\u0580\u0565\u0584 \u057f\u0565\u0584\u057d\u057f\u0568\u055d",instructions_audio:"\u0544\u0578\u0582\u057f\u0584\u0561\u0563\u0580\u0565\u0584 \u0561\u0575\u0576, \u056b\u0576\u0579 \u056c\u057d\u0578\u0582\u0574 \u0565\u0584\u055d",help_btn:"\u0555\u0563\u0576\u0578\u0582\u0569\u0575\u0578\u0582\u0576",play_again:"\u0546\u057e\u0561\u0563\u0561\u0580\u056f\u0565\u056c \u0571\u0561\u0575\u0576\u0568 \u056f\u0580\u056f\u056b\u0576",
-cant_hear_this:"\u0532\u0565\u057c\u0576\u0565\u056c \u0571\u0561\u0575\u0576\u0568 \u0578\u0580\u057a\u0565\u057d MP3",incorrect_try_again:"\u054d\u056d\u0561\u056c \u0567: \u0553\u0578\u0580\u0571\u0565\u0584 \u056f\u0580\u056f\u056b\u0576:",image_alt_text:"reCAPTCHA \u057a\u0561\u057f\u056f\u0565\u0580\u0578\u057e \u056d\u0576\u0564\u056b\u0580",privacy_and_terms:"\u0533\u0561\u0572\u057f\u0576\u056b\u0578\u0582\u0569\u0575\u0561\u0576 & \u057a\u0561\u0575\u0574\u0561\u0576\u0576\u0565\u0580"},
-id:oa,is:{visual_challenge:"F\u00e1 a\u00f0gangspr\u00f3f sem mynd",audio_challenge:"F\u00e1 a\u00f0gangspr\u00f3f sem hlj\u00f3\u00f0skr\u00e1",refresh_btn:"F\u00e1 n\u00fdtt a\u00f0gangspr\u00f3f",instructions_visual:"",instructions_audio:"Sl\u00e1\u00f0u inn \u00fea\u00f0 sem \u00fe\u00fa heyrir:",help_btn:"Hj\u00e1lp",play_again:"Spila hlj\u00f3\u00f0 aftur",cant_hear_this:"S\u00e6kja hlj\u00f3\u00f0 sem MP3",incorrect_try_again:"Rangt. Reyndu aftur.",image_alt_text:"mynd reCAPTCHA a\u00f0gangspr\u00f3fs",
-privacy_and_terms:"Pers\u00f3nuvernd og skilm\u00e1lar"},it:{visual_challenge:"Verifica visiva",audio_challenge:"Verifica audio",refresh_btn:"Nuova verifica",instructions_visual:"Digita il testo:",instructions_audio:"Digita ci\u00f2 che senti:",help_btn:"Guida",play_again:"Riproduci di nuovo audio",cant_hear_this:"Scarica audio in MP3",incorrect_try_again:"Sbagliato. Riprova.",image_alt_text:"Immagine di verifica reCAPTCHA",privacy_and_terms:"Privacy e Termini"},iw:pa,ja:{visual_challenge:"\u753b\u50cf\u3067\u78ba\u8a8d\u3057\u307e\u3059",
-audio_challenge:"\u97f3\u58f0\u3067\u78ba\u8a8d\u3057\u307e\u3059",refresh_btn:"\u5225\u306e\u5358\u8a9e\u3067\u3084\u308a\u76f4\u3057\u307e\u3059",instructions_visual:"\u30c6\u30ad\u30b9\u30c8\u3092\u5165\u529b:",instructions_audio:"\u805e\u3053\u3048\u305f\u5358\u8a9e\u3092\u5165\u529b\u3057\u307e\u3059:",help_btn:"\u30d8\u30eb\u30d7",play_again:"\u3082\u3046\u4e00\u5ea6\u805e\u304f",cant_hear_this:"MP3 \u3067\u97f3\u58f0\u3092\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9",incorrect_try_again:"\u6b63\u3057\u304f\u3042\u308a\u307e\u305b\u3093\u3002\u3082\u3046\u4e00\u5ea6\u3084\u308a\u76f4\u3057\u3066\u304f\u3060\u3055\u3044\u3002",
-image_alt_text:"reCAPTCHA \u78ba\u8a8d\u7528\u753b\u50cf",privacy_and_terms:"\u30d7\u30e9\u30a4\u30d0\u30b7\u30fc\u3068\u5229\u7528\u898f\u7d04"},kn:{visual_challenge:"\u0ca6\u0cc3\u0cb6\u0ccd\u0caf \u0cb8\u0cb5\u0cbe\u0cb2\u0cca\u0c82\u0ca6\u0ca8\u0ccd\u0ca8\u0cc1 \u0cb8\u0ccd\u0cb5\u0cc0\u0c95\u0cb0\u0cbf\u0cb8\u0cbf",audio_challenge:"\u0c86\u0ca1\u0cbf\u0caf\u0ccb \u0cb8\u0cb5\u0cbe\u0cb2\u0cca\u0c82\u0ca6\u0ca8\u0ccd\u0ca8\u0cc1 \u0cb8\u0ccd\u0cb5\u0cc0\u0c95\u0cb0\u0cbf\u0cb8\u0cbf",refresh_btn:"\u0cb9\u0cca\u0cb8 \u0cb8\u0cb5\u0cbe\u0cb2\u0cca\u0c82\u0ca6\u0ca8\u0ccd\u0ca8\u0cc1 \u0caa\u0ca1\u0cc6\u0caf\u0cbf\u0cb0\u0cbf",
-instructions_visual:"",instructions_audio:"\u0ca8\u0cbf\u0cae\u0c97\u0cc6 \u0c95\u0cc7\u0cb3\u0cbf\u0cb8\u0cc1\u0cb5\u0cc1\u0ca6\u0ca8\u0ccd\u0ca8\u0cc1 \u0c9f\u0cc8\u0caa\u0ccd\u200c \u0cae\u0cbe\u0ca1\u0cbf:",help_btn:"\u0cb8\u0cb9\u0cbe\u0caf",play_again:"\u0ca7\u0ccd\u0cb5\u0ca8\u0cbf\u0caf\u0ca8\u0ccd\u0ca8\u0cc1 \u0cae\u0ca4\u0ccd\u0ca4\u0cc6 \u0caa\u0ccd\u0cb2\u0cc7 \u0cae\u0cbe\u0ca1\u0cbf",cant_hear_this:"\u0ca7\u0ccd\u0cb5\u0ca8\u0cbf\u0caf\u0ca8\u0ccd\u0ca8\u0cc1 MP3 \u0cb0\u0cc2\u0caa\u0ca6\u0cb2\u0ccd\u0cb2\u0cbf \u0ca1\u0ccc\u0ca8\u0ccd\u200c\u0cb2\u0ccb\u0ca1\u0ccd \u0cae\u0cbe\u0ca1\u0cbf",
-incorrect_try_again:"\u0ca4\u0caa\u0ccd\u0caa\u0cbe\u0c97\u0cbf\u0ca6\u0cc6. \u0cae\u0ca4\u0ccd\u0ca4\u0cca\u0cae\u0ccd\u0cae\u0cc6 \u0caa\u0ccd\u0cb0\u0caf\u0ca4\u0ccd\u0ca8\u0cbf\u0cb8\u0cbf.",image_alt_text:"reCAPTCHA \u0cb8\u0cb5\u0cbe\u0cb2\u0cc1 \u0c9a\u0cbf\u0ca4\u0ccd\u0cb0",privacy_and_terms:"\u0c97\u0ccc\u0caa\u0ccd\u0caf\u0ca4\u0cc6 \u0cae\u0ca4\u0ccd\u0ca4\u0cc1 \u0ca8\u0cbf\u0caf\u0cae\u0c97\u0cb3\u0cc1"},ko:{visual_challenge:"\uadf8\ub9bc\uc73c\ub85c \ubcf4\uc548\ubb38\uc790 \ubc1b\uae30",
-audio_challenge:"\uc74c\uc131\uc73c\ub85c \ubcf4\uc548\ubb38\uc790 \ubc1b\uae30",refresh_btn:"\ubcf4\uc548\ubb38\uc790 \uc0c8\ub85c \ubc1b\uae30",instructions_visual:"\ud14d\uc2a4\ud2b8 \uc785\ub825:",instructions_audio:"\uc74c\uc131 \ubcf4\uc548\ubb38\uc790 \uc785\ub825:",help_btn:"\ub3c4\uc6c0\ub9d0",play_again:"\uc74c\uc131 \ub2e4\uc2dc \ub4e3\uae30",cant_hear_this:"\uc74c\uc131\uc744 MP3\ub85c \ub2e4\uc6b4\ub85c\ub4dc",incorrect_try_again:"\ud2c0\ub838\uc2b5\ub2c8\ub2e4. \ub2e4\uc2dc \uc2dc\ub3c4\ud574 \uc8fc\uc138\uc694.",
-image_alt_text:"reCAPTCHA \ubcf4\uc548\ubb38\uc790 \uc774\ubbf8\uc9c0",privacy_and_terms:"\uac1c\uc778\uc815\ubcf4 \ubcf4\ud638 \ubc0f \uc57d\uad00"},ln:na,lt:{visual_challenge:"Gauti vaizdin\u012f atpa\u017einimo test\u0105",audio_challenge:"Gauti garso atpa\u017einimo test\u0105",refresh_btn:"Gauti nauj\u0105 atpa\u017einimo test\u0105",instructions_visual:"\u012eveskite tekst\u0105:",instructions_audio:"\u012eveskite tai, k\u0105 girdite:",help_btn:"Pagalba",play_again:"Dar kart\u0105 paleisti gars\u0105",
-cant_hear_this:"Atsisi\u0173sti gars\u0105 kaip MP3",incorrect_try_again:"Neteisingai. Bandykite dar kart\u0105.",image_alt_text:"Testo \u201ereCAPTCHA\u201c vaizdas",privacy_and_terms:"Privatumas ir s\u0105lygos"},lv:{visual_challenge:"Sa\u0146emt vizu\u0101lu izaicin\u0101jumu",audio_challenge:"Sa\u0146emt audio izaicin\u0101jumu",refresh_btn:"Sa\u0146emt jaunu izaicin\u0101jumu",instructions_visual:"Ievadiet tekstu:",instructions_audio:"Ierakstiet dzirdamo:",help_btn:"Pal\u012bdz\u012bba",play_again:"V\u0113lreiz atska\u0146ot ska\u0146u",
-cant_hear_this:"Lejupiel\u0101d\u0113t ska\u0146u MP3\u00a0form\u0101t\u0101",incorrect_try_again:"Nepareizi. M\u0113\u0123iniet v\u0113lreiz.",image_alt_text:"reCAPTCHA izaicin\u0101juma att\u0113ls",privacy_and_terms:"Konfidencialit\u0101te un noteikumi"},ml:{visual_challenge:"\u0d12\u0d30\u0d41 \u0d26\u0d43\u0d36\u0d4d\u0d2f \u0d1a\u0d32\u0d1e\u0d4d\u0d1a\u0d4d \u0d28\u0d47\u0d1f\u0d41\u0d15",audio_challenge:"\u0d12\u0d30\u0d41 \u0d13\u0d21\u0d3f\u0d2f\u0d4b \u0d1a\u0d32\u0d1e\u0d4d\u0d1a\u0d4d \u0d28\u0d47\u0d1f\u0d41\u0d15",
-refresh_btn:"\u0d12\u0d30\u0d41 \u0d2a\u0d41\u0d24\u0d3f\u0d2f \u0d1a\u0d32\u0d1e\u0d4d\u0d1a\u0d4d \u0d28\u0d47\u0d1f\u0d41\u0d15",instructions_visual:"",instructions_audio:"\u0d15\u0d47\u0d7e\u0d15\u0d4d\u0d15\u0d41\u0d28\u0d4d\u0d28\u0d24\u0d4d \u0d1f\u0d48\u0d2a\u0d4d\u0d2a\u0d4d \u0d1a\u0d46\u0d2f\u0d4d\u0d2f\u0d42:",help_btn:"\u0d38\u0d39\u0d3e\u0d2f\u0d02",play_again:"\u0d36\u0d2c\u0d4d\u200c\u0d26\u0d02 \u0d35\u0d40\u0d23\u0d4d\u0d1f\u0d41\u0d02 \u0d2a\u0d4d\u0d32\u0d47 \u0d1a\u0d46\u0d2f\u0d4d\u0d2f\u0d41\u0d15",
-cant_hear_this:"\u0d36\u0d2c\u0d4d\u200c\u0d26\u0d02 MP3 \u0d06\u0d2f\u0d3f \u0d21\u0d57\u0d7a\u0d32\u0d4b\u0d21\u0d4d \u0d1a\u0d46\u0d2f\u0d4d\u0d2f\u0d41\u0d15",incorrect_try_again:"\u0d24\u0d46\u0d31\u0d4d\u0d31\u0d3e\u0d23\u0d4d. \u0d35\u0d40\u0d23\u0d4d\u0d1f\u0d41\u0d02 \u0d36\u0d4d\u0d30\u0d2e\u0d3f\u0d15\u0d4d\u0d15\u0d41\u0d15.",image_alt_text:"reCAPTCHA \u0d1a\u0d32\u0d1e\u0d4d\u0d1a\u0d4d \u0d07\u0d2e\u0d47\u0d1c\u0d4d",privacy_and_terms:"\u0d38\u0d4d\u0d35\u0d15\u0d3e\u0d30\u0d4d\u0d2f\u0d24\u0d2f\u0d41\u0d02 \u0d28\u0d3f\u0d2c\u0d28\u0d4d\u0d27\u0d28\u0d15\u0d33\u0d41\u0d02"},
-mr:{visual_challenge:"\u0926\u0943\u0936\u094d\u200d\u092f\u092e\u093e\u0928 \u0906\u0935\u094d\u0939\u093e\u0928 \u092a\u094d\u0930\u093e\u092a\u094d\u0924 \u0915\u0930\u093e",audio_challenge:"\u0911\u0921\u0940\u0913 \u0906\u0935\u094d\u0939\u093e\u0928 \u092a\u094d\u0930\u093e\u092a\u094d\u0924 \u0915\u0930\u093e",refresh_btn:"\u090f\u0915 \u0928\u0935\u0940\u0928 \u0906\u0935\u094d\u0939\u093e\u0928 \u092a\u094d\u0930\u093e\u092a\u094d\u0924 \u0915\u0930\u093e",instructions_visual:"",instructions_audio:"\u0906\u092a\u0932\u094d\u092f\u093e\u0932\u093e \u091c\u0947 \u0910\u0915\u0942 \u092f\u0947\u0908\u0932 \u0924\u0947 \u091f\u093e\u0907\u092a \u0915\u0930\u093e:",
-help_btn:"\u092e\u0926\u0924",play_again:"\u0927\u094d\u200d\u0935\u0928\u0940 \u092a\u0941\u0928\u094d\u0939\u093e \u092a\u094d\u200d\u0932\u0947 \u0915\u0930\u093e",cant_hear_this:"MP3 \u0930\u0941\u092a\u093e\u0924 \u0927\u094d\u200d\u0935\u0928\u0940 \u0921\u093e\u0909\u0928\u0932\u094b\u0921 \u0915\u0930\u093e",incorrect_try_again:"\u0905\u092f\u094b\u0917\u094d\u200d\u092f. \u092a\u0941\u0928\u094d\u200d\u0939\u093e \u092a\u094d\u0930\u092f\u0924\u094d\u200d\u0928 \u0915\u0930\u093e.",image_alt_text:"reCAPTCHA \u0906\u0935\u094d\u200d\u0939\u093e\u0928 \u092a\u094d\u0930\u0924\u093f\u092e\u093e",
-privacy_and_terms:"\u0917\u094b\u092a\u0928\u0940\u092f\u0924\u093e \u0906\u0923\u093f \u0905\u091f\u0940"},ms:{visual_challenge:"Dapatkan cabaran visual",audio_challenge:"Dapatkan cabaran audio",refresh_btn:"Dapatkan cabaran baru",instructions_visual:"Taipkan teksnya:",instructions_audio:"Taip apa yang didengari:",help_btn:"Bantuan",play_again:"Mainkan bunyi sekali lagi",cant_hear_this:"Muat turun bunyi sebagai MP3",incorrect_try_again:"Tidak betul. Cuba lagi.",image_alt_text:"Imej cabaran reCAPTCHA",
-privacy_and_terms:"Privasi & Syarat"},nl:{visual_challenge:"Een visuele uitdaging proberen",audio_challenge:"Een audio-uitdaging proberen",refresh_btn:"Een nieuwe uitdaging proberen",instructions_visual:"Typ de tekst:",instructions_audio:"Typ wat u hoort:",help_btn:"Help",play_again:"Geluid opnieuw afspelen",cant_hear_this:"Geluid downloaden als MP3",incorrect_try_again:"Onjuist. Probeer het opnieuw.",image_alt_text:"reCAPTCHA-uitdagingsafbeelding",privacy_and_terms:"Privacy en voorwaarden"},no:{visual_challenge:"F\u00e5 en bildeutfordring",
-audio_challenge:"F\u00e5 en lydutfordring",refresh_btn:"F\u00e5 en ny utfordring",instructions_visual:"Skriv inn teksten:",instructions_audio:"Skriv inn det du h\u00f8rer:",help_btn:"Hjelp",play_again:"Spill av lyd p\u00e5 nytt",cant_hear_this:"Last ned lyd som MP3",incorrect_try_again:"Feil. Pr\u00f8v p\u00e5 nytt.",image_alt_text:"reCAPTCHA-utfordringsbilde",privacy_and_terms:"Personvern og vilk\u00e5r"},pl:{visual_challenge:"Poka\u017c podpowied\u017a wizualn\u0105",audio_challenge:"Odtw\u00f3rz podpowied\u017a d\u017awi\u0119kow\u0105",
-refresh_btn:"Nowa podpowied\u017a",instructions_visual:"Przepisz tekst:",instructions_audio:"Wpisz us\u0142yszane s\u0142owa:",help_btn:"Pomoc",play_again:"Odtw\u00f3rz d\u017awi\u0119k ponownie",cant_hear_this:"Pobierz d\u017awi\u0119k jako plik MP3",incorrect_try_again:"Nieprawid\u0142owo. Spr\u00f3buj ponownie.",image_alt_text:"Zadanie obrazkowe reCAPTCHA",privacy_and_terms:"Prywatno\u015b\u0107 i warunki"},pt:qa,"pt-BR":qa,"pt-PT":{visual_challenge:"Obter um desafio visual",audio_challenge:"Obter um desafio de \u00e1udio",
-refresh_btn:"Obter um novo desafio",instructions_visual:"Introduza o texto:",instructions_audio:"Escreva o que ouvir:",help_btn:"Ajuda",play_again:"Reproduzir som novamente",cant_hear_this:"Transferir som como MP3",incorrect_try_again:"Incorreto. Tente novamente.",image_alt_text:"Imagem de teste reCAPTCHA",privacy_and_terms:"Privacidade e Termos de Utiliza\u00e7\u00e3o"},ro:ra,ru:{visual_challenge:"\u0412\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u0430\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430",
-audio_challenge:"\u0417\u0432\u0443\u043a\u043e\u0432\u0430\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430",refresh_btn:"\u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c",instructions_visual:"\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0442\u0435\u043a\u0441\u0442:",instructions_audio:"\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0442\u043e, \u0447\u0442\u043e \u0441\u043b\u044b\u0448\u0438\u0442\u0435:",help_btn:"\u0421\u043f\u0440\u0430\u0432\u043a\u0430",play_again:"\u041f\u0440\u043e\u0441\u043b\u0443\u0448\u0430\u0442\u044c \u0435\u0449\u0435 \u0440\u0430\u0437",
-cant_hear_this:"\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c MP3-\u0444\u0430\u0439\u043b",incorrect_try_again:"\u041d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e. \u041f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u0435 \u043f\u043e\u043f\u044b\u0442\u043a\u0443.",image_alt_text:"\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043f\u043e \u0441\u043b\u043e\u0432\u0443 reCAPTCHA",privacy_and_terms:"\u041f\u0440\u0430\u0432\u0438\u043b\u0430 \u0438 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u044b"},
-sk:{visual_challenge:"Zobrazi\u0165 vizu\u00e1lnu podobu",audio_challenge:"Prehra\u0165 zvukov\u00fa podobu",refresh_btn:"Zobrazi\u0165 nov\u00fd v\u00fdraz",instructions_visual:"Zadajte text:",instructions_audio:"Zadajte, \u010do po\u010dujete:",help_btn:"Pomocn\u00edk",play_again:"Znova prehra\u0165 zvuk",cant_hear_this:"Prevzia\u0165 zvuk v podobe s\u00faboru MP3",incorrect_try_again:"Nespr\u00e1vne. Sk\u00faste to znova.",image_alt_text:"Obr\u00e1zok zadania reCAPTCHA",privacy_and_terms:"Ochrana osobn\u00fdch \u00fadajov a Zmluvn\u00e9 podmienky"},
-sl:{visual_challenge:"Vizualni preskus",audio_challenge:"Zvo\u010dni preskus",refresh_btn:"Nov preskus",instructions_visual:"Vnesite besedilo:",instructions_audio:"Natipkajte, kaj sli\u0161ite:",help_btn:"Pomo\u010d",play_again:"Znova predvajaj zvok",cant_hear_this:"Prenesi zvok kot MP3",incorrect_try_again:"Napa\u010dno. Poskusite znova.",image_alt_text:"Slika izziva reCAPTCHA",privacy_and_terms:"Zasebnost in pogoji"},sr:{visual_challenge:"\u041f\u0440\u0438\u043c\u0438\u0442\u0435 \u0432\u0438\u0437\u0443\u0435\u043b\u043d\u0438 \u0443\u043f\u0438\u0442",
-audio_challenge:"\u041f\u0440\u0438\u043c\u0438\u0442\u0435 \u0430\u0443\u0434\u0438\u043e \u0443\u043f\u0438\u0442",refresh_btn:"\u041f\u0440\u0438\u043c\u0438\u0442\u0435 \u043d\u043e\u0432\u0438 \u0443\u043f\u0438\u0442",instructions_visual:"\u0423\u043d\u0435\u0441\u0438\u0442\u0435 \u0442\u0435\u043a\u0441\u0442:",instructions_audio:"\u041e\u0442\u043a\u0443\u0446\u0430\u0458\u0442\u0435 \u043e\u043d\u043e \u0448\u0442\u043e \u0447\u0443\u0458\u0435\u0442\u0435:",help_btn:"\u041f\u043e\u043c\u043e\u045b",
-play_again:"\u041f\u043e\u043d\u043e\u0432\u043e \u043f\u0443\u0441\u0442\u0438 \u0437\u0432\u0443\u043a",cant_hear_this:"\u041f\u0440\u0435\u0443\u0437\u043c\u0438 \u0437\u0432\u0443\u043a \u043a\u0430\u043e MP3 \u0441\u043d\u0438\u043c\u0430\u043a",incorrect_try_again:"\u041d\u0435\u0442\u0430\u0447\u043d\u043e. \u041f\u043e\u043a\u0443\u0448\u0430\u0458\u0442\u0435 \u043f\u043e\u043d\u043e\u0432\u043e.",image_alt_text:"\u0421\u043b\u0438\u043a\u0430 reCAPTCHA \u043f\u0440\u043e\u0432\u0435\u0440\u0435",
-privacy_and_terms:"\u041f\u0440\u0438\u0432\u0430\u0442\u043d\u043e\u0441\u0442 \u0438 \u0443\u0441\u043b\u043e\u0432\u0438"},sv:{visual_challenge:"H\u00e4mta captcha i bildformat",audio_challenge:"H\u00e4mta captcha i ljudformat",refresh_btn:"H\u00e4mta ny captcha",instructions_visual:"Skriv texten:",instructions_audio:"Skriv det du h\u00f6r:",help_btn:"Hj\u00e4lp",play_again:"Spela upp ljudet igen",cant_hear_this:"H\u00e4mta ljud som MP3",incorrect_try_again:"Fel. F\u00f6rs\u00f6k igen.",image_alt_text:"reCAPTCHA-bild",
-privacy_and_terms:"Sekretess och villkor"},sw:{visual_challenge:"Pata herufi za kusoma",audio_challenge:"Pata herufi za kusikiliza",refresh_btn:"Pata herufi mpya",instructions_visual:"",instructions_audio:"Charaza unachosikia:",help_btn:"Usaidizi",play_again:"Cheza sauti tena",cant_hear_this:"Pakua sauti kama MP3",incorrect_try_again:"Sio sahihi. Jaribu tena.",image_alt_text:"picha ya changamoto ya reCAPTCHA",privacy_and_terms:"Faragha & Masharti"},ta:{visual_challenge:"\u0baa\u0bbe\u0bb0\u0bcd\u0bb5\u0bc8 \u0b9a\u0bc7\u0bb2\u0b9e\u0bcd\u0b9a\u0bc8\u0baa\u0bcd \u0baa\u0bc6\u0bb1\u0bc1\u0b95",
-audio_challenge:"\u0b86\u0b9f\u0bbf\u0baf\u0bcb \u0b9a\u0bc7\u0bb2\u0b9e\u0bcd\u0b9a\u0bc8\u0baa\u0bcd \u0baa\u0bc6\u0bb1\u0bc1\u0b95",refresh_btn:"\u0baa\u0bc1\u0ba4\u0bbf\u0baf \u0b9a\u0bc7\u0bb2\u0b9e\u0bcd\u0b9a\u0bc8\u0baa\u0bcd \u0baa\u0bc6\u0bb1\u0bc1\u0b95",instructions_visual:"",instructions_audio:"\u0b95\u0bc7\u0b9f\u0bcd\u0baa\u0ba4\u0bc8 \u0b9f\u0bc8\u0baa\u0bcd \u0b9a\u0bc6\u0baf\u0bcd\u0b95:",help_btn:"\u0b89\u0ba4\u0bb5\u0bbf",play_again:"\u0b92\u0bb2\u0bbf\u0baf\u0bc8 \u0bae\u0bc0\u0ba3\u0bcd\u0b9f\u0bc1\u0bae\u0bcd \u0b87\u0baf\u0b95\u0bcd\u0b95\u0bc1",
-cant_hear_this:"\u0b92\u0bb2\u0bbf\u0baf\u0bc8 MP3 \u0b86\u0b95 \u0baa\u0ba4\u0bbf\u0bb5\u0bbf\u0bb1\u0b95\u0bcd\u0b95\u0bc1\u0b95",incorrect_try_again:"\u0ba4\u0bb5\u0bb1\u0bbe\u0ba9\u0ba4\u0bc1. \u0bae\u0bc0\u0ba3\u0bcd\u0b9f\u0bc1\u0bae\u0bcd \u0bae\u0bc1\u0baf\u0bb2\u0bb5\u0bc1\u0bae\u0bcd.",image_alt_text:"reCAPTCHA \u0b9a\u0bc7\u0bb2\u0b9e\u0bcd\u0b9a\u0bcd \u0baa\u0b9f\u0bae\u0bcd",privacy_and_terms:"\u0ba4\u0ba9\u0bbf\u0baf\u0bc1\u0bb0\u0bbf\u0bae\u0bc8 & \u0bb5\u0bbf\u0ba4\u0bbf\u0bae\u0bc1\u0bb1\u0bc8\u0b95\u0bb3\u0bcd"},
-te:{visual_challenge:"\u0c12\u0c15 \u0c26\u0c43\u0c36\u0c4d\u0c2f\u0c2e\u0c3e\u0c28 \u0c38\u0c35\u0c3e\u0c32\u0c41\u0c28\u0c41 \u0c38\u0c4d\u0c35\u0c40\u0c15\u0c30\u0c3f\u0c02\u0c1a\u0c02\u0c21\u0c3f",audio_challenge:"\u0c12\u0c15 \u0c06\u0c21\u0c3f\u0c2f\u0c4b \u0c38\u0c35\u0c3e\u0c32\u0c41\u0c28\u0c41 \u0c38\u0c4d\u0c35\u0c40\u0c15\u0c30\u0c3f\u0c02\u0c1a\u0c02\u0c21\u0c3f",refresh_btn:"\u0c15\u0c4d\u0c30\u0c4a\u0c24\u0c4d\u0c24 \u0c38\u0c35\u0c3e\u0c32\u0c41\u0c28\u0c41 \u0c38\u0c4d\u0c35\u0c40\u0c15\u0c30\u0c3f\u0c02\u0c1a\u0c02\u0c21\u0c3f",
-instructions_visual:"",instructions_audio:"\u0c2e\u0c40\u0c30\u0c41 \u0c35\u0c3f\u0c28\u0c4d\u0c28\u0c26\u0c3f \u0c1f\u0c48\u0c2a\u0c4d \u0c1a\u0c47\u0c2f\u0c02\u0c21\u0c3f:",help_btn:"\u0c38\u0c39\u0c3e\u0c2f\u0c02",play_again:"\u0c27\u0c4d\u0c35\u0c28\u0c3f\u0c28\u0c3f \u0c2e\u0c33\u0c4d\u0c32\u0c40 \u0c2a\u0c4d\u0c32\u0c47 \u0c1a\u0c47\u0c2f\u0c3f",cant_hear_this:"\u0c27\u0c4d\u0c35\u0c28\u0c3f\u0c28\u0c3f MP3 \u0c35\u0c32\u0c46 \u0c21\u0c4c\u0c28\u0c4d\u200c\u0c32\u0c4b\u0c21\u0c4d \u0c1a\u0c47\u0c2f\u0c3f",
-incorrect_try_again:"\u0c24\u0c2a\u0c4d\u0c2a\u0c41. \u0c2e\u0c33\u0c4d\u0c32\u0c40 \u0c2a\u0c4d\u0c30\u0c2f\u0c24\u0c4d\u0c28\u0c3f\u0c02\u0c1a\u0c02\u0c21\u0c3f.",image_alt_text:"reCAPTCHA \u0c38\u0c35\u0c3e\u0c32\u0c41 \u0c1a\u0c3f\u0c24\u0c4d\u0c30\u0c02",privacy_and_terms:"\u0c17\u0c4b\u0c2a\u0c4d\u0c2f\u0c24 & \u0c28\u0c3f\u0c2c\u0c02\u0c27\u0c28\u0c32\u0c41"},th:{visual_challenge:"\u0e23\u0e31\u0e1a\u0e04\u0e27\u0e32\u0e21\u0e17\u0e49\u0e32\u0e17\u0e32\u0e22\u0e14\u0e49\u0e32\u0e19\u0e20\u0e32\u0e1e",
-audio_challenge:"\u0e23\u0e31\u0e1a\u0e04\u0e27\u0e32\u0e21\u0e17\u0e49\u0e32\u0e17\u0e32\u0e22\u0e14\u0e49\u0e32\u0e19\u0e40\u0e2a\u0e35\u0e22\u0e07",refresh_btn:"\u0e23\u0e31\u0e1a\u0e04\u0e27\u0e32\u0e21\u0e17\u0e49\u0e32\u0e17\u0e32\u0e22\u0e43\u0e2b\u0e21\u0e48",instructions_visual:"\u0e1e\u0e34\u0e21\u0e1e\u0e4c\u0e02\u0e49\u0e2d\u0e04\u0e27\u0e32\u0e21\u0e19\u0e35\u0e49:",instructions_audio:"\u0e1e\u0e34\u0e21\u0e1e\u0e4c\u0e2a\u0e34\u0e48\u0e07\u0e17\u0e35\u0e48\u0e04\u0e38\u0e13\u0e44\u0e14\u0e49\u0e22\u0e34\u0e19:",
-help_btn:"\u0e04\u0e27\u0e32\u0e21\u0e0a\u0e48\u0e27\u0e22\u0e40\u0e2b\u0e25\u0e37\u0e2d",play_again:"\u0e40\u0e25\u0e48\u0e19\u0e40\u0e2a\u0e35\u0e22\u0e07\u0e2d\u0e35\u0e01\u0e04\u0e23\u0e31\u0e49\u0e07",cant_hear_this:"\u0e14\u0e32\u0e27\u0e42\u0e2b\u0e25\u0e14\u0e40\u0e2a\u0e35\u0e22\u0e07\u0e40\u0e1b\u0e47\u0e19 MP3",incorrect_try_again:"\u0e44\u0e21\u0e48\u0e16\u0e39\u0e01\u0e15\u0e49\u0e2d\u0e07 \u0e25\u0e2d\u0e07\u0e2d\u0e35\u0e01\u0e04\u0e23\u0e31\u0e49\u0e07",image_alt_text:"\u0e23\u0e2b\u0e31\u0e2a\u0e20\u0e32\u0e1e reCAPTCHA",
-privacy_and_terms:"\u0e19\u0e42\u0e22\u0e1a\u0e32\u0e22\u0e2a\u0e48\u0e27\u0e19\u0e1a\u0e38\u0e04\u0e04\u0e25\u0e41\u0e25\u0e30\u0e02\u0e49\u0e2d\u0e01\u0e33\u0e2b\u0e19\u0e14"},tr:{visual_challenge:"G\u00f6rsel sorgu al",audio_challenge:"Sesli sorgu al",refresh_btn:"Yeniden y\u00fckle",instructions_visual:"Metni yaz\u0131n:",instructions_audio:"Duydu\u011funuzu yaz\u0131n:",help_btn:"Yard\u0131m",play_again:"Sesi tekrar \u00e7al",cant_hear_this:"Sesi MP3 olarak indir",incorrect_try_again:"Yanl\u0131\u015f. Tekrar deneyin.",
-image_alt_text:"reCAPTCHA sorusu resmi",privacy_and_terms:"Gizlilik ve \u015eartlar"},uk:{visual_challenge:"\u041e\u0442\u0440\u0438\u043c\u0430\u0442\u0438 \u0432\u0456\u0437\u0443\u0430\u043b\u044c\u043d\u0438\u0439 \u0442\u0435\u043a\u0441\u0442",audio_challenge:"\u041e\u0442\u0440\u0438\u043c\u0430\u0442\u0438 \u0430\u0443\u0434\u0456\u043e\u0437\u0430\u043f\u0438\u0441",refresh_btn:"\u041e\u043d\u043e\u0432\u0438\u0442\u0438 \u0442\u0435\u043a\u0441\u0442",instructions_visual:"\u0412\u0432\u0435\u0434\u0456\u0442\u044c \u0442\u0435\u043a\u0441\u0442:",
-instructions_audio:"\u0412\u0432\u0435\u0434\u0456\u0442\u044c \u043f\u043e\u0447\u0443\u0442\u0435:",help_btn:"\u0414\u043e\u0432\u0456\u0434\u043a\u0430",play_again:"\u0412\u0456\u0434\u0442\u0432\u043e\u0440\u0438\u0442\u0438 \u0437\u0430\u043f\u0438\u0441 \u0449\u0435 \u0440\u0430\u0437",cant_hear_this:"\u0417\u0430\u0432\u0430\u043d\u0442\u0430\u0436\u0438\u0442\u0438 \u0437\u0430\u043f\u0438\u0441 \u044f\u043a MP3",incorrect_try_again:"\u041d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e. \u0421\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u0449\u0435 \u0440\u0430\u0437.",
-image_alt_text:"\u0417\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u043d\u044f \u0437\u0430\u0432\u0434\u0430\u043d\u043d\u044f reCAPTCHA",privacy_and_terms:"\u041a\u043e\u043d\u0444\u0456\u0434\u0435\u043d\u0446\u0456\u0439\u043d\u0456\u0441\u0442\u044c \u0456 \u0443\u043c\u043e\u0432\u0438"},ur:{visual_challenge:"\u0627\u06cc\u06a9 \u0645\u0631\u0626\u06cc \u0686\u06cc\u0644\u0646\u062c \u062d\u0627\u0635\u0644 \u06a9\u0631\u06cc\u06ba",audio_challenge:"\u0627\u06cc\u06a9 \u0622\u0688\u06cc\u0648 \u0686\u06cc\u0644\u0646\u062c \u062d\u0627\u0635\u0644 \u06a9\u0631\u06cc\u06ba",
-refresh_btn:"\u0627\u06cc\u06a9 \u0646\u06cc\u0627 \u0686\u06cc\u0644\u0646\u062c \u062d\u0627\u0635\u0644 \u06a9\u0631\u06cc\u06ba",instructions_visual:"",instructions_audio:"\u062c\u0648 \u0633\u0646\u0627\u0626\u06cc \u062f\u06cc\u062a\u0627 \u06c1\u06d2 \u0648\u06c1 \u0679\u0627\u0626\u067e \u06a9\u0631\u06cc\u06ba:",help_btn:"\u0645\u062f\u062f",play_again:"\u0622\u0648\u0627\u0632 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0686\u0644\u0627\u0626\u06cc\u06ba",cant_hear_this:"\u0622\u0648\u0627\u0632 \u06a9\u0648 MP3 \u06a9\u06d2 \u0628\u0637\u0648\u0631 \u0688\u0627\u0624\u0646 \u0644\u0648\u0688 \u06a9\u0631\u06cc\u06ba",
-incorrect_try_again:"\u063a\u0644\u0637\u06d4 \u062f\u0648\u0628\u0627\u0631\u06c1 \u06a9\u0648\u0634\u0634 \u06a9\u0631\u06cc\u06ba\u06d4",image_alt_text:"reCAPTCHA \u0686\u06cc\u0644\u0646\u062c \u0648\u0627\u0644\u06cc \u0634\u0628\u06cc\u06c1",privacy_and_terms:"\u0631\u0627\u0632\u062f\u0627\u0631\u06cc \u0648 \u0634\u0631\u0627\u0626\u0637"},vi:{visual_challenge:"Nh\u1eadn th\u1eed th\u00e1ch h\u00ecnh \u1ea3nh",audio_challenge:"Nh\u1eadn th\u1eed th\u00e1ch \u00e2m thanh",refresh_btn:"Nh\u1eadn th\u1eed th\u00e1ch m\u1edbi",
-instructions_visual:"Nh\u1eadp v\u0103n b\u1ea3n:",instructions_audio:"Nh\u1eadp n\u1ed9i dung b\u1ea1n nghe th\u1ea5y:",help_btn:"Tr\u1ee3 gi\u00fap",play_again:"Ph\u00e1t l\u1ea1i \u00e2m thanh",cant_hear_this:"T\u1ea3i \u00e2m thanh xu\u1ed1ng d\u01b0\u1edbi d\u1ea1ng MP3",incorrect_try_again:"Kh\u00f4ng ch\u00ednh x\u00e1c. H\u00e3y th\u1eed l\u1ea1i.",image_alt_text:"H\u00ecnh x\u00e1c th\u1ef1c reCAPTCHA",privacy_and_terms:"B\u1ea3o m\u1eadt v\u00e0 \u0111i\u1ec1u kho\u1ea3n"},"zh-CN":sa,"zh-HK":{visual_challenge:"\u56de\u7b54\u5716\u50cf\u9a57\u8b49\u554f\u984c",
-audio_challenge:"\u53d6\u5f97\u8a9e\u97f3\u9a57\u8b49\u554f\u984c",refresh_btn:"\u63db\u4e00\u500b\u9a57\u8b49\u554f\u984c",instructions_visual:"\u8f38\u5165\u6587\u5b57\uff1a",instructions_audio:"\u9375\u5165\u60a8\u6240\u807d\u5230\u7684\uff1a",help_btn:"\u8aaa\u660e",play_again:"\u518d\u6b21\u64ad\u653e\u8072\u97f3",cant_hear_this:"\u5c07\u8072\u97f3\u4e0b\u8f09\u70ba MP3",incorrect_try_again:"\u4e0d\u6b63\u78ba\uff0c\u518d\u8a66\u4e00\u6b21\u3002",image_alt_text:"reCAPTCHA \u9a57\u8b49\u6587\u5b57\u5716\u7247",
-privacy_and_terms:"\u79c1\u96b1\u6b0a\u8207\u689d\u6b3e"},"zh-TW":{visual_challenge:"\u53d6\u5f97\u5716\u7247\u9a57\u8b49\u554f\u984c",audio_challenge:"\u53d6\u5f97\u8a9e\u97f3\u9a57\u8b49\u554f\u984c",refresh_btn:"\u53d6\u5f97\u65b0\u7684\u9a57\u8b49\u554f\u984c",instructions_visual:"\u8acb\u8f38\u5165\u5716\u7247\u4e2d\u7684\u6587\u5b57\uff1a",instructions_audio:"\u8acb\u8f38\u5165\u8a9e\u97f3\u5167\u5bb9\uff1a",help_btn:"\u8aaa\u660e",play_again:"\u518d\u6b21\u64ad\u653e",cant_hear_this:"\u4ee5 MP3 \u683c\u5f0f\u4e0b\u8f09\u8072\u97f3",
-incorrect_try_again:"\u9a57\u8b49\u78bc\u6709\u8aa4\uff0c\u8acb\u518d\u8a66\u4e00\u6b21\u3002",image_alt_text:"reCAPTCHA \u9a57\u8b49\u6587\u5b57\u5716\u7247",privacy_and_terms:"\u96b1\u79c1\u6b0a\u8207\u689d\u6b3e"},zu:{visual_challenge:"Thola inselelo ebonakalayo",audio_challenge:"Thola inselelo yokulalelwayo",refresh_btn:"Thola inselelo entsha",instructions_visual:"",instructions_audio:"Bhala okuzwayo:",help_btn:"Usizo",play_again:"Phinda udlale okulalelwayo futhi",cant_hear_this:"Layisha umsindo njenge-MP3",
-incorrect_try_again:"Akulungile. Zama futhi.",image_alt_text:"umfanekiso oyinselelo we-reCAPTCHA",privacy_and_terms:"Okwangasese kanye nemigomo"},tl:ma,he:pa,"in":oa,mo:ra,zh:sa};var ua=function(a,b){for(var c in a)b.call(void 0,a[c],c,a)},va=function(a){var b=[],c=0,d;for(d in a)b[c++]=a[d];return b},wa=function(a){var b=[],c=0,d;for(d in a)b[c++]=d;return b},xa=function(a){for(var b in a)return!1;return!0},za=function(){var a=ya()?l.google_ad:null,b={},c;for(c in a)b[c]=a[c];return b},Aa="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "),Ba=function(a,b){for(var c,d,e=1;e<arguments.length;e++){d=arguments[e];for(c in d)a[c]=
-d[c];for(var g=0;g<Aa.length;g++)c=Aa[g],Object.prototype.hasOwnProperty.call(d,c)&&(a[c]=d[c])}};var w=function(a){if(Error.captureStackTrace)Error.captureStackTrace(this,w);else{var b=Error().stack;b&&(this.stack=b)}a&&(this.message=String(a))};r(w,Error);w.prototype.name="CustomError";var Ca;var Da=function(a,b){for(var c=a.split("%s"),d="",e=Array.prototype.slice.call(arguments,1);e.length&&1<c.length;)d+=c.shift()+e.shift();return d+c.join("%s")},x=function(a){if(!Ea.test(a))return a;-1!=a.indexOf("&")&&(a=a.replace(Fa,"&amp;"));-1!=a.indexOf("<")&&(a=a.replace(Ga,"&lt;"));-1!=a.indexOf(">")&&(a=a.replace(Ha,"&gt;"));-1!=a.indexOf('"')&&(a=a.replace(Ia,"&quot;"));-1!=a.indexOf("'")&&(a=a.replace(Ja,"&#39;"));return a},Fa=/&/g,Ga=/</g,Ha=/>/g,Ia=/"/g,Ja=/'/g,Ea=/[&<>"']/,Ka=function(a,
-b){return a<b?-1:a>b?1:0},La=function(a){return String(a).replace(/\-([a-z])/g,function(a,c){return c.toUpperCase()})},Ma=function(a){var b=n(void 0)?"undefined".replace(/([-()\[\]{}+?*.$\^|,:#<!\\])/g,"\\$1").replace(/\x08/g,"\\x08"):"\\s";return a.replace(RegExp("(^"+(b?"|["+b+"]+":"")+")([a-z])","g"),function(a,b,e){return b+e.toUpperCase()})};var Na=function(a,b){b.unshift(a);w.call(this,Da.apply(null,b));b.shift()};r(Na,w);Na.prototype.name="AssertionError";var y=function(a,b,c){if(!a){var d="Assertion failed";if(b)var d=d+(": "+b),e=Array.prototype.slice.call(arguments,2);throw new Na(""+d,e||[]);}},Oa=function(a,b){throw new Na("Failure"+(a?": "+a:""),Array.prototype.slice.call(arguments,1));};var z=Array.prototype,Pa=z.indexOf?function(a,b,c){y(null!=a.length);return z.indexOf.call(a,b,c)}:function(a,b,c){c=null==c?0:0>c?Math.max(0,a.length+c):c;if(n(a))return n(b)&&1==b.length?a.indexOf(b,c):-1;for(;c<a.length;c++)if(c in a&&a[c]===b)return c;return-1},Qa=z.forEach?function(a,b,c){y(null!=a.length);z.forEach.call(a,b,c)}:function(a,b,c){for(var d=a.length,e=n(a)?a.split(""):a,g=0;g<d;g++)g in e&&b.call(c,e[g],g,a)},Ra=z.filter?function(a,b,c){y(null!=a.length);return z.filter.call(a,
-b,c)}:function(a,b,c){for(var d=a.length,e=[],g=0,f=n(a)?a.split(""):a,k=0;k<d;k++)if(k in f){var u=f[k];b.call(c,u,k,a)&&(e[g++]=u)}return e},Sa=z.map?function(a,b,c){y(null!=a.length);return z.map.call(a,b,c)}:function(a,b,c){for(var d=a.length,e=Array(d),g=n(a)?a.split(""):a,f=0;f<d;f++)f in g&&(e[f]=b.call(c,g[f],f,a));return e},Ua=function(a){var b;t:{b=Ta;for(var c=a.length,d=n(a)?a.split(""):a,e=0;e<c;e++)if(e in d&&b.call(void 0,d[e],e,a)){b=e;break t}b=-1}return 0>b?null:n(a)?a.charAt(b):
-a[b]},Va=function(a,b){var c=Pa(a,b),d;if(d=0<=c)y(null!=a.length),z.splice.call(a,c,1);return d},Wa=function(a){var b=a.length;if(0<b){for(var c=Array(b),d=0;d<b;d++)c[d]=a[d];return c}return[]},Xa=function(a,b,c){y(null!=a.length);return 2>=arguments.length?z.slice.call(a,b):z.slice.call(a,b,c)};var A,Ya,Za,$a,ab=function(){return l.navigator?l.navigator.userAgent:null};$a=Za=Ya=A=!1;var B;if(B=ab()){var bb=l.navigator;A=0==B.lastIndexOf("Opera",0);Ya=!A&&(-1!=B.indexOf("MSIE")||-1!=B.indexOf("Trident"));Za=!A&&-1!=B.indexOf("WebKit");$a=!A&&!Za&&!Ya&&"Gecko"==bb.product}var cb=A,C=Ya,D=$a,E=Za,db=function(){var a=l.document;return a?a.documentMode:void 0},eb;
-t:{var fb="",gb;if(cb&&l.opera)var hb=l.opera.version,fb="function"==typeof hb?hb():hb;else if(D?gb=/rv\:([^\);]+)(\)|;)/:C?gb=/\b(?:MSIE|rv)[: ]([^\);]+)(\)|;)/:E&&(gb=/WebKit\/(\S+)/),gb)var ib=gb.exec(ab()),fb=ib?ib[1]:"";if(C){var jb=db();if(jb>parseFloat(fb)){eb=String(jb);break t}}eb=fb}
-var kb=eb,lb={},F=function(a){var b;if(!(b=lb[a])){b=0;for(var c=String(kb).replace(/^[\s\xa0]+|[\s\xa0]+$/g,"").split("."),d=String(a).replace(/^[\s\xa0]+|[\s\xa0]+$/g,"").split("."),e=Math.max(c.length,d.length),g=0;0==b&&g<e;g++){var f=c[g]||"",k=d[g]||"",u=RegExp("(\\d*)(\\D*)","g"),L=RegExp("(\\d*)(\\D*)","g");do{var v=u.exec(f)||["","",""],Q=L.exec(k)||["","",""];if(0==v[0].length&&0==Q[0].length)break;b=Ka(0==v[1].length?0:parseInt(v[1],10),0==Q[1].length?0:parseInt(Q[1],10))||Ka(0==v[2].length,
-0==Q[2].length)||Ka(v[2],Q[2])}while(0==b)}b=lb[a]=0<=b}return b},mb=l.document,nb=mb&&C?db()||("CSS1Compat"==mb.compatMode?parseInt(kb,10):5):void 0;var ob=!C||C&&9<=nb,pb=!D&&!C||C&&C&&9<=nb||D&&F("1.9.1");C&&F("9");var qb=function(a,b){var c;c=a.className;c=n(c)&&c.match(/\S+/g)||[];for(var d=Xa(arguments,1),e=c.length+d.length,g=c,f=0;f<d.length;f++)0<=Pa(g,d[f])||g.push(d[f]);a.className=c.join(" ");return c.length==e};var sb=function(a){return a?new rb(9==a.nodeType?a:a.ownerDocument||a.document):Ca||(Ca=new rb)},tb=function(a,b){return n(b)?a.getElementById(b):b},vb=function(a,b){ua(b,function(b,d){"style"==d?a.style.cssText=b:"class"==d?a.className=b:"for"==d?a.htmlFor=b:d in ub?a.setAttribute(ub[d],b):0==d.lastIndexOf("aria-",0)||0==d.lastIndexOf("data-",0)?a.setAttribute(d,b):a[d]=b})},ub={cellpadding:"cellPadding",cellspacing:"cellSpacing",colspan:"colSpan",frameborder:"frameBorder",height:"height",maxlength:"maxLength",
-role:"role",rowspan:"rowSpan",type:"type",usemap:"useMap",valign:"vAlign",width:"width"},xb=function(a,b,c){function d(c){c&&b.appendChild(n(c)?a.createTextNode(c):c)}for(var e=2;e<c.length;e++){var g=c[e];!ea(g)||ga(g)&&0<g.nodeType?d(g):Qa(wb(g)?Wa(g):g,d)}},yb=function(a){for(var b;b=a.firstChild;)a.removeChild(b)},zb=function(a){a&&a.parentNode&&a.parentNode.removeChild(a)},wb=function(a){if(a&&"number"==typeof a.length){if(ga(a))return"function"==typeof a.item||"string"==typeof a.item;if(fa(a))return"function"==
-typeof a.item}return!1},rb=function(a){this.document_=a||l.document||document};h=rb.prototype;h.getDomHelper=sb;h.getElement=function(a){return tb(this.document_,a)};h.$=rb.prototype.getElement;
-h.createDom=function(a,b,c){var d=this.document_,e=arguments,g=e[0],f=e[1];if(!ob&&f&&(f.name||f.type)){g=["<",g];f.name&&g.push(' name="',x(f.name),'"');if(f.type){g.push(' type="',x(f.type),'"');var k={};Ba(k,f);delete k.type;f=k}g.push(">");g=g.join("")}g=d.createElement(g);f&&(n(f)?g.className=f:m(f)?qb.apply(null,[g].concat(f)):vb(g,f));2<e.length&&xb(d,g,e);return g};h.createElement=function(a){return this.document_.createElement(a)};h.createTextNode=function(a){return this.document_.createTextNode(String(a))};
-h.appendChild=function(a,b){a.appendChild(b)};h.getChildren=function(a){return pb&&void 0!=a.children?a.children:Ra(a.childNodes,function(a){return 1==a.nodeType})};var Ab=function(){};Ab.prototype.disposed_=!1;Ab.prototype.dispose=function(){this.disposed_||(this.disposed_=!0,this.disposeInternal())};Ab.prototype.disposeInternal=function(){if(this.onDisposeCallbacks_)for(;this.onDisposeCallbacks_.length;)this.onDisposeCallbacks_.shift()()};var Bb=function(a){Bb[" "](a);return a};Bb[" "]=ca;var Cb=!C||C&&9<=nb,Db=C&&!F("9");!E||F("528");D&&F("1.9b")||C&&F("8")||cb&&F("9.5")||E&&F("528");D&&!F("8")||C&&F("9");var G=function(a,b){this.type=a;this.currentTarget=this.target=b;this.defaultPrevented=this.propagationStopped_=!1;this.returnValue_=!0};G.prototype.disposeInternal=function(){};G.prototype.dispose=function(){};G.prototype.preventDefault=function(){this.defaultPrevented=!0;this.returnValue_=!1};var H=function(a,b){G.call(this,a?a.type:"");this.relatedTarget=this.currentTarget=this.target=null;this.charCode=this.keyCode=this.button=this.screenY=this.screenX=this.clientY=this.clientX=this.offsetY=this.offsetX=0;this.metaKey=this.shiftKey=this.altKey=this.ctrlKey=!1;this.event_=this.state=null;if(a){var c=this.type=a.type;this.target=a.target||a.srcElement;this.currentTarget=b;var d=a.relatedTarget;if(d){if(D){var e;t:{try{Bb(d.nodeName);e=!0;break t}catch(g){}e=!1}e||(d=null)}}else"mouseover"==
-c?d=a.fromElement:"mouseout"==c&&(d=a.toElement);this.relatedTarget=d;this.offsetX=E||void 0!==a.offsetX?a.offsetX:a.layerX;this.offsetY=E||void 0!==a.offsetY?a.offsetY:a.layerY;this.clientX=void 0!==a.clientX?a.clientX:a.pageX;this.clientY=void 0!==a.clientY?a.clientY:a.pageY;this.screenX=a.screenX||0;this.screenY=a.screenY||0;this.button=a.button;this.keyCode=a.keyCode||0;this.charCode=a.charCode||("keypress"==c?a.keyCode:0);this.ctrlKey=a.ctrlKey;this.altKey=a.altKey;this.shiftKey=a.shiftKey;this.metaKey=
-a.metaKey;this.state=a.state;this.event_=a;a.defaultPrevented&&this.preventDefault()}};r(H,G);H.prototype.preventDefault=function(){H.superClass_.preventDefault.call(this);var a=this.event_;if(a.preventDefault)a.preventDefault();else if(a.returnValue=!1,Db)try{if(a.ctrlKey||112<=a.keyCode&&123>=a.keyCode)a.keyCode=-1}catch(b){}};H.prototype.disposeInternal=function(){};var Eb="closure_listenable_"+(1E6*Math.random()|0),Fb=function(a){try{return!(!a||!a[Eb])}catch(b){return!1}},Gb=0;var Hb=function(a,b,c,d,e){this.listener=a;this.proxy=null;this.src=b;this.type=c;this.capture=!!d;this.handler=e;this.key=++Gb;this.removed=this.callOnce=!1},Ib=function(a){a.removed=!0;a.listener=null;a.proxy=null;a.src=null;a.handler=null};var I=function(a){this.src=a;this.listeners={};this.typeCount_=0};I.prototype.add=function(a,b,c,d,e){var g=a.toString();a=this.listeners[g];a||(a=this.listeners[g]=[],this.typeCount_++);var f=Jb(a,b,d,e);-1<f?(b=a[f],c||(b.callOnce=!1)):(b=new Hb(b,this.src,g,!!d,e),b.callOnce=c,a.push(b));return b};
-I.prototype.remove=function(a,b,c,d){a=a.toString();if(!(a in this.listeners))return!1;var e=this.listeners[a];b=Jb(e,b,c,d);return-1<b?(Ib(e[b]),y(null!=e.length),z.splice.call(e,b,1),0==e.length&&(delete this.listeners[a],this.typeCount_--),!0):!1};var Kb=function(a,b){var c=b.type;if(!(c in a.listeners))return!1;var d=Va(a.listeners[c],b);d&&(Ib(b),0==a.listeners[c].length&&(delete a.listeners[c],a.typeCount_--));return d};
-I.prototype.removeAll=function(a){a=a&&a.toString();var b=0,c;for(c in this.listeners)if(!a||c==a){for(var d=this.listeners[c],e=0;e<d.length;e++)++b,Ib(d[e]);delete this.listeners[c];this.typeCount_--}return b};I.prototype.getListener=function(a,b,c,d){a=this.listeners[a.toString()];var e=-1;a&&(e=Jb(a,b,c,d));return-1<e?a[e]:null};var Jb=function(a,b,c,d){for(var e=0;e<a.length;++e){var g=a[e];if(!g.removed&&g.listener==b&&g.capture==!!c&&g.handler==d)return e}return-1};var Lb="closure_lm_"+(1E6*Math.random()|0),J={},Mb=0,Nb=function(a,b,c,d,e){if(m(b)){for(var g=0;g<b.length;g++)Nb(a,b[g],c,d,e);return null}c=Ob(c);return Fb(a)?a.listen(b,c,d,e):Pb(a,b,c,!1,d,e)},Pb=function(a,b,c,d,e,g){if(!b)throw Error("Invalid event type");var f=!!e,k=Qb(a);k||(a[Lb]=k=new I(a));c=k.add(b,c,d,e,g);if(c.proxy)return c;d=Rb();c.proxy=d;d.src=a;d.listener=c;a.addEventListener?a.addEventListener(b,d,f):a.attachEvent(b in J?J[b]:J[b]="on"+b,d);Mb++;return c},Rb=function(){var a=
-Sb,b=Cb?function(c){return a.call(b.src,b.listener,c)}:function(c){c=a.call(b.src,b.listener,c);if(!c)return c};return b},Tb=function(a,b,c,d,e){if(m(b)){for(var g=0;g<b.length;g++)Tb(a,b[g],c,d,e);return null}c=Ob(c);return Fb(a)?a.listenOnce(b,c,d,e):Pb(a,b,c,!0,d,e)},Ub=function(a,b,c,d,e){if(m(b))for(var g=0;g<b.length;g++)Ub(a,b[g],c,d,e);else c=Ob(c),Fb(a)?a.unlisten(b,c,d,e):a&&(a=Qb(a))&&(b=a.getListener(b,c,!!d,e))&&Vb(b)},Vb=function(a){if("number"==typeof a||!a||a.removed)return!1;var b=
-a.src;if(Fb(b))return Kb(b.eventTargetListeners_,a);var c=a.type,d=a.proxy;b.removeEventListener?b.removeEventListener(c,d,a.capture):b.detachEvent&&b.detachEvent(c in J?J[c]:J[c]="on"+c,d);Mb--;(c=Qb(b))?(Kb(c,a),0==c.typeCount_&&(c.src=null,b[Lb]=null)):Ib(a);return!0},Xb=function(a,b,c,d){var e=1;if(a=Qb(a))if(b=a.listeners[b])for(b=Wa(b),a=0;a<b.length;a++){var g=b[a];g&&g.capture==c&&!g.removed&&(e&=!1!==Wb(g,d))}return Boolean(e)},Wb=function(a,b){var c=a.listener,d=a.handler||a.src;a.callOnce&&
-Vb(a);return c.call(d,b)},Sb=function(a,b){if(a.removed)return!0;if(!Cb){var c=b||ba("window.event"),d=new H(c,this),e=!0;if(!(0>c.keyCode||void 0!=c.returnValue)){t:{var g=!1;if(0==c.keyCode)try{c.keyCode=-1;break t}catch(f){g=!0}if(g||void 0==c.returnValue)c.returnValue=!0}c=[];for(g=d.currentTarget;g;g=g.parentNode)c.push(g);for(var g=a.type,k=c.length-1;!d.propagationStopped_&&0<=k;k--)d.currentTarget=c[k],e&=Xb(c[k],g,!0,d);for(k=0;!d.propagationStopped_&&k<c.length;k++)d.currentTarget=c[k],
-e&=Xb(c[k],g,!1,d)}return e}return Wb(a,new H(b,this))},Qb=function(a){a=a[Lb];return a instanceof I?a:null},Yb="__closure_events_fn_"+(1E9*Math.random()>>>0),Ob=function(a){y(a,"Listener can not be null.");if(fa(a))return a;y(a.handleEvent,"An object listener must have handleEvent method.");return a[Yb]||(a[Yb]=function(b){return a.handleEvent(b)})};var K=function(a){this.handler_=a;this.keys_={}};r(K,Ab);var Zb=[];K.prototype.listen=function(a,b,c,d){m(b)||(Zb[0]=b,b=Zb);for(var e=0;e<b.length;e++){var g=Nb(a,b[e],c||this.handleEvent,d||!1,this.handler_||this);if(!g)break;this.keys_[g.key]=g}return this};K.prototype.listenOnce=function(a,b,c,d){return $b(this,a,b,c,d)};var $b=function(a,b,c,d,e,g){if(m(c))for(var f=0;f<c.length;f++)$b(a,b,c[f],d,e,g);else{b=Tb(b,c,d||a.handleEvent,e,g||a.handler_||a);if(!b)return a;a.keys_[b.key]=b}return a};
-K.prototype.unlisten=function(a,b,c,d,e){if(m(b))for(var g=0;g<b.length;g++)this.unlisten(a,b[g],c,d,e);else c=c||this.handleEvent,e=e||this.handler_||this,c=Ob(c),d=!!d,b=Fb(a)?a.getListener(b,c,d,e):a?(a=Qb(a))?a.getListener(b,c,d,e):null:null,b&&(Vb(b),delete this.keys_[b.key]);return this};K.prototype.removeAll=function(){ua(this.keys_,Vb);this.keys_={}};K.prototype.disposeInternal=function(){K.superClass_.disposeInternal.call(this);this.removeAll()};
-K.prototype.handleEvent=function(){throw Error("EventHandler.handleEvent not implemented");};var M=function(){this.eventTargetListeners_=new I(this);this.actualEventTarget_=this};r(M,Ab);M.prototype[Eb]=!0;h=M.prototype;h.parentEventTarget_=null;h.setParentEventTarget=function(a){this.parentEventTarget_=a};h.addEventListener=function(a,b,c,d){Nb(this,a,b,c,d)};h.removeEventListener=function(a,b,c,d){Ub(this,a,b,c,d)};
-h.dispatchEvent=function(a){ac(this);var b,c=this.parentEventTarget_;if(c){b=[];for(var d=1;c;c=c.parentEventTarget_)b.push(c),y(1E3>++d,"infinite loop")}c=this.actualEventTarget_;d=a.type||a;if(n(a))a=new G(a,c);else if(a instanceof G)a.target=a.target||c;else{var e=a;a=new G(d,c);Ba(a,e)}var e=!0,g;if(b)for(var f=b.length-1;!a.propagationStopped_&&0<=f;f--)g=a.currentTarget=b[f],e=bc(g,d,!0,a)&&e;a.propagationStopped_||(g=a.currentTarget=c,e=bc(g,d,!0,a)&&e,a.propagationStopped_||(e=bc(g,d,!1,a)&&
-e));if(b)for(f=0;!a.propagationStopped_&&f<b.length;f++)g=a.currentTarget=b[f],e=bc(g,d,!1,a)&&e;return e};h.disposeInternal=function(){M.superClass_.disposeInternal.call(this);this.eventTargetListeners_&&this.eventTargetListeners_.removeAll(void 0);this.parentEventTarget_=null};h.listen=function(a,b,c,d){ac(this);return this.eventTargetListeners_.add(String(a),b,!1,c,d)};h.listenOnce=function(a,b,c,d){return this.eventTargetListeners_.add(String(a),b,!0,c,d)};
-h.unlisten=function(a,b,c,d){return this.eventTargetListeners_.remove(String(a),b,c,d)};var bc=function(a,b,c,d){b=a.eventTargetListeners_.listeners[String(b)];if(!b)return!0;b=Wa(b);for(var e=!0,g=0;g<b.length;++g){var f=b[g];if(f&&!f.removed&&f.capture==c){var k=f.listener,u=f.handler||f.src;f.callOnce&&Kb(a.eventTargetListeners_,f);e=!1!==k.call(u,d)&&e}}return e&&!1!=d.returnValue_};M.prototype.getListener=function(a,b,c,d){return this.eventTargetListeners_.getListener(String(a),b,c,d)};
-var ac=function(a){y(a.eventTargetListeners_,"Event target is not initialized. Did you call the superclass (goog.events.EventTarget) constructor?")};var N=function(a){M.call(this);this.imageIdToRequestMap_={};this.imageIdToImageMap_={};this.handler_=new K(this);this.parent_=a};r(N,M);var cc=[C&&!F("11")?"readystatechange":"load","abort","error"],dc=function(a,b,c){(c=n(c)?c:c.src)&&(a.imageIdToRequestMap_[b]={src:c,corsRequestType:null})};
-N.prototype.start=function(){var a=this.imageIdToRequestMap_;Qa(wa(a),function(b){var c=a[b];if(c&&(delete a[b],!this.disposed_)){var d;d=this.parent_?sb(this.parent_).createDom("img"):new Image;c.corsRequestType&&(d.crossOrigin=c.corsRequestType);this.handler_.listen(d,cc,this.onNetworkEvent_);this.imageIdToImageMap_[b]=d;d.id=b;d.src=c.src}},this)};
-N.prototype.onNetworkEvent_=function(a){var b=a.currentTarget;if(b){if("readystatechange"==a.type)if("complete"==b.readyState)a.type="load";else return;"undefined"==typeof b.naturalWidth&&("load"==a.type?(b.naturalWidth=b.width,b.naturalHeight=b.height):(b.naturalWidth=0,b.naturalHeight=0));this.dispatchEvent({type:a.type,target:b});!this.disposed_&&(a=b.id,delete this.imageIdToRequestMap_[a],b=this.imageIdToImageMap_[a])&&(delete this.imageIdToImageMap_[a],this.handler_.unlisten(b,cc,this.onNetworkEvent_),
-xa(this.imageIdToImageMap_)&&xa(this.imageIdToRequestMap_)&&this.dispatchEvent("complete"))}};N.prototype.disposeInternal=function(){delete this.imageIdToRequestMap_;delete this.imageIdToImageMap_;var a=this.handler_;a&&"function"==typeof a.dispose&&a.dispose();N.superClass_.disposeInternal.call(this)};var ec="StopIteration"in l?l.StopIteration:Error("StopIteration"),fc=function(){};fc.prototype.next=function(){throw ec;};fc.prototype.__iterator__=function(){return this};var O=function(a,b){this.map_={};this.keys_=[];this.version_=this.count_=0;var c=arguments.length;if(1<c){if(c%2)throw Error("Uneven number of arguments");for(var d=0;d<c;d+=2)this.set(arguments[d],arguments[d+1])}else if(a){a instanceof O?(c=a.getKeys(),d=a.getValues()):(c=wa(a),d=va(a));for(var e=0;e<c.length;e++)this.set(c[e],d[e])}};O.prototype.getValues=function(){gc(this);for(var a=[],b=0;b<this.keys_.length;b++)a.push(this.map_[this.keys_[b]]);return a};
-O.prototype.getKeys=function(){gc(this);return this.keys_.concat()};O.prototype.remove=function(a){return Object.prototype.hasOwnProperty.call(this.map_,a)?(delete this.map_[a],this.count_--,this.version_++,this.keys_.length>2*this.count_&&gc(this),!0):!1};
-var gc=function(a){if(a.count_!=a.keys_.length){for(var b=0,c=0;b<a.keys_.length;){var d=a.keys_[b];Object.prototype.hasOwnProperty.call(a.map_,d)&&(a.keys_[c++]=d);b++}a.keys_.length=c}if(a.count_!=a.keys_.length){for(var e={},c=b=0;b<a.keys_.length;)d=a.keys_[b],Object.prototype.hasOwnProperty.call(e,d)||(a.keys_[c++]=d,e[d]=1),b++;a.keys_.length=c}};O.prototype.set=function(a,b){Object.prototype.hasOwnProperty.call(this.map_,a)||(this.count_++,this.keys_.push(a),this.version_++);this.map_[a]=b};
-O.prototype.__iterator__=function(a){gc(this);var b=0,c=this.keys_,d=this.map_,e=this.version_,g=this,f=new fc;f.next=function(){for(;;){if(e!=g.version_)throw Error("The map has changed since the iterator was created");if(b>=c.length)throw ec;var f=c[b++];return a?f:d[f]}};return f};var hc=function(a){if("function"==typeof a.getValues)return a.getValues();if(n(a))return a.split("");if(ea(a)){for(var b=[],c=a.length,d=0;d<c;d++)b.push(a[d]);return b}return va(a)},ic=function(a,b,c){if("function"==typeof a.forEach)a.forEach(b,c);else if(ea(a)||n(a))Qa(a,b,c);else{var d;if("function"==typeof a.getKeys)d=a.getKeys();else if("function"!=typeof a.getValues)if(ea(a)||n(a)){d=[];for(var e=a.length,g=0;g<e;g++)d.push(g)}else d=wa(a);else d=void 0;for(var e=hc(a),g=e.length,f=0;f<g;f++)b.call(c,
-e[f],d&&d[f],a)}};var kc=function(a){return jc(a||arguments.callee.caller,[])},jc=function(a,b){var c=[];if(0<=Pa(b,a))c.push("[...circular reference...]");else if(a&&50>b.length){c.push(lc(a)+"(");for(var d=a.arguments,e=0;d&&e<d.length;e++){0<e&&c.push(", ");var g;g=d[e];switch(typeof g){case "object":g=g?"object":"null";break;case "string":break;case "number":g=String(g);break;case "boolean":g=g?"true":"false";break;case "function":g=(g=lc(g))?g:"[fn]";break;default:g=typeof g}40<g.length&&(g=g.substr(0,40)+"...");
-c.push(g)}b.push(a);c.push(")\n");try{c.push(jc(a.caller,b))}catch(f){c.push("[exception trying to get caller]\n")}}else a?c.push("[...long stack...]"):c.push("[end]");return c.join("")},lc=function(a){if(mc[a])return mc[a];a=String(a);if(!mc[a]){var b=/function ([^\(]+)/.exec(a);mc[a]=b?b[1]:"[Anonymous]"}return mc[a]},mc={};var nc=function(a,b,c,d,e){this.reset(a,b,c,d,e)};nc.prototype.exception_=null;nc.prototype.exceptionText_=null;var oc=0;nc.prototype.reset=function(a,b,c,d,e){"number"==typeof e||oc++;d||ja();this.level_=a;this.msg_=b;delete this.exception_;delete this.exceptionText_};nc.prototype.setLevel=function(a){this.level_=a};var P=function(a){this.name_=a;this.handlers_=this.children_=this.level_=this.parent_=null},pc=function(a,b){this.name=a;this.value=b};pc.prototype.toString=function(){return this.name};var qc=new pc("SEVERE",1E3),rc=new pc("CONFIG",700),sc=new pc("FINE",500);P.prototype.getParent=function(){return this.parent_};P.prototype.getChildren=function(){this.children_||(this.children_={});return this.children_};P.prototype.setLevel=function(a){this.level_=a};
-var tc=function(a){if(a.level_)return a.level_;if(a.parent_)return tc(a.parent_);Oa("Root logger has no level set.");return null};P.prototype.log=function(a,b,c){if(a.value>=tc(this).value)for(fa(b)&&(b=b()),a=this.getLogRecord(a,b,c),b="log:"+a.msg_,l.console&&(l.console.timeStamp?l.console.timeStamp(b):l.console.markTimeline&&l.console.markTimeline(b)),l.msWriteProfilerMark&&l.msWriteProfilerMark(b),b=this;b;){c=b;var d=a;if(c.handlers_)for(var e=0,g=void 0;g=c.handlers_[e];e++)g(d);b=b.getParent()}};
-P.prototype.getLogRecord=function(a,b,c){var d=new nc(a,String(b),this.name_);if(c){d.exception_=c;var e;var g=arguments.callee.caller;try{var f;var k=ba("window.location.href");if(n(c))f={message:c,name:"Unknown error",lineNumber:"Not available",fileName:k,stack:"Not available"};else{var u,L,v=!1;try{u=c.lineNumber||c.line||"Not available"}catch(Q){u="Not available",v=!0}try{L=c.fileName||c.filename||c.sourceURL||l.$googDebugFname||k}catch(jd){L="Not available",v=!0}f=!v&&c.lineNumber&&c.fileName&&
-c.stack&&c.message&&c.name?c:{message:c.message||"Not available",name:c.name||"UnknownError",lineNumber:u,fileName:L,stack:c.stack||"Not available"}}e="Message: "+x(f.message)+'\nUrl: <a href="view-source:'+f.fileName+'" target="_new">'+f.fileName+"</a>\nLine: "+f.lineNumber+"\n\nBrowser stack:\n"+x(f.stack+"-> ")+"[end]\n\nJS stack traversal:\n"+x(kc(g)+"-> ")}catch(Yc){e="Exception trying to expose exception! You win, we lose. "+Yc}d.exceptionText_=e}return d};
-var uc={},vc=null,wc=function(a){vc||(vc=new P(""),uc[""]=vc,vc.setLevel(rc));var b;if(!(b=uc[a])){b=new P(a);var c=a.lastIndexOf("."),d=a.substr(c+1),c=wc(a.substr(0,c));c.getChildren()[d]=b;b.parent_=c;uc[a]=b}return b};var R=function(a,b){a&&a.log(sc,b,void 0)};var xc=function(a,b,c){if(fa(a))c&&(a=p(a,c));else if(a&&"function"==typeof a.handleEvent)a=p(a.handleEvent,a);else throw Error("Invalid listener argument");return 2147483647<b?-1:l.setTimeout(a,b||0)};var yc=RegExp("^(?:([^:/?#.]+):)?(?://(?:([^/?#]*)@)?([^/#?]*?)(?::([0-9]+))?(?=[/#?]|$))?([^?#]+)?(?:\\?([^#]*))?(?:#(.*))?$"),zc=E,Ac=function(a,b){if(zc){zc=!1;var c=l.location;if(c){var d=c.href;if(d&&(d=(d=Ac(3,d))&&decodeURIComponent(d))&&d!=c.hostname)throw zc=!0,Error();}}return b.match(yc)[a]||null};var Bc=function(){};Bc.prototype.cachedOptions_=null;var Dc=function(a){var b;(b=a.cachedOptions_)||(b={},Cc(a)&&(b[0]=!0,b[1]=!0),b=a.cachedOptions_=b);return b};var Ec,Fc=function(){};r(Fc,Bc);var Gc=function(a){return(a=Cc(a))?new ActiveXObject(a):new XMLHttpRequest},Cc=function(a){if(!a.ieProgId_&&"undefined"==typeof XMLHttpRequest&&"undefined"!=typeof ActiveXObject){for(var b=["MSXML2.XMLHTTP.6.0","MSXML2.XMLHTTP.3.0","MSXML2.XMLHTTP","Microsoft.XMLHTTP"],c=0;c<b.length;c++){var d=b[c];try{return new ActiveXObject(d),a.ieProgId_=d}catch(e){}}throw Error("Could not create ActiveXObject. ActiveX might be disabled, or MSXML might not be installed");}return a.ieProgId_};
-Ec=new Fc;var S=function(a){M.call(this);this.headers=new O;this.xmlHttpFactory_=a||null;this.active_=!1;this.xhrOptions_=this.xhr_=null;this.lastError_=this.lastMethod_=this.lastUri_="";this.inAbort_=this.inOpen_=this.inSend_=this.errorDispatched_=!1;this.timeoutInterval_=0;this.timeoutId_=null;this.responseType_="";this.useXhr2Timeout_=this.withCredentials_=!1};r(S,M);var Hc=S.prototype,Ic=wc("goog.net.XhrIo");Hc.logger_=Ic;
-var Jc=/^https?$/i,Kc=["POST","PUT"],Lc=[],Mc=function(a){var b=new S;Lc.push(b);b.listenOnce("ready",b.cleanupSend_);b.send(a,"POST",void 0,void 0)};S.prototype.cleanupSend_=function(){this.dispose();Va(Lc,this)};
-S.prototype.send=function(a,b,c,d){if(this.xhr_)throw Error("[goog.net.XhrIo] Object is active with another request="+this.lastUri_+"; newUri="+a);b=b?b.toUpperCase():"GET";this.lastUri_=a;this.lastError_="";this.lastMethod_=b;this.errorDispatched_=!1;this.active_=!0;this.xhr_=this.xmlHttpFactory_?Gc(this.xmlHttpFactory_):Gc(Ec);this.xhrOptions_=this.xmlHttpFactory_?Dc(this.xmlHttpFactory_):Dc(Ec);this.xhr_.onreadystatechange=p(this.onReadyStateChange_,this);try{R(this.logger_,T(this,"Opening Xhr")),
-this.inOpen_=!0,this.xhr_.open(b,String(a),!0),this.inOpen_=!1}catch(e){R(this.logger_,T(this,"Error opening Xhr: "+e.message));Nc(this,e);return}a=c||"";var g=new O(this.headers);d&&ic(d,function(a,b){g.set(b,a)});d=Ua(g.getKeys());c=l.FormData&&a instanceof l.FormData;!(0<=Pa(Kc,b))||d||c||g.set("Content-Type","application/x-www-form-urlencoded;charset=utf-8");ic(g,function(a,b){this.xhr_.setRequestHeader(b,a)},this);this.responseType_&&(this.xhr_.responseType=this.responseType_);"withCredentials"in
-this.xhr_&&(this.xhr_.withCredentials=this.withCredentials_);try{Oc(this),0<this.timeoutInterval_&&(this.useXhr2Timeout_=Pc(this.xhr_),R(this.logger_,T(this,"Will abort after "+this.timeoutInterval_+"ms if incomplete, xhr2 "+this.useXhr2Timeout_)),this.useXhr2Timeout_?(this.xhr_.timeout=this.timeoutInterval_,this.xhr_.ontimeout=p(this.timeout_,this)):this.timeoutId_=xc(this.timeout_,this.timeoutInterval_,this)),R(this.logger_,T(this,"Sending request")),this.inSend_=!0,this.xhr_.send(a),this.inSend_=
-!1}catch(f){R(this.logger_,T(this,"Send error: "+f.message)),Nc(this,f)}};var Pc=function(a){return C&&F(9)&&"number"==typeof a.timeout&&void 0!==a.ontimeout},Ta=function(a){return"content-type"==a.toLowerCase()};S.prototype.timeout_=function(){"undefined"!=typeof aa&&this.xhr_&&(this.lastError_="Timed out after "+this.timeoutInterval_+"ms, aborting",R(this.logger_,T(this,this.lastError_)),this.dispatchEvent("timeout"),this.abort(8))};
-var Nc=function(a,b){a.active_=!1;a.xhr_&&(a.inAbort_=!0,a.xhr_.abort(),a.inAbort_=!1);a.lastError_=b;Qc(a);Rc(a)},Qc=function(a){a.errorDispatched_||(a.errorDispatched_=!0,a.dispatchEvent("complete"),a.dispatchEvent("error"))};S.prototype.abort=function(){this.xhr_&&this.active_&&(R(this.logger_,T(this,"Aborting")),this.active_=!1,this.inAbort_=!0,this.xhr_.abort(),this.inAbort_=!1,this.dispatchEvent("complete"),this.dispatchEvent("abort"),Rc(this))};
-S.prototype.disposeInternal=function(){this.xhr_&&(this.active_&&(this.active_=!1,this.inAbort_=!0,this.xhr_.abort(),this.inAbort_=!1),Rc(this,!0));S.superClass_.disposeInternal.call(this)};S.prototype.onReadyStateChange_=function(){if(!this.disposed_)if(this.inOpen_||this.inSend_||this.inAbort_)Sc(this);else this.onReadyStateChangeEntryPoint_()};S.prototype.onReadyStateChangeEntryPoint_=function(){Sc(this)};
-var Sc=function(a){if(a.active_&&"undefined"!=typeof aa)if(a.xhrOptions_[1]&&4==Tc(a)&&2==Uc(a))R(a.logger_,T(a,"Local request error detected and ignored"));else if(a.inSend_&&4==Tc(a))xc(a.onReadyStateChange_,0,a);else if(a.dispatchEvent("readystatechange"),4==Tc(a)){R(a.logger_,T(a,"Request complete"));a.active_=!1;try{var b=Uc(a),c,d;t:switch(b){case 200:case 201:case 202:case 204:case 206:case 304:case 1223:d=!0;break t;default:d=!1}if(!(c=d)){var e;if(e=0===b){var g=Ac(1,String(a.lastUri_));
-if(!g&&self.location)var f=self.location.protocol,g=f.substr(0,f.length-1);e=!Jc.test(g?g.toLowerCase():"")}c=e}if(c)a.dispatchEvent("complete"),a.dispatchEvent("success");else{var k;try{k=2<Tc(a)?a.xhr_.statusText:""}catch(u){R(a.logger_,"Can not get status: "+u.message),k=""}a.lastError_=k+" ["+Uc(a)+"]";Qc(a)}}finally{Rc(a)}}},Rc=function(a,b){if(a.xhr_){Oc(a);var c=a.xhr_,d=a.xhrOptions_[0]?ca:null;a.xhr_=null;a.xhrOptions_=null;b||a.dispatchEvent("ready");try{c.onreadystatechange=d}catch(e){(c=
-a.logger_)&&c.log(qc,"Problem encountered resetting onreadystatechange: "+e.message,void 0)}}},Oc=function(a){a.xhr_&&a.useXhr2Timeout_&&(a.xhr_.ontimeout=null);"number"==typeof a.timeoutId_&&(l.clearTimeout(a.timeoutId_),a.timeoutId_=null)},Tc=function(a){return a.xhr_?a.xhr_.readyState:0},Uc=function(a){try{return 2<Tc(a)?a.xhr_.status:-1}catch(b){return-1}},T=function(a,b){return b+" ["+a.lastMethod_+" "+a.lastUri_+" "+Uc(a)+"]"};var U=function(){};U.getInstance=function(){return U.instance_?U.instance_:U.instance_=new U};U.prototype.nextId_=0;var V=function(a){M.call(this);this.dom_=a||sb()};r(V,M);h=V.prototype;h.idGenerator_=U.getInstance();h.id_=null;h.inDocument_=!1;h.element_=null;h.parent_=null;h.children_=null;h.childIndex_=null;h.wasDecorated_=!1;h.getElement=function(){return this.element_};h.getParent=function(){return this.parent_};h.setParentEventTarget=function(a){if(this.parent_&&this.parent_!=a)throw Error("Method not supported");V.superClass_.setParentEventTarget.call(this,a)};h.getDomHelper=function(){return this.dom_};
-h.createDom=function(){this.element_=this.dom_.createElement("div")};
-var Wc=function(a,b){if(a.inDocument_)throw Error("Component already rendered");a.element_||a.createDom();b?b.insertBefore(a.element_,null):a.dom_.document_.body.appendChild(a.element_);a.parent_&&!a.parent_.inDocument_||Vc(a)},Vc=function(a){a.inDocument_=!0;Xc(a,function(a){!a.inDocument_&&a.getElement()&&Vc(a)})},Zc=function(a){Xc(a,function(a){a.inDocument_&&Zc(a)});a.googUiComponentHandler_&&a.googUiComponentHandler_.removeAll();a.inDocument_=!1};
-V.prototype.disposeInternal=function(){this.inDocument_&&Zc(this);this.googUiComponentHandler_&&(this.googUiComponentHandler_.dispose(),delete this.googUiComponentHandler_);Xc(this,function(a){a.dispose()});!this.wasDecorated_&&this.element_&&zb(this.element_);this.parent_=this.element_=this.childIndex_=this.children_=null;V.superClass_.disposeInternal.call(this)};var Xc=function(a,b){a.children_&&Qa(a.children_,b,void 0)};
-V.prototype.removeChild=function(a,b){if(a){var c=n(a)?a:a.id_||(a.id_=":"+(a.idGenerator_.nextId_++).toString(36)),d;this.childIndex_&&c?(d=this.childIndex_,d=(c in d?d[c]:void 0)||null):d=null;a=d;if(c&&a){d=this.childIndex_;c in d&&delete d[c];Va(this.children_,a);b&&(Zc(a),a.element_&&zb(a.element_));c=a;if(null==c)throw Error("Unable to set parent component");c.parent_=null;V.superClass_.setParentEventTarget.call(c,null)}}if(!a)throw Error("Child is not in parent component");return a};var W=function(a,b,c){V.call(this,c);this.captchaImage_=a;this.adImage_=b&&300==b.naturalWidth&&57==b.naturalHeight?b:null};r(W,V);W.prototype.createDom=function(){W.superClass_.createDom.call(this);var a=this.getElement();this.captchaImage_.alt=X.image_alt_text;this.getDomHelper().appendChild(a,this.captchaImage_);this.adImage_&&(this.adImage_.alt=X.image_alt_text,this.getDomHelper().appendChild(a,this.adImage_),this.adImage_&&$c(this.adImage_)&&(a.innerHTML+='<div id="recaptcha-ad-choices"><div class="recaptcha-ad-choices-collapsed"><img height="15" width="15" alt="AdChoices" border="0" src="//pagead2.googlesyndication.com/pagead/images/adchoices/icon.png"/></div><div class="recaptcha-ad-choices-expanded"><a href="https://support.google.com/adsense/troubleshooter/1631343" target="_blank"><img height="15" width="75" alt="AdChoices" border="0" src="//pagead2.googlesyndication.com/pagead/images/adchoices/en.png"/></a></div></div>'))};
-var $c=function(a){var b=ad(a,"visibility");a=ad(a,"display");return"hidden"!=b&&"none"!=a},ad=function(a,b){var c;t:{c=9==a.nodeType?a:a.ownerDocument||a.document;if(c.defaultView&&c.defaultView.getComputedStyle&&(c=c.defaultView.getComputedStyle(a,null))){c=c[b]||c.getPropertyValue(b)||"";break t}c=""}if(!c&&!(c=a.currentStyle?a.currentStyle[b]:null)&&(c=a.style[La(b)],"undefined"===typeof c)){c=a.style;var d;t:if(d=La(b),void 0===a.style[d]){var e=(E?"Webkit":D?"Moz":C?"ms":cb?"O":null)+Ma(b);
-if(void 0!==a.style[e]){d=e;break t}}c=c[d]||""}return c};W.prototype.disposeInternal=function(){delete this.captchaImage_;delete this.adImage_;W.superClass_.disposeInternal.call(this)};var bd=function(a){return Sa(a,function(a){a=a.toString(16);return 1<a.length?a:"0"+a}).join("")};var cd=function(){this.blockSize=-1};var dd=function(){this.blockSize=-1;this.blockSize=64;this.chain_=Array(4);this.block_=Array(this.blockSize);this.totalLength_=this.blockLength_=0;this.reset()};r(dd,cd);dd.prototype.reset=function(){this.chain_[0]=1732584193;this.chain_[1]=4023233417;this.chain_[2]=2562383102;this.chain_[3]=271733878;this.totalLength_=this.blockLength_=0};
-var ed=function(a,b,c){c||(c=0);var d=Array(16);if(n(b))for(var e=0;16>e;++e)d[e]=b.charCodeAt(c++)|b.charCodeAt(c++)<<8|b.charCodeAt(c++)<<16|b.charCodeAt(c++)<<24;else for(e=0;16>e;++e)d[e]=b[c++]|b[c++]<<8|b[c++]<<16|b[c++]<<24;b=a.chain_[0];c=a.chain_[1];var e=a.chain_[2],g=a.chain_[3],f=0,f=b+(g^c&(e^g))+d[0]+3614090360&4294967295;b=c+(f<<7&4294967295|f>>>25);f=g+(e^b&(c^e))+d[1]+3905402710&4294967295;g=b+(f<<12&4294967295|f>>>20);f=e+(c^g&(b^c))+d[2]+606105819&4294967295;e=g+(f<<17&4294967295|
-f>>>15);f=c+(b^e&(g^b))+d[3]+3250441966&4294967295;c=e+(f<<22&4294967295|f>>>10);f=b+(g^c&(e^g))+d[4]+4118548399&4294967295;b=c+(f<<7&4294967295|f>>>25);f=g+(e^b&(c^e))+d[5]+1200080426&4294967295;g=b+(f<<12&4294967295|f>>>20);f=e+(c^g&(b^c))+d[6]+2821735955&4294967295;e=g+(f<<17&4294967295|f>>>15);f=c+(b^e&(g^b))+d[7]+4249261313&4294967295;c=e+(f<<22&4294967295|f>>>10);f=b+(g^c&(e^g))+d[8]+1770035416&4294967295;b=c+(f<<7&4294967295|f>>>25);f=g+(e^b&(c^e))+d[9]+2336552879&4294967295;g=b+(f<<12&4294967295|
-f>>>20);f=e+(c^g&(b^c))+d[10]+4294925233&4294967295;e=g+(f<<17&4294967295|f>>>15);f=c+(b^e&(g^b))+d[11]+2304563134&4294967295;c=e+(f<<22&4294967295|f>>>10);f=b+(g^c&(e^g))+d[12]+1804603682&4294967295;b=c+(f<<7&4294967295|f>>>25);f=g+(e^b&(c^e))+d[13]+4254626195&4294967295;g=b+(f<<12&4294967295|f>>>20);f=e+(c^g&(b^c))+d[14]+2792965006&4294967295;e=g+(f<<17&4294967295|f>>>15);f=c+(b^e&(g^b))+d[15]+1236535329&4294967295;c=e+(f<<22&4294967295|f>>>10);f=b+(e^g&(c^e))+d[1]+4129170786&4294967295;b=c+(f<<
-5&4294967295|f>>>27);f=g+(c^e&(b^c))+d[6]+3225465664&4294967295;g=b+(f<<9&4294967295|f>>>23);f=e+(b^c&(g^b))+d[11]+643717713&4294967295;e=g+(f<<14&4294967295|f>>>18);f=c+(g^b&(e^g))+d[0]+3921069994&4294967295;c=e+(f<<20&4294967295|f>>>12);f=b+(e^g&(c^e))+d[5]+3593408605&4294967295;b=c+(f<<5&4294967295|f>>>27);f=g+(c^e&(b^c))+d[10]+38016083&4294967295;g=b+(f<<9&4294967295|f>>>23);f=e+(b^c&(g^b))+d[15]+3634488961&4294967295;e=g+(f<<14&4294967295|f>>>18);f=c+(g^b&(e^g))+d[4]+3889429448&4294967295;c=
-e+(f<<20&4294967295|f>>>12);f=b+(e^g&(c^e))+d[9]+568446438&4294967295;b=c+(f<<5&4294967295|f>>>27);f=g+(c^e&(b^c))+d[14]+3275163606&4294967295;g=b+(f<<9&4294967295|f>>>23);f=e+(b^c&(g^b))+d[3]+4107603335&4294967295;e=g+(f<<14&4294967295|f>>>18);f=c+(g^b&(e^g))+d[8]+1163531501&4294967295;c=e+(f<<20&4294967295|f>>>12);f=b+(e^g&(c^e))+d[13]+2850285829&4294967295;b=c+(f<<5&4294967295|f>>>27);f=g+(c^e&(b^c))+d[2]+4243563512&4294967295;g=b+(f<<9&4294967295|f>>>23);f=e+(b^c&(g^b))+d[7]+1735328473&4294967295;
-e=g+(f<<14&4294967295|f>>>18);f=c+(g^b&(e^g))+d[12]+2368359562&4294967295;c=e+(f<<20&4294967295|f>>>12);f=b+(c^e^g)+d[5]+4294588738&4294967295;b=c+(f<<4&4294967295|f>>>28);f=g+(b^c^e)+d[8]+2272392833&4294967295;g=b+(f<<11&4294967295|f>>>21);f=e+(g^b^c)+d[11]+1839030562&4294967295;e=g+(f<<16&4294967295|f>>>16);f=c+(e^g^b)+d[14]+4259657740&4294967295;c=e+(f<<23&4294967295|f>>>9);f=b+(c^e^g)+d[1]+2763975236&4294967295;b=c+(f<<4&4294967295|f>>>28);f=g+(b^c^e)+d[4]+1272893353&4294967295;g=b+(f<<11&4294967295|
-f>>>21);f=e+(g^b^c)+d[7]+4139469664&4294967295;e=g+(f<<16&4294967295|f>>>16);f=c+(e^g^b)+d[10]+3200236656&4294967295;c=e+(f<<23&4294967295|f>>>9);f=b+(c^e^g)+d[13]+681279174&4294967295;b=c+(f<<4&4294967295|f>>>28);f=g+(b^c^e)+d[0]+3936430074&4294967295;g=b+(f<<11&4294967295|f>>>21);f=e+(g^b^c)+d[3]+3572445317&4294967295;e=g+(f<<16&4294967295|f>>>16);f=c+(e^g^b)+d[6]+76029189&4294967295;c=e+(f<<23&4294967295|f>>>9);f=b+(c^e^g)+d[9]+3654602809&4294967295;b=c+(f<<4&4294967295|f>>>28);f=g+(b^c^e)+d[12]+
-3873151461&4294967295;g=b+(f<<11&4294967295|f>>>21);f=e+(g^b^c)+d[15]+530742520&4294967295;e=g+(f<<16&4294967295|f>>>16);f=c+(e^g^b)+d[2]+3299628645&4294967295;c=e+(f<<23&4294967295|f>>>9);f=b+(e^(c|~g))+d[0]+4096336452&4294967295;b=c+(f<<6&4294967295|f>>>26);f=g+(c^(b|~e))+d[7]+1126891415&4294967295;g=b+(f<<10&4294967295|f>>>22);f=e+(b^(g|~c))+d[14]+2878612391&4294967295;e=g+(f<<15&4294967295|f>>>17);f=c+(g^(e|~b))+d[5]+4237533241&4294967295;c=e+(f<<21&4294967295|f>>>11);f=b+(e^(c|~g))+d[12]+1700485571&
-4294967295;b=c+(f<<6&4294967295|f>>>26);f=g+(c^(b|~e))+d[3]+2399980690&4294967295;g=b+(f<<10&4294967295|f>>>22);f=e+(b^(g|~c))+d[10]+4293915773&4294967295;e=g+(f<<15&4294967295|f>>>17);f=c+(g^(e|~b))+d[1]+2240044497&4294967295;c=e+(f<<21&4294967295|f>>>11);f=b+(e^(c|~g))+d[8]+1873313359&4294967295;b=c+(f<<6&4294967295|f>>>26);f=g+(c^(b|~e))+d[15]+4264355552&4294967295;g=b+(f<<10&4294967295|f>>>22);f=e+(b^(g|~c))+d[6]+2734768916&4294967295;e=g+(f<<15&4294967295|f>>>17);f=c+(g^(e|~b))+d[13]+1309151649&
-4294967295;c=e+(f<<21&4294967295|f>>>11);f=b+(e^(c|~g))+d[4]+4149444226&4294967295;b=c+(f<<6&4294967295|f>>>26);f=g+(c^(b|~e))+d[11]+3174756917&4294967295;g=b+(f<<10&4294967295|f>>>22);f=e+(b^(g|~c))+d[2]+718787259&4294967295;e=g+(f<<15&4294967295|f>>>17);f=c+(g^(e|~b))+d[9]+3951481745&4294967295;a.chain_[0]=a.chain_[0]+b&4294967295;a.chain_[1]=a.chain_[1]+(e+(f<<21&4294967295|f>>>11))&4294967295;a.chain_[2]=a.chain_[2]+e&4294967295;a.chain_[3]=a.chain_[3]+g&4294967295};
-dd.prototype.update=function(a,b){void 0===b&&(b=a.length);for(var c=b-this.blockSize,d=this.block_,e=this.blockLength_,g=0;g<b;){if(0==e)for(;g<=c;)ed(this,a,g),g+=this.blockSize;if(n(a))for(;g<b;){if(d[e++]=a.charCodeAt(g++),e==this.blockSize){ed(this,d);e=0;break}}else for(;g<b;)if(d[e++]=a[g++],e==this.blockSize){ed(this,d);e=0;break}}this.blockLength_=e;this.totalLength_+=b};var Y=function(){K.call(this);this.callback_=this.element_=null;this.md5_=new dd};r(Y,K);var fd=function(a,b,c,d,e){a.unwatch();a.element_=b;a.callback_=e;a.listen(b,"keyup",p(a.onChanged_,a,c,d))};Y.prototype.unwatch=function(){this.element_&&this.callback_&&(this.removeAll(),this.callback_=this.element_=null)};
-Y.prototype.onChanged_=function(a,b){var c;c=(c=this.element_.value)?c.replace(/[\s\xa0]+/g,"").toLowerCase():"";this.md5_.reset();this.md5_.update(c+"."+b);c=this.md5_;var d=Array((56>c.blockLength_?c.blockSize:2*c.blockSize)-c.blockLength_);d[0]=128;for(var e=1;e<d.length-8;++e)d[e]=0;for(var g=8*c.totalLength_,e=d.length-8;e<d.length;++e)d[e]=g&255,g/=256;c.update(d);d=Array(16);for(e=g=0;4>e;++e)for(var f=0;32>f;f+=8)d[g++]=c.chain_[e]>>>f&255;bd(d).toLowerCase()==a.toLowerCase()&&this.callback_()};
-Y.prototype.disposeInternal=function(){this.element_=null;Y.superClass_.disposeInternal.call(this)};var hd=function(a,b,c){this.adObject_=a;this.captchaImageUrl_=b;this.opt_successCallback_=c||null;gd(this)},gd=function(a){var b=new N;dc(b,"recaptcha_challenge_image",a.captchaImageUrl_);dc(b,"recaptcha_ad_image",a.adObject_.imageAdUrl);var c={};Nb(b,"load",p(function(a,b){a[b.target.id]=b.target},a,c));Nb(b,"complete",p(a.handleImagesLoaded_,a,c));b.start()};
-hd.prototype.handleImagesLoaded_=function(a){a=new W(a.recaptcha_challenge_image,a.recaptcha_ad_image);var b=tb(document,"recaptcha_image");yb(b);Wc(a,b);a.adImage_&&$c(a.adImage_)&&(Mc(this.adObject_.delayedImpressionUrl),a=new Y,fd(a,tb(document,"recaptcha_response_field"),this.adObject_.hashedAnswer,this.adObject_.salt,p(function(a,b){a.unwatch();Mc(b)},this,a,this.adObject_.engagementUrl)),this.opt_successCallback_&&this.opt_successCallback_("04"+this.adObject_.token))};var ya=function(){var a=l.google_ad;return!!(a&&a.token&&a.imageAdUrl&&a.hashedAnswer&&a.salt&&a.delayedImpressionUrl&&a.engagementUrl)};var X=t;q("RecaptchaStr",X);var Z=l.RecaptchaOptions;q("RecaptchaOptions",Z);var id={tabindex:0,theme:"red",callback:null,lang:null,custom_theme_widget:null,custom_translations:null};q("RecaptchaDefaultOptions",id);
-var $={widget:null,timer_id:-1,style_set:!1,theme:null,type:"image",ajax_verify_cb:null,$:function(a){return"string"==typeof a?document.getElementById(a):a},attachEvent:function(a,b,c){a&&a.addEventListener?a.addEventListener(b,c,!1):a&&a.attachEvent&&a.attachEvent("on"+b,c)},create:function(a,b,c){$.destroy();b&&($.widget=$.$(b));$._init_options(c);$._call_challenge(a)},destroy:function(){var a=$.$("recaptcha_challenge_field");a&&a.parentNode.removeChild(a);-1!=$.timer_id&&clearInterval($.timer_id);
-$.timer_id=-1;if(a=$.$("recaptcha_image"))a.innerHTML="";$.widget&&("custom"!=$.theme?$.widget.innerHTML="":$.widget.style.display="none",$.widget=null)},focus_response_field:function(){$.$("recaptcha_response_field").focus()},get_challenge:function(){return"undefined"==typeof RecaptchaState?null:RecaptchaState.challenge},get_response:function(){var a=$.$("recaptcha_response_field");return a?a.value:null},ajax_verify:function(a){$.ajax_verify_cb=a;a=$.get_challenge()||"";var b=$.get_response()||"";
-a=$._get_api_server()+"/ajaxverify?c="+encodeURIComponent(a)+"&response="+encodeURIComponent(b);$._add_script(a)},_ajax_verify_callback:function(a){$.ajax_verify_cb(a)},_get_overridable_url:function(a){var b=window.location.protocol;if("undefined"!=typeof _RecaptchaOverrideApiServer)a=_RecaptchaOverrideApiServer;else if("undefined"!=typeof RecaptchaState&&"string"==typeof RecaptchaState.server&&0<RecaptchaState.server.length)return RecaptchaState.server.replace(/\/+$/,"");return b+"//"+a},_get_api_server:function(){return $._get_overridable_url("www.google.com/recaptcha/api")},
-_get_static_url_root:function(){return $._get_overridable_url("www.gstatic.com/recaptcha/api")},_call_challenge:function(a){a=$._get_api_server()+"/challenge?k="+a+"&ajax=1&cachestop="+Math.random();$.getLang_()&&(a+="&lang="+$.getLang_());"undefined"!=typeof Z.extra_challenge_params&&(a+="&"+Z.extra_challenge_params);$._add_script(a)},_add_script:function(a){var b=document.createElement("script");b.type="text/javascript";b.src=a;$._get_script_area().appendChild(b)},_get_script_area:function(){var a=
-document.getElementsByTagName("head");return a=!a||1>a.length?document.body:a[0]},_hash_merge:function(a){for(var b={},c=0;c<a.length;c++)for(var d in a[c])b[d]=a[c][d];return b},_init_options:function(a){Z=$._hash_merge([id,a||{}])},challenge_callback:function(){$._reset_timer();X=$._hash_merge([t,ta[$.getLang_()]||{},Z.custom_translations||{}]);window.addEventListener&&window.addEventListener("unload",function(){$.destroy()},!1);$._is_ie()&&window.attachEvent&&window.attachEvent("onbeforeunload",
-function(){});if(0<navigator.userAgent.indexOf("KHTML")){var a=document.createElement("iframe");a.src="about:blank";a.style.height="0px";a.style.width="0px";a.style.visibility="hidden";a.style.border="none";a.appendChild(document.createTextNode("This frame prevents back/forward cache problems in Safari."));document.body.appendChild(a)}$._finish_widget()},_add_css:function(a){if(-1!=navigator.appVersion.indexOf("MSIE 5"))document.write('<style type="text/css">'+a+"</style>");else{var b=document.createElement("style");
-b.type="text/css";b.styleSheet?b.styleSheet.cssText=a:b.appendChild(document.createTextNode(a));$._get_script_area().appendChild(b)}},_set_style:function(a){$.style_set||($.style_set=!0,$._add_css(a+"\n\n.recaptcha_is_showing_audio .recaptcha_only_if_image,.recaptcha_isnot_showing_audio .recaptcha_only_if_audio,.recaptcha_had_incorrect_sol .recaptcha_only_if_no_incorrect_sol,.recaptcha_nothad_incorrect_sol .recaptcha_only_if_incorrect_sol{display:none !important}"))},_init_builtin_theme:function(){var a=
-$.$,b=$._get_static_url_root(),c=s.VertCss,d=s.VertHtml,e=b+"/img/"+$.theme,g="gif",b=$.theme;"clean"==b&&(c=s.CleanCss,d=s.CleanHtml,g="png");c=c.replace(/IMGROOT/g,e);$._set_style(c);$.widget.innerHTML='<div id="recaptcha_area">'+d+"</div>";c=$.getLang_();a("recaptcha_privacy")&&null!=c&&"en"==c.substring(0,2).toLowerCase()&&null!=X.privacy_and_terms&&0<X.privacy_and_terms.length&&(c=document.createElement("a"),c.href="http://www.google.com/intl/en/policies/",c.target="_blank",c.innerHTML=X.privacy_and_terms,
-a("recaptcha_privacy").appendChild(c));c=function(b,c,d,L){var v=a(b);v.src=e+"/"+c+"."+g;c=X[d];v.alt=c;b=a(b+"_btn");b.title=c;$.attachEvent(b,"click",L)};c("recaptcha_reload","refresh","refresh_btn",$.reload);c("recaptcha_switch_audio","audio","audio_challenge",function(){$.switch_type("audio")});c("recaptcha_switch_img","text","visual_challenge",function(){$.switch_type("image")});c("recaptcha_whatsthis","help","help_btn",$.showhelp);"clean"==b&&(a("recaptcha_logo").src=e+"/logo."+g);a("recaptcha_table").className=
-"recaptchatable recaptcha_theme_"+$.theme;b=function(b,c){var d=a(b);d&&(RecaptchaState.rtl&&"span"==d.tagName.toLowerCase()&&(d.dir="rtl"),d.appendChild(document.createTextNode(X[c])))};b("recaptcha_instructions_image","instructions_visual");b("recaptcha_instructions_audio","instructions_audio");b("recaptcha_instructions_error","incorrect_try_again");a("recaptcha_instructions_image")||a("recaptcha_instructions_audio")||(b="audio"==$.type?X.instructions_audio:X.instructions_visual,b=b.replace(/:$/,
-""),a("recaptcha_response_field").setAttribute("placeholder",b))},_finish_widget:function(){var a=$.$,b=Z,c=b.theme;c in{blackglass:1,clean:1,custom:1,red:1,white:1}||(c="red");$.theme||($.theme=c);"custom"!=$.theme?$._init_builtin_theme():$._set_style("");c=document.createElement("span");c.id="recaptcha_challenge_field_holder";c.style.display="none";a("recaptcha_response_field").parentNode.insertBefore(c,a("recaptcha_response_field"));a("recaptcha_response_field").setAttribute("autocomplete","off");
-a("recaptcha_image").style.width="300px";a("recaptcha_image").style.height="57px";$.should_focus=!1;$._set_challenge(RecaptchaState.challenge,"image");$.updateTabIndexes_();$.widget&&($.widget.style.display="");b.callback&&b.callback()},updateTabIndexes_:function(){var a=$.$,b=Z;b.tabindex&&(b=b.tabindex,a("recaptcha_response_field").tabIndex=b++,"audio"==$.type&&a("recaptcha_audio_play_again")&&(a("recaptcha_audio_play_again").tabIndex=b++,a("recaptcha_audio_download"),a("recaptcha_audio_download").tabIndex=
-b++),"custom"!=$.theme&&(a("recaptcha_reload_btn").tabIndex=b++,a("recaptcha_switch_audio_btn").tabIndex=b++,a("recaptcha_switch_img_btn").tabIndex=b++,a("recaptcha_whatsthis_btn").tabIndex=b,a("recaptcha_privacy").tabIndex=b++))},switch_type:function(a){$.type=a;$.reload("audio"==$.type?"a":"v");if("custom"!=$.theme){a=$.$;var b="audio"==$.type?X.instructions_audio:X.instructions_visual,b=b.replace(/:$/,"");a("recaptcha_response_field").setAttribute("placeholder",b)}},reload:function(a){var b=Z,
-c=RecaptchaState;"undefined"==typeof a&&(a="r");c=$._get_api_server()+"/reload?c="+c.challenge+"&k="+c.site+"&reason="+a+"&type="+$.type;$.getLang_()&&(c+="&lang="+$.getLang_());"undefined"!=typeof b.extra_challenge_params&&(c+="&"+b.extra_challenge_params);"audio"==$.type&&(c=b.audio_beta_12_08?c+"&audio_beta_12_08=1":c+"&new_audio_default=1");$.should_focus="t"!=a;$._add_script(c)},finish_reload:function(a,b,c){RecaptchaState.payload_url=c;RecaptchaState.is_incorrect=!1;$._set_challenge(a,b);$.updateTabIndexes_()},
-_set_challenge:function(a,b){var c=$.$,d=RecaptchaState;d.challenge=a;$.type=b;c("recaptcha_challenge_field_holder").innerHTML='<input type="hidden" name="recaptcha_challenge_field" id="recaptcha_challenge_field" value="'+d.challenge+'"/>';if("audio"==b)c("recaptcha_image").innerHTML=$.getAudioCaptchaHtml(),$._loop_playback();else if("image"==b){var e=d.payload_url;e||(e=$._get_api_server()+"/image?c="+d.challenge);ya()?(new hd(za(),e,function(a){RecaptchaState.challenge=a;c("recaptcha_challenge_field").value=
-a}),l.google_ad&&(l.google_ad=null)):c("recaptcha_image").innerHTML='<img id="recaptcha_challenge_image" alt="'+X.image_alt_text+'" height="57" width="300" src="'+e+'" />'}$._css_toggle("recaptcha_had_incorrect_sol","recaptcha_nothad_incorrect_sol",d.is_incorrect);$._css_toggle("recaptcha_is_showing_audio","recaptcha_isnot_showing_audio","audio"==b);$._clear_input();$.should_focus&&$.focus_response_field();$._reset_timer()},_reset_timer:function(){clearInterval($.timer_id);var a=Math.max(1E3*(RecaptchaState.timeout-
-60),6E4);$.timer_id=setInterval(function(){$.reload("t")},a);return a},showhelp:function(){window.open($._get_help_link(),"recaptcha_popup","width=460,height=580,location=no,menubar=no,status=no,toolbar=no,scrollbars=yes,resizable=yes")},_clear_input:function(){$.$("recaptcha_response_field").value=""},_displayerror:function(a){var b=$.$;b("recaptcha_image").innerHTML="";b("recaptcha_image").appendChild(document.createTextNode(a))},reloaderror:function(a){$._displayerror(a)},_is_ie:function(){return 0<
-navigator.userAgent.indexOf("MSIE")&&!window.opera},_css_toggle:function(a,b,c){var d=$.widget;d||(d=document.body);var e=d.className,e=e.replace(RegExp("(^|\\s+)"+a+"(\\s+|$)")," "),e=e.replace(RegExp("(^|\\s+)"+b+"(\\s+|$)")," ");d.className=e+(" "+(c?a:b))},_get_help_link:function(){var a=$._get_api_server().replace(/\/[a-zA-Z0-9]+\/?$/,"/help"),a=a+("?c="+RecaptchaState.challenge);$.getLang_()&&(a+="&hl="+$.getLang_());return a},playAgain:function(){$.$("recaptcha_image").innerHTML=$.getAudioCaptchaHtml();
-$._loop_playback()},_loop_playback:function(){var a=$.$("recaptcha_audio_play_again");a&&$.attachEvent(a,"click",function(){$.playAgain();return!1})},getAudioCaptchaHtml:function(){var a=RecaptchaState.payload_url;a||(a=$._get_api_server()+"/audio.mp3?c="+RecaptchaState.challenge);var b=$._get_static_url_root()+"/img/audiocaptcha.swf?v2",b=$._is_ie()?'<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" id="audiocaptcha" width="0" height="0" codebase="https://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab"><param name="movie" value="'+
-b+'" /><param name="quality" value="high" /><param name="bgcolor" value="#869ca7" /><param name="allowScriptAccess" value="always" /></object><br/>':'<embed src="'+b+'" quality="high" bgcolor="#869ca7" width="0" height="0" name="audiocaptcha" align="middle" play="true" loop="false" quality="high" allowScriptAccess="always" type="application/x-shockwave-flash" pluginspage="http://www.adobe.com/go/getflashplayer" /></embed>',c="";$.checkFlashVer()&&(c="<br/>"+$.getSpan_('<a id="recaptcha_audio_play_again" class="recaptcha_audio_cant_hear_link">'+
-X.play_again+"</a>"));c+="<br/>"+$.getSpan_('<a id="recaptcha_audio_download" class="recaptcha_audio_cant_hear_link" target="_blank" href="'+a+'">'+X.cant_hear_this+"</a>");return b+c},getSpan_:function(a){return"<span"+(RecaptchaState&&RecaptchaState.rtl?' dir="rtl"':"")+">"+a+"</span>"},gethttpwavurl:function(){if("audio"!=$.type)return"";var a=RecaptchaState.payload_url;a||(a=$._get_api_server()+"/image?c="+RecaptchaState.challenge);return a},checkFlashVer:function(){var a=-1!=navigator.appVersion.indexOf("MSIE"),
-b=-1!=navigator.appVersion.toLowerCase().indexOf("win"),c=-1!=navigator.userAgent.indexOf("Opera"),d=-1;if(null!=navigator.plugins&&0<navigator.plugins.length){if(navigator.plugins["Shockwave Flash 2.0"]||navigator.plugins["Shockwave Flash"])d=navigator.plugins["Shockwave Flash"+(navigator.plugins["Shockwave Flash 2.0"]?" 2.0":"")].description.split(" ")[2].split(".")[0]}else if(a&&b&&!c)try{d=(new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7")).GetVariable("$version").split(" ")[1].split(",")[0]}catch(e){}return 9<=
-d},getLang_:function(){return"undefined"!=typeof RecaptchaState&&RecaptchaState.lang?RecaptchaState.lang:Z.lang?Z.lang:null}};q("Recaptcha",$);})()
diff --git a/themes/jquerymobile/js/scripts.js b/themes/jquerymobile/js/scripts.js
deleted file mode 100644
index 0588803b07eef055011dd961f4fc6dd6cc61f09d..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/js/scripts.js
+++ /dev/null
@@ -1 +0,0 @@
-$.mobile.pushStateEnabled = false;
\ No newline at end of file
diff --git a/themes/jquerymobile/js/slick/slick.js b/themes/jquerymobile/js/slick/slick.js
deleted file mode 100644
index 00c5baffbf0e87c98d31b33aa4d67e554a42f4bc..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/js/slick/slick.js
+++ /dev/null
@@ -1,2117 +0,0 @@
-/*
-     _ _      _       _
- ___| (_) ___| | __  (_)___
-/ __| | |/ __| |/ /  | / __|
-\__ \ | | (__|   < _ | \__ \
-|___/_|_|\___|_|\_(_)/ |___/
-                   |__/
-
- Version: 1.3.15
-  Author: Ken Wheeler
- Website: http://kenwheeler.github.io
-    Docs: http://kenwheeler.github.io/slick
-    Repo: http://github.com/kenwheeler/slick
-  Issues: http://github.com/kenwheeler/slick/issues
-
- */
-
-/* global window, document, define, jQuery, setInterval, clearInterval */
-
-(function(factory) {
-    'use strict';
-    if (typeof define === 'function' && define.amd) {
-        define(['jquery'], factory);
-    } else if (typeof exports !== 'undefined') {
-        module.exports = factory(require('jquery'));
-    } else {
-        factory(jQuery);
-    }
-
-}(function($) {
-    'use strict';
-    var Slick = window.Slick || {};
-
-    Slick = (function() {
-
-        var instanceUid = 0;
-
-        function Slick(element, settings) {
-
-            var _ = this,
-                responsiveSettings, breakpoint;
-
-            _.defaults = {
-                accessibility: true,
-                adaptiveHeight: false,
-                appendArrows: $(element),
-                appendDots: $(element),
-                arrows: true,
-                asNavFor: null,
-                prevArrow: '<button type="button" data-role="none" class="slick-prev">Previous</button>',
-                nextArrow: '<button type="button" data-role="none" class="slick-next">Next</button>',
-                autoplay: false,
-                autoplaySpeed: 3000,
-                centerMode: false,
-                centerPadding: '50px',
-                cssEase: 'ease',
-                customPaging: function(slider, i) {
-                    return '<button type="button" data-role="none">' + (i + 1) + '</button>';
-                },
-                dots: false,
-                dotsClass: 'slick-dots',
-                draggable: true,
-                easing: 'linear',
-                fade: false,
-                focusOnSelect: false,
-                infinite: true,
-                initialSlide: 0,
-                lazyLoad: 'ondemand',
-                onBeforeChange: null,
-                onAfterChange: null,
-                onInit: null,
-                onReInit: null,
-                onSetPosition: null,
-                pauseOnHover: true,
-                pauseOnDotsHover: false,
-                respondTo: 'window',
-                responsive: null,
-                rtl: false,
-                slide: 'div',
-                slidesToShow: 1,
-                slidesToScroll: 1,
-                speed: 500,
-                swipe: true,
-                swipeToSlide: false,
-                touchMove: true,
-                touchThreshold: 5,
-                useCSS: true,
-                variableWidth: false,
-                vertical: false,
-                waitForAnimate: true
-            };
-
-            _.initials = {
-                animating: false,
-                dragging: false,
-                autoPlayTimer: null,
-                currentDirection: 0,
-                currentLeft: null,
-                currentSlide: 0,
-                direction: 1,
-                $dots: null,
-                listWidth: null,
-                listHeight: null,
-                loadIndex: 0,
-                $nextArrow: null,
-                $prevArrow: null,
-                slideCount: null,
-                slideWidth: null,
-                $slideTrack: null,
-                $slides: null,
-                sliding: false,
-                slideOffset: 0,
-                swipeLeft: null,
-                $list: null,
-                touchObject: {},
-                transformsEnabled: false
-            };
-
-            $.extend(_, _.initials);
-
-            _.activeBreakpoint = null;
-            _.animType = null;
-            _.animProp = null;
-            _.breakpoints = [];
-            _.breakpointSettings = [];
-            _.cssTransitions = false;
-            _.paused = false;
-            _.positionProp = null;
-            _.respondTo = null;
-            _.shouldClick = true;
-            _.$slider = $(element);
-            _.$slidesCache = null;
-            _.transformType = null;
-            _.transitionType = null;
-            _.windowWidth = 0;
-            _.windowTimer = null;
-
-            _.options = $.extend({}, _.defaults, settings);
-
-            _.currentSlide = _.options.initialSlide;
-
-            _.originalSettings = _.options;
-            responsiveSettings = _.options.responsive || null;
-
-            if (responsiveSettings && responsiveSettings.length > -1) {
-                _.respondTo = _.options.respondTo || "window";
-                for (breakpoint in responsiveSettings) {
-                    if (responsiveSettings.hasOwnProperty(breakpoint)) {
-                        _.breakpoints.push(responsiveSettings[
-                            breakpoint].breakpoint);
-                        _.breakpointSettings[responsiveSettings[
-                            breakpoint].breakpoint] =
-                            responsiveSettings[breakpoint].settings;
-                    }
-                }
-                _.breakpoints.sort(function(a, b) {
-                    return b - a;
-                });
-            }
-
-            _.autoPlay = $.proxy(_.autoPlay, _);
-            _.autoPlayClear = $.proxy(_.autoPlayClear, _);
-            _.changeSlide = $.proxy(_.changeSlide, _);
-            _.clickHandler = $.proxy(_.clickHandler, _);
-            _.selectHandler = $.proxy(_.selectHandler, _);
-            _.setPosition = $.proxy(_.setPosition, _);
-            _.swipeHandler = $.proxy(_.swipeHandler, _);
-            _.dragHandler = $.proxy(_.dragHandler, _);
-            _.keyHandler = $.proxy(_.keyHandler, _);
-            _.autoPlayIterator = $.proxy(_.autoPlayIterator, _);
-
-            _.instanceUid = instanceUid++;
-
-            // A simple way to check for HTML strings
-            // Strict HTML recognition (must start with <)
-            // Extracted from jQuery v1.11 source
-            _.htmlExpr = /^(?:\s*(<[\w\W]+>)[^>]*)$/;
-
-            _.init();
-
-            _.checkResponsive();
-
-        }
-
-        return Slick;
-
-    }());
-
-    Slick.prototype.addSlide = function(markup, index, addBefore) {
-
-        var _ = this;
-
-        if (typeof(index) === 'boolean') {
-            addBefore = index;
-            index = null;
-        } else if (index < 0 || (index >= _.slideCount)) {
-            return false;
-        }
-
-        _.unload();
-
-        if (typeof(index) === 'number') {
-            if (index === 0 && _.$slides.length === 0) {
-                $(markup).appendTo(_.$slideTrack);
-            } else if (addBefore) {
-                $(markup).insertBefore(_.$slides.eq(index));
-            } else {
-                $(markup).insertAfter(_.$slides.eq(index));
-            }
-        } else {
-            if (addBefore === true) {
-                $(markup).prependTo(_.$slideTrack);
-            } else {
-                $(markup).appendTo(_.$slideTrack);
-            }
-        }
-
-        _.$slides = _.$slideTrack.children(this.options.slide);
-
-        _.$slideTrack.children(this.options.slide).detach();
-
-        _.$slideTrack.append(_.$slides);
-
-        _.$slides.each(function(index, element) {
-            $(element).attr("index",index);
-        });
-
-        _.$slidesCache = _.$slides;
-
-        _.reinit();
-
-    };
-
-    Slick.prototype.animateSlide = function(targetLeft, callback) {
-
-        var animProps = {}, _ = this;
-
-        if(_.options.slidesToShow === 1 && _.options.adaptiveHeight === true && _.options.vertical === false) {
-            var targetHeight = _.$slides.eq(_.currentSlide).outerHeight(true);
-            _.$list.animate({height: targetHeight},_.options.speed);
-        }
-
-        if (_.options.rtl === true && _.options.vertical === false) {
-            targetLeft = -targetLeft;
-        }
-        if (_.transformsEnabled === false) {
-            if (_.options.vertical === false) {
-                _.$slideTrack.animate({
-                    left: targetLeft
-                }, _.options.speed, _.options.easing, callback);
-            } else {
-                _.$slideTrack.animate({
-                    top: targetLeft
-                }, _.options.speed, _.options.easing, callback);
-            }
-
-        } else {
-
-            if (_.cssTransitions === false) {
-
-                $({
-                    animStart: _.currentLeft
-                }).animate({
-                    animStart: targetLeft
-                }, {
-                    duration: _.options.speed,
-                    easing: _.options.easing,
-                    step: function(now) {
-                        if (_.options.vertical === false) {
-                            animProps[_.animType] = 'translate(' +
-                                now + 'px, 0px)';
-                            _.$slideTrack.css(animProps);
-                        } else {
-                            animProps[_.animType] = 'translate(0px,' +
-                                now + 'px)';
-                            _.$slideTrack.css(animProps);
-                        }
-                    },
-                    complete: function() {
-                        if (callback) {
-                            callback.call();
-                        }
-                    }
-                });
-
-            } else {
-
-                _.applyTransition();
-
-                if (_.options.vertical === false) {
-                    animProps[_.animType] = 'translate3d(' + targetLeft + 'px, 0px, 0px)';
-                } else {
-                    animProps[_.animType] = 'translate3d(0px,' + targetLeft + 'px, 0px)';
-                }
-                _.$slideTrack.css(animProps);
-
-                if (callback) {
-                    setTimeout(function() {
-
-                        _.disableTransition();
-
-                        callback.call();
-                    }, _.options.speed);
-                }
-
-            }
-
-        }
-
-    };
-
-    Slick.prototype.asNavFor = function(index) {
-        var _ = this, asNavFor = _.options.asNavFor != null ? $(_.options.asNavFor).getSlick() : null;
-        if(asNavFor != null) asNavFor.slideHandler(index, true);
-    };
-
-    Slick.prototype.applyTransition = function(slide) {
-
-        var _ = this,
-            transition = {};
-
-        if (_.options.fade === false) {
-            transition[_.transitionType] = _.transformType + ' ' + _.options.speed + 'ms ' + _.options.cssEase;
-        } else {
-            transition[_.transitionType] = 'opacity ' + _.options.speed + 'ms ' + _.options.cssEase;
-        }
-
-        if (_.options.fade === false) {
-            _.$slideTrack.css(transition);
-        } else {
-            _.$slides.eq(slide).css(transition);
-        }
-
-    };
-
-    Slick.prototype.autoPlay = function() {
-
-        var _ = this;
-
-        if (_.autoPlayTimer) {
-            clearInterval(_.autoPlayTimer);
-        }
-
-        if (_.slideCount > _.options.slidesToShow && _.paused !== true) {
-            _.autoPlayTimer = setInterval(_.autoPlayIterator,
-                _.options.autoplaySpeed);
-        }
-
-    };
-
-    Slick.prototype.autoPlayClear = function() {
-
-        var _ = this;
-        if (_.autoPlayTimer) {
-            clearInterval(_.autoPlayTimer);
-        }
-
-    };
-
-    Slick.prototype.autoPlayIterator = function() {
-
-        var _ = this;
-
-        if (_.options.infinite === false) {
-
-            if (_.direction === 1) {
-
-                if ((_.currentSlide + 1) === _.slideCount -
-                    1) {
-                    _.direction = 0;
-                }
-
-                _.slideHandler(_.currentSlide + _.options.slidesToScroll);
-
-            } else {
-
-                if ((_.currentSlide - 1 === 0)) {
-
-                    _.direction = 1;
-
-                }
-
-                _.slideHandler(_.currentSlide - _.options.slidesToScroll);
-
-            }
-
-        } else {
-
-            _.slideHandler(_.currentSlide + _.options.slidesToScroll);
-
-        }
-
-    };
-
-    Slick.prototype.buildArrows = function() {
-
-        var _ = this;
-
-        if (_.options.arrows === true && _.slideCount > _.options.slidesToShow) {
-
-            _.$prevArrow = $(_.options.prevArrow);
-            _.$nextArrow = $(_.options.nextArrow);
-
-            if (_.htmlExpr.test(_.options.prevArrow)) {
-                _.$prevArrow.appendTo(_.options.appendArrows);
-            }
-
-            if (_.htmlExpr.test(_.options.nextArrow)) {
-                _.$nextArrow.appendTo(_.options.appendArrows);
-            }
-
-            if (_.options.infinite !== true) {
-                _.$prevArrow.addClass('slick-disabled');
-            }
-
-        }
-
-    };
-
-    Slick.prototype.buildDots = function() {
-
-        var _ = this,
-            i, dotString;
-
-        if (_.options.dots === true && _.slideCount > _.options.slidesToShow) {
-
-            dotString = '<ul class="' + _.options.dotsClass + '">';
-
-            for (i = 0; i <= _.getDotCount(); i += 1) {
-                dotString += '<li>' + _.options.customPaging.call(this, _, i) + '</li>';
-            }
-
-            dotString += '</ul>';
-
-            _.$dots = $(dotString).appendTo(
-                _.options.appendDots);
-
-            _.$dots.find('li').first().addClass(
-                'slick-active');
-
-        }
-
-    };
-
-    Slick.prototype.buildOut = function() {
-
-        var _ = this;
-
-        _.$slides = _.$slider.children(_.options.slide +
-            ':not(.slick-cloned)').addClass(
-            'slick-slide');
-        _.slideCount = _.$slides.length;
-
-        _.$slides.each(function(index, element) {
-            $(element).attr("index",index);
-        });
-
-        _.$slidesCache = _.$slides;
-
-        _.$slider.addClass('slick-slider');
-
-        _.$slideTrack = (_.slideCount === 0) ?
-            $('<div class="slick-track"/>').appendTo(_.$slider) :
-            _.$slides.wrapAll('<div class="slick-track"/>').parent();
-
-        _.$list = _.$slideTrack.wrap(
-            '<div class="slick-list"/>').parent();
-        _.$slideTrack.css('opacity', 0);
-
-        if (_.options.centerMode === true) {
-            _.options.slidesToScroll = 1;
-        }
-
-        $('img[data-lazy]', _.$slider).not('[src]').addClass('slick-loading');
-
-        _.setupInfinite();
-
-        _.buildArrows();
-
-        _.buildDots();
-
-        _.updateDots();
-
-        if (_.options.accessibility === true) {
-            _.$list.prop('tabIndex', 0);
-        }
-
-        _.setSlideClasses(typeof this.currentSlide === 'number' ? this.currentSlide : 0);
-
-        if (_.options.draggable === true) {
-            _.$list.addClass('draggable');
-        }
-
-    };
-
-    Slick.prototype.checkResponsive = function() {
-
-        var _ = this,
-            breakpoint, targetBreakpoint, respondToWidth;
-        var sliderWidth = _.$slider.width();
-        var windowWidth = window.innerWidth || $(window).width();
-        if (_.respondTo === "window") {
-          respondToWidth = windowWidth;
-        } else if (_.respondTo === "slider") {
-          respondToWidth = sliderWidth;
-        } else if (_.respondTo === "min") {
-          respondToWidth = Math.min(windowWidth, sliderWidth);
-        }
-
-        if (_.originalSettings.responsive && _.originalSettings
-            .responsive.length > -1 && _.originalSettings.responsive !== null) {
-
-            targetBreakpoint = null;
-
-            for (breakpoint in _.breakpoints) {
-                if (_.breakpoints.hasOwnProperty(breakpoint)) {
-                    if (respondToWidth < _.breakpoints[breakpoint]) {
-                        targetBreakpoint = _.breakpoints[breakpoint];
-                    }
-                }
-            }
-
-            if (targetBreakpoint !== null) {
-                if (_.activeBreakpoint !== null) {
-                    if (targetBreakpoint !== _.activeBreakpoint) {
-                        _.activeBreakpoint =
-                            targetBreakpoint;
-                        _.options = $.extend({}, _.originalSettings,
-                            _.breakpointSettings[
-                                targetBreakpoint]);
-                        _.refresh();
-                    }
-                } else {
-                    _.activeBreakpoint = targetBreakpoint;
-                    _.options = $.extend({}, _.originalSettings,
-                        _.breakpointSettings[
-                            targetBreakpoint]);
-                    _.refresh();
-                }
-            } else {
-                if (_.activeBreakpoint !== null) {
-                    _.activeBreakpoint = null;
-                    _.options = _.originalSettings;
-                    _.refresh();
-                }
-            }
-
-        }
-
-    };
-
-    Slick.prototype.changeSlide = function(event, dontAnimate) {
-
-        var _ = this,
-            $target = $(event.target),
-            indexOffset, slideOffset, unevenOffset,navigables, prevNavigable;
-
-        // If target is a link, prevent default action.
-        $target.is('a') && event.preventDefault();
-
-        unevenOffset = (_.slideCount % _.options.slidesToScroll !== 0);
-        indexOffset = unevenOffset ? 0 : (_.slideCount - _.currentSlide) % _.options.slidesToScroll;
-
-        switch (event.data.message) {
-
-            case 'previous':
-                slideOffset = indexOffset === 0 ? _.options.slidesToScroll : _.options.slidesToShow - indexOffset;
-                if (_.slideCount > _.options.slidesToShow) {
-                    _.slideHandler(_.currentSlide  - slideOffset, false, dontAnimate);
-                }
-                break;
-
-            case 'next':
-                slideOffset = indexOffset === 0 ? _.options.slidesToScroll : indexOffset;
-                if (_.slideCount > _.options.slidesToShow) {
-                    _.slideHandler(_.currentSlide + slideOffset, false, dontAnimate);
-                }
-                break;
-
-            case 'index':
-                var index = event.data.index === 0 ? 0 :
-                    event.data.index || $(event.target).parent().index() * _.options.slidesToScroll;
-
-                navigables = _.getNavigableIndexes();
-                prevNavigable = 0;
-                if(navigables[index] && navigables[index] === index) {
-                    if(index > navigables[navigables.length -1]){
-                        index = navigables[navigables.length -1];
-                    } else {
-                        for(var n in navigables) {
-                            if(index < navigables[n]) {
-                                index = prevNavigable;
-                                break;
-                            }
-                            prevNavigable = navigables[n];
-                        }
-                    }
-                }
-                _.slideHandler(index, false, dontAnimate);
-
-            default:
-                return;
-        }
-
-    };
-
-    Slick.prototype.clickHandler = function(event) {
-
-        var _ = this;
-
-        if(_.shouldClick === false) {
-            event.stopImmediatePropagation();
-            event.stopPropagation();
-            event.preventDefault();
-        }
-
-    }
-
-    Slick.prototype.destroy = function() {
-
-        var _ = this;
-
-        _.autoPlayClear();
-
-        _.touchObject = {};
-
-        $('.slick-cloned', _.$slider).remove();
-        if (_.$dots) {
-            _.$dots.remove();
-        }
-        if (_.$prevArrow && (typeof _.options.prevArrow !== 'object')) {
-            _.$prevArrow.remove();
-        }
-        if (_.$nextArrow && (typeof _.options.nextArrow !== 'object')) {
-            _.$nextArrow.remove();
-        }
-        if (_.$slides.parent().hasClass('slick-track')) {
-            _.$slides.unwrap().unwrap();
-        }
-
-        _.$slides.removeClass(
-            'slick-slide slick-active slick-center slick-visible')
-            .removeAttr('index')
-            .css({
-                position: '',
-                left: '',
-                top: '',
-                zIndex: '',
-                opacity: '',
-                width: ''
-            });
-
-        _.$slider.removeClass('slick-slider');
-        _.$slider.removeClass('slick-initialized');
-
-        _.$list.off('.slick');
-        $(window).off('.slick-' + _.instanceUid);
-        $(document).off('.slick-' + _.instanceUid);
-
-    };
-
-    Slick.prototype.disableTransition = function(slide) {
-
-        var _ = this,
-            transition = {};
-
-        transition[_.transitionType] = "";
-
-        if (_.options.fade === false) {
-            _.$slideTrack.css(transition);
-        } else {
-            _.$slides.eq(slide).css(transition);
-        }
-
-    };
-
-    Slick.prototype.fadeSlide = function(oldSlide, slideIndex, callback) {
-
-        var _ = this;
-
-        if (_.cssTransitions === false) {
-
-            _.$slides.eq(slideIndex).css({
-                zIndex: 1000
-            });
-
-            _.$slides.eq(slideIndex).animate({
-                opacity: 1
-            }, _.options.speed, _.options.easing, callback);
-
-            _.$slides.eq(oldSlide).animate({
-                opacity: 0
-            }, _.options.speed, _.options.easing);
-
-        } else {
-
-            _.applyTransition(slideIndex);
-            _.applyTransition(oldSlide);
-
-            _.$slides.eq(slideIndex).css({
-                opacity: 1,
-                zIndex: 1000
-            });
-
-            _.$slides.eq(oldSlide).css({
-                opacity: 0
-            });
-
-            if (callback) {
-                setTimeout(function() {
-
-                    _.disableTransition(slideIndex);
-                    _.disableTransition(oldSlide);
-
-                    callback.call();
-                }, _.options.speed);
-            }
-
-        }
-
-    };
-
-    Slick.prototype.filterSlides = function(filter) {
-
-        var _ = this;
-
-        if (filter !== null) {
-
-            _.unload();
-
-            _.$slideTrack.children(this.options.slide).detach();
-
-            _.$slidesCache.filter(filter).appendTo(_.$slideTrack);
-
-            _.reinit();
-
-        }
-
-    };
-
-    Slick.prototype.getCurrent = function() {
-
-        var _ = this;
-
-        return _.currentSlide;
-
-    };
-
-    Slick.prototype.getDotCount = function() {
-
-        var _ = this;
-
-        var breakPoint = 0;
-        var counter = 0;
-        var pagerQty = 0;
-
-        if(_.options.infinite === true) {
-            pagerQty = Math.ceil(_.slideCount / _.options.slidesToScroll);
-        } else {
-            while (breakPoint < _.slideCount){
-                ++pagerQty;
-                breakPoint = counter + _.options.slidesToShow;
-                counter += _.options.slidesToScroll <= _.options.slidesToShow ? _.options.slidesToScroll  : _.options.slidesToShow;
-            }
-        }
-
-        return pagerQty - 1;
-
-    };
-
-    Slick.prototype.getLeft = function(slideIndex) {
-
-        var _ = this,
-            targetLeft,
-            verticalHeight,
-            verticalOffset = 0,
-            slideWidth,
-            targetSlide;
-
-        _.slideOffset = 0;
-        verticalHeight = _.$slides.first().outerHeight();
-
-        if (_.options.infinite === true) {
-            if (_.slideCount > _.options.slidesToShow) {
-                _.slideOffset = (_.slideWidth * _.options.slidesToShow) * -1;
-                verticalOffset = (verticalHeight * _.options.slidesToShow) * -1;
-            }
-            if (_.slideCount % _.options.slidesToScroll !== 0) {
-                if (slideIndex + _.options.slidesToScroll > _.slideCount && _.slideCount > _.options.slidesToShow) {
-                    if(slideIndex > _.slideCount) {
-                        _.slideOffset = ((_.options.slidesToShow - (slideIndex - _.slideCount)) * _.slideWidth) * -1;
-                        verticalOffset = ((_.options.slidesToShow - (slideIndex - _.slideCount)) * verticalHeight) * -1;
-                    } else {
-                        _.slideOffset = ((_.slideCount % _.options.slidesToScroll) * _.slideWidth) * -1;
-                        verticalOffset = ((_.slideCount % _.options.slidesToScroll) * verticalHeight) * -1;
-                    }
-                }
-            }
-        } else {
-            if(slideIndex + _.options.slidesToShow > _.slideCount) {
-                _.slideOffset = ((slideIndex + _.options.slidesToShow) - _.slideCount) * _.slideWidth;
-                verticalOffset = ((slideIndex + _.options.slidesToShow) - _.slideCount) * verticalHeight;
-            }
-        }
-
-        if (_.slideCount <= _.options.slidesToShow){
-            _.slideOffset = 0;
-            verticalOffset = 0;
-        }
-
-        if (_.options.centerMode === true && _.options.infinite === true) {
-            _.slideOffset += _.slideWidth * Math.floor(_.options.slidesToShow / 2) - _.slideWidth;
-        } else if (_.options.centerMode === true) {
-            _.slideOffset = 0;
-            _.slideOffset += _.slideWidth * Math.floor(_.options.slidesToShow / 2);
-        }
-
-        if (_.options.vertical === false) {
-            targetLeft = ((slideIndex * _.slideWidth) * -1) + _.slideOffset;
-        } else {
-            targetLeft = ((slideIndex * verticalHeight) * -1) + verticalOffset;
-        }
-
-        if (_.options.variableWidth === true) {
-
-            if(_.slideCount <= _.options.slidesToShow || _.options.infinite === false) {
-                targetSlide = _.$slideTrack.children('.slick-slide').eq(slideIndex);
-            } else {
-                targetSlide = _.$slideTrack.children('.slick-slide').eq(slideIndex + _.options.slidesToShow);
-            }
-            targetLeft = targetSlide[0] ? targetSlide[0].offsetLeft * -1 : 0;
-            if (_.options.centerMode === true) {
-                if(_.options.infinite === false) {
-                    targetSlide = _.$slideTrack.children('.slick-slide').eq(slideIndex);
-                } else {
-                    targetSlide = _.$slideTrack.children('.slick-slide').eq(slideIndex + _.options.slidesToShow + 1);
-                }
-                targetLeft = targetSlide[0] ? targetSlide[0].offsetLeft * -1 : 0;
-                targetLeft += (_.$list.width() - targetSlide.outerWidth()) / 2;
-            }
-        }
-
-         // 1680
-
-        return targetLeft;
-
-    };
-
-    Slick.prototype.getNavigableIndexes = function() {
-
-        var _ = this;
-
-        var breakPoint = 0;
-        var counter = 0;
-        var indexes = [];
-
-        while (breakPoint < _.slideCount){
-            indexes.push(breakPoint);
-            breakPoint = counter + _.options.slidesToScroll;
-            counter += _.options.slidesToScroll <= _.options.slidesToShow ? _.options.slidesToScroll  : _.options.slidesToShow;
-        }
-
-        return indexes;
-
-    };
-
-    Slick.prototype.getSlideCount = function() {
-
-        var _ = this, slidesTraversed;
-
-        if(_.options.swipeToSlide === true) {
-            var swipedSlide = null;
-            _.$slideTrack.find('.slick-slide').each(function(index, slide){
-                if (slide.offsetLeft + ($(slide).outerWidth() / 2) > (_.swipeLeft * -1)) {
-                    swipedSlide = slide;
-                    return false;
-                }
-            });
-            slidesTraversed = Math.abs($(swipedSlide).attr('index') - _.currentSlide);
-            return slidesTraversed;
-        } else {
-            return _.options.slidesToScroll;
-        }
-
-    };
-
-    Slick.prototype.init = function() {
-
-        var _ = this;
-
-        if (!$(_.$slider).hasClass('slick-initialized')) {
-
-            $(_.$slider).addClass('slick-initialized');
-            _.buildOut();
-            _.setProps();
-            _.startLoad();
-            _.loadSlider();
-            _.initializeEvents();
-            _.updateArrows();
-            _.updateDots();
-        }
-
-        if (_.options.onInit !== null) {
-            _.options.onInit.call(this, _);
-        }
-
-    };
-
-    Slick.prototype.initArrowEvents = function() {
-
-        var _ = this;
-
-        if (_.options.arrows === true && _.slideCount > _.options.slidesToShow) {
-            _.$prevArrow.bind('click.slick', {
-                message: 'previous'
-            }, _.changeSlide);
-            _.$nextArrow.bind('click.slick', {
-                message: 'next'
-            }, _.changeSlide);
-        }
-
-    };
-
-    Slick.prototype.initDotEvents = function() {
-
-        var _ = this;
-
-        if (_.options.dots === true && _.slideCount > _.options.slidesToShow) {
-            $('li', _.$dots).bind('click.slick', {
-                message: 'index'
-            }, _.changeSlide);
-        }
-
-        if (_.options.dots === true && _.options.pauseOnDotsHover === true && _.options.autoplay === true) {
-            $('li', _.$dots)
-                .bind('mouseenter.slick', function(){
-                    _.paused = true;
-                    _.autoPlayClear();
-                })
-                .bind('mouseleave.slick', function(){
-                    _.paused = false;
-                    _.autoPlay();
-                });
-        }
-
-    };
-
-    Slick.prototype.initializeEvents = function() {
-
-        var _ = this;
-
-        _.initArrowEvents();
-
-        _.initDotEvents();
-
-        _.$list.bind('touchstart.slick mousedown.slick', {
-            action: 'start'
-        }, _.swipeHandler);
-        _.$list.bind('touchmove.slick mousemove.slick', {
-            action: 'move'
-        }, _.swipeHandler);
-        _.$list.bind('touchend.slick mouseup.slick', {
-            action: 'end'
-        }, _.swipeHandler);
-        _.$list.bind('touchcancel.slick mouseleave.slick', {
-            action: 'end'
-        }, _.swipeHandler);
-
-        _.$list.bind('click.slick', _.clickHandler);
-
-        if (_.options.pauseOnHover === true && _.options.autoplay === true) {
-            _.$list.bind('mouseenter.slick', function(){
-                _.paused = true;
-                _.autoPlayClear();
-            });
-            _.$list.bind('mouseleave.slick', function(){
-                _.paused = false;
-                _.autoPlay();
-            });
-        }
-
-        if(_.options.accessibility === true) {
-            _.$list.bind('keydown.slick', _.keyHandler);
-        }
-
-        if(_.options.focusOnSelect === true) {
-            $(_.options.slide, _.$slideTrack).bind('click.slick', _.selectHandler);
-        }
-
-        $(window).bind('orientationchange.slick.slick-' + _.instanceUid, function() {
-            _.checkResponsive();
-            _.setPosition();
-        });
-
-        $(window).bind('resize.slick.slick-' + _.instanceUid, function() {
-            if ($(window).width() !== _.windowWidth) {
-                clearTimeout(_.windowDelay);
-                _.windowDelay = window.setTimeout(function() {
-                    _.windowWidth = $(window).width();
-                    _.checkResponsive();
-                    _.setPosition();
-                }, 50);
-            }
-        });
-
-        $('*[draggable!=true]', _.$slideTrack).bind('dragstart', function(e){ e.preventDefault(); })
-
-        $(window).bind('load.slick.slick-' + _.instanceUid, _.setPosition);
-        $(document).bind('ready.slick.slick-' + _.instanceUid, _.setPosition);
-
-    };
-
-    Slick.prototype.initUI = function() {
-
-        var _ = this;
-
-        if (_.options.arrows === true && _.slideCount > _.options.slidesToShow) {
-
-            _.$prevArrow.show();
-            _.$nextArrow.show();
-
-        }
-
-        if (_.options.dots === true && _.slideCount > _.options.slidesToShow) {
-
-            _.$dots.show();
-
-        }
-
-        if (_.options.autoplay === true) {
-
-            _.autoPlay();
-
-        }
-
-    };
-
-    Slick.prototype.keyHandler = function(event) {
-
-        var _ = this;
-
-        if (event.keyCode === 37 && _.options.accessibility === true) {
-            _.changeSlide({
-                data: {
-                    message: 'previous'
-                }
-            });
-        } else if (event.keyCode === 39 && _.options.accessibility === true) {
-            _.changeSlide({
-                data: {
-                    message: 'next'
-                }
-            });
-        }
-
-    };
-
-    Slick.prototype.lazyLoad = function() {
-
-        var _ = this,
-            loadRange, cloneRange, rangeStart, rangeEnd;
-
-        function loadImages(imagesScope) {
-            $('img[data-lazy]', imagesScope).each(function() {
-                var image = $(this),
-                    imageSource = $(this).attr('data-lazy');
-
-                image
-                  .load(function() { image.animate({ opacity: 1 }, 200); })
-                  .css({ opacity: 0 })
-                  .attr('src', imageSource)
-                  .removeAttr('data-lazy')
-                  .removeClass('slick-loading');
-            });
-        }
-
-        if (_.options.centerMode === true) {
-            if (_.options.infinite === true) {
-                rangeStart = _.currentSlide + (_.options.slidesToShow/2 + 1);
-                rangeEnd = rangeStart + _.options.slidesToShow + 2;
-            } else {
-                rangeStart = Math.max(0, _.currentSlide - (_.options.slidesToShow/2 + 1));
-                rangeEnd = 2 + (_.options.slidesToShow/2 + 1) + _.currentSlide;
-            }
-        } else {
-            rangeStart = _.options.infinite ? _.options.slidesToShow + _.currentSlide : _.currentSlide;
-            rangeEnd = rangeStart + _.options.slidesToShow;
-            if (_.options.fade === true ) {
-                if(rangeStart > 0) rangeStart--;
-                if(rangeEnd <= _.slideCount) rangeEnd++;
-            }
-        }
-
-        loadRange = _.$slider.find('.slick-slide').slice(rangeStart, rangeEnd);
-        loadImages(loadRange);
-
-          if (_.slideCount <= _.options.slidesToShow){
-              cloneRange = _.$slider.find('.slick-slide')
-              loadImages(cloneRange)
-          }else
-        if (_.currentSlide >= _.slideCount - _.options.slidesToShow) {
-            cloneRange = _.$slider.find('.slick-cloned').slice(0, _.options.slidesToShow);
-            loadImages(cloneRange)
-        } else if (_.currentSlide === 0) {
-            cloneRange = _.$slider.find('.slick-cloned').slice(_.options.slidesToShow * -1);
-            loadImages(cloneRange);
-        }
-
-    };
-
-    Slick.prototype.loadSlider = function() {
-
-        var _ = this;
-
-        _.setPosition();
-
-        _.$slideTrack.css({
-            opacity: 1
-        });
-
-        _.$slider.removeClass('slick-loading');
-
-        _.initUI();
-
-        if (_.options.lazyLoad === 'progressive') {
-            _.progressiveLazyLoad();
-        }
-
-    };
-
-    Slick.prototype.postSlide = function(index) {
-
-        var _ = this;
-
-        if (_.options.onAfterChange !== null) {
-            _.options.onAfterChange.call(this, _, index);
-        }
-
-        _.animating = false;
-
-        _.setPosition();
-
-        _.swipeLeft = null;
-
-        if (_.options.autoplay === true && _.paused === false) {
-            _.autoPlay();
-        }
-
-    };
-
-    Slick.prototype.progressiveLazyLoad = function() {
-
-        var _ = this,
-            imgCount, targetImage;
-
-        imgCount = $('img[data-lazy]', _.$slider).length;
-
-        if (imgCount > 0) {
-            targetImage = $('img[data-lazy]', _.$slider).first();
-            targetImage.attr('src', targetImage.attr('data-lazy')).removeClass('slick-loading').load(function() {
-                targetImage.removeAttr('data-lazy');
-                _.progressiveLazyLoad();
-            })
-         .error(function () {
-          targetImage.removeAttr('data-lazy');
-          _.progressiveLazyLoad();
-         });
-        }
-
-    };
-
-    Slick.prototype.refresh = function() {
-
-        var _ = this,
-            currentSlide = _.currentSlide;
-
-        _.destroy();
-
-        $.extend(_, _.initials);
-
-        _.init();
-
-        _.changeSlide({
-            data: {
-                message: 'index',
-                index: currentSlide,
-            }
-        }, true);
-
-    };
-
-    Slick.prototype.reinit = function() {
-
-        var _ = this;
-
-        _.$slides = _.$slideTrack.children(_.options.slide).addClass(
-            'slick-slide');
-
-        _.slideCount = _.$slides.length;
-
-        if (_.currentSlide >= _.slideCount && _.currentSlide !== 0) {
-            _.currentSlide = _.currentSlide - _.options.slidesToScroll;
-        }
-
-        if (_.slideCount <= _.options.slidesToShow) {
-            _.currentSlide = 0;
-        }
-
-        _.setProps();
-
-        _.setupInfinite();
-
-        _.buildArrows();
-
-        _.updateArrows();
-
-        _.initArrowEvents();
-
-        _.buildDots();
-
-        _.updateDots();
-
-        _.initDotEvents();
-
-        if(_.options.focusOnSelect === true) {
-            $(_.options.slide, _.$slideTrack).bind('click.slick', _.selectHandler);
-        }
-
-        _.setSlideClasses(0);
-
-        _.setPosition();
-
-        if (_.options.onReInit !== null) {
-            _.options.onReInit.call(this, _);
-        }
-
-    };
-
-    Slick.prototype.removeSlide = function(index, removeBefore, removeAll) {
-
-        var _ = this;
-
-        if (typeof(index) === 'boolean') {
-            removeBefore = index;
-            index = removeBefore === true ? 0 : _.slideCount - 1;
-        } else {
-            index = removeBefore === true ? --index : index;
-        }
-
-        if (_.slideCount < 1 || index < 0 || index > _.slideCount - 1) {
-            return false;
-        }
-
-        _.unload();
-
-        if(removeAll === true) {
-            _.$slideTrack.children().remove();
-        } else {
-            _.$slideTrack.children(this.options.slide).eq(index).remove();
-        }
-
-        _.$slides = _.$slideTrack.children(this.options.slide);
-
-        _.$slideTrack.children(this.options.slide).detach();
-
-        _.$slideTrack.append(_.$slides);
-
-        _.$slidesCache = _.$slides;
-
-        _.reinit();
-
-    };
-
-    Slick.prototype.setCSS = function(position) {
-
-        var _ = this,
-            positionProps = {}, x, y;
-
-        if (_.options.rtl === true) {
-            position = -position;
-        }
-        x = _.positionProp == 'left' ? position + 'px' : '0px';
-        y = _.positionProp == 'top' ? position + 'px' : '0px';
-
-        positionProps[_.positionProp] = position;
-
-        if (_.transformsEnabled === false) {
-            _.$slideTrack.css(positionProps);
-        } else {
-            positionProps = {};
-            if (_.cssTransitions === false) {
-                positionProps[_.animType] = 'translate(' + x + ', ' + y + ')';
-                _.$slideTrack.css(positionProps);
-            } else {
-                positionProps[_.animType] = 'translate3d(' + x + ', ' + y + ', 0px)';
-                _.$slideTrack.css(positionProps);
-            }
-        }
-
-    };
-
-    Slick.prototype.setDimensions = function() {
-
-        var _ = this;
-
-        if (_.options.vertical === false) {
-            if (_.options.centerMode === true) {
-                _.$list.css({
-                    padding: ('0px ' + _.options.centerPadding)
-                });
-            }
-        } else {
-            _.$list.height(_.$slides.first().outerHeight(true) * _.options.slidesToShow);
-            if (_.options.centerMode === true) {
-                _.$list.css({
-                    padding: (_.options.centerPadding + ' 0px')
-                });
-            }
-        }
-
-        _.listWidth = _.$list.width();
-        _.listHeight = _.$list.height();
-
-
-        if(_.options.vertical === false && _.options.variableWidth === false) {
-            _.slideWidth = Math.ceil(_.listWidth / _.options.slidesToShow);
-            _.$slideTrack.width(Math.ceil((_.slideWidth * _.$slideTrack.children('.slick-slide').length)));
-
-        } else if (_.options.variableWidth === true) {
-            var trackWidth = 0;
-            _.slideWidth = Math.ceil(_.listWidth / _.options.slidesToShow);
-            _.$slideTrack.children('.slick-slide').each(function(){
-                trackWidth += Math.ceil($(this).outerWidth(true));
-            });
-            _.$slideTrack.width(Math.ceil(trackWidth) + 1);
-        } else {
-            _.slideWidth = Math.ceil(_.listWidth);
-            _.$slideTrack.height(Math.ceil((_.$slides.first().outerHeight(true) * _.$slideTrack.children('.slick-slide').length)));
-        }
-
-        var offset = _.$slides.first().outerWidth(true) - _.$slides.first().width();
-        if (_.options.variableWidth === false) _.$slideTrack.children('.slick-slide').width(_.slideWidth - offset);
-
-    };
-
-    Slick.prototype.setFade = function() {
-
-        var _ = this,
-            targetLeft;
-
-        _.$slides.each(function(index, element) {
-            targetLeft = (_.slideWidth * index) * -1;
-            if (_.options.rtl === true) {
-                $(element).css({
-                    position: 'relative',
-                    right: targetLeft,
-                    top: 0,
-                    zIndex: 800,
-                    opacity: 0
-                });
-            } else {
-                $(element).css({
-                    position: 'relative',
-                    left: targetLeft,
-                    top: 0,
-                    zIndex: 800,
-                    opacity: 0
-                });
-            }
-        });
-
-        _.$slides.eq(_.currentSlide).css({
-            zIndex: 900,
-            opacity: 1
-        });
-
-    };
-
-    Slick.prototype.setHeight = function() {
-
-        var _ = this;
-
-        if(_.options.slidesToShow === 1 && _.options.adaptiveHeight === true && _.options.vertical === false) {
-            var targetHeight = _.$slides.eq(_.currentSlide).outerHeight(true);
-            _.$list.css('height', targetHeight);
-        }
-
-    };
-
-    Slick.prototype.setPosition = function() {
-
-        var _ = this;
-
-        _.setDimensions();
-
-        _.setHeight();
-
-        if (_.options.fade === false) {
-            _.setCSS(_.getLeft(_.currentSlide));
-        } else {
-            _.setFade();
-        }
-
-        if (_.options.onSetPosition !== null) {
-            _.options.onSetPosition.call(this, _);
-        }
-
-    };
-
-    Slick.prototype.setProps = function() {
-
-        var _ = this,
-            bodyStyle = document.body.style;
-
-        _.positionProp = _.options.vertical === true ? 'top' : 'left';
-
-        if (_.positionProp === 'top') {
-            _.$slider.addClass('slick-vertical');
-        } else {
-            _.$slider.removeClass('slick-vertical');
-        }
-
-        if (bodyStyle.WebkitTransition !== undefined ||
-            bodyStyle.MozTransition !== undefined ||
-            bodyStyle.msTransition !== undefined) {
-            if(_.options.useCSS === true) {
-                _.cssTransitions = true;
-            }
-        }
-
-        if (bodyStyle.OTransform !== undefined) {
-            _.animType = 'OTransform';
-            _.transformType = "-o-transform";
-            _.transitionType = 'OTransition';
-            if (bodyStyle.perspectiveProperty === undefined && bodyStyle.webkitPerspective === undefined) _.animType = false;
-        }
-        if (bodyStyle.MozTransform !== undefined) {
-            _.animType = 'MozTransform';
-            _.transformType = "-moz-transform";
-            _.transitionType = 'MozTransition';
-            if (bodyStyle.perspectiveProperty === undefined && bodyStyle.MozPerspective === undefined) _.animType = false;
-        }
-        if (bodyStyle.webkitTransform !== undefined) {
-            _.animType = 'webkitTransform';
-            _.transformType = "-webkit-transform";
-            _.transitionType = 'webkitTransition';
-            if (bodyStyle.perspectiveProperty === undefined && bodyStyle.webkitPerspective === undefined) _.animType = false;
-        }
-        if (bodyStyle.msTransform !== undefined) {
-            _.animType = 'msTransform';
-            _.transformType = "-ms-transform";
-            _.transitionType = 'msTransition';
-            if (bodyStyle.msTransform === undefined) _.animType = false;
-        }
-        if (bodyStyle.transform !== undefined && _.animType !== false) {
-            _.animType = 'transform';
-            _.transformType = "transform";
-            _.transitionType = 'transition';
-        }
-        _.transformsEnabled = (_.animType !== null && _.animType !== false);
-
-    };
-
-
-    Slick.prototype.setSlideClasses = function(index) {
-
-        var _ = this,
-            centerOffset, allSlides, indexOffset, remainder;
-
-        _.$slider.find('.slick-slide').removeClass('slick-active').removeClass('slick-center');
-        allSlides = _.$slider.find('.slick-slide');
-
-        if (_.options.centerMode === true) {
-
-            centerOffset = Math.floor(_.options.slidesToShow / 2);
-
-            if(_.options.infinite === true) {
-
-                if (index >= centerOffset && index <= (_.slideCount - 1) - centerOffset) {
-                    _.$slides.slice(index - centerOffset, index + centerOffset + 1).addClass('slick-active');
-                } else {
-                    indexOffset = _.options.slidesToShow + index;
-                    allSlides.slice(indexOffset - centerOffset + 1, indexOffset + centerOffset + 2).addClass('slick-active');
-                }
-
-                if (index === 0) {
-                    allSlides.eq(allSlides.length - 1 - _.options.slidesToShow).addClass('slick-center');
-                } else if (index === _.slideCount - 1) {
-                    allSlides.eq(_.options.slidesToShow).addClass('slick-center');
-                }
-
-            }
-
-            _.$slides.eq(index).addClass('slick-center');
-
-        } else {
-
-            if (index >= 0 && index <= (_.slideCount - _.options.slidesToShow)) {
-                _.$slides.slice(index, index + _.options.slidesToShow).addClass('slick-active');
-            } else if ( allSlides.length <= _.options.slidesToShow ) {
-                allSlides.addClass('slick-active');
-            } else {
-                remainder = _.slideCount%_.options.slidesToShow;
-                indexOffset = _.options.infinite === true ? _.options.slidesToShow + index : index;
-                if(_.options.slidesToShow == _.options.slidesToScroll && (_.slideCount - index) < _.options.slidesToShow) {
-                    allSlides.slice(indexOffset-(_.options.slidesToShow-remainder), indexOffset + remainder).addClass('slick-active');
-                } else {
-                    allSlides.slice(indexOffset, indexOffset + _.options.slidesToShow).addClass('slick-active');
-                }
-            }
-
-        }
-
-        if (_.options.lazyLoad === 'ondemand') {
-            _.lazyLoad();
-        }
-
-    };
-
-    Slick.prototype.setupInfinite = function() {
-
-        var _ = this,
-            i, slideIndex, infiniteCount;
-
-        if (_.options.fade === true) {
-            _.options.centerMode = false;
-        }
-
-        if (_.options.infinite === true && _.options.fade === false) {
-
-            slideIndex = null;
-
-            if (_.slideCount > _.options.slidesToShow) {
-
-                if (_.options.centerMode === true) {
-                    infiniteCount = _.options.slidesToShow + 1;
-                } else {
-                    infiniteCount = _.options.slidesToShow;
-                }
-
-                for (i = _.slideCount; i > (_.slideCount -
-                    infiniteCount); i -= 1) {
-                    slideIndex = i - 1;
-                    $(_.$slides[slideIndex]).clone(true).attr('id', '')
-                        .attr('index', slideIndex-_.slideCount)
-                        .prependTo(_.$slideTrack).addClass('slick-cloned');
-                }
-                for (i = 0; i < infiniteCount; i += 1) {
-                    slideIndex = i;
-                    $(_.$slides[slideIndex]).clone(true).attr('id', '')
-                        .attr('index', slideIndex+_.slideCount)
-                        .appendTo(_.$slideTrack).addClass('slick-cloned');
-                }
-                _.$slideTrack.find('.slick-cloned').find('[id]').each(function() {
-                    $(this).attr('id', '');
-                });
-
-            }
-
-        }
-
-    };
-
-    Slick.prototype.selectHandler = function(event) {
-
-        var _ = this;
-        var index = parseInt($(event.target).parents('.slick-slide').attr("index"));
-        if(!index) index = 0;
-
-        if(_.slideCount <= _.options.slidesToShow){
-            _.$slider.find('.slick-slide').removeClass('slick-active');
-            _.$slides.eq(index).addClass('slick-active');
-            if(_.options.centerMode === true) {
-                _.$slider.find('.slick-slide').removeClass('slick-center');
-                _.$slides.eq(index).addClass('slick-center');
-            }
-            _.asNavFor(index);
-            return;
-        }
-        _.slideHandler(index);
-
-    };
-
-    Slick.prototype.slideHandler = function(index,sync,dontAnimate) {
-
-        var targetSlide, animSlide, oldSlide, slideLeft, unevenOffset, targetLeft = null,
-            _ = this;
-
-        sync = sync || false;
-
-        if (_.animating === true && _.options.waitForAnimate === true) {
-            return;
-        }
-
-        if (_.options.fade === true && _.currentSlide === index) {
-            return;
-        }
-
-        if (_.slideCount <= _.options.slidesToShow) {
-            return;
-        }
-
-        if (sync === false) {
-            _.asNavFor(index);
-        }
-
-        targetSlide = index;
-        targetLeft = _.getLeft(targetSlide);
-        slideLeft = _.getLeft(_.currentSlide);
-
-        _.currentLeft = _.swipeLeft === null ? slideLeft : _.swipeLeft;
-
-        if (_.options.infinite === false && _.options.centerMode === false && (index < 0 || index > _.getDotCount() * _.options.slidesToScroll)) {
-            if(_.options.fade === false) {
-                targetSlide = _.currentSlide;
-                if(dontAnimate!==true) {
-                    _.animateSlide(slideLeft, function() {
-                        _.postSlide(targetSlide);
-                    });
-                } else {
-                    _.postSlide(targetSlide);
-                }
-            }
-            return;
-        } else if (_.options.infinite === false && _.options.centerMode === true && (index < 0 || index > (_.slideCount - _.options.slidesToScroll))) {
-            if(_.options.fade === false) {
-                targetSlide = _.currentSlide;
-                if(dontAnimate!==true) {
-                    _.animateSlide(slideLeft, function() {
-                        _.postSlide(targetSlide);
-                    });
-                } else {
-                    _.postSlide(targetSlide);
-                }
-            }
-            return;
-        }
-
-        if (_.options.autoplay === true) {
-            clearInterval(_.autoPlayTimer);
-        }
-
-        if (targetSlide < 0) {
-            if (_.slideCount % _.options.slidesToScroll !== 0) {
-                animSlide = _.slideCount - (_.slideCount % _.options.slidesToScroll);
-            } else {
-                animSlide = _.slideCount + targetSlide;
-            }
-        } else if (targetSlide >= _.slideCount) {
-            if (_.slideCount % _.options.slidesToScroll !== 0) {
-                animSlide = 0;
-            } else {
-                animSlide = targetSlide - _.slideCount;
-            }
-        } else {
-            animSlide = targetSlide;
-        }
-
-        _.animating = true;
-
-        if (_.options.onBeforeChange !== null && index !== _.currentSlide) {
-            _.options.onBeforeChange.call(this, _, _.currentSlide, animSlide);
-        }
-
-        oldSlide = _.currentSlide;
-        _.currentSlide = animSlide;
-
-        _.setSlideClasses(_.currentSlide);
-
-        _.updateDots();
-        _.updateArrows();
-
-        if (_.options.fade === true) {
-            if(dontAnimate!==true) {
-                _.fadeSlide(oldSlide,animSlide, function() {
-                    _.postSlide(animSlide);
-                });
-            } else {
-                _.postSlide(animSlide);
-            }
-            return;
-        }
-
-        if(dontAnimate!==true) {
-            _.animateSlide(targetLeft, function() {
-                _.postSlide(animSlide);
-            });
-        } else {
-            _.postSlide(animSlide);
-        }
-
-    };
-
-    Slick.prototype.startLoad = function() {
-
-        var _ = this;
-
-        if (_.options.arrows === true && _.slideCount > _.options.slidesToShow) {
-
-            _.$prevArrow.hide();
-            _.$nextArrow.hide();
-
-        }
-
-        if (_.options.dots === true && _.slideCount > _.options.slidesToShow) {
-
-            _.$dots.hide();
-
-        }
-
-        _.$slider.addClass('slick-loading');
-
-    };
-
-    Slick.prototype.swipeDirection = function() {
-
-        var xDist, yDist, r, swipeAngle, _ = this;
-
-        xDist = _.touchObject.startX - _.touchObject.curX;
-        yDist = _.touchObject.startY - _.touchObject.curY;
-        r = Math.atan2(yDist, xDist);
-
-        swipeAngle = Math.round(r * 180 / Math.PI);
-        if (swipeAngle < 0) {
-            swipeAngle = 360 - Math.abs(swipeAngle);
-        }
-
-        if ((swipeAngle <= 45) && (swipeAngle >= 0)) {
-            return (_.options.rtl === false ? 'left' : 'right');
-        }
-        if ((swipeAngle <= 360) && (swipeAngle >= 315)) {
-            return (_.options.rtl === false ? 'left' : 'right');
-        }
-        if ((swipeAngle >= 135) && (swipeAngle <= 225)) {
-            return (_.options.rtl === false ? 'right' : 'left');
-        }
-
-        return 'vertical';
-
-    };
-
-    Slick.prototype.swipeEnd = function(event) {
-
-        var _ = this, slideCount;
-
-        _.dragging = false;
-
-        _.shouldClick = (_.touchObject.swipeLength > 10) ? false : true;
-
-        if (_.touchObject.curX === undefined) {
-            return false;
-        }
-
-        if (_.touchObject.swipeLength >= _.touchObject.minSwipe) {
-
-            switch (_.swipeDirection()) {
-                case 'left':
-                    _.slideHandler(_.currentSlide + _.getSlideCount());
-                    _.currentDirection = 0;
-                    _.touchObject = {};
-                    break;
-
-                case 'right':
-                    _.slideHandler(_.currentSlide - _.getSlideCount());
-                    _.currentDirection = 1;
-                    _.touchObject = {};
-                    break;
-            }
-        } else {
-            if(_.touchObject.startX !== _.touchObject.curX) {
-                _.slideHandler(_.currentSlide);
-                _.touchObject = {};
-            }
-        }
-
-    };
-
-    Slick.prototype.swipeHandler = function(event) {
-
-        var _ = this;
-
-        if ((_.options.swipe === false) || ('ontouchend' in document && _.options.swipe === false)) {
-           return;
-        } else if (_.options.draggable === false && event.type.indexOf('mouse') !== -1) {
-           return;
-        }
-
-        _.touchObject.fingerCount = event.originalEvent && event.originalEvent.touches !== undefined ?
-            event.originalEvent.touches.length : 1;
-
-        _.touchObject.minSwipe = _.listWidth / _.options
-            .touchThreshold;
-
-        switch (event.data.action) {
-
-            case 'start':
-                _.swipeStart(event);
-                break;
-
-            case 'move':
-                _.swipeMove(event);
-                break;
-
-            case 'end':
-                _.swipeEnd(event);
-                break;
-
-        }
-
-    };
-
-    Slick.prototype.swipeMove = function(event) {
-
-        var _ = this,
-            curLeft, swipeDirection, positionOffset, touches;
-
-        touches = event.originalEvent !== undefined ? event.originalEvent.touches : null;
-
-        if (!_.dragging || touches && touches.length !== 1) {
-            return false;
-        }
-
-        curLeft = _.getLeft(_.currentSlide);
-
-        _.touchObject.curX = touches !== undefined ? touches[0].pageX : event.clientX;
-        _.touchObject.curY = touches !== undefined ? touches[0].pageY : event.clientY;
-
-        _.touchObject.swipeLength = Math.round(Math.sqrt(
-            Math.pow(_.touchObject.curX - _.touchObject.startX, 2)));
-
-        swipeDirection = _.swipeDirection();
-
-        if (swipeDirection === 'vertical') {
-            return;
-        }
-
-        if (event.originalEvent !== undefined && _.touchObject.swipeLength > 4) {
-            event.preventDefault();
-        }
-
-        positionOffset = (_.options.rtl === false ? 1 : -1) * (_.touchObject.curX > _.touchObject.startX ? 1 : -1);
-
-        if (_.options.vertical === false) {
-            _.swipeLeft = curLeft + _.touchObject.swipeLength * positionOffset;
-        } else {
-            _.swipeLeft = curLeft + (_.touchObject
-                .swipeLength * (_.$list.height() / _.listWidth)) * positionOffset;
-        }
-
-        if (_.options.fade === true || _.options.touchMove === false) {
-            return false;
-        }
-
-        if (_.animating === true) {
-            _.swipeLeft = null;
-            return false;
-        }
-
-        _.setCSS(_.swipeLeft);
-
-    };
-
-    Slick.prototype.swipeStart = function(event) {
-
-        var _ = this,
-            touches;
-
-        if (_.touchObject.fingerCount !== 1 || _.slideCount <= _.options.slidesToShow) {
-            _.touchObject = {};
-            return false;
-        }
-
-        if (event.originalEvent !== undefined && event.originalEvent.touches !== undefined) {
-            touches = event.originalEvent.touches[0];
-        }
-
-        _.touchObject.startX = _.touchObject.curX = touches !== undefined ? touches.pageX : event.clientX;
-        _.touchObject.startY = _.touchObject.curY = touches !== undefined ? touches.pageY : event.clientY;
-
-        _.dragging = true;
-
-    };
-
-    Slick.prototype.unfilterSlides = function() {
-
-        var _ = this;
-
-        if (_.$slidesCache !== null) {
-
-            _.unload();
-
-            _.$slideTrack.children(this.options.slide).detach();
-
-            _.$slidesCache.appendTo(_.$slideTrack);
-
-            _.reinit();
-
-        }
-
-    };
-
-    Slick.prototype.unload = function() {
-
-        var _ = this;
-
-        $('.slick-cloned', _.$slider).remove();
-        if (_.$dots) {
-            _.$dots.remove();
-        }
-        if (_.$prevArrow && (typeof _.options.prevArrow !== 'object')) {
-            _.$prevArrow.remove();
-        }
-        if (_.$nextArrow && (typeof _.options.nextArrow !== 'object')) {
-            _.$nextArrow.remove();
-        }
-        _.$slides.removeClass(
-            'slick-slide slick-active slick-visible').css('width', '');
-
-    };
-
-    Slick.prototype.updateArrows = function() {
-
-        var _ = this, centerOffset;
-
-        centerOffset = Math.floor(_.options.slidesToShow / 2)
-
-        if (_.options.arrows === true && _.options.infinite !==
-            true && _.slideCount > _.options.slidesToShow) {
-            _.$prevArrow.removeClass('slick-disabled');
-            _.$nextArrow.removeClass('slick-disabled');
-            if (_.currentSlide === 0) {
-                _.$prevArrow.addClass('slick-disabled');
-                _.$nextArrow.removeClass('slick-disabled');
-            } else if (_.currentSlide >= _.slideCount - _.options.slidesToShow && _.options.centerMode === false) {
-                _.$nextArrow.addClass('slick-disabled');
-                _.$prevArrow.removeClass('slick-disabled');
-            } else if (_.currentSlide > _.slideCount - _.options.slidesToShow + centerOffset  && _.options.centerMode === true) {
-                _.$nextArrow.addClass('slick-disabled');
-                _.$prevArrow.removeClass('slick-disabled');
-            }
-        }
-
-    };
-
-    Slick.prototype.updateDots = function() {
-
-        var _ = this;
-
-        if (_.$dots !== null) {
-
-            _.$dots.find('li').removeClass('slick-active');
-            _.$dots.find('li').eq(Math.floor(_.currentSlide / _.options.slidesToScroll)).addClass('slick-active');
-
-        }
-
-    };
-
-    $.fn.slick = function(options) {
-        var _ = this;
-        return _.each(function(index, element) {
-
-            element.slick = new Slick(element, options);
-
-        });
-    };
-
-    $.fn.slickAdd = function(slide, slideIndex, addBefore) {
-        var _ = this;
-        return _.each(function(index, element) {
-
-            element.slick.addSlide(slide, slideIndex, addBefore);
-
-        });
-    };
-
-    $.fn.slickCurrentSlide = function() {
-        var _ = this;
-        return _.get(0).slick.getCurrent();
-    };
-
-    $.fn.slickFilter = function(filter) {
-        var _ = this;
-        return _.each(function(index, element) {
-
-            element.slick.filterSlides(filter);
-
-        });
-    };
-
-    $.fn.slickGoTo = function(slide, dontAnimate) {
-        var _ = this;
-        return _.each(function(index, element) {
-
-            element.slick.changeSlide({
-                data: {
-                    message: 'index',
-                    index: parseInt(slide)
-                }
-            }, dontAnimate);
-
-        });
-    };
-
-    $.fn.slickNext = function() {
-        var _ = this;
-        return _.each(function(index, element) {
-
-            element.slick.changeSlide({
-                data: {
-                    message: 'next'
-                }
-            });
-
-        });
-    };
-
-    $.fn.slickPause = function() {
-        var _ = this;
-        return _.each(function(index, element) {
-
-            element.slick.autoPlayClear();
-            element.slick.paused = true;
-
-        });
-    };
-
-    $.fn.slickPlay = function() {
-        var _ = this;
-        return _.each(function(index, element) {
-
-            element.slick.paused = false;
-            element.slick.autoPlay();
-
-        });
-    };
-
-    $.fn.slickPrev = function() {
-        var _ = this;
-        return _.each(function(index, element) {
-
-            element.slick.changeSlide({
-                data: {
-                    message: 'previous'
-                }
-            });
-
-        });
-    };
-
-    $.fn.slickRemove = function(slideIndex, removeBefore) {
-        var _ = this;
-        return _.each(function(index, element) {
-
-            element.slick.removeSlide(slideIndex, removeBefore);
-
-        });
-    };
-
-    $.fn.slickRemoveAll = function() {
-        var _ = this;
-        return _.each(function(index, element) {
-
-            element.slick.removeSlide(null, null, true);
-
-        });
-    };
-
-    $.fn.slickGetOption = function(option) {
-        var _ = this;
-        return _.get(0).slick.options[option];
-    };
-
-    $.fn.slickSetOption = function(option, value, refresh) {
-        var _ = this;
-        return _.each(function(index, element) {
-
-            element.slick.options[option] = value;
-
-            if (refresh === true) {
-                element.slick.unload();
-                element.slick.reinit();
-            }
-
-        });
-    };
-
-    $.fn.slickUnfilter = function() {
-        var _ = this;
-        return _.each(function(index, element) {
-
-            element.slick.unfilterSlides();
-
-        });
-    };
-
-    $.fn.unslick = function() {
-        var _ = this;
-        return _.each(function(index, element) {
-
-          if (element.slick) {
-            element.slick.destroy();
-          }
-
-        });
-    };
-
-    $.fn.getSlick = function() {
-        var s = null;
-        var _ = this;
-        _.each(function(index, element) {
-            s = element.slick;
-        });
-
-        return s;
-    };
-
-}));
diff --git a/themes/jquerymobile/js/slick/slick.min.js b/themes/jquerymobile/js/slick/slick.min.js
deleted file mode 100644
index ae481fab8676b4b4323045b9aea33be6603ecff5..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/js/slick/slick.min.js
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
-     _ _      _       _
- ___| (_) ___| | __  (_)___
-/ __| | |/ __| |/ /  | / __|
-\__ \ | | (__|   < _ | \__ \
-|___/_|_|\___|_|\_(_)/ |___/
-                   |__/
-
- Version: 1.3.15
-  Author: Ken Wheeler
- Website: http://kenwheeler.github.io
-    Docs: http://kenwheeler.github.io/slick
-    Repo: http://github.com/kenwheeler/slick
-  Issues: http://github.com/kenwheeler/slick/issues
-
- */
-
-!function(a){"use strict";"function"==typeof define&&define.amd?define(["jquery"],a):"undefined"!=typeof exports?module.exports=a(require("jquery")):a(jQuery)}(function(a){"use strict";var b=window.Slick||{};b=function(){function c(c,d){var f,g,e=this;if(e.defaults={accessibility:!0,adaptiveHeight:!1,appendArrows:a(c),appendDots:a(c),arrows:!0,asNavFor:null,prevArrow:'<button type="button" data-role="none" class="slick-prev">Previous</button>',nextArrow:'<button type="button" data-role="none" class="slick-next">Next</button>',autoplay:!1,autoplaySpeed:3e3,centerMode:!1,centerPadding:"50px",cssEase:"ease",customPaging:function(a,b){return'<button type="button" data-role="none">'+(b+1)+"</button>"},dots:!1,dotsClass:"slick-dots",draggable:!0,easing:"linear",fade:!1,focusOnSelect:!1,infinite:!0,initialSlide:0,lazyLoad:"ondemand",onBeforeChange:null,onAfterChange:null,onInit:null,onReInit:null,onSetPosition:null,pauseOnHover:!0,pauseOnDotsHover:!1,respondTo:"window",responsive:null,rtl:!1,slide:"div",slidesToShow:1,slidesToScroll:1,speed:500,swipe:!0,swipeToSlide:!1,touchMove:!0,touchThreshold:5,useCSS:!0,variableWidth:!1,vertical:!1,waitForAnimate:!0},e.initials={animating:!1,dragging:!1,autoPlayTimer:null,currentDirection:0,currentLeft:null,currentSlide:0,direction:1,$dots:null,listWidth:null,listHeight:null,loadIndex:0,$nextArrow:null,$prevArrow:null,slideCount:null,slideWidth:null,$slideTrack:null,$slides:null,sliding:!1,slideOffset:0,swipeLeft:null,$list:null,touchObject:{},transformsEnabled:!1},a.extend(e,e.initials),e.activeBreakpoint=null,e.animType=null,e.animProp=null,e.breakpoints=[],e.breakpointSettings=[],e.cssTransitions=!1,e.paused=!1,e.positionProp=null,e.respondTo=null,e.shouldClick=!0,e.$slider=a(c),e.$slidesCache=null,e.transformType=null,e.transitionType=null,e.windowWidth=0,e.windowTimer=null,e.options=a.extend({},e.defaults,d),e.currentSlide=e.options.initialSlide,e.originalSettings=e.options,f=e.options.responsive||null,f&&f.length>-1){e.respondTo=e.options.respondTo||"window";for(g in f)f.hasOwnProperty(g)&&(e.breakpoints.push(f[g].breakpoint),e.breakpointSettings[f[g].breakpoint]=f[g].settings);e.breakpoints.sort(function(a,b){return b-a})}e.autoPlay=a.proxy(e.autoPlay,e),e.autoPlayClear=a.proxy(e.autoPlayClear,e),e.changeSlide=a.proxy(e.changeSlide,e),e.clickHandler=a.proxy(e.clickHandler,e),e.selectHandler=a.proxy(e.selectHandler,e),e.setPosition=a.proxy(e.setPosition,e),e.swipeHandler=a.proxy(e.swipeHandler,e),e.dragHandler=a.proxy(e.dragHandler,e),e.keyHandler=a.proxy(e.keyHandler,e),e.autoPlayIterator=a.proxy(e.autoPlayIterator,e),e.instanceUid=b++,e.htmlExpr=/^(?:\s*(<[\w\W]+>)[^>]*)$/,e.init(),e.checkResponsive()}var b=0;return c}(),b.prototype.addSlide=function(b,c,d){var e=this;if("boolean"==typeof c)d=c,c=null;else if(0>c||c>=e.slideCount)return!1;e.unload(),"number"==typeof c?0===c&&0===e.$slides.length?a(b).appendTo(e.$slideTrack):d?a(b).insertBefore(e.$slides.eq(c)):a(b).insertAfter(e.$slides.eq(c)):d===!0?a(b).prependTo(e.$slideTrack):a(b).appendTo(e.$slideTrack),e.$slides=e.$slideTrack.children(this.options.slide),e.$slideTrack.children(this.options.slide).detach(),e.$slideTrack.append(e.$slides),e.$slides.each(function(b,c){a(c).attr("index",b)}),e.$slidesCache=e.$slides,e.reinit()},b.prototype.animateSlide=function(b,c){var d={},e=this;if(1===e.options.slidesToShow&&e.options.adaptiveHeight===!0&&e.options.vertical===!1){var f=e.$slides.eq(e.currentSlide).outerHeight(!0);e.$list.animate({height:f},e.options.speed)}e.options.rtl===!0&&e.options.vertical===!1&&(b=-b),e.transformsEnabled===!1?e.options.vertical===!1?e.$slideTrack.animate({left:b},e.options.speed,e.options.easing,c):e.$slideTrack.animate({top:b},e.options.speed,e.options.easing,c):e.cssTransitions===!1?a({animStart:e.currentLeft}).animate({animStart:b},{duration:e.options.speed,easing:e.options.easing,step:function(a){e.options.vertical===!1?(d[e.animType]="translate("+a+"px, 0px)",e.$slideTrack.css(d)):(d[e.animType]="translate(0px,"+a+"px)",e.$slideTrack.css(d))},complete:function(){c&&c.call()}}):(e.applyTransition(),d[e.animType]=e.options.vertical===!1?"translate3d("+b+"px, 0px, 0px)":"translate3d(0px,"+b+"px, 0px)",e.$slideTrack.css(d),c&&setTimeout(function(){e.disableTransition(),c.call()},e.options.speed))},b.prototype.asNavFor=function(b){var c=this,d=null!=c.options.asNavFor?a(c.options.asNavFor).getSlick():null;null!=d&&d.slideHandler(b,!0)},b.prototype.applyTransition=function(a){var b=this,c={};c[b.transitionType]=b.options.fade===!1?b.transformType+" "+b.options.speed+"ms "+b.options.cssEase:"opacity "+b.options.speed+"ms "+b.options.cssEase,b.options.fade===!1?b.$slideTrack.css(c):b.$slides.eq(a).css(c)},b.prototype.autoPlay=function(){var a=this;a.autoPlayTimer&&clearInterval(a.autoPlayTimer),a.slideCount>a.options.slidesToShow&&a.paused!==!0&&(a.autoPlayTimer=setInterval(a.autoPlayIterator,a.options.autoplaySpeed))},b.prototype.autoPlayClear=function(){var a=this;a.autoPlayTimer&&clearInterval(a.autoPlayTimer)},b.prototype.autoPlayIterator=function(){var a=this;a.options.infinite===!1?1===a.direction?(a.currentSlide+1===a.slideCount-1&&(a.direction=0),a.slideHandler(a.currentSlide+a.options.slidesToScroll)):(0===a.currentSlide-1&&(a.direction=1),a.slideHandler(a.currentSlide-a.options.slidesToScroll)):a.slideHandler(a.currentSlide+a.options.slidesToScroll)},b.prototype.buildArrows=function(){var b=this;b.options.arrows===!0&&b.slideCount>b.options.slidesToShow&&(b.$prevArrow=a(b.options.prevArrow),b.$nextArrow=a(b.options.nextArrow),b.htmlExpr.test(b.options.prevArrow)&&b.$prevArrow.appendTo(b.options.appendArrows),b.htmlExpr.test(b.options.nextArrow)&&b.$nextArrow.appendTo(b.options.appendArrows),b.options.infinite!==!0&&b.$prevArrow.addClass("slick-disabled"))},b.prototype.buildDots=function(){var c,d,b=this;if(b.options.dots===!0&&b.slideCount>b.options.slidesToShow){for(d='<ul class="'+b.options.dotsClass+'">',c=0;c<=b.getDotCount();c+=1)d+="<li>"+b.options.customPaging.call(this,b,c)+"</li>";d+="</ul>",b.$dots=a(d).appendTo(b.options.appendDots),b.$dots.find("li").first().addClass("slick-active")}},b.prototype.buildOut=function(){var b=this;b.$slides=b.$slider.children(b.options.slide+":not(.slick-cloned)").addClass("slick-slide"),b.slideCount=b.$slides.length,b.$slides.each(function(b,c){a(c).attr("index",b)}),b.$slidesCache=b.$slides,b.$slider.addClass("slick-slider"),b.$slideTrack=0===b.slideCount?a('<div class="slick-track"/>').appendTo(b.$slider):b.$slides.wrapAll('<div class="slick-track"/>').parent(),b.$list=b.$slideTrack.wrap('<div class="slick-list"/>').parent(),b.$slideTrack.css("opacity",0),b.options.centerMode===!0&&(b.options.slidesToScroll=1),a("img[data-lazy]",b.$slider).not("[src]").addClass("slick-loading"),b.setupInfinite(),b.buildArrows(),b.buildDots(),b.updateDots(),b.options.accessibility===!0&&b.$list.prop("tabIndex",0),b.setSlideClasses("number"==typeof this.currentSlide?this.currentSlide:0),b.options.draggable===!0&&b.$list.addClass("draggable")},b.prototype.checkResponsive=function(){var c,d,e,b=this,f=b.$slider.width(),g=window.innerWidth||a(window).width();if("window"===b.respondTo?e=g:"slider"===b.respondTo?e=f:"min"===b.respondTo&&(e=Math.min(g,f)),b.originalSettings.responsive&&b.originalSettings.responsive.length>-1&&null!==b.originalSettings.responsive){d=null;for(c in b.breakpoints)b.breakpoints.hasOwnProperty(c)&&e<b.breakpoints[c]&&(d=b.breakpoints[c]);null!==d?null!==b.activeBreakpoint?d!==b.activeBreakpoint&&(b.activeBreakpoint=d,b.options=a.extend({},b.originalSettings,b.breakpointSettings[d]),b.refresh()):(b.activeBreakpoint=d,b.options=a.extend({},b.originalSettings,b.breakpointSettings[d]),b.refresh()):null!==b.activeBreakpoint&&(b.activeBreakpoint=null,b.options=b.originalSettings,b.refresh())}},b.prototype.changeSlide=function(b,c){var f,g,h,i,j,d=this,e=a(b.target);switch(e.is("a")&&b.preventDefault(),h=0!==d.slideCount%d.options.slidesToScroll,f=h?0:(d.slideCount-d.currentSlide)%d.options.slidesToScroll,b.data.message){case"previous":g=0===f?d.options.slidesToScroll:d.options.slidesToShow-f,d.slideCount>d.options.slidesToShow&&d.slideHandler(d.currentSlide-g,!1,c);break;case"next":g=0===f?d.options.slidesToScroll:f,d.slideCount>d.options.slidesToShow&&d.slideHandler(d.currentSlide+g,!1,c);break;case"index":var k=0===b.data.index?0:b.data.index||a(b.target).parent().index()*d.options.slidesToScroll;if(i=d.getNavigableIndexes(),j=0,i[k]&&i[k]===k)if(k>i[i.length-1])k=i[i.length-1];else for(var l in i){if(k<i[l]){k=j;break}j=i[l]}d.slideHandler(k,!1,c);default:return}},b.prototype.clickHandler=function(a){var b=this;b.shouldClick===!1&&(a.stopImmediatePropagation(),a.stopPropagation(),a.preventDefault())},b.prototype.destroy=function(){var b=this;b.autoPlayClear(),b.touchObject={},a(".slick-cloned",b.$slider).remove(),b.$dots&&b.$dots.remove(),b.$prevArrow&&"object"!=typeof b.options.prevArrow&&b.$prevArrow.remove(),b.$nextArrow&&"object"!=typeof b.options.nextArrow&&b.$nextArrow.remove(),b.$slides.parent().hasClass("slick-track")&&b.$slides.unwrap().unwrap(),b.$slides.removeClass("slick-slide slick-active slick-center slick-visible").removeAttr("index").css({position:"",left:"",top:"",zIndex:"",opacity:"",width:""}),b.$slider.removeClass("slick-slider"),b.$slider.removeClass("slick-initialized"),b.$list.off(".slick"),a(window).off(".slick-"+b.instanceUid),a(document).off(".slick-"+b.instanceUid)},b.prototype.disableTransition=function(a){var b=this,c={};c[b.transitionType]="",b.options.fade===!1?b.$slideTrack.css(c):b.$slides.eq(a).css(c)},b.prototype.fadeSlide=function(a,b,c){var d=this;d.cssTransitions===!1?(d.$slides.eq(b).css({zIndex:1e3}),d.$slides.eq(b).animate({opacity:1},d.options.speed,d.options.easing,c),d.$slides.eq(a).animate({opacity:0},d.options.speed,d.options.easing)):(d.applyTransition(b),d.applyTransition(a),d.$slides.eq(b).css({opacity:1,zIndex:1e3}),d.$slides.eq(a).css({opacity:0}),c&&setTimeout(function(){d.disableTransition(b),d.disableTransition(a),c.call()},d.options.speed))},b.prototype.filterSlides=function(a){var b=this;null!==a&&(b.unload(),b.$slideTrack.children(this.options.slide).detach(),b.$slidesCache.filter(a).appendTo(b.$slideTrack),b.reinit())},b.prototype.getCurrent=function(){var a=this;return a.currentSlide},b.prototype.getDotCount=function(){var a=this,b=0,c=0,d=0;if(a.options.infinite===!0)d=Math.ceil(a.slideCount/a.options.slidesToScroll);else for(;b<a.slideCount;)++d,b=c+a.options.slidesToShow,c+=a.options.slidesToScroll<=a.options.slidesToShow?a.options.slidesToScroll:a.options.slidesToShow;return d-1},b.prototype.getLeft=function(a){var c,d,g,b=this,e=0;return b.slideOffset=0,d=b.$slides.first().outerHeight(),b.options.infinite===!0?(b.slideCount>b.options.slidesToShow&&(b.slideOffset=-1*b.slideWidth*b.options.slidesToShow,e=-1*d*b.options.slidesToShow),0!==b.slideCount%b.options.slidesToScroll&&a+b.options.slidesToScroll>b.slideCount&&b.slideCount>b.options.slidesToShow&&(a>b.slideCount?(b.slideOffset=-1*(b.options.slidesToShow-(a-b.slideCount))*b.slideWidth,e=-1*(b.options.slidesToShow-(a-b.slideCount))*d):(b.slideOffset=-1*b.slideCount%b.options.slidesToScroll*b.slideWidth,e=-1*b.slideCount%b.options.slidesToScroll*d))):a+b.options.slidesToShow>b.slideCount&&(b.slideOffset=(a+b.options.slidesToShow-b.slideCount)*b.slideWidth,e=(a+b.options.slidesToShow-b.slideCount)*d),b.slideCount<=b.options.slidesToShow&&(b.slideOffset=0,e=0),b.options.centerMode===!0&&b.options.infinite===!0?b.slideOffset+=b.slideWidth*Math.floor(b.options.slidesToShow/2)-b.slideWidth:b.options.centerMode===!0&&(b.slideOffset=0,b.slideOffset+=b.slideWidth*Math.floor(b.options.slidesToShow/2)),c=b.options.vertical===!1?-1*a*b.slideWidth+b.slideOffset:-1*a*d+e,b.options.variableWidth===!0&&(g=b.slideCount<=b.options.slidesToShow||b.options.infinite===!1?b.$slideTrack.children(".slick-slide").eq(a):b.$slideTrack.children(".slick-slide").eq(a+b.options.slidesToShow),c=g[0]?-1*g[0].offsetLeft:0,b.options.centerMode===!0&&(g=b.options.infinite===!1?b.$slideTrack.children(".slick-slide").eq(a):b.$slideTrack.children(".slick-slide").eq(a+b.options.slidesToShow+1),c=g[0]?-1*g[0].offsetLeft:0,c+=(b.$list.width()-g.outerWidth())/2)),c},b.prototype.getNavigableIndexes=function(){for(var a=this,b=0,c=0,d=[];b<a.slideCount;)d.push(b),b=c+a.options.slidesToScroll,c+=a.options.slidesToScroll<=a.options.slidesToShow?a.options.slidesToScroll:a.options.slidesToShow;return d},b.prototype.getSlideCount=function(){var c,b=this;if(b.options.swipeToSlide===!0){var d=null;return b.$slideTrack.find(".slick-slide").each(function(c,e){return e.offsetLeft+a(e).outerWidth()/2>-1*b.swipeLeft?(d=e,!1):void 0}),c=Math.abs(a(d).attr("index")-b.currentSlide)}return b.options.slidesToScroll},b.prototype.init=function(){var b=this;a(b.$slider).hasClass("slick-initialized")||(a(b.$slider).addClass("slick-initialized"),b.buildOut(),b.setProps(),b.startLoad(),b.loadSlider(),b.initializeEvents(),b.updateArrows(),b.updateDots()),null!==b.options.onInit&&b.options.onInit.call(this,b)},b.prototype.initArrowEvents=function(){var a=this;a.options.arrows===!0&&a.slideCount>a.options.slidesToShow&&(a.$prevArrow.on("click.slick",{message:"previous"},a.changeSlide),a.$nextArrow.on("click.slick",{message:"next"},a.changeSlide))},b.prototype.initDotEvents=function(){var b=this;b.options.dots===!0&&b.slideCount>b.options.slidesToShow&&a("li",b.$dots).on("click.slick",{message:"index"},b.changeSlide),b.options.dots===!0&&b.options.pauseOnDotsHover===!0&&b.options.autoplay===!0&&a("li",b.$dots).on("mouseenter.slick",function(){b.paused=!0,b.autoPlayClear()}).on("mouseleave.slick",function(){b.paused=!1,b.autoPlay()})},b.prototype.initializeEvents=function(){var b=this;b.initArrowEvents(),b.initDotEvents(),b.$list.on("touchstart.slick mousedown.slick",{action:"start"},b.swipeHandler),b.$list.on("touchmove.slick mousemove.slick",{action:"move"},b.swipeHandler),b.$list.on("touchend.slick mouseup.slick",{action:"end"},b.swipeHandler),b.$list.on("touchcancel.slick mouseleave.slick",{action:"end"},b.swipeHandler),b.$list.on("click.slick",b.clickHandler),b.options.pauseOnHover===!0&&b.options.autoplay===!0&&(b.$list.on("mouseenter.slick",function(){b.paused=!0,b.autoPlayClear()}),b.$list.on("mouseleave.slick",function(){b.paused=!1,b.autoPlay()})),b.options.accessibility===!0&&b.$list.on("keydown.slick",b.keyHandler),b.options.focusOnSelect===!0&&a(b.options.slide,b.$slideTrack).on("click.slick",b.selectHandler),a(window).on("orientationchange.slick.slick-"+b.instanceUid,function(){b.checkResponsive(),b.setPosition()}),a(window).on("resize.slick.slick-"+b.instanceUid,function(){a(window).width()!==b.windowWidth&&(clearTimeout(b.windowDelay),b.windowDelay=window.setTimeout(function(){b.windowWidth=a(window).width(),b.checkResponsive(),b.setPosition()},50))}),a("*[draggable!=true]",b.$slideTrack).on("dragstart",function(a){a.preventDefault()}),a(window).on("load.slick.slick-"+b.instanceUid,b.setPosition),a(document).on("ready.slick.slick-"+b.instanceUid,b.setPosition)},b.prototype.initUI=function(){var a=this;a.options.arrows===!0&&a.slideCount>a.options.slidesToShow&&(a.$prevArrow.show(),a.$nextArrow.show()),a.options.dots===!0&&a.slideCount>a.options.slidesToShow&&a.$dots.show(),a.options.autoplay===!0&&a.autoPlay()},b.prototype.keyHandler=function(a){var b=this;37===a.keyCode&&b.options.accessibility===!0?b.changeSlide({data:{message:"previous"}}):39===a.keyCode&&b.options.accessibility===!0&&b.changeSlide({data:{message:"next"}})},b.prototype.lazyLoad=function(){function g(b){a("img[data-lazy]",b).each(function(){var b=a(this),c=a(this).attr("data-lazy");b.load(function(){b.animate({opacity:1},200)}).css({opacity:0}).attr("src",c).removeAttr("data-lazy").removeClass("slick-loading")})}var c,d,e,f,b=this;b.options.centerMode===!0?b.options.infinite===!0?(e=b.currentSlide+(b.options.slidesToShow/2+1),f=e+b.options.slidesToShow+2):(e=Math.max(0,b.currentSlide-(b.options.slidesToShow/2+1)),f=2+(b.options.slidesToShow/2+1)+b.currentSlide):(e=b.options.infinite?b.options.slidesToShow+b.currentSlide:b.currentSlide,f=e+b.options.slidesToShow,b.options.fade===!0&&(e>0&&e--,f<=b.slideCount&&f++)),c=b.$slider.find(".slick-slide").slice(e,f),g(c),b.slideCount<=b.options.slidesToShow?(d=b.$slider.find(".slick-slide"),g(d)):b.currentSlide>=b.slideCount-b.options.slidesToShow?(d=b.$slider.find(".slick-cloned").slice(0,b.options.slidesToShow),g(d)):0===b.currentSlide&&(d=b.$slider.find(".slick-cloned").slice(-1*b.options.slidesToShow),g(d))},b.prototype.loadSlider=function(){var a=this;a.setPosition(),a.$slideTrack.css({opacity:1}),a.$slider.removeClass("slick-loading"),a.initUI(),"progressive"===a.options.lazyLoad&&a.progressiveLazyLoad()},b.prototype.postSlide=function(a){var b=this;null!==b.options.onAfterChange&&b.options.onAfterChange.call(this,b,a),b.animating=!1,b.setPosition(),b.swipeLeft=null,b.options.autoplay===!0&&b.paused===!1&&b.autoPlay()},b.prototype.progressiveLazyLoad=function(){var c,d,b=this;c=a("img[data-lazy]",b.$slider).length,c>0&&(d=a("img[data-lazy]",b.$slider).first(),d.attr("src",d.attr("data-lazy")).removeClass("slick-loading").load(function(){d.removeAttr("data-lazy"),b.progressiveLazyLoad()}).error(function(){d.removeAttr("data-lazy"),b.progressiveLazyLoad()}))},b.prototype.refresh=function(){var b=this,c=b.currentSlide;b.destroy(),a.extend(b,b.initials),b.init(),b.changeSlide({data:{message:"index",index:c}},!0)},b.prototype.reinit=function(){var b=this;b.$slides=b.$slideTrack.children(b.options.slide).addClass("slick-slide"),b.slideCount=b.$slides.length,b.currentSlide>=b.slideCount&&0!==b.currentSlide&&(b.currentSlide=b.currentSlide-b.options.slidesToScroll),b.slideCount<=b.options.slidesToShow&&(b.currentSlide=0),b.setProps(),b.setupInfinite(),b.buildArrows(),b.updateArrows(),b.initArrowEvents(),b.buildDots(),b.updateDots(),b.initDotEvents(),b.options.focusOnSelect===!0&&a(b.options.slide,b.$slideTrack).on("click.slick",b.selectHandler),b.setSlideClasses(0),b.setPosition(),null!==b.options.onReInit&&b.options.onReInit.call(this,b)},b.prototype.removeSlide=function(a,b,c){var d=this;return"boolean"==typeof a?(b=a,a=b===!0?0:d.slideCount-1):a=b===!0?--a:a,d.slideCount<1||0>a||a>d.slideCount-1?!1:(d.unload(),c===!0?d.$slideTrack.children().remove():d.$slideTrack.children(this.options.slide).eq(a).remove(),d.$slides=d.$slideTrack.children(this.options.slide),d.$slideTrack.children(this.options.slide).detach(),d.$slideTrack.append(d.$slides),d.$slidesCache=d.$slides,d.reinit(),void 0)},b.prototype.setCSS=function(a){var d,e,b=this,c={};b.options.rtl===!0&&(a=-a),d="left"==b.positionProp?a+"px":"0px",e="top"==b.positionProp?a+"px":"0px",c[b.positionProp]=a,b.transformsEnabled===!1?b.$slideTrack.css(c):(c={},b.cssTransitions===!1?(c[b.animType]="translate("+d+", "+e+")",b.$slideTrack.css(c)):(c[b.animType]="translate3d("+d+", "+e+", 0px)",b.$slideTrack.css(c)))},b.prototype.setDimensions=function(){var b=this;if(b.options.vertical===!1?b.options.centerMode===!0&&b.$list.css({padding:"0px "+b.options.centerPadding}):(b.$list.height(b.$slides.first().outerHeight(!0)*b.options.slidesToShow),b.options.centerMode===!0&&b.$list.css({padding:b.options.centerPadding+" 0px"})),b.listWidth=b.$list.width(),b.listHeight=b.$list.height(),b.options.vertical===!1&&b.options.variableWidth===!1)b.slideWidth=Math.ceil(b.listWidth/b.options.slidesToShow),b.$slideTrack.width(Math.ceil(b.slideWidth*b.$slideTrack.children(".slick-slide").length));else if(b.options.variableWidth===!0){var c=0;b.slideWidth=Math.ceil(b.listWidth/b.options.slidesToShow),b.$slideTrack.children(".slick-slide").each(function(){c+=Math.ceil(a(this).outerWidth(!0))}),b.$slideTrack.width(Math.ceil(c)+1)}else b.slideWidth=Math.ceil(b.listWidth),b.$slideTrack.height(Math.ceil(b.$slides.first().outerHeight(!0)*b.$slideTrack.children(".slick-slide").length));var d=b.$slides.first().outerWidth(!0)-b.$slides.first().width();b.options.variableWidth===!1&&b.$slideTrack.children(".slick-slide").width(b.slideWidth-d)},b.prototype.setFade=function(){var c,b=this;b.$slides.each(function(d,e){c=-1*b.slideWidth*d,b.options.rtl===!0?a(e).css({position:"relative",right:c,top:0,zIndex:800,opacity:0}):a(e).css({position:"relative",left:c,top:0,zIndex:800,opacity:0})}),b.$slides.eq(b.currentSlide).css({zIndex:900,opacity:1})},b.prototype.setHeight=function(){var a=this;if(1===a.options.slidesToShow&&a.options.adaptiveHeight===!0&&a.options.vertical===!1){var b=a.$slides.eq(a.currentSlide).outerHeight(!0);a.$list.css("height",b)}},b.prototype.setPosition=function(){var a=this;a.setDimensions(),a.setHeight(),a.options.fade===!1?a.setCSS(a.getLeft(a.currentSlide)):a.setFade(),null!==a.options.onSetPosition&&a.options.onSetPosition.call(this,a)},b.prototype.setProps=function(){var a=this,b=document.body.style;a.positionProp=a.options.vertical===!0?"top":"left","top"===a.positionProp?a.$slider.addClass("slick-vertical"):a.$slider.removeClass("slick-vertical"),(void 0!==b.WebkitTransition||void 0!==b.MozTransition||void 0!==b.msTransition)&&a.options.useCSS===!0&&(a.cssTransitions=!0),void 0!==b.OTransform&&(a.animType="OTransform",a.transformType="-o-transform",a.transitionType="OTransition",void 0===b.perspectiveProperty&&void 0===b.webkitPerspective&&(a.animType=!1)),void 0!==b.MozTransform&&(a.animType="MozTransform",a.transformType="-moz-transform",a.transitionType="MozTransition",void 0===b.perspectiveProperty&&void 0===b.MozPerspective&&(a.animType=!1)),void 0!==b.webkitTransform&&(a.animType="webkitTransform",a.transformType="-webkit-transform",a.transitionType="webkitTransition",void 0===b.perspectiveProperty&&void 0===b.webkitPerspective&&(a.animType=!1)),void 0!==b.msTransform&&(a.animType="msTransform",a.transformType="-ms-transform",a.transitionType="msTransition",void 0===b.msTransform&&(a.animType=!1)),void 0!==b.transform&&a.animType!==!1&&(a.animType="transform",a.transformType="transform",a.transitionType="transition"),a.transformsEnabled=null!==a.animType&&a.animType!==!1},b.prototype.setSlideClasses=function(a){var c,d,e,f,b=this;b.$slider.find(".slick-slide").removeClass("slick-active").removeClass("slick-center"),d=b.$slider.find(".slick-slide"),b.options.centerMode===!0?(c=Math.floor(b.options.slidesToShow/2),b.options.infinite===!0&&(a>=c&&a<=b.slideCount-1-c?b.$slides.slice(a-c,a+c+1).addClass("slick-active"):(e=b.options.slidesToShow+a,d.slice(e-c+1,e+c+2).addClass("slick-active")),0===a?d.eq(d.length-1-b.options.slidesToShow).addClass("slick-center"):a===b.slideCount-1&&d.eq(b.options.slidesToShow).addClass("slick-center")),b.$slides.eq(a).addClass("slick-center")):a>=0&&a<=b.slideCount-b.options.slidesToShow?b.$slides.slice(a,a+b.options.slidesToShow).addClass("slick-active"):d.length<=b.options.slidesToShow?d.addClass("slick-active"):(f=b.slideCount%b.options.slidesToShow,e=b.options.infinite===!0?b.options.slidesToShow+a:a,b.options.slidesToShow==b.options.slidesToScroll&&b.slideCount-a<b.options.slidesToShow?d.slice(e-(b.options.slidesToShow-f),e+f).addClass("slick-active"):d.slice(e,e+b.options.slidesToShow).addClass("slick-active")),"ondemand"===b.options.lazyLoad&&b.lazyLoad()},b.prototype.setupInfinite=function(){var c,d,e,b=this;if(b.options.fade===!0&&(b.options.centerMode=!1),b.options.infinite===!0&&b.options.fade===!1&&(d=null,b.slideCount>b.options.slidesToShow)){for(e=b.options.centerMode===!0?b.options.slidesToShow+1:b.options.slidesToShow,c=b.slideCount;c>b.slideCount-e;c-=1)d=c-1,a(b.$slides[d]).clone(!0).attr("id","").attr("index",d-b.slideCount).prependTo(b.$slideTrack).addClass("slick-cloned");for(c=0;e>c;c+=1)d=c,a(b.$slides[d]).clone(!0).attr("id","").attr("index",d+b.slideCount).appendTo(b.$slideTrack).addClass("slick-cloned");b.$slideTrack.find(".slick-cloned").find("[id]").each(function(){a(this).attr("id","")})}},b.prototype.selectHandler=function(b){var c=this,d=parseInt(a(b.target).parents(".slick-slide").attr("index"));return d||(d=0),c.slideCount<=c.options.slidesToShow?(c.$slider.find(".slick-slide").removeClass("slick-active"),c.$slides.eq(d).addClass("slick-active"),c.options.centerMode===!0&&(c.$slider.find(".slick-slide").removeClass("slick-center"),c.$slides.eq(d).addClass("slick-center")),c.asNavFor(d),void 0):(c.slideHandler(d),void 0)},b.prototype.slideHandler=function(a,b,c){var d,e,f,g,i=null,j=this;return b=b||!1,j.animating===!0&&j.options.waitForAnimate===!0||j.options.fade===!0&&j.currentSlide===a||j.slideCount<=j.options.slidesToShow?void 0:(b===!1&&j.asNavFor(a),d=a,i=j.getLeft(d),g=j.getLeft(j.currentSlide),j.currentLeft=null===j.swipeLeft?g:j.swipeLeft,j.options.infinite===!1&&j.options.centerMode===!1&&(0>a||a>j.getDotCount()*j.options.slidesToScroll)?(j.options.fade===!1&&(d=j.currentSlide,c!==!0?j.animateSlide(g,function(){j.postSlide(d)}):j.postSlide(d)),void 0):j.options.infinite===!1&&j.options.centerMode===!0&&(0>a||a>j.slideCount-j.options.slidesToScroll)?(j.options.fade===!1&&(d=j.currentSlide,c!==!0?j.animateSlide(g,function(){j.postSlide(d)}):j.postSlide(d)),void 0):(j.options.autoplay===!0&&clearInterval(j.autoPlayTimer),e=0>d?0!==j.slideCount%j.options.slidesToScroll?j.slideCount-j.slideCount%j.options.slidesToScroll:j.slideCount+d:d>=j.slideCount?0!==j.slideCount%j.options.slidesToScroll?0:d-j.slideCount:d,j.animating=!0,null!==j.options.onBeforeChange&&a!==j.currentSlide&&j.options.onBeforeChange.call(this,j,j.currentSlide,e),f=j.currentSlide,j.currentSlide=e,j.setSlideClasses(j.currentSlide),j.updateDots(),j.updateArrows(),j.options.fade===!0?(c!==!0?j.fadeSlide(f,e,function(){j.postSlide(e)}):j.postSlide(e),void 0):(c!==!0?j.animateSlide(i,function(){j.postSlide(e)}):j.postSlide(e),void 0)))},b.prototype.startLoad=function(){var a=this;a.options.arrows===!0&&a.slideCount>a.options.slidesToShow&&(a.$prevArrow.hide(),a.$nextArrow.hide()),a.options.dots===!0&&a.slideCount>a.options.slidesToShow&&a.$dots.hide(),a.$slider.addClass("slick-loading")},b.prototype.swipeDirection=function(){var a,b,c,d,e=this;return a=e.touchObject.startX-e.touchObject.curX,b=e.touchObject.startY-e.touchObject.curY,c=Math.atan2(b,a),d=Math.round(180*c/Math.PI),0>d&&(d=360-Math.abs(d)),45>=d&&d>=0?e.options.rtl===!1?"left":"right":360>=d&&d>=315?e.options.rtl===!1?"left":"right":d>=135&&225>=d?e.options.rtl===!1?"right":"left":"vertical"},b.prototype.swipeEnd=function(){var b=this;if(b.dragging=!1,b.shouldClick=b.touchObject.swipeLength>10?!1:!0,void 0===b.touchObject.curX)return!1;if(b.touchObject.swipeLength>=b.touchObject.minSwipe)switch(b.swipeDirection()){case"left":b.slideHandler(b.currentSlide+b.getSlideCount()),b.currentDirection=0,b.touchObject={};break;case"right":b.slideHandler(b.currentSlide-b.getSlideCount()),b.currentDirection=1,b.touchObject={}}else b.touchObject.startX!==b.touchObject.curX&&(b.slideHandler(b.currentSlide),b.touchObject={})},b.prototype.swipeHandler=function(a){var b=this;if(!(b.options.swipe===!1||"ontouchend"in document&&b.options.swipe===!1||b.options.draggable===!1&&-1!==a.type.indexOf("mouse")))switch(b.touchObject.fingerCount=a.originalEvent&&void 0!==a.originalEvent.touches?a.originalEvent.touches.length:1,b.touchObject.minSwipe=b.listWidth/b.options.touchThreshold,a.data.action){case"start":b.swipeStart(a);break;case"move":b.swipeMove(a);break;case"end":b.swipeEnd(a)}},b.prototype.swipeMove=function(a){var c,d,e,f,b=this;return f=void 0!==a.originalEvent?a.originalEvent.touches:null,!b.dragging||f&&1!==f.length?!1:(c=b.getLeft(b.currentSlide),b.touchObject.curX=void 0!==f?f[0].pageX:a.clientX,b.touchObject.curY=void 0!==f?f[0].pageY:a.clientY,b.touchObject.swipeLength=Math.round(Math.sqrt(Math.pow(b.touchObject.curX-b.touchObject.startX,2))),d=b.swipeDirection(),"vertical"!==d?(void 0!==a.originalEvent&&b.touchObject.swipeLength>4&&a.preventDefault(),e=(b.options.rtl===!1?1:-1)*(b.touchObject.curX>b.touchObject.startX?1:-1),b.swipeLeft=b.options.vertical===!1?c+b.touchObject.swipeLength*e:c+b.touchObject.swipeLength*(b.$list.height()/b.listWidth)*e,b.options.fade===!0||b.options.touchMove===!1?!1:b.animating===!0?(b.swipeLeft=null,!1):(b.setCSS(b.swipeLeft),void 0)):void 0)},b.prototype.swipeStart=function(a){var c,b=this;return 1!==b.touchObject.fingerCount||b.slideCount<=b.options.slidesToShow?(b.touchObject={},!1):(void 0!==a.originalEvent&&void 0!==a.originalEvent.touches&&(c=a.originalEvent.touches[0]),b.touchObject.startX=b.touchObject.curX=void 0!==c?c.pageX:a.clientX,b.touchObject.startY=b.touchObject.curY=void 0!==c?c.pageY:a.clientY,b.dragging=!0,void 0)},b.prototype.unfilterSlides=function(){var a=this;null!==a.$slidesCache&&(a.unload(),a.$slideTrack.children(this.options.slide).detach(),a.$slidesCache.appendTo(a.$slideTrack),a.reinit())},b.prototype.unload=function(){var b=this;a(".slick-cloned",b.$slider).remove(),b.$dots&&b.$dots.remove(),b.$prevArrow&&"object"!=typeof b.options.prevArrow&&b.$prevArrow.remove(),b.$nextArrow&&"object"!=typeof b.options.nextArrow&&b.$nextArrow.remove(),b.$slides.removeClass("slick-slide slick-active slick-visible").css("width","")},b.prototype.updateArrows=function(){var b,a=this;b=Math.floor(a.options.slidesToShow/2),a.options.arrows===!0&&a.options.infinite!==!0&&a.slideCount>a.options.slidesToShow&&(a.$prevArrow.removeClass("slick-disabled"),a.$nextArrow.removeClass("slick-disabled"),0===a.currentSlide?(a.$prevArrow.addClass("slick-disabled"),a.$nextArrow.removeClass("slick-disabled")):a.currentSlide>=a.slideCount-a.options.slidesToShow&&a.options.centerMode===!1?(a.$nextArrow.addClass("slick-disabled"),a.$prevArrow.removeClass("slick-disabled")):a.currentSlide>a.slideCount-a.options.slidesToShow+b&&a.options.centerMode===!0&&(a.$nextArrow.addClass("slick-disabled"),a.$prevArrow.removeClass("slick-disabled")))},b.prototype.updateDots=function(){var a=this;null!==a.$dots&&(a.$dots.find("li").removeClass("slick-active"),a.$dots.find("li").eq(Math.floor(a.currentSlide/a.options.slidesToScroll)).addClass("slick-active"))},a.fn.slick=function(a){var c=this;return c.each(function(c,d){d.slick=new b(d,a)})},a.fn.slickAdd=function(a,b,c){var d=this;return d.each(function(d,e){e.slick.addSlide(a,b,c)})},a.fn.slickCurrentSlide=function(){var a=this;return a.get(0).slick.getCurrent()},a.fn.slickFilter=function(a){var b=this;return b.each(function(b,c){c.slick.filterSlides(a)})},a.fn.slickGoTo=function(a,b){var c=this;return c.each(function(c,d){d.slick.changeSlide({data:{message:"index",index:parseInt(a)}},b)})},a.fn.slickNext=function(){var a=this;return a.each(function(a,b){b.slick.changeSlide({data:{message:"next"}})})},a.fn.slickPause=function(){var a=this;return a.each(function(a,b){b.slick.autoPlayClear(),b.slick.paused=!0})},a.fn.slickPlay=function(){var a=this;return a.each(function(a,b){b.slick.paused=!1,b.slick.autoPlay()})},a.fn.slickPrev=function(){var a=this;return a.each(function(a,b){b.slick.changeSlide({data:{message:"previous"}})})},a.fn.slickRemove=function(a,b){var c=this;return c.each(function(c,d){d.slick.removeSlide(a,b)})},a.fn.slickRemoveAll=function(){var a=this;return a.each(function(a,b){b.slick.removeSlide(null,null,!0)})},a.fn.slickGetOption=function(a){var b=this;return b.get(0).slick.options[a]},a.fn.slickSetOption=function(a,b,c){var d=this;return d.each(function(d,e){e.slick.options[a]=b,c===!0&&(e.slick.unload(),e.slick.reinit())})},a.fn.slickUnfilter=function(){var a=this;return a.each(function(a,b){b.slick.unfilterSlides()})},a.fn.unslick=function(){var a=this;return a.each(function(a,b){b.slick&&b.slick.destroy()})},a.fn.getSlick=function(){var a=null,b=this;return b.each(function(b,c){a=c.slick}),a}});
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/Auth/AbstractBase/login.phtml b/themes/jquerymobile/templates/Auth/AbstractBase/login.phtml
deleted file mode 100644
index cdb07cf53e6811a9f4b7dbf011b2859ab767126c..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/Auth/AbstractBase/login.phtml
+++ /dev/null
@@ -1,24 +0,0 @@
-<? $account = $this->auth()->getManager(); ?>
-<h3><?=$this->transEsc('Login')?></h3>
-<?=$this->flashmessages()?>
-<? $sessionInitiator = $account->getSessionInitiator($this->serverUrl($this->url('myresearch-home'))); ?>
-<? if (!$sessionInitiator): // display default login form if no login URL provided ?>
-  <form method="post" action="<?=$this->url('myresearch-home')?>" name="loginForm" data-ajax="false">
-    <input type="hidden" name="auth_method" value="<?=$account->getAuthMethod()?>" />
-    <input type="hidden" name="csrf" value="<?=$this->escapeHtmlAttr($account->getCsrfHash(true))?>" />
-    <div data-role="fieldcontain">
-      <?=$this->auth()->getLoginFields()?>
-    </div>
-    <div data-role="fieldcontain">
-      <input type="submit" name="processLogin" value="<?=$this->transEsc('Login')?>"/>
-    </div>
-  </form>
-  <? if ($account->supportsCreation()): ?>
-    <a rel="external" data-role="button" class="new_account" href="<?=$this->url('myresearch-account')?>?auth_method=<?=$account->getAuthMethod()?>"><?=$this->transEsc('Create New Account')?></a>
-  <? endif; ?>
-  <? if ($account->supportsRecovery()): ?>
-    <a rel="external" data-role="button" class="recover_password" href="<?=$this->url('myresearch-recover')?>?auth_method=<?=$account->getAuthMethod()?>"><?=$this->transEsc('Forgot Password')?></a>
-  <? endif; ?>
-<? else: ?>
-  <a rel="external" data-role="button" href="<?=$this->escapeHtmlAttr($sessionInitiator)?>"><?=$this->transEsc("Institutional Login")?></a>
-<? endif; ?>
diff --git a/themes/jquerymobile/templates/Auth/AbstractBase/logindesc.phtml b/themes/jquerymobile/templates/Auth/AbstractBase/logindesc.phtml
deleted file mode 100644
index 9f4088f8d270f09bc536fa26d8dd35282a49294a..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/Auth/AbstractBase/logindesc.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<h3><?=$this->transEsc('Login')?></h3>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/Auth/AbstractBase/loginfields.phtml b/themes/jquerymobile/templates/Auth/AbstractBase/loginfields.phtml
deleted file mode 100644
index 104268d728c1fbd82e1e871ae11738175c82f4d5..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/Auth/AbstractBase/loginfields.phtml
+++ /dev/null
@@ -1,4 +0,0 @@
-<label for="login_<?=$this->escapeHtmlAttr($topClass)?>_username"><?=$this->transEsc('Username')?>:</label>
-<input id="login_<?=$this->escapeHtmlAttr($topClass)?>_username" type="text" name="username" value="<?=$this->escapeHtmlAttr($this->request->get('username'))?>"/>
-<label for="login_<?=$this->escapeHtmlAttr($topClass)?>_password"><?=$this->transEsc('Password')?>:</label>
-<input id="login_<?=$this->escapeHtmlAttr($topClass)?>_password" type="password" name="password"/>
diff --git a/themes/jquerymobile/templates/Auth/AbstractBase/newpassword.phtml b/themes/jquerymobile/templates/Auth/AbstractBase/newpassword.phtml
deleted file mode 100644
index 62dd2c42cb21ba05a2d3967caaa95addbfbe1c3f..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/Auth/AbstractBase/newpassword.phtml
+++ /dev/null
@@ -1,18 +0,0 @@
-<div data-role="fieldcontain" class="ui-field-contain ui-body ui-br">
-  <? if (isset($this->username)): ?>
-    <input type="hidden" name="username" value="<?=$this->username ?>"/>
-    <label class="ui-input-text"><?=$this->transEsc('Username') ?>:</label>
-    <input type="text" name="username" id="username" value="<?=$this->username ?>" disabled class="ui-input-text ui-body-c ui-corner-all ui-shadow-inset" style="border:1px solid #CCC;box-shadow:rgba(0, 0, 0, 0.1) 0px 1px 4px 0px inset;color:#777"/><br/>
-  <? endif; ?>
-  <? if (isset($this->verifyold) && $this->verifyold || isset($this->oldpwd)): ?>
-    <label for="oldpwd" class="ui-input-text"><?=$this->transEsc('old_password') ?>:</label>
-    <input type="password" name="oldpwd" id="oldpwd" class="ui-input-text ui-body-c ui-corner-all ui-shadow-inset"/><br/>
-  <? endif; ?>
-  <label for="password" class="ui-input-text"><?=$this->transEsc('new_password') ?>:</label>
-  <input type="password" name="password" id="password" class="ui-input-text ui-body-c ui-corner-all ui-shadow-inset"/><br/>
-  <? if ($this->passwordPolicy['hint']): ?>
-    <p><?=$this->transEsc($this->passwordPolicy['hint']) ?></p>
-  <? endif; ?>
-  <label for="password2" class="ui-input-text"><?=$this->transEsc('confirm_new_password') ?>:</label>
-  <input type="password" name="password2" id="password2" class="ui-input-text ui-body-c ui-corner-all ui-shadow-inset"/><br/>
-</div>
diff --git a/themes/jquerymobile/templates/Auth/CAS/logindesc.phtml b/themes/jquerymobile/templates/Auth/CAS/logindesc.phtml
deleted file mode 100644
index fab51a92a722fa166127618844ea2ac4bdf3c765..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/Auth/CAS/logindesc.phtml
+++ /dev/null
@@ -1,2 +0,0 @@
-<h3><?=$this->transEsc('Institutional Login')?></h3>
-<p><?=$this->transEsc('institutional_login_desc')?></p>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/Auth/ChoiceAuth/login.phtml b/themes/jquerymobile/templates/Auth/ChoiceAuth/login.phtml
deleted file mode 100644
index b4482128d3e9295f047b37118a3763b873c92538..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/Auth/ChoiceAuth/login.phtml
+++ /dev/null
@@ -1,12 +0,0 @@
-<p><?=$this->transEsc('choose_login_method')?></p>
-<div id="authcontainer">
-<? foreach ($this->auth()->getManager()->getSelectableAuthOptions() as $loop=>$method):?>
-  <div class="authmethod<?=$loop?>">
-    <? $this->auth()->getManager()->setAuthMethod($method) ?>
-    <?=$this->auth()->getLoginDesc() ?>
-    <?=$this->auth()->getLogin() ?>
-  </div>
-<? endforeach ?>
-</div>
-<div class="clearer"></div>
-<? $this->auth()->getManager()->setAuthMethod('ChoiceAuth') ?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/Auth/Database/create.phtml b/themes/jquerymobile/templates/Auth/Database/create.phtml
deleted file mode 100644
index ab79ddce8c52a9931abf43eaedbbd6907a45e50a..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/Auth/Database/create.phtml
+++ /dev/null
@@ -1,15 +0,0 @@
-<label for="account_firstname"><?=$this->transEsc('First Name')?>:</label>
-<input id="account_firstname" type="text" name="firstname" value="<?=$this->escapeHtmlAttr($this->request->get('firstname'))?>" />
-<label for="account_lastname"><?=$this->transEsc('Last Name')?>:</label>
-<input id="account_lastname" type="text" name="lastname" value="<?=$this->escapeHtmlAttr($this->request->get('lastname'))?>" />
-<label for="account_email"><?=$this->transEsc('Email Address')?>:</label>
-<input id="account_email" type="text" name="email" value="<?=$this->escapeHtmlAttr($this->request->get('email'))?>" />
-<label for="account_username"><?=$this->transEsc('Desired Username')?>:</label>
-<input id="account_username" type="text" name="username" value="<?=$this->escapeHtmlAttr($this->request->get('username'))?>" />
-<label for="account_password"><?=$this->transEsc('Password')?>:</label>
-<input id="account_password" type="password" name="password" />
-<? if ($this->passwordPolicy['hint']): ?>
-  <p><?=$this->transEsc($this->passwordPolicy['hint']) ?></p>
-<? endif; ?>
-<label for="account_password2"><?=$this->transEsc('Password Again')?>:</label>
-<input id="account_password2" type="password" name="password2" />
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/Auth/Database/logindesc.phtml b/themes/jquerymobile/templates/Auth/Database/logindesc.phtml
deleted file mode 100644
index 10d39c2498b61e3e4b59cd9f9283eb0b6e3d1b34..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/Auth/Database/logindesc.phtml
+++ /dev/null
@@ -1,2 +0,0 @@
-<h3><?=$this->transEsc('Local Login')?></h3>
-<p><?=$this->transEsc('local_login_desc')?></p>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/Auth/Database/recovery.phtml b/themes/jquerymobile/templates/Auth/Database/recovery.phtml
deleted file mode 100644
index ec53cae7c0aeecf12e98c970ed0641d3b5218ce0..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/Auth/Database/recovery.phtml
+++ /dev/null
@@ -1,11 +0,0 @@
-<div data-role="fieldcontain">
-  <label for="username"><?=$this->transEsc('recovery_by_username') ?>:</label>
-  <input type="text" id="username" name="username" style="margin-top:.5em;height:28px"/>
-</div>
-<div style="text-align:center"><?=$this->translate('conjunction_or') ?></div>
-<div data-role="fieldcontain">
-  <label for="email"><?=$this->transEsc('recovery_by_email') ?>:</label>
-  <input type="email" id="email" name="email" style="margin-top:.5em;height:28px"/>
-</div>
-<?=$this->recaptcha()->html($this->useRecaptcha) ?>
-<input type="submit" name="submit" value="<?=$this->transEsc('Recover Account') ?>"/>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/Auth/ILS/logindesc.phtml b/themes/jquerymobile/templates/Auth/ILS/logindesc.phtml
deleted file mode 100644
index 73ac1374e787e6fcedcf9ed95a8293f66808ea10..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/Auth/ILS/logindesc.phtml
+++ /dev/null
@@ -1,2 +0,0 @@
-<h3><?=$this->transEsc('Catalog Login')?></h3>
-<p><?=$this->transEsc('catalog_login_desc')?></p>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/Auth/LDAP/logindesc.phtml b/themes/jquerymobile/templates/Auth/LDAP/logindesc.phtml
deleted file mode 100644
index fab51a92a722fa166127618844ea2ac4bdf3c765..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/Auth/LDAP/logindesc.phtml
+++ /dev/null
@@ -1,2 +0,0 @@
-<h3><?=$this->transEsc('Institutional Login')?></h3>
-<p><?=$this->transEsc('institutional_login_desc')?></p>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/Auth/MultiILS/loginfields.phtml b/themes/jquerymobile/templates/Auth/MultiILS/loginfields.phtml
deleted file mode 100644
index a49842249df933d3fe5d378fe3c71ed273cdddfd..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/Auth/MultiILS/loginfields.phtml
+++ /dev/null
@@ -1,11 +0,0 @@
-<label for="login_target"><?=$this->transEsc('login_target')?>:</label>
-<?$currentTarget = $this->request->get('target'); if (!$currentTarget) $currentTarget = $this->auth()->getManager()->getDefaultLoginTarget();?>
-<select id="login_target" name="target">
-  <?foreach ($this->auth()->getManager()->getLoginTargets() as $target):?>
-  <option value="<?=$this->escapeHtmlAttr($target)?>"<?=($target == $currentTarget ? ' selected="selected"' : '')?>><?=$this->transEsc("source_$target", null, $target)?></option>
-  <? endforeach ?>
-</select>
-<label for="login_<?=$this->escapeHtmlAttr($topClass)?>_username"><?=$this->transEsc('Username')?>:</label>
-<input id="login_<?=$this->escapeHtmlAttr($topClass)?>_username" type="text" name="username" value="<?=$this->escapeHtmlAttr($this->request->get('username'))?>"/>
-<label for="login_<?=$this->escapeHtmlAttr($topClass)?>_password"><?=$this->transEsc('Password')?>:</label>
-<input id="login_<?=$this->escapeHtmlAttr($topClass)?>_password" type="password" name="password"/>
diff --git a/themes/jquerymobile/templates/Auth/Shibboleth/logindesc.phtml b/themes/jquerymobile/templates/Auth/Shibboleth/logindesc.phtml
deleted file mode 100644
index fab51a92a722fa166127618844ea2ac4bdf3c765..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/Auth/Shibboleth/logindesc.phtml
+++ /dev/null
@@ -1,2 +0,0 @@
-<h3><?=$this->transEsc('Institutional Login')?></h3>
-<p><?=$this->transEsc('institutional_login_desc')?></p>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/Helpers/email-form-fields.phtml b/themes/jquerymobile/templates/Helpers/email-form-fields.phtml
deleted file mode 100644
index 0d5586d46ceb987b6c5f0e17a3abc87d697d769d..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/Helpers/email-form-fields.phtml
+++ /dev/null
@@ -1,30 +0,0 @@
-<div data-role="fieldcontain">
-  <? $toValidations = ($this->maxRecipients == 1) ? array('required'=>'This field is required', 'email'=>'Email address is invalid') : array('required'=>'This field is required')?>
-  <label for="email_to"><?=$this->transEsc('To')?>:</label>
-  <input id="email_to" type="text" name="to" value="<?=isset($this->to) ? $this->to : ''?>" size="40" class="mainFocus <?=$this->jqueryValidation($toValidations)?>"/>
-  <? if ($this->maxRecipients != 1): ?>
-    <p style="text-align: right;">
-      <?=$this->transEsc('email_multiple_recipients_note')?>
-      <? if ($this->maxRecipients > 1): ?>
-        <?=$this->transEsc('email_maximum_recipients_note', array('%%max%%' => $this->maxRecipients))?>
-      <? endif; ?>
-    </p>
-  <? endif; ?>
-  <? if (!$this->disableFrom): ?>
-    <label for="email_from"><?=$this->transEsc('From')?>:</label>
-    <input id="email_from" type="text" name="from" value="<?=isset($this->from) ? $this->from : ''?>" size="40" class="<?=$this->jqueryValidation(array('required'=>'This field is required', 'email'=>'Email address is invalid'))?>"/>
-  <? endif; ?>
-  <? if ($this->editableSubject): ?>
-    <label for="email_subject"><?=$this->transEsc('email_subject')?>:</label>
-    <input id="email_subject" type="text" name="subject" value="<?=isset($this->subject) ? $this->subject : ''?>" size="40" class="<?=$this->jqueryValidation(array('required'=>'This field is required'))?>"/>
-  <? endif; ?>
-  <label for="email_message"><?=$this->transEsc('Message')?>:</label>
-  <textarea id="email_message" name="message"><?=isset($this->message) ? $this->message : ''?></textarea>
-</div>
-<?=$this->recaptcha()->html($this->useRecaptcha) ?>
-<div data-role="fieldcontain">
-  <input class="button" type="submit" name="submit" value="<?=$this->transEsc('Send')?>"/>
-</div>
-<? if ($this->disableFrom && $this->userEmailInFrom): ?>
-  <input type="checkbox" id="ccme" name="ccself"/><label for="ccme"><?=$this->translate('send_email_copy_to_me'); ?></label>
-<? endif; ?>
diff --git a/themes/jquerymobile/templates/Helpers/openurl.phtml b/themes/jquerymobile/templates/Helpers/openurl.phtml
deleted file mode 100644
index 48267456b53f95c89ee6e1bbee5da0a4318c7279..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/Helpers/openurl.phtml
+++ /dev/null
@@ -1,25 +0,0 @@
-<? if (!$this->openUrlImageBasedSrc || $this->openUrlImageBasedMode == 'both'): ?>
-  <a rel="external" href="<?=$this->escapeHtmlAttr($this->openUrlBase . '?' . $this->openUrl)?>">
-    <? if ($this->openUrlGraphic): ?>
-      <?
-          $style = '';
-          if ($this->openUrlGraphicWidth) {
-              $style .= 'width:' . $this->escapeHtmlAttr($this->openUrlGraphicWidth) . 'px;';
-          }
-          if ($this->openUrlGraphicHeight) {
-              $style .= 'height:' . $this->escapeHtmlAttr($this->openUrlGraphicHeight) . 'px;';
-          }
-      ?>
-      <img src="<?=$this->escapeHtmlAttr($this->openUrlGraphic)?>" alt="<?=$this->transEsc('Get full text')?>" style="<?=$style?>" />
-    <? else: ?>
-      <?=$this->transEsc('Get full text')?>
-    <? endif; ?>
-  </a>
-<? endif; ?>
-
-<? if ($this->openUrlImageBasedSrc): ?>
-  <? $ibOpenUrl = $this->openUrlImageBasedOverride ? $this->openUrlImageBasedOverride : $this->openUrl; ?>
-  <a rel="external" href="<?=$this->escapeHtmlAttr($this->openUrlBase . '?' . $ibOpenUrl)?>"<?=$class_ib?>>
-    <img data-recordid="<?=$this->escapeHtmlAttr($this->driver->getUniqueId())?>" src="<?=$this->escapeHtmlAttr($this->openUrlImageBasedSrc)?>" alt="<?=$this->transEsc('Get full text')?>" />
-  </a>
-<? endif; ?>
diff --git a/themes/jquerymobile/templates/Helpers/pagination.phtml b/themes/jquerymobile/templates/Helpers/pagination.phtml
deleted file mode 100644
index 242fc41abaf96f1bb1c51ce14f265b8a4f66983b..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/Helpers/pagination.phtml
+++ /dev/null
@@ -1,21 +0,0 @@
-<? if ($this->pageCount): ?>
-<div data-role="controlgroup" data-type="horizontal" align="center">
-
-<!-- Previous page link -->
-<? if (isset($this->previous)): ?>
-  <? $newParams = $this->params; $newParams['page'] = $this->previous; ?>
-  <a rel="external" data-role="button" data-rel="back" href="<?= $this->currentPath() . '?' . http_build_query($newParams); ?>">
-    &laquo; <?=$this->transEsc('Prev')?>
-  </a>
-<? endif; ?>
-
-<!-- Next page link -->
-<? if (isset($this->next)): ?>
-  <? $newParams = $this->params; $newParams['page'] = $this->next; ?>
-  <a rel="external" data-role="button" href="<?= $this->currentPath() . '?' . http_build_query($newParams); ?>">
-    <?=$this->transEsc('Next');?> &raquo;
-  </a>
-<? endif; ?>
-
-</div>
-<? endif; ?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/Recommend/AlphaBrowseLink.phtml b/themes/jquerymobile/templates/Recommend/AlphaBrowseLink.phtml
deleted file mode 100644
index ff7aa235d05c00aded224a3ca119ba7c73bafeda..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/Recommend/AlphaBrowseLink.phtml
+++ /dev/null
@@ -1,14 +0,0 @@
-<?
-  $index = $this->recommend->getIndex();
-  $from = $this->recommend->getQuery();
-  $link = $this->translate(
-    'alphabrowselink_html',
-    [
-      '%%index%%' => $this->transEsc('browse_' . $index),
-      '%%from%%' => $this->escapeHtml($from),
-      '%%url%%' => $this->url('alphabrowse-home')
-        . '?from=' . urlencode($from) . '&amp;source=' . urlencode($index) 
-    ]
-  );
-?>
-<div class="info"><?=$link?></div>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/Recommend/AuthorFacets.phtml b/themes/jquerymobile/templates/Recommend/AuthorFacets.phtml
deleted file mode 100644
index 0df1e74df188b2630299fe4da6e7178c92ad5afc..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/Recommend/AuthorFacets.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<? /* Not supported in mobile theme. */ ?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/Recommend/AuthorInfo.phtml b/themes/jquerymobile/templates/Recommend/AuthorInfo.phtml
deleted file mode 100644
index 0df1e74df188b2630299fe4da6e7178c92ad5afc..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/Recommend/AuthorInfo.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<? /* Not supported in mobile theme. */ ?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/Recommend/AuthorityRecommend.phtml b/themes/jquerymobile/templates/Recommend/AuthorityRecommend.phtml
deleted file mode 100644
index 0df1e74df188b2630299fe4da6e7178c92ad5afc..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/Recommend/AuthorityRecommend.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<? /* Not supported in mobile theme. */ ?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/Recommend/CatalogResults.phtml b/themes/jquerymobile/templates/Recommend/CatalogResults.phtml
deleted file mode 100644
index 0df1e74df188b2630299fe4da6e7178c92ad5afc..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/Recommend/CatalogResults.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<? /* Not supported in mobile theme. */ ?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/Recommend/CollectionSideFacets.phtml b/themes/jquerymobile/templates/Recommend/CollectionSideFacets.phtml
deleted file mode 100644
index 0df1e74df188b2630299fe4da6e7178c92ad5afc..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/Recommend/CollectionSideFacets.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<? /* Not supported in mobile theme. */ ?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/Recommend/DPLATerms.phtml b/themes/jquerymobile/templates/Recommend/DPLATerms.phtml
deleted file mode 100644
index 0df1e74df188b2630299fe4da6e7178c92ad5afc..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/Recommend/DPLATerms.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<? /* Not supported in mobile theme. */ ?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/Recommend/Deprecated.phtml b/themes/jquerymobile/templates/Recommend/Deprecated.phtml
deleted file mode 100644
index 63445d34f9c1ebc4c55c092c9dcf8965c9fd3c66..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/Recommend/Deprecated.phtml
+++ /dev/null
@@ -1,2 +0,0 @@
-<? /* do nothing -- this module is a placeholder for old deprecated features
-      to prevent legacy configurations from causing fatal errors. */ ?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/Recommend/EuropeanaResults.phtml b/themes/jquerymobile/templates/Recommend/EuropeanaResults.phtml
deleted file mode 100644
index 0df1e74df188b2630299fe4da6e7178c92ad5afc..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/Recommend/EuropeanaResults.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<? /* Not supported in mobile theme. */ ?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/Recommend/EuropeanaResultsDeferred.phtml b/themes/jquerymobile/templates/Recommend/EuropeanaResultsDeferred.phtml
deleted file mode 100644
index 0df1e74df188b2630299fe4da6e7178c92ad5afc..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/Recommend/EuropeanaResultsDeferred.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<? /* Not supported in mobile theme. */ ?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/Recommend/ExpandFacets.phtml b/themes/jquerymobile/templates/Recommend/ExpandFacets.phtml
deleted file mode 100644
index 0df1e74df188b2630299fe4da6e7178c92ad5afc..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/Recommend/ExpandFacets.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<? /* Not supported in mobile theme. */ ?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/Recommend/FacetCloud.phtml b/themes/jquerymobile/templates/Recommend/FacetCloud.phtml
deleted file mode 100644
index 0df1e74df188b2630299fe4da6e7178c92ad5afc..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/Recommend/FacetCloud.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<? /* Not supported in mobile theme. */ ?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/Recommend/FavoriteFacets.phtml b/themes/jquerymobile/templates/Recommend/FavoriteFacets.phtml
deleted file mode 100644
index e5a5a90ec3449595e7a75a91c611a08ba0914c9f..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/Recommend/FavoriteFacets.phtml
+++ /dev/null
@@ -1,18 +0,0 @@
-<? $sideFacetSet = $this->recommend->getFacetSet(); ?>
-<? if (isset($sideFacetSet['lists']) && !empty($sideFacetSet['lists']['list'])): ?>
-  <div data-role="collapsible" data-collapsed="true">
-    <h3><?=$this->transEsc('Your Lists')?></h3>
-    <ul class="mylists" data-role="listview" data-inset="true" data-dividertheme="e">
-      <? foreach ($sideFacetSet['lists']['list'] as $current): ?>
-        <li>
-          <? if ($current['isApplied']): ?>
-            <?=$this->escapeHtml($current['displayText'])?>
-          <? else: ?>
-            <a data-ajax="false" href="<?=$this->url('userList', array('id' => $current['value']))?>"><?=$this->escapeHtml($current['displayText'])?></a>
-          <? endif; ?>
-          <span class="ui-li-count"><?=$this->escapeHtml($current['count'])?></span>
-        </li>
-      <? endforeach; ?>
-    </ul>
-  </div>
-<? endif; ?>
diff --git a/themes/jquerymobile/templates/Recommend/Libraryh3lp.phtml b/themes/jquerymobile/templates/Recommend/Libraryh3lp.phtml
deleted file mode 100644
index 623feb15aaf1d875fb56ff08dd6209df29f4eb94..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/Recommend/Libraryh3lp.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<iframe src="https://us.libraryh3lp.com/chat/<?=$this->escapeHtmlAttr($this->recommend->getChatId())?>?skin=<?=urlencode($this->recommend->getSkin())?>" frameborder="1" style="border: 2px inset black; width: 350px; height: 300px;"></iframe>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/Recommend/OpenLibrarySubjects.phtml b/themes/jquerymobile/templates/Recommend/OpenLibrarySubjects.phtml
deleted file mode 100644
index 0df1e74df188b2630299fe4da6e7178c92ad5afc..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/Recommend/OpenLibrarySubjects.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<? /* Not supported in mobile theme. */ ?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/Recommend/OpenLibrarySubjectsDeferred.phtml b/themes/jquerymobile/templates/Recommend/OpenLibrarySubjectsDeferred.phtml
deleted file mode 100644
index 0df1e74df188b2630299fe4da6e7178c92ad5afc..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/Recommend/OpenLibrarySubjectsDeferred.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<? /* Not supported in mobile theme. */ ?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/Recommend/PubDateVisAjax.phtml b/themes/jquerymobile/templates/Recommend/PubDateVisAjax.phtml
deleted file mode 100644
index 0df1e74df188b2630299fe4da6e7178c92ad5afc..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/Recommend/PubDateVisAjax.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<? /* Not supported in mobile theme. */ ?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/Recommend/RandomRecommend.phtml b/themes/jquerymobile/templates/Recommend/RandomRecommend.phtml
deleted file mode 100644
index 0df1e74df188b2630299fe4da6e7178c92ad5afc..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/Recommend/RandomRecommend.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<? /* Not supported in mobile theme. */ ?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/Recommend/RemoveFilters.phtml b/themes/jquerymobile/templates/Recommend/RemoveFilters.phtml
deleted file mode 100644
index 9fabf33b4b4f4248be1a0e6a42a5fe413f650520..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/Recommend/RemoveFilters.phtml
+++ /dev/null
@@ -1,6 +0,0 @@
-<? if ($this->recommend->hasFilters()): ?>
-  <div class="info">
-    <?=$this->transEsc('nohit_active_filters')?> 
-    <a href="<?=$this->recommend->getFilterlessUrl()?>"><?=$this->transEsc('nohit_query_without_filters')?></a>
-  </div>
-<? endif; ?>
diff --git a/themes/jquerymobile/templates/Recommend/ResultGoogleMapAjax.phtml b/themes/jquerymobile/templates/Recommend/ResultGoogleMapAjax.phtml
deleted file mode 100644
index 0df1e74df188b2630299fe4da6e7178c92ad5afc..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/Recommend/ResultGoogleMapAjax.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<? /* Not supported in mobile theme. */ ?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/Recommend/SideFacets-dialog.phtml b/themes/jquerymobile/templates/Recommend/SideFacets-dialog.phtml
deleted file mode 100644
index 0cc16e6f721a004c671d02ba109e1e9bcea9b855..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/Recommend/SideFacets-dialog.phtml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?
-    $results = $this->recommend->getResults();
-    $sideFacetSet = $this->recommend->getFacetSet();
-    $hierarchicalFacets = $this->recommend->getHierarchicalFacets();
-?>
-<? if (!empty($sideFacetSet) && $results->getResultTotal() > 0): ?>
-  <div data-role="dialog" id="Search-narrow">
-    <div data-role="header" data-theme="d" data-position="inline">
-      <h1><?=$this->transEsc('Narrow Search')?></h1>
-    </div>
-    <div data-role="content">
-      <div data-role="collapsible-set" class="narrow-search">
-        <? $i = 0; foreach ($sideFacetSet as $title => $cluster): ?>
-          <? $hierarchical = in_array($title, $hierarchicalFacets); ?>
-          <? if (empty($cluster['list'])) { continue; } // skip empty facets ?>
-          <div data-role="collapsible" data-collapsed="<?=$i++ == 0 ? 'false' : 'true'?>">
-            <h4><?=$this->transEsc($cluster['label'])?></h4>
-            <ul class="narrow" data-role="listview" data-inset="true">
-              <? foreach ($cluster['list'] as $thisFacet): ?>
-                <? $indent = $hierarchical
-                    ? str_pad('', 4 * $thisFacet['level'] * 6, '&nbsp;', STR_PAD_LEFT)
-                    : ''; ?>
-                <? if ($thisFacet['isApplied']): ?>
-                  <li data-icon="check" class="checked"><a rel="external" href="<?=$this->currentPath().$results->getUrlQuery()->removeFacet($title, $thisFacet['value'], true, $thisFacet['operator']) ?>" data-rel="external"><?=$indent?><?=$this->escapeHtml($thisFacet['displayText'])?></a> <span class="ui-li-count"><?=$this->localizedNumber($thisFacet['count'])?></span></li>
-                <? else: ?>
-                  <li><a rel="external" href="<?=$this->currentPath().$results->getUrlQuery()->addFacet($title, $thisFacet['value'], $thisFacet['operator'])?>"><?=$indent?><?=$this->escapeHtml($thisFacet['displayText'])?></a> <span class="ui-li-count"><?=$this->localizedNumber($thisFacet['count'])?></span></li>
-                <? endif; ?>
-              <? endforeach; ?>
-            </ul>
-          </div>
-        <? endforeach; ?>
-      </div>
-    </div>
-  </div>
-<? endif; ?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/Recommend/SideFacets.phtml b/themes/jquerymobile/templates/Recommend/SideFacets.phtml
deleted file mode 100644
index e93c5c27218b0a37512a0fb5c41a0d9d4fad3fc6..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/Recommend/SideFacets.phtml
+++ /dev/null
@@ -1,22 +0,0 @@
-<? $results = $this->recommend->getResults(); ?>
-<? $filterList = $this->recommend->getVisibleFilters(); if (!empty($filterList)): ?>
-  <ul class="filters" data-role="listview" data-inset="true" data-dividertheme="e">
-    <li data-role="list-divider"><?=$this->transEsc('adv_search_filters')?></li>
-    <? $i = 0; foreach ($filterList as $field => $filters): ?>
-      <? foreach ($filters as $j => $filter): ?>
-        <?
-            $removeLink = $this->currentPath().$results->getUrlQuery()->removeFacet($filter['field'], $filter['value'], true, $filter['operator']);
-            if ($filter['displayText'] == '[* TO *]') $filter['displayText'] = $this->translate('filter_wildcard');
-        ?>
-        <li data-icon="minus">
-          <a data-icon="minus" rel="external" href="<?=$removeLink?>"><?=($i++ > 0 && ($j == 0 || $filter['operator'] != 'OR')) ? $this->transEsc("AND") . ' ' : ''?><? if ($filter['operator'] == 'NOT') echo $this->transEsc('NOT') . ' '; if ($filter['operator'] == 'OR' && $j > 0) echo $this->transEsc('OR') . ' '; ?><?=$this->transEsc($field)?>: <?=$this->escapeHtml($filter['displayText'])?></a>
-        </li>
-      <? endforeach; ?>
-    <? endforeach; ?>
-  </ul>
-<? endif; ?>
-<?
-    // Actual facet options are loaded as an extra hidden dialog box -- inject these into the appropriate
-    // area of the layout object (they won't work if simply displayed inline):
-    $this->layout()->extraDialogs .= $this->render('Recommend/SideFacets-dialog.phtml');
-?>
diff --git a/themes/jquerymobile/templates/Recommend/SpellingSuggestions.phtml b/themes/jquerymobile/templates/Recommend/SpellingSuggestions.phtml
deleted file mode 100644
index 0df1e74df188b2630299fe4da6e7178c92ad5afc..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/Recommend/SpellingSuggestions.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<? /* Not supported in mobile theme. */ ?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/Recommend/SummonBestBets.phtml b/themes/jquerymobile/templates/Recommend/SummonBestBets.phtml
deleted file mode 100644
index 0df1e74df188b2630299fe4da6e7178c92ad5afc..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/Recommend/SummonBestBets.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<? /* Not supported in mobile theme. */ ?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/Recommend/SummonBestBetsDeferred.phtml b/themes/jquerymobile/templates/Recommend/SummonBestBetsDeferred.phtml
deleted file mode 100644
index 0df1e74df188b2630299fe4da6e7178c92ad5afc..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/Recommend/SummonBestBetsDeferred.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<? /* Not supported in mobile theme. */ ?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/Recommend/SummonDatabases.phtml b/themes/jquerymobile/templates/Recommend/SummonDatabases.phtml
deleted file mode 100644
index 0df1e74df188b2630299fe4da6e7178c92ad5afc..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/Recommend/SummonDatabases.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<? /* Not supported in mobile theme. */ ?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/Recommend/SummonDatabasesDeferred.phtml b/themes/jquerymobile/templates/Recommend/SummonDatabasesDeferred.phtml
deleted file mode 100644
index 0df1e74df188b2630299fe4da6e7178c92ad5afc..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/Recommend/SummonDatabasesDeferred.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<? /* Not supported in mobile theme. */ ?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/Recommend/SummonResults.phtml b/themes/jquerymobile/templates/Recommend/SummonResults.phtml
deleted file mode 100644
index 0df1e74df188b2630299fe4da6e7178c92ad5afc..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/Recommend/SummonResults.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<? /* Not supported in mobile theme. */ ?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/Recommend/SummonResultsDeferred.phtml b/themes/jquerymobile/templates/Recommend/SummonResultsDeferred.phtml
deleted file mode 100644
index 0df1e74df188b2630299fe4da6e7178c92ad5afc..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/Recommend/SummonResultsDeferred.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<? /* Not supported in mobile theme. */ ?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/Recommend/SummonTopics.phtml b/themes/jquerymobile/templates/Recommend/SummonTopics.phtml
deleted file mode 100644
index 0df1e74df188b2630299fe4da6e7178c92ad5afc..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/Recommend/SummonTopics.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<? /* Not supported in mobile theme. */ ?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/Recommend/SwitchQuery.phtml b/themes/jquerymobile/templates/Recommend/SwitchQuery.phtml
deleted file mode 100644
index bf0db3cc02e6a14c61a2b2d8af3a5d68d7006fa5..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/Recommend/SwitchQuery.phtml
+++ /dev/null
@@ -1,10 +0,0 @@
-<? $suggestions = $this->recommend->getSuggestions(); if (!empty($suggestions)): ?>
-  <div class="info">
-    <p><?=$this->transEsc('switchquery_intro')?></p>
-    <ul>
-      <? foreach ($suggestions as $desc => $query): ?>
-        <li><?=$this->transEsc($desc)?>: <a href="<?=$this->recommend->getResults()->getUrlQuery()->setSearchTerms($query)?>"><?=$this->escapeHtml($query)?></a>.</li>
-      <? endforeach; ?>
-    </ul>
-  </div>
-<? endif; ?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/Recommend/SwitchTab.phtml b/themes/jquerymobile/templates/Recommend/SwitchTab.phtml
deleted file mode 100644
index 58f701ab2479d4f8ed3e8146b78ba384e36bfddd..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/Recommend/SwitchTab.phtml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?
-  $searchTabs = is_object($this->params)
-    ? $this->searchtabs()->getTabConfigForParams($this->params) : [];
-?>
-<? if (count($searchTabs) > 0): ?>
-  <div class="info">
-    <?=$this->transEsc('nohit_change_tab', array('%%activeTab%%' => $this->translate($this->recommend->getActiveTab($searchTabs)['label'])))?>
-    <ul>
-    <? $inactiveTabs = $this->recommend->getInactiveTabs($searchTabs); ?>
-    <? foreach ($inactiveTabs as $tab): ?>
-      <li>
-        <? if (!$tab['selected']): ?><a rel="external" href="<?=$this->escapeHtmlAttr($tab['url'])?>"><? endif; ?>
-          <?=$this->transEsc($tab['label']); ?>
-        <? if (!$tab['selected']): ?></a><? endif; ?>
-      </li>
-    <? endforeach; ?>
-    </ul>
-  </div>
-<? endif; ?>
diff --git a/themes/jquerymobile/templates/Recommend/SwitchType.phtml b/themes/jquerymobile/templates/Recommend/SwitchType.phtml
deleted file mode 100644
index 48bf99dce3722173bf2a92fc20b228ca8e44946d..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/Recommend/SwitchType.phtml
+++ /dev/null
@@ -1,6 +0,0 @@
-<? if ($handler = $this->recommend->getNewHandler()): ?>
-  <div class="info">
-    <?=$this->transEsc('widen_prefix')?>
-    <a href="<?=$this->recommend->getResults()->getUrlQuery()->setHandler($handler)?>"><?=$this->transEsc($this->recommend->getNewHandlerName())?></a>.
-  </div>
-<? endif; ?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/Recommend/TopFacets.phtml b/themes/jquerymobile/templates/Recommend/TopFacets.phtml
deleted file mode 100644
index 0df1e74df188b2630299fe4da6e7178c92ad5afc..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/Recommend/TopFacets.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<? /* Not supported in mobile theme. */ ?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/Recommend/WebResults.phtml b/themes/jquerymobile/templates/Recommend/WebResults.phtml
deleted file mode 100644
index 0df1e74df188b2630299fe4da6e7178c92ad5afc..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/Recommend/WebResults.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<? /* Not supported in mobile theme. */ ?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/Recommend/WorldCatIdentities.phtml b/themes/jquerymobile/templates/Recommend/WorldCatIdentities.phtml
deleted file mode 100644
index 0df1e74df188b2630299fe4da6e7178c92ad5afc..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/Recommend/WorldCatIdentities.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<? /* Not supported in mobile theme. */ ?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/RecordDriver/EDS/core.phtml b/themes/jquerymobile/templates/RecordDriver/EDS/core.phtml
deleted file mode 100644
index 9ca1ac3f0520e67c3374f36a4b32153487d647b7..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/RecordDriver/EDS/core.phtml
+++ /dev/null
@@ -1,86 +0,0 @@
-<? $this->headLink()->appendStylesheet('EDS.css'); ?>
-<?
-  $items = $this->driver->getItems();
-  $dbLabel = $this->driver->getDbLabel();
-  $thumb = $this->driver->getThumbnail('medium');
-  $customLinks = $this->driver->getCustomLinks();
-  $accessLevel = $this->driver->getAccessLevel();
-  $restrictedView = empty($accessLevel) ? false : true;
-?>
-<? /* Display thumbnail if appropriate: */ ?>
-<? $mediumThumb = $this->record($this->driver)->getThumbnail('medium'); $largeThumb = $this->record($this->driver)->getThumbnail('large'); ?>
-<? if ($largeThumb): ?><a rel="external" href="<?=$this->escapeHtmlAttr($largeThumb)?>"><? endif; ?>
-  <div class="recordcover">
-    <? if ($mediumThumb): ?>
-      <img alt="<?=$this->transEsc('Cover Image')?>" class="recordcover" src="<?=$this->escapeHtmlAttr($mediumThumb);?>"/>
-    <? else: ?>
-      <span class="recordcover pt-icon pt-<?=$this->driver->getPubTypeId()?>" style="float:none"></span>
-    <? endif; ?>
-    <? $pLink = $this->driver->getPLink();
-        if($pLink): ?>
-        <br/><a href="<?=$this->escapeHtmlAttr($pLink)?>">
-          <?=$this->transEsc('View in EDS')?>
-        </a>
-    <? endif; ?>
-    <? $pdfLink = $this->driver->getPdfLink();
-        if ($pdfLink): ?>
-        <br/><a href="<?=$pdfLink?>" class="icon pdf fulltext">
-          <?=$this->transEsc('PDF Full Text')?>
-        </a>
-    <? endif; ?>
-    <? if ($this->driver->hasHTMLFullTextAvailable()): ?>
-      <br/><a href="<?=$this->recordLink()->getUrl($this->driver, 'fulltext')?>#html" class="icon html fulltext">
-          <?=$this->transEsc('HTML Full Text')?>
-        </a>
-    <? endif; ?>
-
-    <? $customLinks = array_merge($this->driver->getFTCustomLinks(), $this->driver->getCustomLinks());
-    if (!empty($customLinks)): ?>
-      <? foreach ($customLinks as $customLink): ?>
-      <? $url = isset($customLink['Url']) ? $customLink['Url'] : '';
-          $mot = isset($customLink['MouseOverText'])? $customLink['MouseOverText'] : '';
-          $icon = isset ($customLink['Icon']) ? $customLink['Icon'] : '';
-          $name = isset($customLink['Text']) ? $customLink['Text'] : '';
-      ?>
-      <br /><span>
-        <a href="<?=$this->escapeHtmlAttr($url)?>" target="_blank" title="<?=$this->escapeHtmlAttr($mot)?>" class="custom-link">
-          <? if ($icon): ?><img src="<?=$this->escapeHtmlAttr($icon)?>" /> <? endif; ?><?=$this->escapeHtml($name)?>
-        </a>
-      </span>
-      <? endforeach; ?>
-    <? endif; ?>
-  </div>
-<? if ($largeThumb): ?></a><? endif; ?>
-
-<br/><h3><?=$this->driver->getTitle()?></h3>
-
-<dl class="biblio" summary="<?=$this->transEsc('Bibliographic Details')?>">
-  <? foreach ($items as $key => $item): ?>
-    <? if (!empty($item['Data'])): ?>
-      <dt><?=$this->transEsc($item['Label'])?>:</dt>
-      <dd><?=$this->driver->linkUrls($item['Data'])?></dd>
-    <? endif; ?>
-  <? endforeach; ?>
-
-  <? if ($dbLabel): ?>
-    <dt><?=$this->transEsc('Database')?>:</dt>
-    <dd><?=$this->escapeHtml($dbLabel)?></dd>
-  <? endif; ?>
-
-  <?if ($this->driver->hasHTMLFullTextAvailable() && !$restrictedView):
-      $fullText = $this->driver->getHtmlFullText();?>
-    <dt><?=$this->transEsc('Full Text')?>:</dt>
-    <dd>
-      <?=$fullText?>
-    </dd>
-  <? elseif ($this->driver->hasHTMLFullTextAvailable() && $restrictedView): ?>
-    <dd>
-      <?=$this->transEsc('Full text is not displayed to guests')?>
-    </dd>
-    <dd>
-      <a class="login" href="<?=$this->url('myresearch-home')?>">
-        <strong><?=$this->transEsc('Login for full access')?></strong>
-      </a>
-    </dd>
-  <? endif; ?>
-</dl>
diff --git a/themes/jquerymobile/templates/RecordDriver/EDS/result-list.phtml b/themes/jquerymobile/templates/RecordDriver/EDS/result-list.phtml
deleted file mode 100644
index 5d95546b179c14b7b45591c9186f9cf87fde9aba..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/RecordDriver/EDS/result-list.phtml
+++ /dev/null
@@ -1,33 +0,0 @@
-<?
-  $this->headLink()->appendStylesheet('EDS.css');
-  $accessLevel = $this->driver->getAccessLevel();
-  $restrictedView = empty($accessLevel) ? false : true;
-?>
-<a rel="external" href="<?=$this->recordLink()->getUrl($this->driver)?>">
-  <div class="result source<?=$this->escapeHtmlAttr($this->driver->getSourceIdentifier())?> recordId<?=$this->driver->supportsAjaxStatus()?' ajaxItemId':''?>">
-    <input type="hidden" value="<?=$this->escapeHtmlAttr($this->driver->getUniqueID())?>" class="hiddenId" />
-    <? $items =  $this->driver->getItems();
-
-    $titlePrinted=false;
-    if ($this->driver->getTitle()!="") {
-      echo '<h3 class="ui-li-heading">'.$this->escapeHtml($this->driver->getTitle()).'</h3>';
-      $titlePrinted=true;
-    }
-
-    if (isset($items) && !empty($items)) :
-      foreach ($items as $item):
-        if (!empty($item)): ?>
-          <? if( ('Ti' == $item['Group']) && ($titlePrinted==false) ): ?>
-            <h3 class="ui-li-heading"><?=strip_tags($item['Data'])?></h3>
-          <? elseif ('Ti' != $item['Group']): ?>
-            <p class="ui-li-desc"><strong><?=$this->transEsc($item['Label'])?></strong>: <?=strip_tags($item['Data'])?></p>
-          <? endif; ?>
-        <? endif;
-      endforeach;
-    elseif ($restrictedView): ?>
-      <a class="login" href="<?=$this->url('myresearch-home')?>">
-        <strong><?=$this->transEsc('Login for full access')?></strong>
-      </a><br/>
-    <? endif; ?>
-  </div>
-</a>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/RecordDriver/EIT/format-class.phtml b/themes/jquerymobile/templates/RecordDriver/EIT/format-class.phtml
deleted file mode 100644
index 180fac1b46c5cf5a9185f236af60f398917b62aa..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/RecordDriver/EIT/format-class.phtml
+++ /dev/null
@@ -1,44 +0,0 @@
-<?
-  // Convert EIT formats to VuFind formats so icons display correctly:
-  switch ($this->format) {
-      case 'Audio Recording':
-          echo 'audio';
-          break;
-      case 'Book':
-      case 'Book Chapter':
-          echo 'book';
-          break;
-      case 'Computer File':
-      case 'Web Resource':
-          echo 'electronic';
-          break;
-      case 'Dissertation':
-      case 'Manuscript':
-      case 'Paper':
-      case 'Patent':
-          echo 'manuscript';
-          break;
-      case 'eBook':
-          echo 'ebook';
-          break;
-      case 'Kit':
-          echo 'kit';
-          break;
-      case 'Image':
-      case 'Photograph':
-          echo 'photo';
-          break;
-      case 'Music Score':
-          echo 'musicalscore';
-          break;
-      case 'Newspaper Article':
-          echo 'newspaper';
-          break;
-      case 'Video Recording':
-          echo 'video';
-          break;
-      default:
-          echo 'journal';
-          break;
-  }
-?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/RecordDriver/EIT/link-author.phtml b/themes/jquerymobile/templates/RecordDriver/EIT/link-author.phtml
deleted file mode 100644
index fcd1912bf6ce6d588e00276dac54092067fbd0d0..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/RecordDriver/EIT/link-author.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<?=$this->url('eit-search')?>?lookfor=%22<?=urlencode($this->lookfor)?>%22&amp;type=AU
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/RecordDriver/EIT/link-journaltitle.phtml b/themes/jquerymobile/templates/RecordDriver/EIT/link-journaltitle.phtml
deleted file mode 100644
index b31db1dbcdfdb53209ba90ae6277693c389c4e95..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/RecordDriver/EIT/link-journaltitle.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<?=$this->url('eit-search')?>?lookfor=%22<?=urlencode($this->lookfor)?>%22
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/RecordDriver/EIT/link-series.phtml b/themes/jquerymobile/templates/RecordDriver/EIT/link-series.phtml
deleted file mode 100644
index 57f80eb30fd10256af415826ff5b4f3d98d3e43e..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/RecordDriver/EIT/link-series.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<?=$this->url('eit-search')?>?lookfor=%22<?=urlencode($this->lookfor)?>%22&amp;type=TI
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/RecordDriver/EIT/link-subject.phtml b/themes/jquerymobile/templates/RecordDriver/EIT/link-subject.phtml
deleted file mode 100644
index 37ed90fbfb17025a69265874851819eeb93e00dc..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/RecordDriver/EIT/link-subject.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<?=$this->url('eit-search')?>?lookfor=%22<?=urlencode($this->lookfor)?>%22&amp;type=SU
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/RecordDriver/EIT/link-title.phtml b/themes/jquerymobile/templates/RecordDriver/EIT/link-title.phtml
deleted file mode 100644
index 57f80eb30fd10256af415826ff5b4f3d98d3e43e..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/RecordDriver/EIT/link-title.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<?=$this->url('eit-search')?>?lookfor=%22<?=urlencode($this->lookfor)?>%22&amp;type=TI
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/RecordDriver/LibGuides/result-list.phtml b/themes/jquerymobile/templates/RecordDriver/LibGuides/result-list.phtml
deleted file mode 100644
index df1627a06f51d642211867c5cb49467cf059d235..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/RecordDriver/LibGuides/result-list.phtml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?
-    $url = $this->driver->getUniqueId();
-?>
-<a rel="external" href="<?=$this->escapeHtmlAttr($url)?>">
-  <div class="result">
-    <h3><?=$this->record($this->driver)->getTitleHtml()?></h3>
-  </div>
-</a>
diff --git a/themes/jquerymobile/templates/RecordDriver/Pazpar2/link-author.phtml b/themes/jquerymobile/templates/RecordDriver/Pazpar2/link-author.phtml
deleted file mode 100644
index 34ec85e9849867608a0a901e72ab8ff8f452cfe1..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/RecordDriver/Pazpar2/link-author.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<?=$this->url('pazpar2-search')?>?lookfor=<?=urlencode($this->lookfor)?>&amp;type=author
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/RecordDriver/Pazpar2/link-series.phtml b/themes/jquerymobile/templates/RecordDriver/Pazpar2/link-series.phtml
deleted file mode 100644
index 203012a0d1e20fd416074e7aeabf72b45f06f3c5..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/RecordDriver/Pazpar2/link-series.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<?=$this->url('pazpar2-search')?>?lookfor=%22<?=urlencode($this->lookfor)?>%22&amp;type=series
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/RecordDriver/Pazpar2/link-subject.phtml b/themes/jquerymobile/templates/RecordDriver/Pazpar2/link-subject.phtml
deleted file mode 100644
index 12428b058b52d3d15abe04107fd9a063b3d719b6..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/RecordDriver/Pazpar2/link-subject.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<?=$this->url('pazpar2-search')?>?lookfor=%22<?=urlencode($this->lookfor)?>%22&amp;type=subject
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/RecordDriver/Pazpar2/link-title.phtml b/themes/jquerymobile/templates/RecordDriver/Pazpar2/link-title.phtml
deleted file mode 100644
index f0f81ef686c85302fd1beb62b9e565bd305602f7..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/RecordDriver/Pazpar2/link-title.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<?=$this->url('pazpar2-search')?>?lookfor=%22<?=urlencode($this->lookfor)?>%22&amp;type=title
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/RecordDriver/Pazpar2/result-list.phtml b/themes/jquerymobile/templates/RecordDriver/Pazpar2/result-list.phtml
deleted file mode 100644
index cf6ace0c90d3fc133d98f77ab7313eeb7b9ac887..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/RecordDriver/Pazpar2/result-list.phtml
+++ /dev/null
@@ -1,19 +0,0 @@
-<b>
-  <div class="result source<?=$this->escapeHtmlAttr($this->driver->getSourceIdentifier())?> recordId<?=$this->driver->supportsAjaxStatus()?' ajaxItemId':''?>">
-    <input type="hidden" value="<?=$this->escapeHtmlAttr($this->driver->getUniqueID())?>" class="hiddenId" />
-    <h3><?=$this->record($this->driver)->getTitleHtml()?></h3>
-    <? $summAuthors = $this->driver->getPrimaryAuthorsWithHighlighting(); if (!empty($summAuthors)): ?>
-      <p><?=$this->transEsc('by')?>
-      <? $authorCount = count($summAuthors); foreach ($summAuthors as $i => $summAuthor): ?>
-        <?=$this->highlight($summAuthor)?><?=$i + 1 < $authorCount ? ';' : ''?>
-      <? endforeach; ?></p>
-    <? endif; ?>
-    <? $locations = $this->driver->getProviders(); if (!empty($locations)): ?>
-      <p><strong><?=$this->transEsc('Provider')?>:</strong> <?=$this->escapeHtml(implode(', ', $locations))?></p>
-    <? endif; ?>
-    <? $summCallNo = $this->driver->getCallNumber(); if (!empty($summCallNo)): ?>
-      <p><strong><?=$this->transEsc('Call Number')?>:</strong> <?=$this->escapeHtml($summCallNo)?></p>
-    <? endif; ?>
-    <?=$this->record($this->driver)->getFormatList()?>
-  </div>
-</b>
diff --git a/themes/jquerymobile/templates/RecordDriver/Primo/format-class.phtml b/themes/jquerymobile/templates/RecordDriver/Primo/format-class.phtml
deleted file mode 100644
index 6702f4f504060de147dca96d74fd5cae34f5f159..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/RecordDriver/Primo/format-class.phtml
+++ /dev/null
@@ -1,47 +0,0 @@
-<?
-  // Convert Primo formats to VuFind formats so icons display correctly:
-  switch ($this->format) {
-      case 'Audio Recording':
-          echo 'audio';
-          break;
-      case 'Book':
-      case 'Book Chapter':
-          echo 'book';
-          break;
-      case 'Computer File':
-      case 'Website':
-          echo 'electronic';
-          break;
-      case 'Dissertation':
-      case 'Manuscript':
-      case 'Paper':
-      case 'Patent':
-          echo 'manuscript';
-          break;
-      case 'eBook':
-          echo 'ebook';
-          break;
-      case 'Kit':
-          echo 'kit';
-          break;
-      case 'Image':
-      case 'Photograph':
-          echo 'photo';
-          break;
-      case 'Score':
-          echo 'musicalscore';
-          break;
-      case 'Newspaper Article':
-          echo 'newspaper';
-          break;
-      case 'Video':
-          echo 'video';
-          break;
-      case 'Map':
-          echo 'map';
-          break;
-      default:
-          echo 'journal';
-          break;
-  }
-?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/RecordDriver/Primo/link-author.phtml b/themes/jquerymobile/templates/RecordDriver/Primo/link-author.phtml
deleted file mode 100644
index e3dfe3c20cc2f7d0b09206e61747de172a8c2a7c..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/RecordDriver/Primo/link-author.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<?=$this->url('primo-search')?>?lookfor=<?=urlencode($this->lookfor)?>&amp;type=Author
diff --git a/themes/jquerymobile/templates/RecordDriver/Primo/link-issn.phtml b/themes/jquerymobile/templates/RecordDriver/Primo/link-issn.phtml
deleted file mode 100644
index acb39b5f503cfaaf703de3644f24a3f424e4b455..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/RecordDriver/Primo/link-issn.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<?=$this->url('primo-search')?>?lookfor=<?=urlencode($this->lookfor)?>&amp;type=ISSN
diff --git a/themes/jquerymobile/templates/RecordDriver/Primo/link-journaltitle.phtml b/themes/jquerymobile/templates/RecordDriver/Primo/link-journaltitle.phtml
deleted file mode 100644
index 5b35541ccd0bd6e546408aa741d6e98c27ac9424..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/RecordDriver/Primo/link-journaltitle.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<?=$this->url('primo-search')?>?lookfor=%22<?=urlencode($this->lookfor)?>%22&amp;type=AllFields
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/RecordDriver/Primo/link-subject.phtml b/themes/jquerymobile/templates/RecordDriver/Primo/link-subject.phtml
deleted file mode 100644
index d24131fce6cea768c8d2faa353428329c8036456..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/RecordDriver/Primo/link-subject.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<?=$this->url('primo-search')?>?lookfor=<?=urlencode($this->lookfor)?>&amp;type=Subject
diff --git a/themes/jquerymobile/templates/RecordDriver/Primo/link-title.phtml b/themes/jquerymobile/templates/RecordDriver/Primo/link-title.phtml
deleted file mode 100644
index 863c2e40063faf1c2a2774906a506eca80dd4a74..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/RecordDriver/Primo/link-title.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<?=$this->url('primo-search')?>?lookfor=%22<?=urlencode($this->lookfor)?>%22&amp;type=Title
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/RecordDriver/SolrAuth/result-list.phtml b/themes/jquerymobile/templates/RecordDriver/SolrAuth/result-list.phtml
deleted file mode 100644
index 2691e77b0a142b7296ede5d181b11839fee50467..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/RecordDriver/SolrAuth/result-list.phtml
+++ /dev/null
@@ -1,11 +0,0 @@
-<?
-    $heading = $this->driver->getTitle();
-    if (empty($heading)) {
-        $heading = $this->translate('Heading unavailable.');
-    }
-?>
-<a rel="external" href="<?=$this->url('authority-record')?>?id=<?=urlencode($this->driver->getUniqueId())?>">
-  <div class="result">
-    <h3><?=$this->escapeHtml($heading)?></h3>
-  </div>
-</a>
diff --git a/themes/jquerymobile/templates/RecordDriver/SolrDefault/collection-info.phtml b/themes/jquerymobile/templates/RecordDriver/SolrDefault/collection-info.phtml
deleted file mode 100644
index 550e2f6ca9fcde390bdda1f2a40f98235efc538b..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/RecordDriver/SolrDefault/collection-info.phtml
+++ /dev/null
@@ -1,4 +0,0 @@
-<h1><?=$this->escapeHtml($this->driver->getShortTitle())?></h1>
-<? $summ = $this->driver->getSummary(); if (!empty($summ)): ?>
-  <p><?=$this->escapeHtml($summ[0])?></p>
-<? endif; ?>
diff --git a/themes/jquerymobile/templates/RecordDriver/SolrDefault/collection-record.phtml b/themes/jquerymobile/templates/RecordDriver/SolrDefault/collection-record.phtml
deleted file mode 100644
index 916453d1dfcca7f01dd6797a1e72960fe9edb1c2..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/RecordDriver/SolrDefault/collection-record.phtml
+++ /dev/null
@@ -1,55 +0,0 @@
-<h3><?=$this->escapeHtml($this->driver->getShortTitle() . ' ' . $this->driver->getSubtitle() . ' ' . $this->driver->getTitleSection())?></h3>
-<p><a rel="external" href="<?=$this->recordLink()->getUrl($this->driver)?>"><?=$this->transEsc('View Full ' . ($this->driver->isCollection() ? 'Collection' : 'Record'))?></a></p>
-
-<dl class="biblio" title="<?=$this->transEsc('Bibliographic Details')?>">
-  <? $summary = $this->driver->getSummary(); $summary = isset($summary[0]) ? $summary[0] : false; ?>
-  <? if ($summary): ?>
-    <dt><?=$this->transEsc('Description')?>: </dt>
-    <dd><?=$this->escapeHtml($summary)?></dd>
-  <? endif; ?>
-
-  <? $authors = $this->driver->getDeduplicatedAuthors(); ?>
-  <? if (isset($authors['main']) && !empty($authors['main'])): ?>
-    <dt><?=$this->transEsc(count($authors['main']) > 1 ? 'Main Authors' : 'Main Author')?>: </dt>
-    <dd>
-      <p><? $i = 0; foreach ($authors['main'] as $author => $roles): ?><?=($i++ == 0)?'':', '?><a rel="external" href="<?=$this->record($this->driver)->getLink('author', $author)?>"><?=$this->escapeHtml($author)?></a><? if (count($roles) > 0): ?> (<? $j = 0; foreach ($roles as $role): ?><?=($j++ == 0)?'':', '?><?=$this->transEsc("CreatorRoles::" . $role)?><? endforeach; ?>)<? endif; ?><? endforeach; ?></p>
-    </dd>
-  <? endif; ?>
-
-  <? if (isset($authors['corporate']) && !empty($authors['corporate'])): ?>
-    <dt><?=$this->transEsc(count($authors['corporate']) > 1 ? 'Corporate Author' : 'Corporate Authors')?>: </dt>
-    <dd>
-      <p><? $i = 0; foreach ($authors['corporate'] as $corporate => $roles): ?><?=($i++ == 0)?'':', '?><a rel="external" href="<?=$this->record($this->driver)->getLink('author', $corporate)?>"><?=$this->escapeHtml($corporate)?></a><? if (count($roles) > 0): ?> (<? $j = 0; foreach ($roles as $role): ?><?=($j++ == 0)?'':', '?><?=$this->transEsc("CreatorRoles::" . $role)?><? endforeach; ?>)<? endif; ?><? endforeach; ?></p>
-    </dd>
-  <? endif; ?>
-
-  <? $langs = $this->driver->getLanguages(); if (!empty($langs)): ?>
-    <dt><?=$this->transEsc('Language')?>: </dt>
-    <dd><? foreach ($langs as $lang): ?><?= $this->escapeHtml($lang)?> <? endforeach; ?></dd>
-  <? endif; ?>
-
-  <? $formats = $this->driver->getFormats(); if (!empty($formats)): ?>
-    <dt><?=$this->transEsc('Format')?>: </dt>
-    <dd><?=$this->record($this->driver)->getFormatList()?></dd>
-  <? endif; ?>
-
-  <? $access = $this->driver->getAccessRestrictions(); if (!empty($access)): ?>
-    <? $contentDisplayed = true; ?>
-    <dt><?=$this->transEsc('Access')?>: </dt>
-    <dd>
-      <? foreach ($access as $field): ?>
-        <p><?=$this->escapeHtml($field)?></p>
-      <? endforeach; ?>
-    </dd>
-  <? endif; ?>
-
-  <? $related = $this->driver->getRelationshipNotes(); if (!empty($related)): ?>
-    <? $contentDisplayed = true; ?>
-    <dt><?=$this->transEsc('Related Items')?>: </dt>
-    <dd>
-      <? foreach ($related as $field): ?>
-        <p><?=$this->escapeHtml($field)?></p>
-      <? endforeach; ?>
-    </dd>
-  <? endif; ?>
-</dl>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/RecordDriver/SolrDefault/core.phtml b/themes/jquerymobile/templates/RecordDriver/SolrDefault/core.phtml
deleted file mode 100644
index f9a570094fbacc741b5cf9c50ba3fb91c029ab02..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/RecordDriver/SolrDefault/core.phtml
+++ /dev/null
@@ -1,212 +0,0 @@
-<?
-  if($loggedin = $this->auth()->isLoggedIn()) {
-    $user_id = $loggedin->id;
-    $loggedin = true;
-  } else {
-    $user_id = false;
-  }
-
-  $formatRoles = function ($roles) {
-    if (count($roles) == 0) {
-      return '';
-    }
-    $that = $this;
-    $translate = function ($str) use ($that) {
-      return $that->transEsc('CreatorRoles::' . $str);
-    };
-    return ' (' . implode(', ', array_unique(array_map($translate, $roles))) . ')';
-  };
-?>
-<? /* Display thumbnail if appropriate: */ ?>
-<?=$this->record($this->driver)->getCover('core', 'medium', $this->record($this->driver)->getThumbnail('large')); ?>
-
-<h3><?=$this->escapeHtml($this->driver->getShortTitle() . ' ' . $this->driver->getSubtitle() . ' ' . $this->driver->getTitleSection())?></h3>
-
-<? $summary = $this->driver->getSummary(); $summary = isset($summary[0]) ? $summary[0] : false; ?>
-<? if ($summary): ?><p><?=$this->escapeHtml($this->truncate($summary, 200))?></p><? endif; ?>
-
-<dl class="biblio" title="<?=$this->transEsc('Bibliographic Details')?>">
-  <? $journalTitle = $this->driver->getContainerTitle(); if (!empty($journalTitle)): ?>
-    <dt><?=$this->transEsc('Published in')?>:</dt>
-      <dd>
-      <?
-        $containerSource = $this->driver->getSourceIdentifier();
-        $containerID = $this->driver->getContainerRecordID();
-      ?>
-      <a rel="external" href="<?=($containerID ? $this->recordLink()->getUrl("$containerSource|$containerID") : $this->record($this->driver)->getLink('journaltitle', $journalTitle))?>"><?=$this->escapeHtml($journalTitle)?></a>
-      <? $ref = $this->driver->getContainerReference(); if (!empty($ref)) { echo $this->escapeHtml($ref); } ?>
-    </dd>
-  <? endif; ?>
-
-  <? $nextTitles = $this->driver->getNewerTitles(); $prevTitles = $this->driver->getPreviousTitles(); ?>
-  <? if (!empty($nextTitles)): ?>
-    <dt><?=$this->transEsc('New Title')?>: </dt>
-    <dd>
-      <? foreach($nextTitles as $field): ?>
-        <p><a rel="external" href="<?=$this->record($this->driver)->getLink('title', $field)?>"><?=$this->escapeHtml($field)?></a></p>
-      <? endforeach; ?>
-    </dd>
-  <? endif; ?>
-
-  <? if (!empty($prevTitles)): ?>
-    <dt><?=$this->transEsc('Previous Title')?>: </dt>
-    <dd>
-      <? foreach($prevTitles as $field): ?>
-        <p><a rel="external" href="<?=$this->record($this->driver)->getLink('title', $field)?>"><?=$this->escapeHtml($field)?></a></p>
-      <? endforeach; ?>
-    </dd>
-  <? endif; ?>
-
-  <? $authors = $this->driver->getDeduplicatedAuthors(); ?>
-  <? if (isset($authors['main']) && !empty($authors['main'])): ?>
-    <dt><?=$this->transEsc(count($authors['main']) > 1 ? 'Main Authors' : 'Main Author')?>: </dt>
-    <dd>
-      <p><? $i = 0; foreach ($authors['main'] as $author => $roles): ?><?=($i++ == 0)?'':', '?><a rel="external" href="<?=$this->record($this->driver)->getLink('author', $author)?>"><?=$this->escapeHtml($author)?></a><?=$formatRoles($roles)?><? endforeach; ?></p>
-    </dd>
-  <? endif; ?>
-
-  <? $formats = $this->driver->getFormats(); if (!empty($formats)): ?>
-    <dt><?=$this->transEsc('Format')?>: </dt>
-    <dd><?=$this->record($this->driver)->getFormatList()?></dd>
-  <? endif; ?>
-
-  <? $langs = $this->driver->getLanguages(); if (!empty($langs)): ?>
-    <dt><?=$this->transEsc('Language')?>: </dt>
-    <dd><? foreach ($langs as $lang): ?><?= $this->escapeHtml($lang)?> <? endforeach; ?></dd>
-  <? endif; ?>
-
-  <? $publications = $this->driver->getPublicationDetails(); if (!empty($publications)): ?>
-    <dt><?=$this->transEsc('Published')?>: </dt>
-    <dd>
-      <? foreach ($publications as $field): ?>
-        <p><?=$this->escapeHtml($field)?></p>
-      <? endforeach; ?>
-    </dd>
-  <? endif; ?>
-
-  <? $edition = $this->driver->getEdition(); if (!empty($edition)): ?>
-    <dt><?=$this->transEsc('Edition')?>: </dt>
-    <dd><?=$this->escapeHtml($edition)?></dd>
-  <? endif; ?>
-
-  <? $subjects = $this->driver->getAllSubjectHeadings(); if (!empty($subjects)): ?>
-  <tr valign="top">
-    <dt><?=$this->transEsc('Subjects')?>: </dt>
-    <dd>
-      <? foreach ($subjects as $field): ?>
-      <p>
-        <? $subject = ''; ?>
-        <? $i = 0; foreach ($field as $subfield): ?>
-          <?=($i++ == 0) ? '' : ' -- '?>
-          <? $subject = trim($subject . ' ' . $subfield); ?>
-          <a rel="external" href="<?=$this->record($this->driver)->getLink('subject', $subject)?>" class="subjectHeading"><?=$this->escapeHtml($subfield)?></a>
-        <? endforeach; ?>
-      </p>
-      <? endforeach; ?>
-    </dd>
-  </tr>
-  <? endif; ?>
-
-  <? if (isset($authors['corporate']) && !empty($authors['corporate'])): ?>
-    <dt><?=$this->transEsc(count($authors['corporate']) > 1 ? 'Corporate Author' : 'Corporate Authors')?>: </dt>
-    <dd>
-      <p><? $i = 0; foreach ($authors['corporate'] as $corporate => $roles): ?><?=($i++ == 0)?'':', '?><a rel="external" href="<?=$this->record($this->driver)->getLink('author', $corporate)?>"><?=$this->escapeHtml($corporate)?></a><?=$formatRoles($roles)?><? endforeach; ?></p>
-    </dd>
-  <? endif; ?>
-
-  <? if (isset($authors['secondary']) && !empty($authors['secondary'])): ?>
-    <dt><?=$this->transEsc('Other Authors')?>: </dt>
-    <dd>
-      <p><? $i = 0; foreach ($authors['secondary'] as $author => $roles): ?><?=($i++ == 0)?'':', '?><a rel="external" href="<?=$this->record($this->driver)->getLink('author', $author)?>"><?=$this->escapeHtml($author)?></a><?=$formatRoles($roles)?><? endforeach; ?></p>
-    </dd>
-  <? endif; ?>
-
-  <?/* Display series section if at least one series exists. */?>
-  <? $series = $this->driver->getSeries(); if (!empty($series)): ?>
-    <dt><?=$this->transEsc('Series')?>: </dt>
-    <dd>
-      <? foreach ($series as $field): ?>
-        <?/* Depending on the record driver, $field may either be an array with
-           "name" and "number" keys or a flat string containing only the series
-           name.  We should account for both cases to maximize compatibility. */?>
-        <? if (is_array($field)): ?>
-          <? if (!empty($field['name'])): ?>
-            <p>
-            <a rel="external" href="<?=$this->record($this->driver)->getLink('series', $field['name'])?>"><?=$this->escapeHtml($field['name'])?></a>
-            <? if (!empty($field['number'])): ?>
-              <?=$this->escapeHtml($field['number'])?>
-            <? endif; ?>
-            </p>
-          <? endif; ?>
-        <? else: ?>
-          <p><a rel="external" href="<?=$this->record($this->driver)->getLink('series', $field)?>"><?=$this->escapeHtml($field)?></a></p>
-        <? endif; ?>
-      <? endforeach; ?>
-    </dd>
-  <? endif; ?>
-
-  <? $childRecordCount = $this->driver->tryMethod('getChildRecordCount'); if ($childRecordCount): ?>
-    <dt><?=$this->transEsc('child_records')?>: </dt>
-    <dd><a rel="external" href="<?=$this->recordLink()->getChildRecordSearchUrl($this->driver)?>"><?=$this->transEsc('child_record_count', array('%%count%%' => $childRecordCount))?></a></dd>
-  <? endif; ?>
-
-  <?
-      $openUrl = $this->openUrl($this->driver, 'record');
-      $openUrlActive = $openUrl->isActive();
-      // Account for replace_other_urls setting
-      $urls = $this->record($this->driver)->getLinkDetails($openUrlActive);
-  ?>
-  <? if (!empty($urls) || $openUrlActive): ?>
-    <dt><?=$this->transEsc('Online Access')?>: </dt>
-    <dd>
-      <? foreach ($urls as $current): ?>
-        <p><a rel="external" href="<?=$this->escapeHtmlAttr($this->proxyUrl($current['url']))?>"><?=$this->escapeHtml($current['desc'])?></a></p>
-      <? endforeach; ?>
-      <? if ($openUrlActive): ?>
-        <?=$openUrl->renderTemplate()?><br/>
-      <? endif; ?>
-    </dd>
-  <? endif; ?>
-
-  <? $recordLinks = $this->driver->getAllRecordLinks(); if (!empty($recordLinks)): ?>
-    <dt><?=$this->transEsc('Related Items')?>:</dt>
-    <dd>
-      <? foreach ($recordLinks as $recordLink): ?>
-        <p>
-          <?=$this->transEsc($recordLink['title'])?>:
-          <a href="<?=$this->recordLink()->related($recordLink['link'])?>"><?=$this->escapeHtml($recordLink['value'])?></a>
-        </p>
-      <? endforeach; ?>
-      <? /* if we have record links, display relevant explanatory notes */
-        $related = $this->driver->getRelationshipNotes();
-        if (!empty($related)): ?>
-          <? foreach ($related as $field): ?>
-            <p><?=$this->escapeHtml($field)?></p>
-          <? endforeach; ?>
-      <? endif; ?>
-    </dd>
-  <? endif; ?>
-
-  <? $tagList = ($this->usertags()->getMode() !== 'disabled') ? $this->driver->getTags(null, null, 'count', $user_id) : array(); ?>
-  <? if (count($tagList) > 0): ?>
-    <dt><?=$this->transEsc('Tags')?>: </dt>
-    <dd id="tagList">
-      <? $i=0; foreach ($tagList as $tag): ?>
-        <? if($loggedin): ?>
-          <? $is_me = isset($tag['is_me']) && !is_null($tag['is_me']) ? $tag['is_me'] : false; ?>
-          <span class="tag ui-btn ui-btn-inline ui-mini ui-btn-corner-all ui-btn-up-<?=$is_me ? 'b' : 'c' ?>">
-            <a rel="external" href="<?=$this->url('tag-home')?>?lookfor=<?=urlencode($tag->tag)?>" class="text ui-btn-text">
-              <?=$this->escapeHtml($tag->tag)?> (<?=$this->escapeHtml($tag->cnt)?>)
-            </a>
-            <form method="POST" action="<?=$this->recordLink()->getActionUrl($this->driver, $is_me ? 'DeleteTag' : 'AddTag') ?>" class="tag-form">
-              <input type="hidden" name="tag" value="<?=$this->escapeHtmlAttr($tag['tag'])?>"/>
-              <button type="submit" onClick="ajaxTagUpdate('<?=$this->escapeHtmlAttr($tag['tag'])?>', <?=$is_me ? 'true' : 'false' ?>);return false;" data-theme="<?=$is_me ? 'c' : 'b' ?>" data-icon="<?=$is_me ? 'minus' : 'plus' ?>" data-iconpos="notext" data-inline="true" data-mini="true">&nbsp;</button>
-            </form>
-          </span>
-        <? else: ?>
-          <a rel="external" href="<?=$this->url('tag-home')?>?lookfor=<?=urlencode($tag->tag)?>"><?=$this->escapeHtml($tag->tag)?></a> (<?=$this->escapeHtml($tag->cnt)?>)<?=(++$i < count($tagList)) ? ', ' : '' ?>
-        <? endif; ?>
-      <? endforeach; ?>
-    </dd>
-  <? endif; ?>
-</dl>
diff --git a/themes/jquerymobile/templates/RecordDriver/SolrDefault/format-class.phtml b/themes/jquerymobile/templates/RecordDriver/SolrDefault/format-class.phtml
deleted file mode 100644
index 2e2ce73b628f19dc2eb4028d1dad39cad505c089..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/RecordDriver/SolrDefault/format-class.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<?=preg_replace('/[^a-z0-9]/', '', strtolower($this->format))?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/RecordDriver/SolrDefault/format-list.phtml b/themes/jquerymobile/templates/RecordDriver/SolrDefault/format-list.phtml
deleted file mode 100644
index 6c85fc0e601bfbddafb42d18d9f12c691bedd4df..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/RecordDriver/SolrDefault/format-list.phtml
+++ /dev/null
@@ -1,5 +0,0 @@
-<p>
-  <? foreach ($this->driver->getFormats() as $format): ?>
-    <span class="iconlabel <?=$this->record($this->driver)->getFormatClass($format)?>"><?=$this->transEsc($format)?></span>
-  <? endforeach; ?>
-</p>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/RecordDriver/SolrDefault/link-author.phtml b/themes/jquerymobile/templates/RecordDriver/SolrDefault/link-author.phtml
deleted file mode 100644
index 1ef515fe458f58dbc0a53af91c01a7cbb097086e..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/RecordDriver/SolrDefault/link-author.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<?=$this->url('author-home')?>?author=<?=urlencode($this->lookfor)?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/RecordDriver/SolrDefault/link-journaltitle.phtml b/themes/jquerymobile/templates/RecordDriver/SolrDefault/link-journaltitle.phtml
deleted file mode 100644
index 5987653afd9f7c4fff7a830588128fde1077c8a4..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/RecordDriver/SolrDefault/link-journaltitle.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<?=$this->url('search-results')?>?lookfor=%22<?=urlencode($this->lookfor)?>%22&amp;type=JournalTitle
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/RecordDriver/SolrDefault/link-series.phtml b/themes/jquerymobile/templates/RecordDriver/SolrDefault/link-series.phtml
deleted file mode 100644
index bf7507d0a50c08a2edefcb6054506c4ca4c4dee1..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/RecordDriver/SolrDefault/link-series.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<?=$this->url('search-results')?>?lookfor=%22<?=urlencode($this->lookfor)?>%22&amp;type=Series
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/RecordDriver/SolrDefault/link-subject.phtml b/themes/jquerymobile/templates/RecordDriver/SolrDefault/link-subject.phtml
deleted file mode 100644
index 07a34f729d9e6eda12dbc8cbd2bb8b8b3ded9791..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/RecordDriver/SolrDefault/link-subject.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<?=$this->url('search-results')?>?lookfor=%22<?=urlencode($this->lookfor)?>%22&amp;type=Subject
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/RecordDriver/SolrDefault/link-title.phtml b/themes/jquerymobile/templates/RecordDriver/SolrDefault/link-title.phtml
deleted file mode 100644
index eca8c06502d139dd4ea37d34bb01aa516b9bd08e..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/RecordDriver/SolrDefault/link-title.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<?=$this->url('search-results')?>?lookfor=%22<?=urlencode($this->lookfor)?>%22&amp;type=Title
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/RecordDriver/SolrDefault/list-entry.phtml b/themes/jquerymobile/templates/RecordDriver/SolrDefault/list-entry.phtml
deleted file mode 100644
index f0084a3a352f839d0a7debc11d58cdf3c924ece1..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/RecordDriver/SolrDefault/list-entry.phtml
+++ /dev/null
@@ -1,72 +0,0 @@
-<?
-    // Set up some convenience variables:
-    $id = $this->driver->getUniqueId();
-    $source = $this->driver->getSourceIdentifier();
-    if (isset($this->list) && is_object($this->list)) {
-        $list_id = $this->list->id;
-        $user_id = $this->list->user_id;
-    } else {
-        $list_id = null;
-        $user_id = $this->user ? $this->user->id : null;
-    }
-?>
-<? $missing = $this->driver instanceof \VuFind\RecordDriver\Missing; ?>
-<a<? if (!$missing): ?> rel="external" href="<?=$this->recordLink()->getUrl($this->driver)?>"<? endif; ?>>
-  <div class="result source<?=$this->escapeHtmlAttr($this->driver->getSourceIdentifier())?> recordId<?=$this->driver->supportsAjaxStatus()?' ajaxItemId':''?>">
-    <input type="hidden" value="<?=$this->escapeHtmlAttr($this->driver->getUniqueID())?>" class="hiddenId" />
-    <h3><?=$this->record($this->driver)->getTitleHtml()?></h3>
-    <? $listAuthors = $this->driver->getPrimaryAuthors(); if (!empty($listAuthors)): ?>
-      <p><?=$this->transEsc('by')?>
-        <? $authorCount = count($listAuthors); foreach ($listAuthors as $i => $listAuthor): ?>
-            <?=$this->escapeHtml($listAuthor) . ($i + 1 < $authorCount ? ';' : '') ?>
-        <? endforeach; ?>
-      </p>
-    <? endif; ?>
-    <? $listTags = ($this->usertags()->getMode() !== 'disabled') ? $this->driver->getTags(
-        $list_id, // get tags for all lists if no single list is selected
-        $user_id, 'tag'
-       ) : array();
-    ?>
-    <? if (count($listTags) > 0): ?>
-      <p>
-        <strong><?=$this->transEsc('Your Tags')?>:</strong>
-        <? $i = 0; foreach ($listTags as $tag): ?><?=($i++ == 0)?'':', '?><?=$this->escapeHtml($tag->tag)?><? endforeach; ?>
-      </p>
-    <? endif; ?>
-    <? $listNotes = $this->driver->getListNotes($list_id, $user_id); ?>
-    <? if (count($listNotes) > 0): ?>
-      <p><strong><?=$this->transEsc('Notes')?>:</strong></p>
-      <? foreach ($listNotes as $note): ?>
-        <p><?=$this->escapeHtml($note)?></p>
-      <? endforeach; ?>
-    <? endif; ?>
-
-    <? if ($this->driver->supportsAjaxStatus()): ?>
-      <p class="callnumAndLocation">
-        <strong><?=$this->transEsc('Call Number')?>:</strong>
-        <span class="callnumber ajax_availability hide"><?=$this->transEsc('Loading')?>...</span><br />
-        <strong><?=$this->transEsc('Located')?>:</strong>
-        <span class="location ajax_availability hide"><?=$this->transEsc('Loading')?>...</span>
-      </p>
-    <? else: ?>
-      <? $summCallNo = $this->driver->getCallNumber(); if (!empty($summCallNo)): ?>
-        <p><strong><?=$this->transEsc('Call Number')?>:</strong> <?=$this->escapeHtml($summCallNo)?></p>
-      <? endif; ?>
-    <? endif; ?>
-    <?=$this->record($this->driver)->getFormatList()?>
-    <? if ($this->driver->supportsAjaxStatus()): ?>
-      <p><span class="ajax_availability hide status"><?=$this->transEsc('Loading')?>...</span></p>
-    <? endif; ?>
-  </div>
-</a>
-<? // Allow editing if a list is selected and edit is allowed OR if no list is selected
-   // and a user is logged in (which means we are viewing all of the user's favorites)
-   if ((isset($list) && $list->editAllowed($this->user)) || (!isset($list) && $this->user)): ?>
-     <? /* Use a different delete URL if we're removing from a specific list or the overall favorites: */
-       $deleteUrl = is_null($list_id)
-           ? $this->url('myresearch-favorites')
-           : $this->url('userList', array('id' => $list_id));
-       $deleteUrl .= '?delete=' . urlencode($id) . '&amp;source=' . urlencode($source);
-     ?>
-     <a class="delete_from_mylist" href="<?=$deleteUrl?>" rel="external"><?=$this->transEsc('Delete')?></a>
-<? endif; ?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/RecordDriver/SolrDefault/result-list.phtml b/themes/jquerymobile/templates/RecordDriver/SolrDefault/result-list.phtml
deleted file mode 100644
index 2cf0b32238e851ca2bfc2babbf902429bd78b1a3..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/RecordDriver/SolrDefault/result-list.phtml
+++ /dev/null
@@ -1,33 +0,0 @@
-<a rel="external" href="<?=$this->recordLink()->getUrl($this->driver)?>">
-  <div class="result source<?=$this->escapeHtmlAttr($this->driver->getSourceIdentifier())?> recordId<?=$this->driver->supportsAjaxStatus()?' ajaxItemId':''?>">
-    <input type="hidden" value="<?=$this->escapeHtmlAttr($this->driver->getUniqueID())?>" class="hiddenId" />
-    <h3><?=$this->record($this->driver)->getTitleHtml()?></h3>
-    <? $summAuthors = $this->driver->getPrimaryAuthorsWithHighlighting(); if (!empty($summAuthors)): ?>
-      <p><?=$this->transEsc('by')?>
-      <? $authorCount = count($summAuthors); foreach ($summAuthors as $i => $summAuthor): ?>
-        <?=$this->highlight($summAuthor)?><?=$i + 1 < $authorCount ? ';' : ''?>
-      <? endforeach; ?></p>
-    <? endif; ?>
-    <? if ($this->driver->supportsAjaxStatus()): ?>
-      <p class="callnumAndLocation">
-        <strong><?=$this->transEsc('Call Number')?>:</strong>
-        <span class="callnumber ajax_availability hide"><?=$this->transEsc('Loading')?>...</span><br />
-        <strong><?=$this->transEsc('Located')?>:</strong>
-        <span class="location ajax_availability hide"><?=$this->transEsc('Loading')?>...</span>
-      </p>
-    <? else: ?>
-      <? $summCallNo = $this->driver->getCallNumber(); if (!empty($summCallNo)): ?>
-        <p><strong><?=$this->transEsc('Call Number')?>:</strong> <?=$this->escapeHtml($summCallNo)?></p>
-      <? endif; ?>
-    <? endif; ?>
-    <?=$this->record($this->driver)->getFormatList()?>
-    <?
-       $openUrl = $this->openUrl($this->driver, 'results');
-       $openUrlActive = $openUrl->isActive();
-       $urls = $this->record($this->driver)->getLinkDetails($openUrlActive);
-    ?>
-    <? if (!$openUrlActive && empty($urls) && $this->driver->supportsAjaxStatus()): ?>
-      <p><span class="ajax_availability hide status"><?=$this->transEsc('Loading')?>...</span></p>
-    <? endif; ?>
-  </div>
-</a>
diff --git a/themes/jquerymobile/templates/RecordDriver/SolrDefault/toolbar.phtml b/themes/jquerymobile/templates/RecordDriver/SolrDefault/toolbar.phtml
deleted file mode 100644
index f9a1a971b1b22526d03aa1654fe6d01e696e73bf..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/RecordDriver/SolrDefault/toolbar.phtml
+++ /dev/null
@@ -1,13 +0,0 @@
-<div data-role="controlgroup">
-  <? if ($this->userlist()->getMode() !== 'disabled'): ?>
-    <a href="<?=$this->recordLink()->getActionUrl($this->driver, 'Save')?>" data-role="button" rel="external"><?=$this->transEsc("Add to favorites")?></a>
-  <? endif; ?>
-  <? if ($this->usertags()->getMode() !== 'disabled'): ?>
-    <a href="<?=$this->recordLink()->getActionUrl($this->driver, 'AddTag')?>" data-role="button" rel="external"><?=$this->transEsc("Add Tag")?></a>
-  <? endif; ?>
-  <? if (count($this->driver->getCitationFormats()) > 0): ?>
-    <a href="<?=$this->recordLink()->getActionUrl($this->driver, 'Cite')?>" data-role="button" rel="external"><?=$this->transEsc("Cite this")?></a>
-  <? endif; ?>
-  <a href="<?=$this->recordLink()->getActionUrl($this->driver, 'Email')?>" data-role="button" rel="external"><?=$this->transEsc("Email this")?></a>
-  <a href="<?=$this->recordLink()->getActionUrl($this->driver, 'SMS')?>" data-role="button" rel="external"><?=$this->transEsc("Text this")?></a>
-</div>
diff --git a/themes/jquerymobile/templates/RecordDriver/SolrWeb/result-list.phtml b/themes/jquerymobile/templates/RecordDriver/SolrWeb/result-list.phtml
deleted file mode 100644
index b205c9e871992dc0726e27edb1fe8323094606d1..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/RecordDriver/SolrWeb/result-list.phtml
+++ /dev/null
@@ -1,16 +0,0 @@
-<?
-    $url = $this->driver->getUrl();
-?>
-<a rel="external" href="<?=$this->escapeHtmlAttr($url)?>">
-  <div class="result">
-    <h3><?=$this->record($this->driver)->getTitleHtml()?></h3>
-  </div>
-  <? $snippet = $this->driver->getHighlightedSnippet(); ?>
-  <? $summary = $this->driver->getSummary(); ?>
-  <? if (!empty($snippet)): ?>
-    <p><?=$this->highlight($snippet['snippet'])?></p>
-  <? elseif (!empty($summary)): ?>
-    <p><?=$this->escapeHtml($summary[0])?></p>
-  <? endif; ?>
-  <span style="color:#008000;" class="ui-li-desc"><?=$this->escapeHtml($url)?></span>
-</a>
diff --git a/themes/jquerymobile/templates/RecordDriver/Summon/format-class.phtml b/themes/jquerymobile/templates/RecordDriver/Summon/format-class.phtml
deleted file mode 100644
index 5601e7f5710eb1c0cfd601f580dcdb2eeed2b292..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/RecordDriver/Summon/format-class.phtml
+++ /dev/null
@@ -1,44 +0,0 @@
-<?
-  // Convert Summon formats to VuFind formats so icons display correctly:
-  switch ($this->format) {
-      case 'Audio Recording':
-          echo 'audio';
-          break;
-      case 'Book':
-      case 'Book Chapter':
-          echo 'book';
-          break;
-      case 'Computer File':
-      case 'Web Resource':
-          echo 'electronic';
-          break;
-      case 'Dissertation':
-      case 'Manuscript':
-      case 'Paper':
-      case 'Patent':
-          echo 'manuscript';
-          break;
-      case 'eBook':
-          echo 'ebook';
-          break;
-      case 'Kit':
-          echo 'kit';
-          break;
-      case 'Image':
-      case 'Photograph':
-          echo 'photo';
-          break;
-      case 'Music Score':
-          echo 'musicalscore';
-          break;
-      case 'Newspaper Article':
-          echo 'newspaper';
-          break;
-      case 'Video Recording':
-          echo 'video';
-          break;
-      default:
-          echo 'journal';
-          break;
-  }
-?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/RecordDriver/Summon/link-author.phtml b/themes/jquerymobile/templates/RecordDriver/Summon/link-author.phtml
deleted file mode 100644
index 5aebd76f472dedf0a45e8d96de75376ed44caa8e..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/RecordDriver/Summon/link-author.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<?=$this->url('summon-search')?>?lookfor=%22<?=urlencode($this->lookfor)?>%22&amp;type=Author
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/RecordDriver/Summon/link-journaltitle.phtml b/themes/jquerymobile/templates/RecordDriver/Summon/link-journaltitle.phtml
deleted file mode 100644
index 5536935b4f4be76c407a7dd867e1d3f1365c31aa..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/RecordDriver/Summon/link-journaltitle.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<?=$this->url('summon-search')?>?lookfor=%22<?=urlencode($this->lookfor)?>%22&amp;type=PublicationTitle
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/RecordDriver/Summon/link-series.phtml b/themes/jquerymobile/templates/RecordDriver/Summon/link-series.phtml
deleted file mode 100644
index 26a9524f15a53509bf7ac0cb7d8416536fbdbbda..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/RecordDriver/Summon/link-series.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<?=$this->url('summon-search')?>?lookfor=%22<?=urlencode($this->lookfor)?>%22&amp;type=PublicationSeriesTitle
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/RecordDriver/Summon/link-subject.phtml b/themes/jquerymobile/templates/RecordDriver/Summon/link-subject.phtml
deleted file mode 100644
index cf66f99c10196f7e8380bf6955a933fc2730e6e9..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/RecordDriver/Summon/link-subject.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<?=$this->url('summon-search')?>?lookfor=%22<?=urlencode($this->lookfor)?>%22&amp;type=Subject
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/RecordDriver/Summon/link-title.phtml b/themes/jquerymobile/templates/RecordDriver/Summon/link-title.phtml
deleted file mode 100644
index 57cdc24f2d6d29a12d49a08447a5d08928a47b85..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/RecordDriver/Summon/link-title.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<?=$this->url('summon-search')?>?lookfor=%22<?=urlencode($this->lookfor)?>%22&amp;type=Title
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/RecordDriver/WorldCat/link-author.phtml b/themes/jquerymobile/templates/RecordDriver/WorldCat/link-author.phtml
deleted file mode 100644
index c64269d9bd5bb19862f2a7c56ad83d4ea4c03054..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/RecordDriver/WorldCat/link-author.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<?=$this->url('worldcat-search')?>?lookfor=<?=urlencode($this->lookfor)?>&amp;type=srw.au
diff --git a/themes/jquerymobile/templates/RecordDriver/WorldCat/link-series.phtml b/themes/jquerymobile/templates/RecordDriver/WorldCat/link-series.phtml
deleted file mode 100644
index d95ad084838175f0a631beffe32ea08268c1dd06..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/RecordDriver/WorldCat/link-series.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<?=$this->url('worldcat-search')?>?lookfor=%22<?=urlencode($this->lookfor)?>%22&amp;type=srw.se
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/RecordDriver/WorldCat/link-subject.phtml b/themes/jquerymobile/templates/RecordDriver/WorldCat/link-subject.phtml
deleted file mode 100644
index 6b6bb5c92351d841d4bb25b8cf4b28bdd27e4013..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/RecordDriver/WorldCat/link-subject.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<?=$this->url('worldcat-search')?>?lookfor=%22<?=urlencode($this->lookfor)?>%22&amp;type=srw.su
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/RecordDriver/WorldCat/link-title.phtml b/themes/jquerymobile/templates/RecordDriver/WorldCat/link-title.phtml
deleted file mode 100644
index 03f8d524558d20d3a643d5ea3b36e76553d3a8e2..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/RecordDriver/WorldCat/link-title.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<?=$this->url('worldcat-search')?>?lookfor=%22<?=urlencode($this->lookfor)?>%22&amp;type=srw.ti%3Asrw.se
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/RecordTab/collectionhierarchytree.phtml b/themes/jquerymobile/templates/RecordTab/collectionhierarchytree.phtml
deleted file mode 100644
index 0e11a7cf9f14846a32b3e619a7eed50902ac57e2..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/RecordTab/collectionhierarchytree.phtml
+++ /dev/null
@@ -1,10 +0,0 @@
-<? if (($collectionRecord = $this->tab->getActiveRecord()) !== false): ?>
-  <? $this->headTitle($this->translate('hierarchy_tree') . ': ' . $this->driver->getBreadcrumb()); ?>
-  <? if ($collectionRecord === null): ?>
-    <?=$this->render('collection/collection-record-error.phtml')?>
-  <? else: ?>
-    <?=$this->record($collectionRecord)->getCollectionBriefRecord()?>
-  <? endif; ?>
-<? else: ?>
-  <?=$this->render('RecordTab/hierarchytree.phtml')?>
-<? endif; ?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/RecordTab/collectionlist.phtml b/themes/jquerymobile/templates/RecordTab/collectionlist.phtml
deleted file mode 100644
index 5d541acacba4d2d2ad7eb6662362b68e0ea9b494..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/RecordTab/collectionlist.phtml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?
-    // Set page title.
-    $this->headTitle($this->translate('Collection Items') . ': ' . $this->driver->getBreadcrumb());
-
-    // Get search results
-    $results = $this->tab->getResults();
-    $params = $this->tab->getParams();
-    $searchDetails = array('results' => $results, 'params' => $params);
-?>
-<? if (($recordTotal = $results->getResultTotal()) > 0): // only display these at very top if we have results ?>
-  <p>
-  <?=$this->transEsc("Showing")?>
-  <strong><?=$this->localizedNumber($results->getStartRecord())?></strong> - <strong><?=$this->localizedNumber($results->getEndRecord())?></strong>
-  <?=$this->transEsc('of')?> <strong><?=$this->localizedNumber($recordTotal)?></strong> <?=$this->transEsc('Items')?>
-  </p>
-  <?=$this->render('search/list-' . $results->getParams()->getView() . '.phtml', $searchDetails)?>
-  <?=$this->paginationControl($results->getPaginator(), 'Sliding', 'search/pagination.phtml', array('results' => $results))?>
-<? else: ?>
-  <?=$this->transEsc('collection_empty')?>
-<? endif; ?>
diff --git a/themes/jquerymobile/templates/RecordTab/description.phtml b/themes/jquerymobile/templates/RecordTab/description.phtml
deleted file mode 100644
index 5536c4045db378fbc5b080d2b043b99ee1908dce..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/RecordTab/description.phtml
+++ /dev/null
@@ -1,193 +0,0 @@
-<?
-    // Set page title.
-    $this->headTitle($this->translate('Description') . ': ' . $this->driver->getBreadcrumb());
-
-    // Grab clean ISBN for convenience:
-    $isbn = $this->driver->getCleanISBN();
-
-    // Activate Syndetics Plus if necessary:
-    if ($this->syndeticsPlus()->isActive()) {
-        $this->headScript()->appendFile($this->syndeticsPlus()->getScript());
-    }
-?>
-<dl class="biblio" title="<?=$this->transEsc('Description')?>">
-  <? $summ = $this->driver->getSummary(); if (!empty($summ)): ?>
-    <? $contentDisplayed = true; ?>
-    <dt><?=$this->transEsc('Summary')?>: </dt>
-    <dd>
-      <? foreach ($summ as $field): ?>
-        <p><?=$this->escapeHtml($field)?></p>
-      <? endforeach; ?>
-    </dd>
-  <? endif; ?>
-
-  <? $dateSpan = $this->driver->getDateSpan(); if (!empty($dateSpan)): ?>
-    <? $contentDisplayed = true; ?>
-    <dt><?=$this->transEsc('Published')?>: </dt>
-    <dd>
-      <? foreach ($dateSpan as $field): ?>
-        <p><?=$this->escapeHtml($field)?></p>
-      <? endforeach; ?>
-    </dd>
-  <? endif; ?>
-
-  <? $notes = $this->driver->getGeneralNotes(); if (!empty($notes)): ?>
-    <? $contentDisplayed = true; ?>
-    <dt><?=$this->transEsc('Item Description')?>: </dt>
-    <dd>
-      <? foreach ($notes as $field): ?>
-        <p><?=$this->escapeHtml($field)?></p>
-      <? endforeach; ?>
-    </dd>
-  <? endif; ?>
-
-  <? $physical = $this->driver->getPhysicalDescriptions(); if (!empty($physical)): ?>
-    <? $contentDisplayed = true; ?>
-    <dt><?=$this->transEsc('Physical Description')?>: </dt>
-    <dd>
-      <? foreach ($physical as $field): ?>
-        <p><?=$this->escapeHtml($field)?></p>
-      <? endforeach; ?>
-    </dd>
-  <? endif; ?>
-
-  <? $freq = $this->driver->getPublicationFrequency(); if (!empty($freq)): ?>
-    <? $contentDisplayed = true; ?>
-    <dt><?=$this->transEsc('Publication Frequency')?>: </dt>
-    <dd>
-      <? foreach ($freq as $field): ?>
-        <p><?=$this->escapeHtml($field)?></p>
-      <? endforeach; ?>
-    </dd>
-  <? endif; ?>
-
-  <? $playTime = $this->driver->getPlayingTimes(); if (!empty($playTime)): ?>
-    <? $contentDisplayed = true; ?>
-    <dt><?=$this->transEsc('Playing Time')?>: </dt>
-    <dd>
-      <? foreach ($playTime as $field): ?>
-        <p><?=$this->escapeHtml($field)?></p>
-      <? endforeach; ?>
-    </dd>
-  <? endif; ?>
-
-  <? $system = $this->driver->getSystemDetails(); if (!empty($system)): ?>
-    <? $contentDisplayed = true; ?>
-    <dt><?=$this->transEsc('Format')?>: </dt>
-    <dd>
-      <? foreach ($system as $field): ?>
-        <p><?=$this->escapeHtml($field)?></p>
-      <? endforeach; ?>
-    </dd>
-  <? endif; ?>
-
-  <? $audience = $this->driver->getTargetAudienceNotes(); if (!empty($audience)): ?>
-    <? $contentDisplayed = true; ?>
-    <dt><?=$this->transEsc('Audience')?>: </dt>
-    <dd>
-      <? foreach ($audience as $field): ?>
-        <p><?=$this->escapeHtml($field)?></p>
-      <? endforeach; ?>
-    </dd>
-  <? endif; ?>
-
-  <? $awards = $this->driver->getAwards(); if (!empty($awards)): ?>
-    <? $contentDisplayed = true; ?>
-    <dt><?=$this->transEsc('Awards')?>: </dt>
-    <dd>
-      <? foreach ($awards as $field): ?>
-        <p><?=$this->escapeHtml($field)?></p>
-      <? endforeach; ?>
-    </dd>
-  <? endif; ?>
-
-  <? $credits = $this->driver->getProductionCredits(); if (!empty($credits)): ?>
-    <? $contentDisplayed = true; ?>
-    <dt><?=$this->transEsc('Production Credits')?>: </dt>
-    <dd>
-      <? foreach ($credits as $field): ?>
-        <p><?=$this->escapeHtml($field)?></p>
-      <? endforeach; ?>
-    </dd>
-  <? endif; ?>
-
-  <? $bib = $this->driver->getBibliographyNotes(); if (!empty($bib)): ?>
-    <? $contentDisplayed = true; ?>
-    <dt><?=$this->transEsc('Bibliography')?>: </dt>
-    <dd>
-      <? foreach ($bib as $field): ?>
-        <p><?=$this->escapeHtml($field)?></p>
-      <? endforeach; ?>
-    </dd>
-  <? endif; ?>
-
-  <? $isbns = $this->driver->getISBNs(); if (!empty($isbns)): ?>
-    <? $contentDisplayed = true; ?>
-    <dt><?=$this->transEsc('ISBN')?>: </dt>
-    <dd>
-      <? foreach ($isbns as $field): ?>
-        <p><?=$this->escapeHtml($field)?></p>
-      <? endforeach; ?>
-    </dd>
-  <? endif; ?>
-
-  <? $issns = $this->driver->getISSNs(); if (!empty($issns)): ?>
-    <? $contentDisplayed = true; ?>
-    <dt><?=$this->transEsc('ISSN')?>: </dt>
-    <dd>
-      <? foreach ($issns as $field): ?>
-        <p><?=$this->escapeHtml($field)?></p>
-      <? endforeach; ?>
-    </dd>
-  <? endif; ?>
-
-  <? $doi = $this->driver->tryMethod('getCleanDOI'); if (!empty($doi)): ?>
-    <? $contentDisplayed = true; ?>
-    <dt><?=$this->transEsc('DOI')?>: </dt>
-    <dd><p><?=$this->escapeHtml($doi)?></p></dd>
-  <? endif; ?>
-
-  <? $related = $this->driver->getRelationshipNotes(); if (!empty($related)): ?>
-    <? $contentDisplayed = true; ?>
-    <dt><?=$this->transEsc('Related Items')?>: </dt>
-    <dd>
-      <? foreach ($related as $field): ?>
-        <p><?=$this->escapeHtml($field)?></p>
-      <? endforeach; ?>
-    </dd>
-  <? endif; ?>
-
-  <? $access = $this->driver->getAccessRestrictions(); if (!empty($access)): ?>
-    <? $contentDisplayed = true; ?>
-    <dt><?=$this->transEsc('Access')?>: </dt>
-    <dd>
-      <? foreach ($access as $field): ?>
-        <p><?=$this->escapeHtml($field)?></p>
-      <? endforeach; ?>
-    </dd>
-  <? endif; ?>
-
-  <? $findingAids = $this->driver->getFindingAids(); if (!empty($findingAids)): ?>
-    <? $contentDisplayed = true; ?>
-    <dt><?=$this->transEsc('Finding Aid')?>: </dt>
-    <dd>
-      <? foreach ($findingAids as $field): ?>
-        <p><?=$this->escapeHtml($field)?></p>
-      <? endforeach; ?>
-    </dd>
-  <? endif; ?>
-
-  <? $publicationPlaces = $this->driver->getHierarchicalPlaceNames(); if (!empty($publicationPlaces)): ?>
-    <? $contentDisplayed = true; ?>
-    <dt><?=$this->transEsc('Publication_Place')?>: </dt>
-    <dd>
-      <? foreach ($publicationPlaces as $field): ?>
-         <p><?=$this->escapeHtml($field)?></p>
-      <? endforeach; ?>
-    </dd>
-    <? endif; ?>
-
-  <? if (!isset($contentDisplayed) || !$contentDisplayed): // Avoid errors if there were no rows above ?>
-    <dd><p><?=$this->transEsc('no_description')?></p></dd>
-  <? endif; ?>
-</dl>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/RecordTab/excerpt.phtml b/themes/jquerymobile/templates/RecordTab/excerpt.phtml
deleted file mode 100644
index 09d6b34abde0a84ce1373be3d20fdeb6017a7a0e..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/RecordTab/excerpt.phtml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?
-    // Set page title.
-    $this->headTitle($this->translate('Excerpt') . ': ' . $this->driver->getBreadcrumb());
-
-    // Grab excerpt data:
-    $excerpts = $this->tab->getContent();
-
-    // Activate Syndetics Plus if necessary:
-    if ($this->syndeticsPlus()->isActive()) {
-        $this->headScript()->appendFile($this->syndeticsPlus()->getScript());
-    }
-?>
-<? if (count($excerpts) > 0): ?>
-  <? foreach ($excerpts as $provider => $list): ?>
-    <? foreach ($list as $excerpt): ?>
-      <p class="summary"><?=$excerpt['Content']?></p>
-      <?=isset($excerpt['Copyright']) ? $excerpt['Copyright'] : ''?>
-      <hr/>
-    <? endforeach; ?>
-  <? endforeach; ?>
-<? else: ?>
-  <?=$this->transEsc('No excerpts were found for this record.')?>
-<? endif; ?>
diff --git a/themes/jquerymobile/templates/RecordTab/hierarchytree.phtml b/themes/jquerymobile/templates/RecordTab/hierarchytree.phtml
deleted file mode 100644
index a951a6dd517a108e01592a3f5e196340c17eab23..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/RecordTab/hierarchytree.phtml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?
-    // Set page title.
-    $this->headTitle($this->translate('hierarchy_tree') . ': ' . $this->driver->getBreadcrumb());
-    $hierarchyTreeList = $this->tab->getTreeList();
-    $activeTree = $this->tab->getActiveTree();
-?>
-<div>
-  <? if (count($hierarchyTreeList) > 1): ?>
-    <div id="treeSelector">
-      <? foreach ($hierarchyTreeList as $hierarchy => $hierarchyTitle): ?>
-        <a class="tree<?=($activeTree == $hierarchy) ? ' currentTree' : ''?>" href="<?=$this->recordLink()->getTabUrl($this->driver, 'HierarchyTree')?>?hierarchy=<?=urlencode($hierarchy)?>"><?=$this->escapeHtml($hierarchyTitle)?></a>
-      <? endforeach; ?>
-    </div>
-  <? endif; ?>
-  <? if ($activeTree): ?>
-    <div id="hierarchyTreeHolder">
-      <div id="hierarchyTree">
-        <?=str_replace(' href="', ' data-ajax="false" href="', $this->tab->renderTree($this->url('home')))?>
-      </div>
-    </div>
-  <? endif; ?>
-</div>
diff --git a/themes/jquerymobile/templates/RecordTab/holdingsils.phtml b/themes/jquerymobile/templates/RecordTab/holdingsils.phtml
deleted file mode 100644
index 3da187abb51a5ea1de8ecc724c674fd13056b832..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/RecordTab/holdingsils.phtml
+++ /dev/null
@@ -1,152 +0,0 @@
-<?
-    // Set up convenience variables:
-    $account = $this->auth()->getManager();
-    $user = $account->isLoggedIn();
-    $offlineMode = $this->ils()->getOfflineMode();
-    try {
-        $holdings = $this->driver->getRealTimeHoldings();
-    } catch (\VuFind\Exception\ILS $e) {
-        $holdings = [];
-        $offlineMode = 'ils-offline';
-    }
-
-    // Set page title.
-    $this->headTitle($this->translate('Holdings') . ': ' . $this->driver->getBreadcrumb());
-?>
-
-<?=$this->context($this)->renderInContext('librarycards/selectcard.phtml', array('user' => $this->auth()->isLoggedIn())); ?>
-
-<? if ($offlineMode == "ils-offline"): ?>
-  <div class="sysInfo">
-    <h2><?=$this->transEsc('ils_offline_title')?></h2>
-    <p><strong><?=$this->transEsc('ils_offline_status')?></strong></p>
-    <p><?=$this->transEsc('ils_offline_holdings_message')?></p>
-    <? $supportEmail = $this->escapeHtmlAttr($this->systemEmail()); ?>
-    <p><a href="mailto:<?=$supportEmail?>"><?=$supportEmail?></a></p>
-  </div>
-<? endif; ?>
-<? if (($this->ils()->getHoldsMode() == 'driver' && !empty($holdings)) || $this->ils()->getTitleHoldsMode() == 'driver'): ?>
-  <? if ($account->loginEnabled() && $offlineMode != 'ils-offline'): ?>
-    <? if (!$user): ?>
-      <div class="info">
-        <a href="<?=$this->recordLink()->getTabUrl($this->driver, 'Holdings')?>?login=true&amp;catalogLogin=true"><?=$this->transEsc("Login")?></a> <?=$this->transEsc("hold_login")?>
-      </div>
-    <? elseif (!$user->cat_username): ?>
-      <div class="info">
-        <?=str_replace('href="', 'rel="external" href="', $this->translate("hold_profile_html", array('%%url%%' => $this->recordLink()->getTabUrl($this->driver, 'Holdings') . '?catalogLogin=true')))?>
-      </div>
-    <? endif; ?>
-  <? endif; ?>
-<? endif; ?>
-<? $holdingTitleHold = $this->driver->tryMethod('getRealTimeTitleHold'); if (!empty($holdingTitleHold)): ?>
-    <a rel="external" class="holdPlace" href="<?=$this->recordLink()->getRequestUrl($holdingTitleHold, false)?>"><?=$this->transEsc('title_hold_place')?></a>
-<? endif; ?>
-<? foreach ($holdings as $holding): ?>
-<h4>
-  <? $locationText = $this->transEsc('location_' . $holding['location'], array(), $holding['location']); ?>
-  <? if (isset($holding['locationhref']) && $holding['locationhref']): ?>
-    <a href="<?=$holding['locationhref']?>" rel="external"><?=$locationText?></a>
-  <? else: ?>
-    <?=$locationText?>
-  <? endif; ?>
-</h4>
-<table class="holdings" summary="<?=$this->transEsc('Holdings details from')?> <?=$this->transEsc($holding['location'])?>">
-  <? $callNos = $this->tab->getUniqueCallNumbers($holding['items']); if (!empty($callNos)): ?>
-  <tr>
-    <th><?=$this->transEsc("Call Number")?>: </th>
-    <td>
-      <? foreach ($callNos as $callNo): ?>
-        <? if ($this->callnumberHandler): ?>
-          <a href="<?=$this->url('alphabrowse-home') ?>?source=<?=$this->escapeHtmlAttr($this->callnumberHandler) ?>&amp;from=<?=$this->escapeHtmlAttr($callNo) ?>"><?=$this->escapeHtml($callNo)?></a>
-        <? else: ?>
-          <?=$this->escapeHtml($callNo)?>
-        <? endif; ?>
-        <br />
-      <? endforeach; ?>
-    </td>
-  </tr>
-  <? endif; ?>
-  <? if (isset($holding['textfields'])): foreach ($holding['textfields'] as $textFieldName => $textFields): ?>
-    <tr>
-      <? // Translation for summary is a special case for backwards-compatibility ?>
-      <th><?=$textFieldName == 'summary' ? $this->transEsc("Volume Holdings") : $this->transEsc(ucfirst($textFieldName))?>:</th>
-      <td>
-        <? foreach ($textFields as $current): ?>
-          <?=$this->escapeHtml($current)?><br/>
-        <? endforeach; ?>
-      </td>
-    </tr>
-  <? endforeach; endif; ?>
-  <? foreach ($holding['items'] as $row): ?>
-    <? $check = (isset($row['check']) && $row['check']); ?>
-    <? if (isset($row['barcode']) && $row['barcode'] != ""): ?>
-      <tr>
-        <th><?=$this->transEsc("Copy")?> <?=$this->escapeHtml($row['number'])?></th>
-        <td>
-          <? if ($row['reserve'] == "Y"): ?>
-            <?=$this->transEsc("On Reserve - Ask at Circulation Desk")?><br />
-          <? endif; ?>
-          <? if (isset($row['use_unknown_message']) && $row['use_unknown_message']): ?>
-            <span class="unknown"><?=$this->transEsc("status_unknown_message")?></span>
-          <? else: ?>
-            <? if ($row['availability']): ?>
-              <? /* Begin Available Items (Holds) */ ?>
-               <span class="available"><?=$this->transEsc("Available")?></span>
-              <? if (isset($row['link']) && $row['link']): ?>
-                <br />
-                <a rel="external" class="holdPlace<?=$check ? ' checkRequest' : ''?>" href="<?=$this->recordLink()->getRequestUrl($row['link'], false)?>"><span><?=$this->transEsc($check ? "Check Hold" : "Place a Hold")?></span></a>
-              <? endif; ?>
-            <? else: ?>
-              <? /* Begin Unavailable Items (Recalls) */ ?>
-              <span class="checkedout"><?=$this->transEsc($row['status'])?></span>
-              <? if (isset($row['returnDate']) && $row['returnDate']): ?> <span class="statusExtra"><?=$this->escapeHtml($row['returnDate'])?></span><? endif; ?>
-              <? if (isset($row['duedate']) && $row['duedate']): ?>
-                <span class="statusExtra"><?=$this->transEsc("Due")?>: <?=$this->escapeHtml($row['duedate'])?></span>
-              <? endif; ?>
-              <? if (isset($row['requests_placed']) && $row['requests_placed'] > 0): ?>
-                <span><?=$this->transEsc("Requests")?>: <?=$this->escapeHtml($row['requests_placed'])?></span>
-              <? endif; ?>
-              <? if (isset($row['link']) && $row['link']): ?>
-                <br />
-                <a rel="external" class="holdPlace<?=$check ? ' checkRequest' : ''?>" href="<?=$this->recordLink()->getRequestUrl($row['link'], false)?>"><span><?=$this->transEsc($check ? "Check Recall" : "Recall This")?></span></a>
-              <? endif; ?>
-            <? endif; ?>
-            <? if (isset($row['item_notes'])): ?>
-              <ul>
-                <li>
-                  <?=$this->transEsc("Item Notes")?>:
-                  <ul>
-                    <? foreach ($row['item_notes'] as $item_note): ?>
-                      <li><?=$this->escapeHtml($item_note) ?></li>
-                    <? endforeach; ?>
-                  </ul>
-                </li>
-              </ul>
-            <? endif; ?>
-          <? endif; ?>
-        </td>
-      </tr>
-    <? endif; ?>
-  <? endforeach; ?>
-  <? if (!empty($holding['purchase_history'])): ?>
-    <tr>
-      <th><?=$this->transEsc("Most Recent Received Issues")?>:</th>
-      <td>
-        <? foreach ($holding['purchase_history'] as $current): ?>
-          <?=$this->escapeHtml($current['issue'])?><br/>
-        <? endforeach; ?>
-      </td>
-    </tr>
-  <? endif; ?>
-</table>
-<? endforeach; ?>
-
-<? $history = $this->driver->getRealTimeHistory(); ?>
-<? if (is_array($history) && !empty($history)): ?>
-<h4><?=$this->transEsc("Most Recent Received Issues")?></h4>
-<ul>
-  <? foreach ($history as $row): ?>
-    <li><?=$this->escapeHtml($row['issue'])?></li>
-  <? endforeach; ?>
-</ul>
-<? endif; ?>
diff --git a/themes/jquerymobile/templates/RecordTab/holdingsworldcat.phtml b/themes/jquerymobile/templates/RecordTab/holdingsworldcat.phtml
deleted file mode 100644
index 8148ca6d4cc364f638e60273721c9755374a63a5..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/RecordTab/holdingsworldcat.phtml
+++ /dev/null
@@ -1,24 +0,0 @@
-<? $holdings = $this->tab->getHoldings(); if ($holdings && count($holdings) > 0): ?>
-<h3><?=$this->transEsc('Holdings at Other Libraries')?></h3>
-<table cellpadding="2" cellspacing="0" border="0" class="citation" width="100%">
-<? foreach ($holdings as $holding): ?>
-  <tr>
-    <th colspan="2">
-      <? if (isset($holding->electronicAddress->text) && !empty($holding->electronicAddress->text)): ?>
-      <a href="<?=$this->escapeHtmlAttr($holding->electronicAddress->text)?>"><?=$this->escapeHtml($holding->physicalLocation)?></a>
-      <? else: ?>
-      <?=$this->escapeHtml($holding->physicalLocation)?>
-      <? endif; ?>
-    </th>
-  </tr>
-  <tr>
-    <th><?=$this->transEsc('Address')?>: </th>
-    <td><?=$this->escapeHtml($holding->physicalAddress->text)?></td>
-  </tr>
-  <tr>
-    <th><?=$this->transEsc('Copies')?>: </th>
-    <td><?=$this->escapeHtml($holding->holdingSimple->copiesSummary->copiesCount)?></td>
-  </tr>
-<? endforeach; ?>
-</table>
-<? endif; ?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/RecordTab/map.phtml b/themes/jquerymobile/templates/RecordTab/map.phtml
deleted file mode 100644
index 1d088d2ec8b3a9984fbedeb5abd8f421c493cda6..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/RecordTab/map.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<!-- not supported in mobile interface -->
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/RecordTab/preview.phtml b/themes/jquerymobile/templates/RecordTab/preview.phtml
deleted file mode 100644
index 1d088d2ec8b3a9984fbedeb5abd8f421c493cda6..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/RecordTab/preview.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<!-- not supported in mobile interface -->
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/RecordTab/reviews.phtml b/themes/jquerymobile/templates/RecordTab/reviews.phtml
deleted file mode 100644
index be958a929e20e2ec55babfe53b53d34835f2ebcc..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/RecordTab/reviews.phtml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?
-    // Set page title.
-    $this->headTitle($this->translate('Reviews') . ': ' . $this->driver->getBreadcrumb());
-
-    // Grab review data:
-    $reviews = $this->tab->getContent();
-
-    // Activate Syndetics Plus if necessary:
-    if ($this->syndeticsPlus()->isActive()) {
-        $this->headScript()->appendFile($this->syndeticsPlus()->getScript());
-    }
-?>
-<? if (count($reviews) > 0): ?>
-  <? foreach ($reviews as $provider => $list): ?>
-    <? foreach ($list as $review): ?>
-      <? if (isset($review['Summary']) && !empty($review['Summary'])): ?>
-        <p>
-          <? if (isset($review['Rating'])): ?>
-            <img src="<?=$this->imageLink($review['Rating'] . '.gif')?>" alt="<?=$review['Rating']?>/5 Stars"/>
-          <? endif; ?>
-          <strong><?=$review['Summary']?></strong> <?=isset($review['Date']) ? strftime('%B %e, %Y', strtotime($review['Date'])) : ''?>
-        </p>
-      <? endif; ?>
-      <? if (isset($review['Source'])): ?><strong><?=$this->transEsc('Review by')?> <?=$review['Source']?></strong><? endif; ?>
-      <p class="summary">
-        <?=isset($review['Content']) ? $review['Content'] : ''?>
-        <? if ((!isset($review['Content']) || empty($review['Content'])) && isset($review['ReviewURL'])): ?>
-          <a rel="external" href="<?=$this->escapeHtmlAttr($review['ReviewURL'])?>"><?=$this->transEsc('Read the full review online...')?></a>
-        <? endif; ?>
-      </p>
-      <?=isset($review['Copyright']) ? $review['Copyright'] : ''?>
-      <hr/>
-    <? endforeach; ?>
-  <? endforeach; ?>
-<? else: ?>
-  <?=$this->transEsc('No reviews were found for this record')?>.
-<? endif; ?>
diff --git a/themes/jquerymobile/templates/RecordTab/similaritemscarousel.phtml b/themes/jquerymobile/templates/RecordTab/similaritemscarousel.phtml
deleted file mode 100644
index 7a1c9bb01d66bb6044cfaef4f8fb5e3d7fe05979..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/RecordTab/similaritemscarousel.phtml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?
-  echo $this->headLink()->appendStylesheet('slick/slick.css');
-  echo $this->inlineScript(\Zend\View\Helper\HeadScript::FILE, 'slick/slick.js', 'SET');
-?>
-<h4><?=$this->transEsc('Similar Items')?></h4>
-<? $similarRecords = $this->tab->getResults(); ?>
-<? if (!empty($similarRecords)): ?>
-  <div id="similar-items-carousel">
-    <? foreach ($similarRecords as $index=>$data): ?>
-      <div>
-        <a class="hover-overlay" href="<?=$this->recordLink()->getUrl($data)?>">
-          <? $thumb = $this->record($data)->getThumbnail('large'); ?>
-          <img src="<?=$thumb ?>" title="<?=$data->getTitle() ?>"/>
-          <div class="content">
-            <? $formats = $data->getFormats(); ?>
-            <i class="fa fa-x<? if (count($formats) > 0): ?> fa-<?=preg_replace('/[^a-z0-9]/', '', strtolower($formats[0]))?>" title="<?=$formats[0] ?><? endif; ?>"></i>
-            <b><?=$this->escapeHtml($data->getTitle())?></b>
-            <? $authors = $data->getPrimaryAuthors(); if (!empty($authors)): ?>
-              <br/><?=$this->transEsc('by')?>: <?=$this->escapeHtml($authors[0]);?><? if (count($authors) > 1): ?>, <?=$this->transEsc('more_authors_abbrev')?><? endif; ?>
-            <? endif; ?>
-            <? $pubDates = $data->getPublicationDates(); if (!empty($pubDates)): ?>
-              <br/><?=$this->transEsc('Published')?>: (<?=$this->escapeHtml($pubDates[0])?>)
-            <? endif; ?>
-          </div>
-        </a>
-      </div>
-    <? endforeach; ?>
-  </div>
-<? $carouselJS = <<<JS
-$('#similar-items-carousel').slick({
-  dots:true,
-  slidesToShow: 4,
-  slidesToScroll: 4
-});
-JS;
-    echo $this->inlineScript(\Zend\View\Helper\HeadScript::SCRIPT, $carouselJS, 'SET'); ?>
-<? else: ?>
-  <p><?=$this->transEsc('Cannot find similar records')?></p>
-<? endif; ?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/RecordTab/staffviewarray.phtml b/themes/jquerymobile/templates/RecordTab/staffviewarray.phtml
deleted file mode 100644
index 4420e0d0f2bbb1b82ff78e17d599a0faf441eb40..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/RecordTab/staffviewarray.phtml
+++ /dev/null
@@ -1,17 +0,0 @@
-<?
-    // Set page title.
-    $this->headTitle($this->translate('Staff View') . ': ' . $this->driver->getBreadcrumb());
-?>
-<dl class="biblio" title="<?=$this->transEsc('Staff View')?>">
-  <? foreach ($this->driver->getRawData() as $field => $values): ?>
-    <dt><?=$this->escapeHtml($field)?></dt>
-    <dd>
-      <div style="width: 500px; overflow: auto;">
-        <? if (!is_array($values)) { $values = array($values); } ?>
-        <? foreach ($values as $value): ?>
-          <p><?=$this->escapeHtml(is_array($value) ? print_r($value, true) : $value)?></p>
-        <? endforeach; ?>
-      </div>
-    </dd>
-  <? endforeach; ?>
-</table>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/RecordTab/staffviewmarc.phtml b/themes/jquerymobile/templates/RecordTab/staffviewmarc.phtml
deleted file mode 100644
index cc89c983995ada977b5bafc4efa71b2dd0f67420..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/RecordTab/staffviewmarc.phtml
+++ /dev/null
@@ -1,5 +0,0 @@
-<?
-    // Set page title.
-    $this->headTitle($this->translate('Staff View') . ': ' . $this->driver->getBreadcrumb());
-?>
-<?=\VuFind\XSLT\Processor::process('record-marc.xsl', $this->driver->getXML('marc21'))?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/RecordTab/toc.phtml b/themes/jquerymobile/templates/RecordTab/toc.phtml
deleted file mode 100644
index e51b3a37a468b7b35f917d407b1f4a48d4f7c770..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/RecordTab/toc.phtml
+++ /dev/null
@@ -1,16 +0,0 @@
-<?
-    // Set page title.
-    $this->headTitle($this->translate('Table of Contents') . ': ' . $this->driver->getBreadcrumb());
-
-    $toc = $this->driver->getTOC();
-?>
-<? if (!empty($toc)): ?>
-  <h4><?=$this->transEsc('Table of Contents')?>: </h4>
-  <ul class="toc">
-    <? foreach ($toc as $line): ?>
-      <li><?=$this->escapeHtml($line)?></li>
-    <? endforeach; ?>
-  </ul>
-<? else: ?>
-  <p><?=$this->transEsc("Table of Contents unavailable")?>.</p>
-<? endif; ?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/RecordTab/usercomments.phtml b/themes/jquerymobile/templates/RecordTab/usercomments.phtml
deleted file mode 100644
index 824f636bb5909125628be04aa93463fc34ea272f..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/RecordTab/usercomments.phtml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?
-    // Set page title.
-    $this->headTitle($this->translate('Comments') . ': ' . $this->driver->getBreadcrumb());
-?>
-<ul class="results comments" data-role="listview" data-split-icon="minus" data-split-theme="d" data-inset="true" data-dividertheme="e">
-  <?=$this->render('record/comments-list.phtml')?>
-</ul>
-
-<form action="<?=$this->recordLink()->getActionUrl($this->driver, 'AddComment')?>" method="post" data-ajax="false">
-  <input type="hidden" name="id" value="<?=$this->escapeHtmlAttr($this->driver->getUniqueId())?>"/>
-  <input type="hidden" name="source" value="<?=$this->escapeHtmlAttr($this->driver->getSourceIdentifier())?>"/>
-  <div data-role="fieldcontain">
-    <label for="comments_form_comment"><?=$this->transEsc("Your Comment")?>:</label>
-    <textarea id="comments_form_comment" name="comment"></textarea>
-  </div>
-  <?=$this->recaptcha()->html($this->tab->isRecaptchaActive()) ?>
-  <div data-role="fieldcontain">
-    <input type="submit" value="<?=$this->transEsc("Add your comment")?>"/>
-  </div>
-</form>
diff --git a/themes/jquerymobile/templates/ajax/status-available-services.phtml b/themes/jquerymobile/templates/ajax/status-available-services.phtml
deleted file mode 100644
index 34637569ac4e3cc087167287d505dec12530817a..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/ajax/status-available-services.phtml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?
-// defaultServiceStatusMessage for multiple status and as fallback for missing translations
-$defaultServiceStatusMessage = 'HoldingStatus::services_available_html';
-
-// generate serviceStatusMessage
-$serviceStatusMessage =
-    count($services) == 1
-        ? $this->transEsc('HoldingStatus::service_available_' . $services[0], [], $defaultServiceStatusMessage)
-        : $defaultServiceStatusMessage ;
-
-// build the translated serviceList for usage in defaultServiceStatusMessage
-$that = $this;
-$translator = function ($in) use ($that) {
-    return '<span class="service_' . $in . '">' . $that->transEsc('HoldingStatus::service_' . $in, [], $in) . '</span>';
-};
-$serviceList = implode('', array_map($translator, $services));
-
-?>
-<span class="available services-<?=implode('-', $services)?>">
-  <?=$serviceStatusMessage === $defaultServiceStatusMessage
-      ? $this->translate($serviceStatusMessage, ['%%list%%' => $serviceList])
-      : '<span class="service_' . $services[0] . '">' . $serviceStatusMessage . '</span>' ?>
-</span>
diff --git a/themes/jquerymobile/templates/ajax/status-available.phtml b/themes/jquerymobile/templates/ajax/status-available.phtml
deleted file mode 100644
index aa1ada91ffa142a34291afd5f9a75f735847e077..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/ajax/status-available.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<span class="available"><?=$this->transEsc("Available")?></span>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/ajax/status-full.phtml b/themes/jquerymobile/templates/ajax/status-full.phtml
deleted file mode 100644
index e01dc8c7a37cfa1d4d7c116a1c655b3bd4c6690e..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/ajax/status-full.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<? /* full status is ignored by mobile theme. */ ?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/ajax/status-unavailable.phtml b/themes/jquerymobile/templates/ajax/status-unavailable.phtml
deleted file mode 100644
index 5f17859891601209f6033ff9e9d1ada615517297..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/ajax/status-unavailable.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<span class="checkedout"><?=$this->transEsc("Checked Out")?></span>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/ajax/status-unknown.phtml b/themes/jquerymobile/templates/ajax/status-unknown.phtml
deleted file mode 100644
index c6ef06ef2e3fb0edb1cb77223fc03b06b0146268..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/ajax/status-unknown.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<span class="unknown"><?=$this->transEsc("status_unknown_message")?></span>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/alphabrowse/home.phtml b/themes/jquerymobile/templates/alphabrowse/home.phtml
deleted file mode 100644
index 9fdd7c07d96287cc351056244170669bfc9ab875..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/alphabrowse/home.phtml
+++ /dev/null
@@ -1,88 +0,0 @@
-<?
-  $this->headTitle($this->translate('Browse the Collection Alphabetically'));
-  $baseQuery = array('source' => $this->source, 'from' => $this->from);
-?>
-
-<div data-role="page">
-  <? if (!$this->result): ?>
-    <?=$this->mobileMenu()->header() ?>
-    <div class="resulthead">
-      <form method="get" action="<?=$this->url('alphabrowse-home')?>" name="alphaBrowseForm" id="alphaBrowseForm" data-ajax="false">
-        <div class="ui-body ui-body-d">
-          <label for="alphaBrowseForm_source"><?=$this->transEsc('Browse Alphabetically') ?></label>
-          <select id="alphaBrowseForm_source" name="source">
-            <? foreach ($this->alphaBrowseTypes as $key => $item): ?>
-              <option value="<?=$this->escapeHtmlAttr($key) ?>"<? if ($this->source == $key): ?> selected="selected"<? endif; ?>><?=$this->transEsc($item) ?></option>
-            <? endforeach; ?>
-          </select>
-          <label for="alphaBrowseForm_from"><?=$this->transEsc('starting from') ?></label>
-          <input type="search" name="from" id="alphaBrowseForm_from" value="<?=$this->escapeHtmlAttr($this->from) ?>"/>
-          <input type="submit" data-theme="b" value="<?=$this->transEsc('Browse') ?>"/>
-        </div>
-      </form>
-    </div>
-  <? else: ?>
-    <?=$this->mobileMenu()->header(array(
-      'extraButtons' => array('<a rel="external" href="'
-        . $this->url('alphabrowse-home')
-        . '" data-icon="home" class="ui-btn-left">'
-        . $this->transEsc("Browse Home")
-        . '</a>'
-    ))) ?>
-    <? ob_start(); ?>
-      <div class="ui-grid-a">
-        <div class="ui-block-a">
-          <? if (isset($this->prevpage)): ?>
-            <a data-role="button" data-mini="true" data-icon="arrow-l" href="<?=$this->escapeHtmlAttr($this->url('alphabrowse-home', array(), array('query' => $baseQuery + array('page' => $this->prevpage))))?>"><?=$this->transEsc('Prev')?></a>
-          <? endif; ?>
-        </div>
-        <div class="ui-block-b">
-          <? if (isset($this->nextpage)): ?>
-            <a data-role="button" data-mini="true" data-icon="arrow-r" data-iconpos="right" href="<?=$this->escapeHtmlAttr($this->url('alphabrowse-home', array(), array('query' => $baseQuery + array('page' => $this->nextpage))))?>"><?=$this->transEsc('Next')?></a>
-          <? endif; ?>
-        </div>
-      </div>
-    <? $pageLinks = ob_get_contents(); ?>
-    <? ob_end_clean(); ?>
-    <?=$pageLinks ?>
-    <div class="alphaBrowseResult">
-      <ul class="ui-listview" data-role="listview">
-      <? foreach ($this->result['Browse']['items'] as $i => $item): ?>
-        <? $highlight = (isset($this->highlight_row) && $i == $this->highlight_row) ? true : false ?>
-        <li class="ui-li-has-count<?=$highlight ? ' info' : '' ?>">
-          <? if ($highlight && isset($this->match_type) && ($this->match_type == "NONE")): ?>
-            <?// this is the right row but query doesn't match value ?>
-              <?=$this->transEsc('your_match_would_be_here') ?>
-            </li>
-            <li class="ui-li-has-count">
-          <? endif; ?>
-          <? if ($item['count'] > 0 || count($item['useInstead']) > 0): ?>
-            <? if (count($item['useInstead']) > 0): ?>
-              <? $query = array('from' => implode($item['useInstead'])) + $baseQuery; ?>
-              <? $searchLink = $this->escapeHtmlAttr($this->url('alphabrowse-home', array(), array('query' => $query))); ?>
-            <? else: ?>
-              <? $searchLink = $this->escapeHtmlAttr($this->alphabrowse()->getUrl($this->source, $item)); ?>
-            <? endif; ?>
-          <? endif; ?>
-          <a class="ui-link-inherit" data-ajax="false" href="<?=$searchLink ?>">
-            <div class="ui-btn-text">
-              <?=$this->escapeHtml($item['heading'])?>
-              <? if (count($item['useInstead']) > 0): ?>
-              <i>(<?=$this->transEsc('Use instead') ?>: <?=implode($item['useInstead']) ?>)</i>
-              <? endif; ?>
-            </div>
-          </a>
-          <? if ($item['count'] > 0): ?><span class="ui-li-count ui-btn-up-c ui-btn-corner-all"><?=$item['count']?></span><? endif; ?>
-          <span class="ui-icon ui-icon-arrow-r ui-icon-shadow"></span>
-        </li>
-      <? endforeach; ?>
-      <? if (isset($this->highlight_end)): ?>
-        <li class="ui-li-has-count info">
-          <?=$this->transEsc('your_match_would_be_here') ?>
-        </li>
-      <? endif; ?>
-      </ul>
-    </div>
-    <?=$pageLinks ?>
-  <? endif; ?>
-</div>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/author/home.phtml b/themes/jquerymobile/templates/author/home.phtml
deleted file mode 100644
index 8cda4f3e6066f9e0ef9e9ed8ca1b55bc09482e0e..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/author/home.phtml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?
-    // Set page title.
-    $this->headTitle($this->translate('Author Results for') . ':');
-?>
-<div data-role="page">
-  <?=$this->mobileMenu()->header()?>
-  <div data-role="content">
-    <form method="get" action="<?=$this->url('author-search')?>" data-ajax="false">
-      <div data-role="fieldcontain">
-        <label class="offscreen" for="author_lookfor"><?=$this->transEsc('Author Results for')?>:</label>
-        <input type="search" id="author_lookfor" name="lookfor" />
-      </div>
-      <div data-role="fieldcontain">
-        <input type="submit" value="<?=$this->transEsc('Find')?>" />
-      </div>
-    </form>
-  </div>
-  <?=$this->mobileMenu()->footer()?>
-</div>
diff --git a/themes/jquerymobile/templates/author/results.phtml b/themes/jquerymobile/templates/author/results.phtml
deleted file mode 100644
index ced264acc6d1c326d7d61b509890bbb525a60b8a..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/author/results.phtml
+++ /dev/null
@@ -1,9 +0,0 @@
-<?
-    // Load standard settings from the default search results screen:
-    echo $this->render('search/results.phtml');
-
-    // Override some details...
-
-    // Set up page title:
-    $this->headTitle($this->translate('Author Search Results'));
-?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/author/search.phtml b/themes/jquerymobile/templates/author/search.phtml
deleted file mode 100644
index 30dd8161fc38f90331736785794e1611f7391d0b..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/author/search.phtml
+++ /dev/null
@@ -1,14 +0,0 @@
-<?
-    // Hide the total result count -- because of limitations in the way facet
-    // paging works, we can't actually determine an accurate total count.  (Note
-    // that this setting simply modifies the behavior of search/results.phtml below).
-    $this->skipTotalCount = true;
-
-    // Load standard settings from the default search results screen:
-    echo $this->render('search/results.phtml');
-
-    // Override some details...
-
-    // Set up page title:
-    $this->headTitle($this->translate('Author Browse'));
-?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/authority/home.phtml b/themes/jquerymobile/templates/authority/home.phtml
deleted file mode 100644
index 881bf39a2f68368ad5874c06cb393530cc3140f8..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/authority/home.phtml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?
-    $this->overrideHomeOptions = '';  // turn off extra options
-    echo $this->render('search/home.phtml');
-?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/authority/record.phtml b/themes/jquerymobile/templates/authority/record.phtml
deleted file mode 100644
index ae55ebc78f6bfd2e3a0ce246e49e7f4e37f355bd..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/authority/record.phtml
+++ /dev/null
@@ -1,7 +0,0 @@
-<div data-role="page">
-  <?=$this->mobileMenu()->header(array('searchLink' => 'authority-home'))?>
-  <div data-role="content">
-    <?=$this->record($this->driver)->getTab($this->tabs['Details'])?>
-  </div>
-  <?=$this->mobileMenu()->footer()?>
-</div>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/authority/search.phtml b/themes/jquerymobile/templates/authority/search.phtml
deleted file mode 100644
index 3b7964113c5b0aa7b1ceb59d902357399bfc2581..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/authority/search.phtml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?
-    // Override top search link:
-    $this->searchLink = 'authority-home';
-
-    // Load standard settings from the default search results screen:
-    echo $this->render('search/results.phtml');
-?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/browse/home.phtml b/themes/jquerymobile/templates/browse/home.phtml
deleted file mode 100644
index d44e545c72582343e6498b21007dab39b69156f0..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/browse/home.phtml
+++ /dev/null
@@ -1,79 +0,0 @@
-<?
-  $this->headTitle($this->translate('Browse the Catalog'));
-
-  $BROWSE_BASE = $this->url('browse-' . strtolower($this->currentAction));
-  $SEARCH_BASE = $this->url($this->currentAction == 'Tag' ? 'tag-home' : 'search-results');
-
-  $BACK_LINK = $this->url('browse-home');
-  if (isset($this->findby) || ($this->currentAction == 'LCC' && isset($this->query))) {
-    $BACK_LINK = $BROWSE_BASE;
-  }
-  if (isset($this->query) && $this->currentAction != 'LCC') {
-    $BACK_LINK .= '?findby='.urlencode($this->findby).'&amp;query_field='.$this->browse()->getSolrField($this->findby, $this->currentAction);
-  }
-?>
-
-<div data-role="header" class="ui-bar-b">
-<? if (!isset($this->currentAction)): ?>
-  <a data-ajax="false" href="<?=$this->url('home') ?>" data-icon="home"><?=$this->transEsc('Search Home') ?></a>
-  <h1><?=$this->transEsc('Choose a Category to Begin Browsing') ?></h1>
-<? else: ?>
-  <a data-ajax="false" href="<?=$BACK_LINK ?>" data-icon="arrow-l"><?=$this->transEsc('navigate_back')?></a>
-  <h1>Browsing By <?=$this->currentAction ?></h1>
-  <a data-ajax="false" href="<?=$this->url('browse-home') ?>" data-icon="home"><?=$this->transEsc('Browse Home') ?></a>
-<? endif; ?>
-</div>
-
-<div data-role="page" id="Search-home">
-  <?=$this->mobileMenu()->header(array('searchLink' => false, 'results' => null))?>
-  <div data-role="content">
-    <ul class="results ui-listview" data-role="listview" data-split-icon="plus" data-split-theme="c">
-      <!-- Links to searches -->
-      <? if (isset($this->query) || !empty($this->resultList)): ?>
-        <? if (!empty($this->resultList)): ?>
-          <? foreach($this->resultList as $result): ?>
-          <li>
-            <a data-ajax="false" href="<?=$SEARCH_BASE ?>?<?=$this->paramTitle ?><?=urlencode($result['value']) ?><? if ($this->searchParams): foreach($this->searchParams as $var=>$val): ?>&<?=$var ?>=<?=urlencode($val) ?><? endforeach;endif; ?>"><?=$this->escapeHtml($result['displayText'])/*html*/?> (<?=$this->localizedNumber($result['count']) ?>)</a>
-          </li>
-          <? endforeach; ?>
-        <!-- No Results -->
-        <? else: ?>
-          <li>
-            <a href=""><?=$this->transEsc('nohit_heading') ?></a>
-          </li>
-        <? endif; ?>
-
-      <!-- Layers 2-3 -->
-      <? elseif (!empty($this->secondaryList)): ?>
-      <? foreach($this->secondaryList as $secondary): ?>
-      <li>
-        <a data-ajax="false" href="<?=$BROWSE_BASE ?>?findby=<?=urlencode($this->findby) ?>&category=<?=urlencode($this->category) ?>&query=<?=urlencode($secondary['value']) ?><? if ($this->facetPrefix): ?>&facet_prefix=<?=urlencode($secondary['displayText']) ?><? endif; ?><? if ($this->secondaryParams): foreach($this->secondaryParams as $var=>$val): ?>&<?=$var ?>=<?=urlencode($val) ?><? endforeach;endif; ?>"><?=$this->escapeHtml($secondary['displayText']) ?><? if ($this->findby != 'alphabetical'): ?> (<?=$this->localizedNumber($secondary['count']) ?>)<? endif; ?></a>
-      </li>
-      <? endforeach; ?>
-
-      <!-- Layer 1 -->
-      <? elseif (!empty($this->categoryList)): ?>
-      <? foreach($this->categoryList as $findby=>$category): ?>
-      <li>
-        <a data-ajax="false" href="<?=$BROWSE_BASE ?>?findby=<?=urlencode($findby) ?>&query_field=<?=$this->browse()->getSolrField($findby, $this->currentAction) ?>">
-          <? if(is_string($category)): ?>
-            <?=$this->transEsc($category)?>
-          <? else: ?>
-            <?=$this->transEsc($category['text'])?> (<?=$this->localizedNumber($category['count'])?>)
-          <? endif; ?>
-        </a>
-      </li>
-      <? endforeach; ?>
-
-      <!-- Home -->
-      <? else: ?>
-      <? foreach ($this->browseOptions as $item=>$currentOption): ?>
-        <li>
-          <a data-ajax="false" href="<?=$this->url('browse-' . strtolower($currentOption['action'])); ?>"><?=$this->transEsc($currentOption['description']) ?></a>
-        </li>
-      <? endforeach; ?>
-      <? endif; ?>
-    </ul>
-  </div>
-  <?=$this->mobileMenu()->footer()?>
-</div>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/collection/collection-record-error.phtml b/themes/jquerymobile/templates/collection/collection-record-error.phtml
deleted file mode 100644
index e680913f886300200b8cec09d12dd3e561c77e5e..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/collection/collection-record-error.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<h3><?=$this->transEsc('Cannot find record')?></h3>
diff --git a/themes/jquerymobile/templates/collection/view.phtml b/themes/jquerymobile/templates/collection/view.phtml
deleted file mode 100644
index 742104655cacb911beb9ccd76fb25db45ac59bec..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/collection/view.phtml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?
-    // Grab tab contents up front -- this will set the page title, which we need to
-    // do before we display the page header below.
-    $activeTab = false;
-    foreach ($this->tabs as $tab => $obj) {
-        if (strtolower($tab) == strtolower($this->activeTab)) {
-            $activeTab = $tab;
-        }
-    }
-    $tab = $activeTab ? $this->record($this->driver)->getTab($this->tabs[$activeTab]) : '';
-?>
-<div data-role="page" id="Record-view">
-  <?=$this->mobileMenu()->header()?>
-  <div class="record" data-role="content" data-record-id="<?=$this->escapeHtmlAttr($this->driver->getUniqueId())?>">
-    <?=$this->flashmessages()?>
-    <? if ($this->activeTab == $this->defaultTab): ?>
-      <?=$this->record($this->driver)->getCollectionMetadata()?>
-    <? else: ?>
-      <h3><?=$this->escapeHtml($this->driver->getBreadcrumb())?></h3>
-    <? endif; ?>
-    <?=$tab?>
-    <?=$this->record($this->driver)->getToolbar()?>
-  </div>
-  <?=$this->mobileMenu()->footer()?>
-</div>
diff --git a/themes/jquerymobile/templates/collections/bytitle.phtml b/themes/jquerymobile/templates/collections/bytitle.phtml
deleted file mode 100644
index 36b5b62e6612765d3ef8c402093d6af67acb06f7..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/collections/bytitle.phtml
+++ /dev/null
@@ -1,18 +0,0 @@
-<? $this->headTitle($this->translate(empty($collections) ? 'collection_empty' : 'collection_disambiguation')); ?>
-<div data-role="page" id="Search-list" class="results-page">
-  <?=$this->mobileMenu()->header()?>
-  <div data-role="content">
-    <? if (!empty($collections)): ?>
-      <ul class="results" data-role="listview" data-split-icon="plus" data-split-theme="c">
-        <? foreach ($collections as $i => $collection): ?>
-         <li>
-           <a rel="external" href="<?=$this->url('collection', array('id' => $collection->getUniqueId()))?>"><h3><?=$this->escapeHtml($collection->getTitle())?></h3>
-           <p><?=$this->escapeHtml(implode(' ', $collection->getSummary()))?></p>
-           </a>
-         </li>
-        <? endforeach; ?>
-      </ul>
-    <? endif; ?>
-  </div>
-  <?=$this->mobileMenu()->footer()?>
-</div>
diff --git a/themes/jquerymobile/templates/collections/home.phtml b/themes/jquerymobile/templates/collections/home.phtml
deleted file mode 100644
index c7fb890ca2f2614913fc60ed78eda8208f84a00a..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/collections/home.phtml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?
-    $this->headTitle($this->translate('Collection Browse'));
-?>
-<? ob_start(); ?>
-  <div class="ui-grid-a">
-    <? if (isset($prevpage)): ?>
-      <div class="ui-block-a">
-        <a rel="external" data-role="button" data-mini="true" data-icon="arrow-l" href="<?=$this->url('collections-home')?>?from=<?=urlencode($from)?>&amp;page=<?=urlencode($prevpage)?><?=$this->escapeHtml($filterString)?>">&laquo; <?=$this->transEsc('Prev')?></a>
-      </div>
-    <? endif; ?>
-    <? if (isset($nextpage)): ?>
-      <div class="ui-block-b">
-        <a rel="external" data-role="button" data-mini="true" data-icon="arrow-r" href="<?=$this->url('collections-home')?>?from=<?=urlencode($from)?>&amp;page=<?=urlencode($nextpage)?><?=$this->escapeHtml($filterString)?>"><?=$this->transEsc('Next')?> &raquo;</a>
-      </div>
-    <? endif; ?>
-  </div>
-<? $pageLinks = ob_get_contents(); ?>
-<? ob_end_clean(); ?>
-
-<h2><?=$this->transEsc('Collection Browse')?></h2>
-
-<div data-role="page" id="Search-list" class="results-page">
-  <?=$this->mobileMenu()->header()?>
-  <?=$pageLinks?>
-  <div data-role="content">
-    <?=$this->render('collections/list.phtml')?>
-  </div>
-  <?=$pageLinks?>
-  <?=$this->mobileMenu()->footer()?>
-</div>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/collections/list.phtml b/themes/jquerymobile/templates/collections/list.phtml
deleted file mode 100644
index f08acb0aa7581cd715d361a9732af5dc9a26576f..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/collections/list.phtml
+++ /dev/null
@@ -1,12 +0,0 @@
-<ul class="ui-listview" data-role="listview">
-  <? foreach ($result as $i => $item): ?>
-    <li class="ui-li-has-count">
-      <a class="ui-link-inherit" data-ajax="false" href="<?=$this->url('collection', array('id' => $item['value']))?>">
-        <div class="ui-btn-text"><?=$this->escapeHtml($item['displayText'])?></div>
-        <? /* subtract one from the number of items to exclude the record representing the collection itself. */ ?>
-        <span class="ui-li-count ui-btn-up-c ui-btn-corner-all"><b><?=$item['count'] - 1?></b> <?=$this->transEsc('items')?></span>
-        <span class="ui-icon ui-icon-arrow-r ui-icon-shadow"></span>
-      </a>
-    </li>
-  <? endforeach; ?>
-</ul>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/combined/home.phtml b/themes/jquerymobile/templates/combined/home.phtml
deleted file mode 100644
index 881bf39a2f68368ad5874c06cb393530cc3140f8..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/combined/home.phtml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?
-    $this->overrideHomeOptions = '';  // turn off extra options
-    echo $this->render('search/home.phtml');
-?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/combined/results-ajax.phtml b/themes/jquerymobile/templates/combined/results-ajax.phtml
deleted file mode 100644
index 840e63c31c63a72e1a47d04d82d64c14d621b004..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/combined/results-ajax.phtml
+++ /dev/null
@@ -1,17 +0,0 @@
-<?
-    $view = $currentSearch['view'];
-    $results = $view->results;
-    $params = $results->getParams();
-    $lookfor = $params->getDisplayQuery();
-
-    // Set up Javascript for use below:
-    $loadJs = 'var url = path + "/Combined/Result?id=' . urlencode($searchClassId)
-        . '&lookfor=' . urlencode($lookfor) . '";'
-        . "\$('#" . $this->escapeHtml($currentSearch['domId']) . "').load(url, '', function(responseText) {"
-        . "if (responseText.length == 0) $('#combined_" . $this->escapeHtml($searchClassId) . "').hide();"
-        . "$('.combinedButton').button(); });";
-?>
-<h2><?=$this->transEsc($currentSearch['label'])?></h2>
-<p><?=$this->transEsc("Loading")?>... <img src="<?=$this->imageLink('loading.gif')?>" /></p>
-<?=$this->inlineScript(\Zend\View\Helper\HeadScript::SCRIPT, '$(document).ready(function(){' . $loadJs . '});', 'SET')?>
-<noscript><?=$this->transEsc('Please enable JavaScript.')?></noscript>
diff --git a/themes/jquerymobile/templates/combined/results-list.phtml b/themes/jquerymobile/templates/combined/results-list.phtml
deleted file mode 100644
index 3ecad6625b4a4b6c3a5130d646111445b9619157..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/combined/results-list.phtml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?
-  $view = $currentSearch['view'];
-  $results = $view->results;
-  $params = $results->getParams();
-  $lookfor = $params->getDisplayQuery();
-  $recordTotal = $results->getResultTotal();
-
-  // More link should use default limit, not custom limit:
-  $limit = $params->getLimit();
-  $params->setLimit($params->getOptions()->getDefaultLimit());
-  $moreUrl = $this->url($params->getOptions()->getSearchAction()) . $results->getUrlQuery()->setPage(1);
-  $params->setLimit($limit);
-?>
-<h2><?=$this->transEsc($currentSearch['label'])?></h2>
-<? if (isset($currentSearch['sublabel'])): ?>
-  <p><i><?=$this->transEsc($currentSearch['sublabel'])?></i></p>
-<? endif; ?>
-<? if ($recordTotal < 1): ?>
-  <p class="error">
-    <? if (isset($view->overrideEmptyMessage)): ?>
-      <?=$view->overrideEmptyMessage?>
-    <? else: ?>
-      <?=$this->transEsc('nohit_prefix')?> - <strong><?=$this->escapeHtml($lookfor)?></strong> - <?=$this->transEsc('nohit_suffix')?>
-    <? endif; ?>
-  </p>
-  <? if (isset($view->parseError)): ?>
-    <p class="error"><?=$this->transEsc('nohit_parse_error')?></p>
-  <? endif; ?>
-  <? foreach ($results->getRecommendations('noresults') as $current): ?>
-    <?=$this->recommend($current)?>
-  <? endforeach; ?>
-<? else: ?>
-  <div data-role="controlgroup">
-    <a class="combinedButton" href="<?=$moreUrl?>" data-role="button" rel="external"><?=$this->transEsc("Search Results") . ' (' . $this->localizedNumber($recordTotal) . ')' ?></a>
-  </div>
-<? endif; ?>
diff --git a/themes/jquerymobile/templates/combined/results.phtml b/themes/jquerymobile/templates/combined/results.phtml
deleted file mode 100644
index 2620b26674210a15fa875e55336ff1ea5cc5aacd..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/combined/results.phtml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?
-    // Set up page title:
-    $lookfor = $this->params->getDisplayQuery();
-    if (isset($this->overrideTitle)) {
-        $this->headTitle($this->overrideTitle);
-    } else {
-        $this->headTitle($this->translate('Search Results') . (empty($lookfor) ? '' : " - {$lookfor}"));
-    }
-?>
-<div data-role="page" id="Search-list" class="results-page">
-  <?=$this->mobileMenu()->header()?>
-  <div data-role="content">
-    <?=$this->flashmessages()?>
-    <? foreach ($this->combinedResults as $searchClassId => $currentSearch): ?>
-      <? if ((!isset($currentSearch['ajax']) || !$currentSearch['ajax']) && isset($currentSearch['hide_if_empty']) && $currentSearch['hide_if_empty'] && $currentSearch['view']->results->getResultTotal() == 0) { continue; } ?>
-      <div class="combinedResult" id="<?=$this->escapeHtmlAttr($currentSearch['domId'])?>">
-        <? if (isset($currentSearch['ajax']) && $currentSearch['ajax']): ?>
-          <?=$this->render('combined/results-ajax.phtml', array('searchClassId' => $searchClassId, 'currentSearch' => $currentSearch))?>
-        <? else: ?>
-          <?=$this->render('combined/results-list.phtml', array('searchClassId' => $searchClassId, 'currentSearch' => $currentSearch))?>
-        <? endif; ?>
-      </div>
-    <? endforeach; ?>
-  </div>
-  <?=$this->mobileMenu()->footer()?>
-</div>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/confirm/confirm.phtml b/themes/jquerymobile/templates/confirm/confirm.phtml
deleted file mode 100644
index 989cd48eccc7030ba71859b9e53b2abed4f10270..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/confirm/confirm.phtml
+++ /dev/null
@@ -1,27 +0,0 @@
-<div data-role="page" id="MyResearch-login">
-  <?=$this->mobileMenu()->header()?>
-  <div data-role="content">
-    <h3><?=$this->transEsc($this->title) ?></h3>
-
-    <?=$this->flashmessages();?>
-
-    <form action="<?=$this->escapeHtmlAttr($this->confirm)?>" method="post" data-ajax="false">
-      <? if (isset($this->extras)): ?>
-        <? foreach ($this->extras as $extra=>$value): ?>
-          <? if (is_array($value)): ?>
-            <? foreach ($value as $current): ?>
-              <input type="hidden" name="<?=$this->escapeHtmlAttr($extra) ?>[]" value="<?=$this->escapeHtmlAttr($current) ?>" />
-            <? endforeach; ?>
-          <? else: ?>
-            <input type="hidden" name="<?=$this->escapeHtmlAttr($extra) ?>" value="<?=$this->escapeHtmlAttr($value) ?>" />
-          <? endif; ?>
-        <? endforeach; ?>
-      <? endif;?>
-      <input type="submit" name="confirm" value="<?=$this->transEsc('confirm_dialog_yes') ?>" />
-    </form>
-    <form action="<?=$this->escapeHtmlAttr($this->cancel) ?>" method="post" data-ajax="false">
-      <input type="submit" name="cancel" value="<?=$this->transEsc('confirm_dialog_no') ?>" />
-    </form>
-  </div>
-  <?=$this->mobileMenu()->footer()?>
-</div>
diff --git a/themes/jquerymobile/templates/default-footer-navbar.phtml b/themes/jquerymobile/templates/default-footer-navbar.phtml
deleted file mode 100644
index a72c5bbba364ca6f11286b6a48fb9b1256d53cc3..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/default-footer-navbar.phtml
+++ /dev/null
@@ -1,12 +0,0 @@
-<? $account = $this->auth()->getManager(); ?>
-<div data-role="navbar">
-  <ul>
-    <li><a data-rel="dialog" href="#Language-dialog" data-transition="pop"><?=$this->transEsc('Language')?></a></li>
-    <? if (is_object($account) && $account->loginEnabled()): // hide login/logout if unavailable ?>
-      <li><a rel="external" href="<?=$this->url((is_object($account) && $account->isLoggedIn()) ? 'myresearch-home' : 'myresearch-userlogin')?>"><?=$this->transEsc('Account')?></a></li>
-    <? endif; ?>
-    <? if (is_object($account) && $account->isLoggedIn()): ?>
-      <li><a rel="external" href="<?=$this->url('myresearch-logout')?>"><?=$this->transEsc("Log Out")?></a></li>
-    <? endif; ?>
-  </ul>
-</div>
diff --git a/themes/jquerymobile/templates/eds/advanced.phtml b/themes/jquerymobile/templates/eds/advanced.phtml
deleted file mode 100644
index 68c3c4754ca0f189bae3fa355482c399f6e9ec5f..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/eds/advanced.phtml
+++ /dev/null
@@ -1,123 +0,0 @@
-<?
-  // Set page title.
-  $this->headTitle($this->translate('Advanced Search'));
-  // Set default value if necessary:
-  if (!isset($this->searchClassId)) {
-    $this->searchClassId = 'Solr';
-  }
-  // Load search actions and settings (if any):
-  $options = $this->searchOptions($this->searchClassId);
-  $basicSearch = $options->getSearchAction();
-  $searchHome = $basicSearch;
-  $searchHome['action'] = 'Home';
-  $lastSort = $this->searchMemory()->getLastSort($options->getSearchClassId());
-  $lastLimit = $this->searchMemory()->getLastLimit($options->getSearchClassId());
-?>
-<div data-role="page" id="Search-home">
-  <?=$this->mobileMenu()->header(array('hideSearchLink' => true))?>
-  <div data-role="content">
-    <!-- SEARCH BOXES -->
-    <form method="get" action="<?=$this->url($basicSearch)?>" data-ajax="false">
-      <input type="hidden" name="join" value="AND" />
-      <fieldset class="ui-grid-a">
-      <? for ($i = 0; $i < 3; $i++): ?>
-        <div class="ui-block-a">
-          <? if ($i == 0): ?>
-            <input type="hidden" name="op0[]" value="AND" />
-            <label for="search_lookfor0">
-              <?=$this->transEsc("Search")?>
-            </label>
-          <? else: ?>
-            <select id="searchForm_type" name="op0[]" data-mini="true">
-              <? foreach (array('AND', 'OR', 'NOT') as $searchVal): ?>
-                <option value="<?=$this->escapeHtmlAttr($searchVal)?>"<?=$this->searchIndex == $searchVal ? ' selected="selected"' : ''?>>
-                  <?=$this->transEsc($searchVal)?>
-                </option>
-              <? endforeach; ?>
-            </select>
-          <? endif; ?>
-        </div>
-        <div class="ui-block-b">
-          <input id="search_lookfor<?=$i ?>" type="text" name="lookfor0[]" style="margin-top:.5em;height:28px"/>
-        </div>
-      <? endfor; ?>
-      </fieldset>
-      <fieldset class="ui-grid-a">
-        <hr/>
-        <h3><?=$this->transEsc('eds_modes_and_expanders')?></h3>
-        <? foreach ($this->expanderList as $field => $expander):
-          $value = $expander['Value'] ?>
-          <label class="checkbox" for="expand_<?=$this->escapeHtmlAttr(str_replace(' ', '+', $field))?>">
-            <input id="expand_<?=$this->escapeHtmlAttr(str_replace(' ', '+', $field))?>" type="checkbox" <?=(isset($expander['selected']) && $expander['selected'])?'checked="checked"':''?> name="filter[]" value="EXPAND:<?=$this->escapeHtmlAttr($value)?>">
-            <?=$this->transEsc('eds_expander_' . $value, array(), $expander['Label'])?>
-          </label>
-        <? endforeach; ?>
-        <hr/>
-        <h3><?=$this->transEsc('Limit To')?></h3>
-        <? foreach ($this->limiterList as $field => $facet): ?>
-          <? switch($facet['Type']){
-              case 'multiselectvalue': ?>
-                <h3><?=$this->transEsc($facet['Label'])?></h3>
-                <select id="limit_<?=$this->escapeHtmlAttr($field)?>" name="filter[]" multiple="multiple" size="10">
-                  <? foreach ($facet['LimiterValues'] as $id => $facetValue): ?>
-                    <? $value = $facetValue['Value']; ?>
-                    <option value="<?='LIMIT|'.$this->escapeHtmlAttr($field . ':' . $facetValue['Value'])?>"<?=(isset($facetValue['selected']) && $facetValue['selected'])?' selected="selected"':''?>><?=$this->escapeHtml($facetValue['Value'])?></option>
-                  <? endforeach; ?>
-                </select>
-                <!-- <br/> -->
-                <? break;
-              case 'select':
-                $value = $facet['LimiterValues'][0]['Value'] ?>
-                <label class="checkbox" for="limit_<?=$this->escapeHtmlAttr(str_replace(' ', '+', $field))?>">
-                  <input id="limit_<?=$this->escapeHtmlAttr(str_replace(' ', '+', $field))?>" type="checkbox" <?=(isset($facet['LimiterValues'][0]['selected']) && $facet['LimiterValues'][0]['selected'])?'checked="checked"':''?> name="filter[]" value="<?=$this->escapeHtmlAttr('LIMIT|'.$field . ':' . $value)?>">
-                  <?=$this->transEsc('eds_limiter_' . $field, array(), $facet['Label'])?>
-                </label>
-                <? break;
-              case 'text': ?>
-                <!-- not implemented -->
-                <? break;
-              case 'numeric':?>
-                <!--  not implemented -->
-                <? break;
-              case 'numericrange':?>
-                <!--  not implemented -->
-                <? break;
-              case 'ymrange': ?>
-                <!--  not implemented -->
-                <? break;
-              case 'yrange': ?>
-                <!--  not implemented -->
-                <? break;
-              case 'historicalrange':?>
-                <!--  not implemented -->
-                <? break;
-              case 'singleselectvalue':?>
-                <!--  not implemented -->
-                <? break;
-            }; ?>
-        <? endforeach; ?>
-        <hr/>
-        <div class="ui-block-a">
-          <select id="search_bool0" name="bool0[]">
-            <option value="AND"><?=$this->transEsc("search_match")?>: <?=$this->transEsc('search_AND') ?></option>
-            <option value="OR" ><?=$this->transEsc("search_match")?>: <?=$this->transEsc('search_OR')  ?></option>
-            <option value="NOT"><?=$this->transEsc("search_match")?>: <?=$this->transEsc('search_NOT') ?></option>
-          </select>
-        </div>
-        <div class="ui-block-b">
-          <input type="submit" name="submit" value="<?=$this->transEsc("Find")?>" data-role="button" data-theme="b"/>
-        </div>
-      </fieldset>
-      <?
-        /* Load hidden limit preference from Session */
-        if (!empty($lastLimit)) {
-          echo '<input type="hidden" name="limit" value="' . $this->escapeHtmlAttr($lastLimit) . '" />';
-        }
-        if (!empty($lastSort)) {
-          echo '<input type="hidden" name="sort" value="' . $this->escapeHtmlAttr($lastSort) . '" />';
-        }
-      ?>
-    </form>
-  </div>
-  <?=$this->mobileMenu()->footer()?>
-</div>
diff --git a/themes/jquerymobile/templates/eds/home.phtml b/themes/jquerymobile/templates/eds/home.phtml
deleted file mode 100644
index f386b6f023e9d51abc89dcf5612012fdebc2b306..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/eds/home.phtml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?
-  $this->overrideHomeOptions = '';  // turn off extra options
-  echo $this->render('search/home.phtml');
-?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/eds/search.phtml b/themes/jquerymobile/templates/eds/search.phtml
deleted file mode 100644
index a1f2bef83e8cce9df08e6acf285887435c887dd7..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/eds/search.phtml
+++ /dev/null
@@ -1,5 +0,0 @@
-<?
-  // Load standard settings from the default search results screen:
-  $this->overrideSideFacetCaption = 'Refine Results';
-  echo $this->render('search/results.phtml');
-?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/eit/advanced.phtml b/themes/jquerymobile/templates/eit/advanced.phtml
deleted file mode 100644
index 6d2d837a3c7db2d7eb01978580cf3ba3fa6c7a0f..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/eit/advanced.phtml
+++ /dev/null
@@ -1,5 +0,0 @@
-<?
-  // There are no EIT-specific advanced search controls, so just load the
-  // standard advanced search layout:
-  echo $this->render('search/advanced/layout.phtml');
-?>
diff --git a/themes/jquerymobile/templates/eit/home.phtml b/themes/jquerymobile/templates/eit/home.phtml
deleted file mode 100644
index 881bf39a2f68368ad5874c06cb393530cc3140f8..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/eit/home.phtml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?
-    $this->overrideHomeOptions = '';  // turn off extra options
-    echo $this->render('search/home.phtml');
-?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/eit/search.phtml b/themes/jquerymobile/templates/eit/search.phtml
deleted file mode 100644
index c1797c1cd4a1ebb2ccad84718b1e225e51cac6a8..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/eit/search.phtml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?
-    // Load standard settings from the default search results screen:
-    echo $this->render('search/results.phtml');
-?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/error/unavailable.phtml b/themes/jquerymobile/templates/error/unavailable.phtml
deleted file mode 100644
index fa3d30171719d7ce9e5c7c1c918602742330c347..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/error/unavailable.phtml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?
-    // Set page title.
-    $this->headTitle($this->translate('System Unavailable'));
-?>
-<div data-role="page" id="Search-home">
-  <?=$this->mobileMenu()->header(array('searchLink' => false))?>
-  <div data-role="content">
-    <div class="error unavailable">
-      <p>
-        <?=$this->transEsc('The system is currently unavailable due to system maintenance')?>.
-        <?=$this->transEsc('Please check back soon')?>.
-      </p>
-      <p>
-        <?=$this->transEsc('Please contact the Library Reference Department for assistance')?>
-        <br/>
-        <? $supportEmail = $this->escapeHtmlAttr($this->systemEmail()); ?>
-        <a href="mailto:<?=$supportEmail?>"><?=$supportEmail?></a>
-      </p>
-    </div>
-  </div>
-</div>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/footer.phtml b/themes/jquerymobile/templates/footer.phtml
deleted file mode 100644
index 0dc231d6a2d411de20e941c2bd1b24c56959e889..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/footer.phtml
+++ /dev/null
@@ -1,14 +0,0 @@
-<div class="footer-text"><a href="#" class="standard-view" rel="external"><?=$this->transEsc('Go to Standard View')?></a></div>
-
-<div data-role="footer" data-theme="b">
-  <?
-    // if a module has footer-navbar.tpl, then use it, otherwise use default
-    try {
-        echo $this->render("{$this->layout()->templateDir}/footer-navbar.phtml");
-    } catch (\Zend\View\Exception\RuntimeException $e) {
-        // no module-specific footer navbar found -- use default.
-        echo $this->render('default-footer-navbar.phtml');
-    }
-  ?>
-</div>
-<? if (!empty($this->layout()->poweredBy)): ?><div data-role="footer"><p><?=$this->layout()->poweredBy?></p></div><? endif; ?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/header.phtml b/themes/jquerymobile/templates/header.phtml
deleted file mode 100644
index 5750b3e373c95a340973a39aa431046771b0f140..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/header.phtml
+++ /dev/null
@@ -1,31 +0,0 @@
-<div data-role="header" data-theme="b">
-  <? if (isset($this->extraButtons) && is_array($this->extraButtons)): ?>
-    <?=implode('', $this->extraButtons)?>
-  <? endif; ?>
-
-  <h1><? foreach ($this->headTitle() as $str) echo trim($str, ':/') . ' '; ?></h1>
-
-  <?
-      // If no search link value was passed in, pick a default:
-      if (!isset($this->searchLink)) {
-          $this->searchLink = 'search-home';
-      }
-  ?>
-  <? if ($this->searchLink): ?>
-    <a rel="external" href="<?=$this->url($this->searchLink)?>" data-icon="search"  class="ui-btn-right">
-      <?=$this->transEsc('Search')?>
-    </a>
-  <? endif; ?>
-
-  <?
-    // if a module has header-navbar.tpl, then use it
-    try {
-        echo $this->render("{$this->layout()->templateDir}/header-navbar.phtml");
-    } catch (\Zend\View\Exception\RuntimeException $e) {
-        // if this is a record view, load the record header; otherwise, do nothing:
-        if (substr($this->layout()->templateDir, -6) == 'record') {
-            echo $this->render('record/header-navbar.phtml');
-        }
-    }
-  ?>
-</div>
diff --git a/themes/jquerymobile/templates/layout/layout.phtml b/themes/jquerymobile/templates/layout/layout.phtml
deleted file mode 100644
index 26eb02d6d6f2c38ece9dd799caac871decdadcc4..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/layout/layout.phtml
+++ /dev/null
@@ -1,54 +0,0 @@
-<?=$this->doctype('HTML5')?>
-<html lang="<?=$this->layout()->userLang?>">
-  <head>
-    <meta charset="utf-8"/>
-    <meta name="format-detection" content="telephone=no"/>
-    <meta name="viewport" content="width=device-width, minimum-scale=1, maximum-scale=1"/>
-    <?$this->headThemeResources()?>
-    <?=$this->headMeta()?>
-    <?=$this->headTitle()?>
-    <?=$this->headLink()?>
-    <?=$this->headStyle()?>
-    <?
-        // Set global path for Javascript code:
-        $this->headScript()->prependScript("path = '" . rtrim($this->url('home'), '/') . "';");
-
-        // Session keep-alive
-        if ($this->KeepAlive()) {
-            $this->headScript()->appendScript('var keepAliveInterval = '
-                . $this->KeepAlive());
-            $this->headScript()->appendFile("keep_alive.js");
-        }
-        if ($this->recaptcha()->active()) {
-            $this->headScript()->appendFile("recaptcha_ajax.js");
-        }
-    ?>
-    <?=$this->headScript()?>
-  </head>
-  <body>
-    <?=$this->layout()->content?>
-    <?=$this->layout()->extraDialogs?>
-    <div data-role="dialog" id="Language-dialog">
-      <div data-role="header" data-theme="d" data-position="inline">
-        <h1><?=$this->transEsc("Language")?></h1>
-      </div>
-      <div data-role="content">
-        <? if (isset($this->layout()->allLangs) && count($this->layout()->allLangs) > 1): ?>
-        <form method="post" name="langForm" action="#" id="langForm" data-ajax="false">
-          <div data-role="fieldcontain">
-            <label for="langForm_mylang"><?=$this->transEsc("Language")?>:</label>
-            <select id="langForm_mylang" name="mylang">
-              <? foreach ($this->layout()->allLangs as $langCode => $langName): ?>
-                <option value="<?=$langCode?>"<?=$this->layout()->userLang == $langCode ? ' selected="selected"' : ''?>><?=$this->displayLanguageOption($langName)?></option>
-              <? endforeach; ?>
-            </select>
-            <input type="submit" value="<?=$this->transEsc("Set")?>" />
-          </div>
-        </form>
-        <? endif; ?>
-      </div>
-    </div>
-    <?=$this->googleanalytics()?>
-    <?=$this->piwik()?>
-  </body>
-</html>
diff --git a/themes/jquerymobile/templates/libguides/home.phtml b/themes/jquerymobile/templates/libguides/home.phtml
deleted file mode 100644
index d13d4348c1e39e2222b5f16ce7d65ecd7816ef92..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/libguides/home.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<?=$this->render('search/home.phtml');?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/libguides/results.phtml b/themes/jquerymobile/templates/libguides/results.phtml
deleted file mode 100644
index c1797c1cd4a1ebb2ccad84718b1e225e51cac6a8..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/libguides/results.phtml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?
-    // Load standard settings from the default search results screen:
-    echo $this->render('search/results.phtml');
-?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/librarycards/editcard.phtml b/themes/jquerymobile/templates/librarycards/editcard.phtml
deleted file mode 100644
index 222360f807b7ca94007112732ab884632d47cdc6..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/librarycards/editcard.phtml
+++ /dev/null
@@ -1,50 +0,0 @@
-<?
-    // Set up page title:
-    $pageTitle = empty($this->card->id) ? 'Add a Library Card' : "Edit Library Card";
-    $this->headTitle($this->translate($pageTitle));
-?>
-<div data-role="page" id="LibraryCards-editCard">
-  <?=$this->mobileMenu()->header()?>
-  <div data-role="content">
-    <h3><?=$this->transEsc($pageTitle); ?></h3>
-
-    <?=$this->flashmessages()?>
-
-    <form method="post" name="<?=empty($this->card->id) ? 'newCardForm' : 'editCardForm'?>" data-ajax="false">
-      <label class="displayBlock" for="card_name"><?=$this->transEsc('Library Card Name'); ?>:</label>
-      <input id="card_name" type="text" name="card_name" value="<?=$this->escapeHtmlAttr($this->cardName)?>" size="50"
-        class="mainFocus <?=$this->jqueryValidation(array('required'=>'This field is required')) ?>"/>
-      <br class="clear"/>
-
-      <? if ($this->targets !== null): ?>
-      <label class="displayBlock" for="login_target"><?=$this->transEsc('login_target')?>:</label>
-      <select id="login_target" name="target">
-      <? foreach ($this->targets as $target): ?>
-        <option value="<?=$this->escapeHtmlAttr($target)?>"<?=($target == $this->target ? ' selected="selected"' : '')?>><?=$this->transEsc("source_$target", null, $target)?></option>
-      <? endforeach; ?>
-      </select>
-      <br class="clear"/>
-      <? endif; ?>
-
-      <label class="displayBlock" for="login_username"><?=$this->transEsc('Username')?>:</label>
-      <input id="login_username" type="text" name="username" value="<?=$this->escapeHtmlAttr($this->username)?>" size="15" class="<?=$this->jqueryValidation(array('required'=>'This field is required'))?>"/>
-      <br class="clear"/>
-      <label class="displayBlock" for="login_password"><?=$this->transEsc('Password')?>:</label>
-      <input id="login_password" type="password" name="password" value="<?=$this->escapeHtmlAttr($this->password)?>" size="15" class="<?=$this->jqueryValidation(array('required'=>'This field is required'))?>"/>
-      <br class="clear"/>
-
-      <div class="ui-body ui-body-b">
-        <fieldset class="ui-grid-a">
-            <div class="ui-block-a">
-                <input class="button" data-role="button" data-theme="b" type="submit" name="submit" value="<?=$this->transEsc('Save') ?>"/>
-            </div>
-            <? if (!empty($this->card->id)): ?>
-              <div class="ui-block-b">
-                <a data-role="button" data-theme="c" data-mini="true" href="<?=$this->url('librarycards-deletecard') ?>?cardID=<?=urlencode($this->card->id)?>" id="deleteCard<?=$this->card->id ?>" title="<?=$this->transEsc("Delete")?>"><?=$this->transEsc("Delete")?></a>
-              </div>
-            <? endif; ?>
-        </fieldset>
-      </div>
-    </div>
-  <?=$this->mobileMenu()->footer()?>
-</div>
diff --git a/themes/jquerymobile/templates/librarycards/home.phtml b/themes/jquerymobile/templates/librarycards/home.phtml
deleted file mode 100644
index dbf4e9d66b65c3447f60759b9cad888bf8676dbc..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/librarycards/home.phtml
+++ /dev/null
@@ -1,45 +0,0 @@
-<?
-    // Set up page title:
-    $this->headTitle($this->translate('Library Cards'));
-
-    // Set up extra button for header:
-    $extraButton = '<a rel="external" href="'
-            . $this->url('editLibraryCard', array('id' => 'NEW'))
-            . '" data-icon="gear" class="ui-btn-left">'
-            . $this->transEsc("Add a Library Card")
-            . '</a>';
-?>
-
-<div data-role="page" id="LibraryCards-home" class="results-page">
-  <?=$this->mobileMenu()->header(array('extraButtons'=>array($extraButton)))?>
-  <div data-role="content">
-
-    <?=$this->flashmessages();?>
-
-    <? if ($this->libraryCards->count() == 0): ?>
-      <?=$this->transEsc('You do not have any library cards')?>
-    <? else: ?>
-      <h3><?=$this->transEsc('Library Cards')?></h3>
-
-      <ul class="results librarycards" data-role="listview" data-split-theme="d" data-inset="false">
-      <? foreach ($this->libraryCards as $record): ?>
-        <li>
-          <a rel="external" href="<?=$this->url('editLibraryCard') . $this->escapeHtmlAttr($record['id']) ?>">
-
-          <?=$this->escapeHtml($record['card_name'])?><br />
-          <? $username = $record['cat_username']; if ($this->multipleTargets): ?>
-            <? $target = ''; ?>
-            <? if (strstr($username, '.')): ?>
-              <? list($target, $username) = explode('.', $username, 2); ?>
-            <? endif; ?>
-            <?=$this->transEsc('login_target')?>: <?=$target ? $this->transEsc("source_$target", null, $target) : '&nbsp;' ?><br />
-          <? endif; ?>
-          <?=$this->transEsc('Username')?>: <?=$this->escapeHtml($username)?>
-          </a>
-        </li>
-        <? endforeach; ?>
-      </ul>
-    <? endif; ?>
-  </div>
-  <?=$this->mobileMenu()->footer()?>
-</div>
diff --git a/themes/jquerymobile/templates/librarycards/selectcard.phtml b/themes/jquerymobile/templates/librarycards/selectcard.phtml
deleted file mode 100644
index f58b5751bb6593381cb4412c9e8ba074523c620d..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/librarycards/selectcard.phtml
+++ /dev/null
@@ -1,30 +0,0 @@
-<? if ($this->user): ?>
-  <?$cards = $this->user->getLibraryCards(); if ($cards->count() > 1): ?>
-    <form id="library_card_form" action="<?=$this->url('librarycards-selectcard')?>" method="get" data-ajax="false">
-      <label for="library_card"><?=$this->transEsc('Library Card')?></label>
-      <select id="library_card" name="cardID" class="jumpMenu">
-        <? foreach ($cards as $card): ?>
-          <?
-            $target = '';
-            $username = $card->cat_username;
-            if (strstr($username, '.')) {
-              list($target, $username) = explode('.', $username, 2);
-            }
-            $display = $this->transEsc($card->card_name ? $card->card_name : $card->cat_username);
-            if ($target) {
-              $display .= ' (' . $this->transEsc("source_$target", null, $target) . ')';
-            }
-          ?>
-          <option value="<?=$this->escapeHtmlAttr($card->id)?>"<?=$card->cat_username == $this->user->cat_username ? ' selected="selected"' : ''?>><?=$display ?></option>
-        <? endforeach; ?>
-      </select>
-      <noscript><input type="submit" class="btn btn-default" value="<?=$this->transEsc("Set")?>" /></noscript>
-    </form>
-    <script type="text/javascript">
-      $('#library_card').die('change');
-      $('#library_card').live('change', function() {
-        $('#library_card_form').submit();
-      });
-    </script>
-  <? endif; ?>
-<? endif; ?>
diff --git a/themes/jquerymobile/templates/missingrecord/home.phtml b/themes/jquerymobile/templates/missingrecord/home.phtml
deleted file mode 100644
index 60b1fa554ba5931f980df575c3e90a45d6f5dcd2..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/missingrecord/home.phtml
+++ /dev/null
@@ -1,7 +0,0 @@
-<div data-role="page">
-  <?=$this->mobileMenu()->header()?>
-  <div data-role="content">
-    <?=$this->flashmessages()?>
-  </div>
-  <?=$this->mobileMenu()->footer()?>
-</div>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/myresearch/account.phtml b/themes/jquerymobile/templates/myresearch/account.phtml
deleted file mode 100644
index 288d8feba58f3663ce9b2fb3596f8201671d1a69..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/myresearch/account.phtml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?
-    // Set up page title:
-    $this->headTitle($this->translate('User Account'));
-?>
-<div data-role="page" id="MyResearch-account">
-  <?=$this->mobileMenu()->header()?>
-  <div data-role="content">
-    <?=$this->flashmessages();?>
-    <form method="post" name="accountForm" id="accountForm" data-ajax="false">
-      <div data-role="fieldcontain">
-        <?=$this->auth()->getCreateFields()?>
-      </div>
-      <?=$this->recaptcha()->html($this->useRecaptcha) ?>
-      <div data-role="fieldcontain">
-        <input type="submit" name="submit" value="<?=$this->transEsc('Submit')?>"/>
-      </div>
-    </form>
-  </div>
-  <?=$this->mobileMenu()->footer()?>
-</div>
diff --git a/themes/jquerymobile/templates/myresearch/cataloglogin.phtml b/themes/jquerymobile/templates/myresearch/cataloglogin.phtml
deleted file mode 100644
index 855822c90dda1a5567dc09d63d7bccd2fdddf819..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/myresearch/cataloglogin.phtml
+++ /dev/null
@@ -1,51 +0,0 @@
-<?
-    // Set up page title:
-    $this->headTitle($this->translate('Login'));
-
-    // Convenience variable:
-    $offlineMode = $this->ils()->getOfflineMode();
-?>
-<div data-role="page" id="MyResearch-login">
-  <?=$this->mobileMenu()->header()?>
-  <div data-role="content">
-    <? if ($offlineMode == "ils-offline"): ?>
-      <div class="sysInfo">
-        <h2><?=$this->transEsc('ils_offline_title')?></h2>
-        <p><strong><?=$this->transEsc('ils_offline_status')?></strong></p>
-        <p><?=$this->transEsc('ils_offline_login_message')?></p>
-        <? $supportEmail = $this->escapeHtmlAttr($this->systemEmail()); ?>
-        <p><a href="mailto:<?=$supportEmail?>"><?=$supportEmail?></a></p>
-      </div>
-    <? else: ?>
-      <h3><?=$this->transEsc('Library Catalog Profile')?></h3>
-      <?=$this->flashmessages()?>
-      <p><?=$this->transEsc('cat_establish_account')?></p>
-      <form method="post" data-ajax="false">
-
-        <? if ($this->targets !== null): ?>
-        <div data-role="fieldcontain">
-          <label class="displayBlock" for="login_target"><?=$this->transEsc('login_target')?>:</label>
-          <select id="login_target" name="target">
-          <? foreach ($this->targets as $target): ?>
-            <option value="<?=$this->escapeHtmlAttr($target)?>"><?=$this->transEsc("source_$target", null, $target)?></option>
-          <? endforeach; ?>
-          </select>
-        </div>
-        <? endif; ?>
-
-        <div data-role="fieldcontain">
-          <label class="displayBlock" for="profile_cat_username"><?=$this->transEsc('Library Catalog Username')?>:</label>
-          <input id="profile_cat_username" type="text" name="cat_username" value="" size="25"/>
-        </div>
-        <div data-role="fieldcontain">
-          <label class="displayBlock" for="profile_cat_password"><?=$this->transEsc('Library Catalog Password')?>:</label>
-          <input id="profile_cat_password" type="password" name="cat_password" value="" size="25"/>
-        </div>
-        <div data-role="fieldcontain">
-          <input type="submit" name="submit" value="<?=$this->transEsc('Save')?>"/>
-        </div>
-      </form>
-    <? endif; ?>
-  </div>
-  <?=$this->mobileMenu()->footer()?>
-</div>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/myresearch/checkedout.phtml b/themes/jquerymobile/templates/myresearch/checkedout.phtml
deleted file mode 100644
index a8263f937aa622c23e4ae4fa6e46383ee428513a..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/myresearch/checkedout.phtml
+++ /dev/null
@@ -1,149 +0,0 @@
-<?
-    // Set up page title:
-    $this->headTitle($this->translate('Checked Out Items'));
-?>
-<div data-role="page" id="MyResearch-checkedout">
-  <?=$this->mobileMenu()->header()?>
-  <div data-role="content">
-    <h3><?=$this->transEsc('Your Checked Out Items')?></h3>
-    <?=$this->flashmessages()?>
-
-    <?=$this->context($this)->renderInContext('librarycards/selectcard.phtml', array('user' => $this->auth()->isLoggedIn())); ?>
-
-    <? if (!empty($this->transactions)): ?>
-      <? if ($this->renewForm): ?>
-      <form name="renewals" method="post" id="renewals">
-        <fieldset data-type="horizontal" data-role="controlgroup">
-          <input type="submit" class="button renew" name="renewSelected" value="<?=$this->transEsc("renew_selected")?>" />
-          <input type="submit" class="button renewAll" name="renewAll" value="<?=$this->transEsc('renew_all')?>" />
-        </fieldset>
-      <? endif; ?>
-
-      <? if ($paginator): ?>
-        <?=$this->transEsc("Showing")?>
-        <? $start = $paginator->getAbsoluteItemNumber(1);
-           $end = $paginator->getAbsoluteItemNumber($paginator->getItemCountPerPage());
-           $total = $paginator->getTotalItemCount();
-        ?>
-        <strong><?=$this->localizedNumber($start)?></strong> - <strong><?=$this->localizedNumber($end > $total ? $total : $end)?></strong>
-        <?=$this->transEsc('of')?> <strong><?=$this->localizedNumber($total)?></strong>
-      <? endif; ?>
-
-      <? foreach ($hiddenTransactions as $ilsDetails): ?>
-        <? if (isset($this->renewResult[$ilsDetails['item_id']])): ?>
-          <? $renewDetails = $this->renewResult[$ilsDetails['item_id']]; ?>
-          <? $prefix = isset($ilsDetails['title']) ? $ilsDetails['title'] : $ilsDetails['item_id']; ?>
-          <? if (isset($renewDetails['success']) && $renewDetails['success']): ?>
-            <div class="success"><?=$this->escapeHtml($prefix . ': ') . $this->transEsc('renew_success')?></div>
-          <? else: ?>
-            <div class="error"><?=$this->escapeHtml($prefix . ': ') . $this->transEsc('renew_fail')?><? if (isset($renewDetails['sysMessage'])): ?>: <?=$this->escapeHtml($renewDetails['sysMessage'])?><? endif; ?></div>
-          <? endif; ?>
-        <? endif; ?>
-        <? if (isset($ilsDetails['renewable']) && $ilsDetails['renewable'] && isset($ilsDetails['renew_details'])): ?>
-          <? $safeId = preg_replace('/[^a-zA-Z0-9]/', '', $ilsDetails['renew_details']); ?>
-          <input type="hidden" name="renewAllIDS[]" value="<?=$this->escapeHtmlAttr($ilsDetails['renew_details'])?>" />
-        <? endif; ?>
-      <? endforeach; ?>
-
-      <ul class="results checkedout-list" data-role="listview">
-      <? foreach ($this->transactions as $resource): ?>
-        <? $ilsDetails = $resource->getExtraDetail('ils_details'); ?>
-        <li>
-          <?
-              // Flag to track whether we have an open anchor tag:
-              $openAnchor = false;
-
-              // If this is a non-missing Solr record, we should display a link:
-              if (is_a($resource, 'VuFind\\RecordDriver\\SolrDefault') && !is_a($resource, 'VuFind\\RecordDriver\\Missing')) {
-                  $title = $resource->getTitle();
-                  $title = empty($title) ? $this->transEsc('Title not available') : $this->escapeHtml($title);
-                  echo '<a rel="external" href="' . $this->recordLink()->getUrl($resource) . '">';
-                  $openAnchor = true;
-              } else if (isset($ilsDetails['title']) && !empty($ilsDetails['title'])){
-                  // If the record is not available in Solr, perhaps the ILS driver sent us a title we can show...
-                  $title = $this->escapeHtml($ilsDetails['title']);
-              } else {
-                  // Last resort -- indicate that no title could be found.
-                  $title = $this->transEsc('Title not available');
-              }
-          ?>
-          <div class="result">
-            <h3><?=$title?></h3>
-            <? $listAuthors = $resource->getPrimaryAuthors(); if (!empty($listAuthors)): ?>
-              <p><?=$this->transEsc('by')?> <?=$this->escapeHtml($listAuthors[0])?><? if (count($listAuthors) > 1): ?>, <?=$this->transEsc('more_authors_abbrev')?><? endif; ?></p>
-            <? endif; ?>
-            <? $formats = $resource->getFormats(); if (count($formats) > 0): ?>
-              <?=$this->record($resource)->getFormatList()?>
-            <? endif; ?>
-
-            <? if (!empty($ilsDetails['borrowingLocation'])): ?>
-              <strong><?=$this->transEsc('Borrowing Location')?>:</strong> <?=$this->transEsc('location_' . $ilsDetails['borrowingLocation'], array(), $ilsDetails['borrowingLocation'])?>
-              <br />
-            <? endif; ?>
-
-            <? if (isset($ilsDetails['renew'])): ?>
-              <strong><?=$this->transEsc('Renewed')?>:</strong> <?=$this->transEsc($ilsDetails['renew'])?>
-              <? if (isset($ilsDetails['renewLimit'])): ?>
-                / <?=$this->transEsc($ilsDetails['renewLimit'])?>
-              <? endif; ?>
-              <br />
-            <? endif; ?>
-
-            <? $showStatus = true; ?>
-
-            <? if (isset($this->renewResult[$ilsDetails['item_id']])): ?>
-              <? $renewDetails = $this->renewResult[$ilsDetails['item_id']]; ?>
-              <? if (isset($renewDetails['success']) && $renewDetails['success']): ?>
-                <? $showStatus = false; ?>
-                <strong><?=$this->transEsc('Due Date')?>: <?=$this->escapeHtml($renewDetails['new_date'])?> <? if (isset($renewDetails['new_time'])): ?><?=$this->escapeHtml($renewDetails['new_time'])?><? endif; ?></strong>
-                <div class="success"><?=$this->transEsc('renew_success')?></div>
-              <? else: ?>
-                <strong><?=$this->transEsc('Due Date')?>: <?=$this->escapeHtml($ilsDetails['duedate'])?><? if (isset($ilsDetails['dueTime'])): ?> <?=$this->escapeHtml($ilsDetails['dueTime'])?><? endif; ?></strong>
-                <div class="error"><?=$this->transEsc('renew_fail')?><? if (isset($renewDetails['sysMessage'])): ?>: <?=$this->escapeHtml($renewDetails['sysMessage'])?><? endif; ?></div>
-              <? endif; ?>
-            <? else: ?>
-              <strong><?=$this->transEsc('Due Date')?>: <?=$this->escapeHtml($ilsDetails['duedate'])?><? if (isset($ilsDetails['dueTime'])): ?> <?=$this->escapeHtml($ilsDetails['dueTime'])?><? endif; ?></strong>
-              <? if ($showStatus): ?>
-                <? if (isset($ilsDetails['dueStatus']) && $ilsDetails['dueStatus'] == "overdue"): ?>
-                  <div class="error"><?=$this->transEsc("renew_item_overdue")?></div>
-                <? elseif (isset($ilsDetails['dueStatus']) && $ilsDetails['dueStatus'] == "due"): ?>
-                  <div class="notice"><?=$this->transEsc("renew_item_due")?></div>
-                <? endif; ?>
-              <? endif; ?>
-            <? endif; ?>
-
-            <? if ($showStatus && isset($ilsDetails['message']) && !empty($ilsDetails['message'])): ?>
-              <div class="info"><?=$this->transEsc($ilsDetails['message'])?></div>
-            <? endif; ?>
-          </div>
-          <? if ($openAnchor): ?></a><? endif; ?>
-
-          <? if ($this->renewForm): ?>
-            <? if (isset($ilsDetails['renewable']) && $ilsDetails['renewable'] && isset($ilsDetails['renew_details'])): ?>
-                <div data-role="fieldcontain">
-                  <fieldset data-type="horizontal" data-role="controlgroup">
-                    <? $safeId = preg_replace('/[^a-zA-Z0-9]/', '', $ilsDetails['renew_details']); ?>
-                    <label for="checkbox_<?=$safeId?>"><?=$this->transEsc("Select this record")?></label>
-                    <input type="checkbox" name="renewSelectedIDS[]" value="<?=$this->escapeHtmlAttr($ilsDetails['renew_details'])?>" class="checkbox" style="margin-left: 0" id="checkbox_<?=$safeId?>" />
-                    <input type="hidden" name="renewAllIDS[]" value="<?=$this->escapeHtmlAttr($ilsDetails['renew_details'])?>" />
-                  </fieldset>
-                </div>
-            <? endif; ?>
-          <? endif; ?>
-        </li>
-      <? endforeach; ?>
-      </ul>
-      <? if ($this->renewForm): ?>
-        <fieldset data-type="horizontal" data-role="controlgroup">
-          <input type="submit" class="button renew" name="renewSelected" value="<?=$this->transEsc("renew_selected")?>" />
-          <input type="submit" class="button renewAll" name="renewAll" value="<?=$this->transEsc('renew_all')?>" />
-        </fieldset>
-      </form>
-      <? endif; ?>
-      <?=$paginator ? $this->paginationControl($paginator, 'Sliding', 'Helpers/pagination.phtml') : ''?>
-    <? else: ?>
-      <p><?=$this->transEsc('You do not have any items checked out')?>.</p>
-    <? endif; ?>
-  </div>
-  <?=$this->mobileMenu()->footer()?>
-</div>
diff --git a/themes/jquerymobile/templates/myresearch/editlist.phtml b/themes/jquerymobile/templates/myresearch/editlist.phtml
deleted file mode 100644
index ddd548301ab55c5032ac2de2369cdd84223ba983..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/myresearch/editlist.phtml
+++ /dev/null
@@ -1,45 +0,0 @@
-<?
-    // Set up page title:
-    $pageTitle = $this->newList ? 'Create a List' : "edit_list";
-    $this->headTitle($this->translate($pageTitle));
-?>
-<div data-role="page" id="MyResearch-editlist">
-  <?=$this->mobileMenu()->header()?>
-  <div data-role="content">
-    <h3><?=$this->transEsc($pageTitle); ?></h3>
-
-    <?=$this->flashmessages()?>
-
-    <form method="post" name="<?=$this->newList ? 'newList' : 'editListForm'?>" data-ajax="false">
-    <label class="displayBlock" for="list_title"><?=$this->transEsc('List'); ?>:</label>
-    <input id="list_title" type="text" name="title" value="<?=isset($this->list['title']) ? $this->escapeHtml($this->list['title']) : ''?>" size="50"
-      class="mainFocus <?=$this->jqueryValidation(array('required'=>'This field is required')) ?>"/>
-    <label class="displayBlock" for="list_desc"><?=$this->transEsc('Description') ?></label>
-    <textarea id="list_desc" name="desc" rows="3" cols="50"><?=isset($this->list['description']) ? $this->escapeHtml($this->list['description']) : ''?></textarea>
-    <? if ($this->userlist()->getMode() === 'public_only'): ?>
-      <input type="hidden" name="public" value="1" />
-    <? elseif ($this->userlist()->getMode() === 'private_only'): ?>
-      <input type="hidden" name="public" value="0" />
-    <? else: ?>
-      <fieldset>
-        <legend><?=$this->transEsc('Access') ?></legend>
-        <input id="list_public_1" type="radio" name="public" value="1"<? if ($this->list->isPublic()): ?> checked="checked"<? endif; ?>/> <label for="list_public_1"><?=$this->transEsc('Public') ?></label>
-        <input id="list_public_0" type="radio" name="public" value="0"<? if (!$this->list->isPublic()): ?> checked="checked"<? endif; ?>/> <label for="list_public_0"><?=$this->transEsc('Private') ?></label>
-      </fieldset>
-    <? endif; ?>
-    <div class="ui-body ui-body-b">
-        <fieldset class="ui-grid-a">
-            <div class="ui-block-a">
-                <input class="button" data-role="button" data-theme="b" type="submit" name="submit" value="<?=$this->transEsc('Save') ?>"/>
-            </div>
-            <? if (!empty($this->list->id)): ?>
-              <div class="ui-block-b">
-                <a data-role="button" data-theme="c" data-mini="true" href="<?=$this->url('myresearch-deletelist') ?>?listID=<?=urlencode($this->list->id)?>" id="deleteList<?=$this->list->id ?>" title="<?=$this->transEsc("delete_list")?>"><?=$this->transEsc("delete_list")?></a>
-              </div>
-            <? endif; ?>
-        </fieldset>
-    </div>
-    </form>
-  </div>
-  <?=$this->mobileMenu()->footer()?>
-</div>
diff --git a/themes/jquerymobile/templates/myresearch/fines.phtml b/themes/jquerymobile/templates/myresearch/fines.phtml
deleted file mode 100644
index 8ed86308e91f62f8cd635abefe01cba3e636a820..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/myresearch/fines.phtml
+++ /dev/null
@@ -1,45 +0,0 @@
-<?
-    // Set up page title:
-    $this->headTitle($this->translate('My Fines'));
-?>
-<div data-role="page" id="MyResearch-checkedout">
-  <?=$this->mobileMenu()->header()?>
-  <div data-role="content">
-    <h3><?=$this->transEsc('Your Fines')?></h3>
-    <?=$this->flashmessages()?>
-
-    <?=$this->context($this)->renderInContext('librarycards/selectcard.phtml', array('user' => $this->auth()->isLoggedIn())); ?>
-
-    <? if (empty($this->fines)): ?>
-      <p><?=$this->transEsc('You do not have any fines')?></p>
-    <? else: ?>
-      <ul class="results fines" data-role="listview">
-        <? foreach ($this->fines as $record): ?>
-          <li>
-            <? if ($showLink = (!empty($record['title']) && is_object($record['driver']))): ?>
-              <a rel="external" href="<?=$this->recordLink()->getUrl($record['driver'])?>">
-            <? endif; ?>
-            <div class="result">
-              <h3>
-                <? if (empty($record['title'])): ?>
-                  <?=$this->transEsc('not_applicable')?>
-                <? else: ?>
-                  <?=$this->escapeHtml(trim($record['title'], '/:'))?>
-                <? endif; ?>
-              </h3>
-              <span class="ui-li-aside"><?=isset($record['balance']) ? $this->safeMoneyFormat($record['balance']/100.00) : ''?></span>
-              <p><strong><?=$this->transEsc('Due Date')?></strong>: <?=isset($record['duedate']) ? $this->escapeHtml($record['duedate']) : ''?></p>
-              <p><strong><?=$this->transEsc('Checked Out')?></strong>: <?=isset($record['checkout']) ? $this->escapeHtml($record['checkout']) : ''?></p>
-              <p><strong><?=$this->transEsc('Fine')?></strong>: <?=isset($record['fine']) ? $this->escapeHtml($record['fine']) : ''?></p>
-              <p><strong><?=$this->transEsc('Fee')?></strong>: <?=isset($record['amount']) ? $this->safeMoneyFormat($record['amount']/100.00) : ''?></p>
-            </div>
-            <? if ($showLink): ?>
-              </a>
-            <? endif; ?>
-          </li>
-        <? endforeach; ?>
-      </ul>
-    <? endif; ?>
-  </div>
-  <?=$this->mobileMenu()->footer()?>
-</div>
diff --git a/themes/jquerymobile/templates/myresearch/footer-navbar.phtml b/themes/jquerymobile/templates/myresearch/footer-navbar.phtml
deleted file mode 100644
index 52bad29bdb93438df44019dcf6c66fe53bc841c3..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/myresearch/footer-navbar.phtml
+++ /dev/null
@@ -1,43 +0,0 @@
-<? $user = $this->auth()->isLoggedIn(); if ($user): ?>
-  <?
-    $rows = [];
-    if ($this->userlist()->getMode() !== 'disabled') {
-      $rows[] = '<li><a rel="external" '
-        . ($this->layout()->templateName=="mylist" ? ' class="ui-btn-active"' : '')
-        . ' href="' . $this->url('myresearch-favorites') . '">'
-        . $this->transEsc('Favorites') . '</a></li>';
-    }
-    $rows[] = '<li><a rel="external" '
-      . ($this->layout()->templateName=="history" ? ' class="ui-btn-active"' : '')
-      . ' href="' . $this->url('search-history') . '?require_login">'
-      . $this->transEsc('History') . '</a></li>';
-    if ($this->auth()->getManager()->supportsPasswordChange()) {
-      $rows[] = '<li><a rel="external" href="'
-        . $this->url('myresearch-changepassword') . '">'
-        . $this->transEsc("Change Password") . '</a></li>';
-    }
-    if ($user->libraryCardsEnabled()) {
-      $rows[] = '<li><a rel="external" href="'
-        . $this->url('librarycards-home') . '">'
-        . $this->transEsc('Library Cards') . '</a></li>';
-    }
-    $rows[] = '<li><a rel="external" href="'
-      . $this->url('myresearch-logout') . '">' . $this->transEsc("Log Out")
-      . '</a></li>';
-  ?>
-  <div data-role="navbar">
-    <ul>
-      <? foreach ($rows as $i => $row): ?>
-        <? if ($i > 0 && $i % 3 === 0): ?>
-    </ul>
-  </div>
-  <div data-role="navbar">
-    <ul>
-        <? endif; ?>
-        <?=$row?>
-      <? endforeach; ?>
-    </ul>
-  </div>
-<? else: ?>
-  <?=$this->render('default-footer-navbar.phtml');?>
-<? endif; ?>
diff --git a/themes/jquerymobile/templates/myresearch/header-navbar.phtml b/themes/jquerymobile/templates/myresearch/header-navbar.phtml
deleted file mode 100644
index ef5187198fd12270e733364558255f5dee51b82a..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/myresearch/header-navbar.phtml
+++ /dev/null
@@ -1,15 +0,0 @@
-<? if ($this->auth()->isLoggedIn() && 'ils-none' !== $this->ils()->getOfflineMode()): ?>
-  <div data-role="navbar">
-    <ul>
-      <? if ($this->ils()->checkCapability('getMyTransactions')): ?>
-        <li><a rel="external" <?=$this->layout()->templateName=="checkedout" ? ' class="ui-btn-active"' : ''?> href="<?=$this->url('myresearch-checkedout')?>"><?=$this->transEsc('Checked Out')?></a></li>
-      <? endif; ?>
-      <? if ($this->ils()->checkCapability('getMyHolds')): ?>
-        <li><a rel="external" <?=$this->layout()->templateName=="holds" ? ' class="ui-btn-active"' : ''?> href="<?=$this->url('myresearch-holds')?>"><?=$this->transEsc('Holds')?></a></li>
-      <? endif; ?>
-      <? if ($this->ils()->checkCapability('getMyFines')): ?>
-        <li><a rel="external" <?=$this->layout()->templateName=="fines" ? ' class="ui-btn-active"' : ''?> href="<?=$this->url('myresearch-fines')?>"><?=$this->transEsc('Fines')?></a></li>
-      <? endif; ?>
-    </ul>
-  </div>
-<? endif; ?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/myresearch/holds.phtml b/themes/jquerymobile/templates/myresearch/holds.phtml
deleted file mode 100644
index 3118692dda43b1238da157320bdde5da35fd16a4..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/myresearch/holds.phtml
+++ /dev/null
@@ -1,144 +0,0 @@
-<?
-    // Set up page title:
-    $this->headTitle($this->translate('My Holds'));
-?>
-<div data-role="page" id="MyResearch-checkedout">
-  <?=$this->mobileMenu()->header()?>
-  <div data-role="content">
-    <h3><?=$this->transEsc('Your Holds and Recalls') ?></h3>
-
-    <?=$this->flashmessages()?>
-
-    <?=$this->context($this)->renderInContext('librarycards/selectcard.phtml', array('user' => $this->auth()->isLoggedIn())); ?>
-
-    <? if (!empty($this->recordList)): ?>
-      <? if ($this->cancelForm): ?>
-        <form name="cancelForm" method="post" id="cancelHold">
-          <fieldset data-type="horizontal" data-role="controlgroup">
-            <input type="submit" class="button holdCancel" name="cancelSelected" value="<?=$this->transEsc("hold_cancel_selected") ?>" onClick="return confirm('<?=$this->transEsc("confirm_hold_cancel_selected_text") ?>')" />
-            <input type="submit" class="button holdCancelAll" name="cancelAll" value="<?=$this->transEsc("hold_cancel_all") ?>" onClick="return confirm('<?=$this->transEsc("confirm_hold_cancel_all_text") ?>')" />
-          </fieldset>
-      <? endif; ?>
-
-      <ul class="results holds" data-role="listview">
-      <? foreach ($this->recordList as $resource): ?>
-        <? $ilsDetails = $resource->getExtraDetail('ils_details'); ?>
-        <li>
-          <?
-              // Flag to track whether we have an open anchor tag:
-              $openAnchor = false;
-
-              // If this is a non-missing Solr record, we should display a link:
-              if (is_a($resource, 'VuFind\\RecordDriver\\SolrDefault') && !is_a($resource, 'VuFind\\RecordDriver\\Missing')) {
-                  $title = $resource->getTitle();
-                  $title = empty($title) ? $this->transEsc('Title not available') : $this->escapeHtml($title);
-                  echo '<a rel="external" href="' . $this->recordLink()->getUrl($resource) . '">';
-                  $openAnchor = true;
-              } else if (isset($ilsDetails['title']) && !empty($ilsDetails['title'])){
-                  // If the record is not available in Solr, perhaps the ILS driver sent us a title we can show...
-                  $title = $this->escapeHtml($ilsDetails['title']);
-              } else {
-                  // Last resort -- indicate that no title could be found.
-                  $title = $this->transEsc('Title not available');
-              }
-          ?>
-          <div class="result">
-            <h3><?=$title?></h3>
-            <? $listAuthors = $resource->getPrimaryAuthors(); if (!empty($listAuthors)): ?>
-              <p><?=$this->transEsc('by')?> <?=$this->escapeHtml($listAuthors[0])?><? if (count($listAuthors) > 1): ?>, <?=$this->transEsc('more_authors_abbrev')?><? endif; ?></p>
-            <? endif; ?>
-            <? $formats = $resource->getFormats(); if (count($formats) > 0): ?>
-              <?=$this->record($resource)->getFormatList()?>
-            <? endif; ?>
-            <? if (isset($ilsDetails['volume']) && !empty($ilsDetails['volume'])): ?>
-              <p><strong><?=$this->transEsc('Volume')?>:</strong> <?=$this->escapeHtml($ilsDetails['volume'])?></p>
-            <? endif; ?>
-
-            <? if (isset($ilsDetails['publication_year']) && !empty($ilsDetails['publication_year'])): ?>
-              <p><strong><?=$this->transEsc('Year of Publication')?>:</strong> <?=$this->escapeHtml($ilsDetails['publication_year'])?></p>
-            <? endif; ?>
-
-            <? if (!empty($ilsDetails['requestGroup'])): ?>
-              <p>
-                <strong><?=$this->transEsc('hold_requested_group') ?>:</strong>
-                <?=$this->transEsc('request_group_' . $ilsDetails['requestGroup'], null, $ilsDetails['requestGroup'])?>
-              </p>
-            <? endif; ?>
-
-            <? /* Depending on the ILS driver, the "location" value may be a string or an ID; figure out the best
-               value to display... */ ?>
-            <? $pickupDisplay = ''; ?>
-            <? $pickupTranslate = false; ?>
-            <? if (isset($ilsDetails['location'])): ?>
-              <? if ($this->pickup): ?>
-                <? foreach ($this->pickup as $library): ?>
-                  <? if ($library['locationID'] == $ilsDetails['location']): ?>
-                    <? $pickupDisplay = $library['locationDisplay']; ?>
-                    <? $pickupTranslate = true; ?>
-                  <? endif; ?>
-                <? endforeach; ?>
-              <? endif; ?>
-              <? if (empty($pickupDisplay)): ?>
-                <? $pickupDisplay = $ilsDetails['location']; ?>
-              <? endif; ?>
-            <? endif; ?>
-            <? if (!empty($pickupDisplay)): ?>
-              <p>
-                <strong><?=$this->transEsc('pick_up_location') ?>:</strong>
-                <?=$pickupTranslate ? $this->transEsc('location_' . $pickupDisplay, null, $pickupDisplay) : $this->escapeHtml($pickupDisplay)?>
-              </p>
-            <? endif; ?>
-
-            <? if (isset($this->cancelResults['items'])): ?>
-              <? foreach ($this->cancelResults['items'] as $itemId=>$cancelResult): ?>
-                <? if ($itemId == $ilsDetails['item_id'] && $cancelResult['success'] == false): ?>
-                  <div class="error"><?=$this->transEsc($cancelResult['status']) ?><? if ($cancelResult['sysMessage']) echo ' : ' . $this->transEsc($cancelResult['sysMessage']); ?></div>
-                <? endif; ?>
-              <? endforeach; ?>
-            <? endif; ?>
-
-            <? if (isset($ilsDetails['available']) && $ilsDetails['available'] == true): ?>
-              <div class="userMsg" style="margin-bottom: 10px;"><?=$this->transEsc("hold_available") ?></div>
-            <? elseif (isset($ilsDetails['in_transit']) && $ilsDetails['in_transit']): ?>
-              <div class="userMsg" style="margin-bottom: 10px;"><?=$this->transEsc('request_in_transit') . (is_string($ilsDetails['in_transit']) ? ': ' . $this->transEsc('institution_' . $ilsDetails['in_transit'], array(), $ilsDetails['in_transit']) : '') ?></div>
-            <? elseif (isset($ilsDetails['position'])): ?>
-              <p><strong><?=$this->transEsc("hold_queue_position") ?>:</strong> <?=$this->escapeHtml($ilsDetails['position']) ?></p>
-            <? endif; ?>
-
-            <p>
-              <? if (!empty($ilsDetails['create'])): ?>
-                <strong><?=$this->transEsc('Created') ?>:</strong> <?=$this->escapeHtml($ilsDetails['create']) ?>
-                <? if (!empty($ilsDetails['expire'])): ?>|<? endif; ?>
-              <? endif; ?>
-              <? if (!empty($ilsDetails['expire'])): ?>
-                <strong><?=$this->transEsc('Expires') ?>:</strong> <?=$this->escapeHtml($ilsDetails['expire']) ?>
-              <? endif; ?>
-            </p>
-          </div>
-          <? if ($openAnchor): ?></a><? endif; ?>
-          <? if ($this->cancelForm && isset($ilsDetails['cancel_details'])): ?>
-            <div data-role="fieldcontain">
-              <fieldset data-type="horizontal" data-role="controlgroup">
-                <? $safeId = preg_replace('/[^a-zA-Z0-9]/', '', $resource->getUniqueId()); ?>
-                <label for="checkbox_<?=$safeId?>"><?=$this->transEsc("Select this record")?></label>
-                <input type="hidden" name="cancelAllIDS[]" value="<?=$this->escapeHtmlAttr($ilsDetails['cancel_details']) ?>" />
-                <input type="checkbox" name="cancelSelectedIDS[]" value="<?=$this->escapeHtmlAttr($ilsDetails['cancel_details']) ?>" class="checkbox" style="margin-left:0;" id="checkbox_<?=$safeId?>" />
-              </fieldset>
-            </div>
-          <? endif; ?>
-        </li>
-      <? endforeach; ?>
-      </ul>
-      <? if ($this->cancelForm): ?>
-          <fieldset data-type="horizontal" data-role="controlgroup">
-            <input type="submit" class="button holdCancel" name="cancelSelected" value="<?=$this->transEsc("hold_cancel_selected") ?>" onClick="return confirm('<?=$this->transEsc("confirm_hold_cancel_selected_text") ?>')" />
-            <input type="submit" class="button holdCancelAll" name="cancelAll" value="<?=$this->transEsc("hold_cancel_all") ?>" onClick="return confirm('<?=$this->transEsc("confirm_hold_cancel_all_text") ?>')" />
-          </fieldset>
-      </form>
-      <? endif; ?>
-    <? else: ?>
-      <p><?=$this->transEsc('You do not have any holds or recalls placed') ?>.</p>
-    <? endif; ?>
-  </div>
-  <?=$this->mobileMenu()->footer()?>
-</div>
diff --git a/themes/jquerymobile/templates/myresearch/login.phtml b/themes/jquerymobile/templates/myresearch/login.phtml
deleted file mode 100644
index e78e7ac13a7a94ce95ffb3c708b70f167a3d1764..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/myresearch/login.phtml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?
-    // Set up page title:
-    $this->headTitle($this->translate('Login'));
-
-    // Convenience variables:
-    $account = $this->auth()->getManager();
-    $hideLogin = !(is_object($account) && $account->loginEnabled());
-    $offlineMode = $this->ils()->getOfflineMode();
-?>
-<div data-role="page" id="MyResearch-login">
-  <?=$this->mobileMenu()->header()?>
-  <div data-role="content">
-    <? if ($offlineMode == "ils-offline"): ?>
-      <div class="sysInfo">
-        <h2><?=$this->transEsc('ils_offline_title')?></h2>
-        <p><strong><?=$this->transEsc('ils_offline_status')?></strong></p>
-        <p><?=$this->transEsc('ils_offline_login_message')?></p>
-        <? $supportEmail = $this->escapeHtmlAttr($this->systemEmail()); ?>
-        <p><a href="mailto:<?=$supportEmail?>"><?=$supportEmail?></a></p>
-      </div>
-    <? elseif ($hideLogin): ?>
-      <div class="error"><?=$this->transEsc('login_disabled')?></div>
-    <? endif; ?>
-
-    <? if (!$hideLogin): ?>
-      <?=$this->auth()->getLogin()?>
-    <? endif; ?>
-  </div>
-  <?=$this->mobileMenu()->footer()?>
-</div>
-
diff --git a/themes/jquerymobile/templates/myresearch/mylist.phtml b/themes/jquerymobile/templates/myresearch/mylist.phtml
deleted file mode 100644
index 2cd1dca0c958d1fbba6614d5647fc26c162d577a..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/myresearch/mylist.phtml
+++ /dev/null
@@ -1,60 +0,0 @@
-<?
-    // Grab list object from search results (if applicable):
-    $list = $this->results->getListObject();
-
-    // Grab current user (if any):
-    $user = $this->auth()->isLoggedIn();
-
-    // Set up page title:
-    $this->headTitle(isset($list) ? $list->title : $this->translate('Favorites'));
-
-    // Load Javascript dependencies into header:
-    $this->headScript()->appendFile("check_item_statuses.js");
-
-    // Set up extra button for header:
-    $extraButton = (isset($list) && $list->editAllowed($user))
-        ? '<a rel="external" href="'
-            . $this->url('editList', array('id' => $list->id))
-            . '" data-icon="gear" class="ui-btn-left">'
-            . $this->transEsc("edit_list")
-            . '</a>'
-        : '';
-?>
-
-<div data-role="page" id="MyResearch-list" class="results-page">
-  <?=$this->mobileMenu()->header(array('extraButtons'=>array($extraButton)))?>
-  <div data-role="content">
-    <? foreach ($this->results->getRecommendations('side') as $current): ?>
-      <?=$this->recommend($current)?>
-    <? endforeach; ?>
-
-    <? if (isset($list)): ?>
-      <h3><?=$this->escapeHtml($list->title)?></h3>
-      <? if (!empty($list->description)): ?><p><?=$this->escapeHtml($list->description)?></p><? endif; ?>
-    <? else: ?>
-      <h3><?=$this->transEsc("Your Favorites")?></h3>
-    <? endif; ?>
-
-    <?=$this->flashmessages();?>
-
-    <? if (($recordTotal = $this->results->getResultTotal()) > 0): ?>
-      <p>
-        <strong><?=$this->localizedNumber($this->results->getStartRecord())?></strong> - <strong><?=$this->localizedNumber($this->results->getEndRecord())?></strong>
-        <?=$this->transEsc('of')?> <strong><?=$this->localizedNumber($recordTotal)?></strong>
-      </p>
-
-      <ul class="results mylist" data-role="listview" data-split-icon="minus" data-split-theme="d" data-inset="false">
-        <? $i = 0; foreach ($this->results->getResults() as $current): ?>
-          <li>
-            <?=$this->record($current)->getListEntry($list, $user)?>
-          </li>
-        <? endforeach; ?>
-      </ul>
-
-      <?=$this->paginationControl($this->results->getPaginator(), 'Sliding', 'search/pagination.phtml', array('results' => $this->results))?>
-    <? else: ?>
-      <p><?=$this->transEsc('You do not have any saved resources')?></p>
-    <? endif; ?>
-  </div>
-  <?=$this->mobileMenu()->footer()?>
-</div>
diff --git a/themes/jquerymobile/templates/myresearch/newpassword.phtml b/themes/jquerymobile/templates/myresearch/newpassword.phtml
deleted file mode 100644
index ee3335dcddd2a912a045c455f3e7863d671bed0a..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/myresearch/newpassword.phtml
+++ /dev/null
@@ -1,33 +0,0 @@
-<?
-  // Set up page title:
-  $this->headTitle(isset($list) ? $list->title : $this->translate('Create New Password'));
-
-  // Set up extra button for header:
-  $extraButton = '<a rel="external" href="'
-    . $this->url('myresearch-home')
-    . '" data-icon="back" class="ui-btn-left">'
-    . $this->transEsc('Account')
-    . '</a>';
-?>
-<div data-role="page" id="MyResearch-newpassword" class="newpassword">
-  <?=$this->mobileMenu()->header(array('extraButtons'=>array($extraButton))) ?>
-  <div data-role="content">
-    <?=$this->flashmessages() ?>
-    <? if (!$this->auth()->getManager()->supportsPasswordChange($this->auth_method)): ?>
-      <div class="error"><?=$this->transEsc('recovery_new_disabled') ?></div>
-    <? elseif (!isset($this->hash)): ?>
-      <div class="error"><?=$this->transEsc('recovery_user_not_found') ?></div>
-    <? else: ?>
-      <form data-ajax="false" action="<?=$this->url('myresearch-newpassword') ?>" method="post">
-        <?=$this->auth()->getNewPasswordForm() ?>
-        <input type="hidden" value="<?=$this->escapeHtmlAttr($this->auth()->getManager()->getCsrfHash(true))?>" name="csrf"/>
-        <input type="hidden" value="<?=$this->escapeHtmlAttr($this->hash) ?>" name="hash"/>
-        <input type="hidden" value="<?=$this->escapeHtmlAttr($this->username) ?>" name="username"/>
-        <input type="hidden" value="<?=$this->escapeHtmlAttr($this->auth_method) ?>" name="auth_method"/>
-        <?=$this->recaptcha()->html($this->useRecaptcha) ?>
-        <input type="submit" name="submit" value="<?=$this->transEsc('Submit') ?>"/>
-      </form>
-    <? endif; ?>
-  </div>
-  <?=$this->mobileMenu()->footer() ?>
-</div>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/myresearch/profile.phtml b/themes/jquerymobile/templates/myresearch/profile.phtml
deleted file mode 100644
index b5afd066898154158d1d3265fbcc124d4e20e73e..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/myresearch/profile.phtml
+++ /dev/null
@@ -1,33 +0,0 @@
-<?
-    // Set up page title:
-    $this->headTitle($this->translate('My Profile'));
-?>
-<div data-role="page" id="MyResearch-login">
-  <?=$this->mobileMenu()->header()?>
-  <div data-role="content">
-    <h3><?=$this->transEsc('Your Profile')?></h3>
-    <?=$this->flashmessages();?>
-
-    <?=$this->context($this)->renderInContext('librarycards/selectcard.phtml', array('user' => $this->auth()->isLoggedIn())); ?>
-
-    <dl class="biblio">
-    <?
-        echo $this->renderArray(
-            '<dt>%%LABEL%%:</dt><dd>%%VALUE%%</dd>', $this->profile,
-            array(
-                $this->transEsc('First Name') => 'firstname',
-                $this->transEsc('Last Name') => 'lastname',
-                $this->transEsc('Address') . ' 1' => 'address1',
-                $this->transEsc('Address') . ' 2' => 'address2',
-                $this->transEsc('Zip') => 'zip',
-                $this->transEsc('City') => 'city',
-                $this->transEsc('Country') => 'country',
-                $this->transEsc('Phone Number') => 'phone',
-                $this->transEsc('Group') => 'group'
-            )
-        );
-     ?>
-     </dl>
-  </div>
-  <?=$this->mobileMenu()->footer()?>
-</div>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/myresearch/recover.phtml b/themes/jquerymobile/templates/myresearch/recover.phtml
deleted file mode 100644
index e2db3e51acc5c89bf9258f73a043176bc5e4c609..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/myresearch/recover.phtml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?
-  // Set up page title:
-  $this->headTitle($this->translate('recovery_title'));
-
-  // Set up extra button for header:
-  $extraButton = '<a rel="external" href="'
-    . $this->url('myresearch-userlogin')
-    . '" data-icon="back" class="ui-btn-left">';
-  $extraButton .= $this->transEsc('Login');
-  $extraButton .= '</a>';
-?>
-<div data-role="page" id="MyResearch-recover" class="results-page">
-  <?=$this->mobileMenu()->header(array('extraButtons'=>array($extraButton))) ?>
-  <div data-role="content">
-    <?=$this->flashmessages()?>
-    <? if (!$this->auth()->getManager()->supportsRecovery()): ?>
-      <div class="error"><?=$this->transEsc('recovery_disabled') ?></div>
-    <? else: ?>
-      <form data-ajax="false" method="post">
-        <?=$this->auth()->getPasswordRecoveryForm() ?>
-      </form>
-    <? endif; ?>
-  </div>
-  <?=$this->mobileMenu()->footer() ?>
-</div>
diff --git a/themes/jquerymobile/templates/pazpar2/home.phtml b/themes/jquerymobile/templates/pazpar2/home.phtml
deleted file mode 100644
index d13d4348c1e39e2222b5f16ce7d65ecd7816ef92..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/pazpar2/home.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<?=$this->render('search/home.phtml');?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/pazpar2/search.phtml b/themes/jquerymobile/templates/pazpar2/search.phtml
deleted file mode 100644
index c1797c1cd4a1ebb2ccad84718b1e225e51cac6a8..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/pazpar2/search.phtml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?
-    // Load standard settings from the default search results screen:
-    echo $this->render('search/results.phtml');
-?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/primo/advanced.phtml b/themes/jquerymobile/templates/primo/advanced.phtml
deleted file mode 100644
index 006c6fd476de8e2694497415d893423c70f977c7..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/primo/advanced.phtml
+++ /dev/null
@@ -1,66 +0,0 @@
-<?
-  // Set page title.
-  $this->headTitle($this->translate('Advanced Search'));
-  // Set default value if necessary:
-  if (!isset($this->searchClassId)) {
-    $this->searchClassId = 'Solr';
-  }
-  // Load search actions and settings (if any):
-  $options = $this->searchOptions($this->searchClassId);
-  $basicSearch = $options->getSearchAction();
-  $lastSort = $this->searchMemory()->getLastSort($options->getSearchClassId());
-  $lastLimit = $this->searchMemory()->getLastLimit($options->getSearchClassId());
-?>
-<div data-role="page" id="Search-home">
-  <?=$this->mobileMenu()->header(array('hideSearchLink' => true))?>
-  <div data-role="content">
-    <!-- SEARCH BOXES -->
-    <form id="advSearchForm" name="searchForm"  method="get" action="<?=$this->url($this->options->getSearchAction())?>" data-ajax="false">
-      <input type="hidden" name="join" value="AND" />
-      <? $numGroups = 1; $numRows = 3; // hard-coded sizes ?>
-      <? for ($i = 0; $i < $numGroups; $i++): ?>
-        <input type="hidden" name="bool<?=$i?>[]" value="AND" />
-        <fieldset class="ui-grid-b">
-        <? for ($j = 0; $j < $numRows; $j++): ?>
-          <div class="ui-block-a">
-            <select id="search_type<?=$i?>_<?=$j?>" name="type<?=$i?>[]">
-              <? foreach ($this->options->getAdvancedHandlers() as $searchVal => $searchDesc): ?>
-                <option value="<?=$this->escapeHtmlAttr($searchVal)?>"><?=$this->transEsc($searchDesc)?></option>
-              <? endforeach; ?>
-            </select>
-          </div>
-          <div class="ui-block-b">
-            <select id="searchForm_op<?=$i?>_<?=$j?>" name="op<?=$i?>[]">
-              <? foreach ($this->options->getAdvancedOperators() as $searchVal => $searchDesc): ?>
-                <option value="<?=$this->escapeHtmlAttr($searchVal)?>"><?=$this->transEsc($searchDesc)?></option>
-              <? endforeach; ?>
-            </select>
-          </div>
-          <div class="ui-block-c">
-            <input id="search_lookfor<?=$i?>_<?=$j?>" type="text" value="" name="lookfor<?=$i?>[]" style="margin-top:.5em;height:28px"/>
-          </div>
-        <? endfor; ?>
-        </fieldset>
-      <? endfor; ?>
-      <? if (!empty($lastSort)): ?>
-        <input type="hidden" name="sort" value="<?=$this->escapeHtmlAttr($lastSort)?>" />
-      <? endif; ?>
-      <hr/>
-      <fieldset class="ui-grid-solo">
-        <div class="ui-block-a">
-          <input type="submit" name="submit" value="<?=$this->transEsc("Find")?>" data-role="button" data-theme="b"/>
-        </div>
-      </fieldset>
-      <?
-        /* Load hidden limit preference from Session */
-        if (!empty($lastLimit)) {
-          echo '<input type="hidden" name="limit" value="' . $this->escapeHtmlAttr($lastLimit) . '" />';
-        }
-        if (!empty($lastSort)) {
-          echo '<input type="hidden" name="sort" value="' . $this->escapeHtmlAttr($lastSort) . '" />';
-        }
-      ?>
-    </form>
-  </div>
-  <?=$this->mobileMenu()->footer()?>
-</div>
diff --git a/themes/jquerymobile/templates/primo/home.phtml b/themes/jquerymobile/templates/primo/home.phtml
deleted file mode 100644
index 881bf39a2f68368ad5874c06cb393530cc3140f8..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/primo/home.phtml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?
-    $this->overrideHomeOptions = '';  // turn off extra options
-    echo $this->render('search/home.phtml');
-?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/primo/search.phtml b/themes/jquerymobile/templates/primo/search.phtml
deleted file mode 100644
index c1797c1cd4a1ebb2ccad84718b1e225e51cac6a8..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/primo/search.phtml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?
-    // Load standard settings from the default search results screen:
-    echo $this->render('search/results.phtml');
-?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/record/addtag.phtml b/themes/jquerymobile/templates/record/addtag.phtml
deleted file mode 100644
index b18c7dea3c9d46bade79140424dee600438e8313..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/record/addtag.phtml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?
-    // Set page title.
-    $this->headTitle($this->translate('Add Tag'));
-?>
-<div data-role="page" id="Record-view">
-  <?=$this->mobileMenu()->header()?>
-  <div data-role="content">
-    <form method="post" name="tagRecord" data-ajax="false">
-      <input type="hidden" name="submit" value="1" />
-      <input type="hidden" name="id" value="<?=$this->escapeHtmlAttr($this->driver->getUniqueId())?>" />
-      <input type="hidden" name="source" value="<?=$this->escapeHtmlAttr($this->driver->getSourceIdentifier())?>" />
-      <div data-role="fieldcontain">
-        <label for="addtag_tag"><?=$this->transEsc("Tags")?>:</label>
-        <input id="addtag_tag" type="text" name="tag" value=""/>
-        <p><?=$this->transEsc("add_tag_note")?></p>
-      </div>
-      <div data-role="fieldcontain">
-        <input type="submit" value="<?=$this->transEsc('Save')?>"/>
-      </div>
-    </form>
-  </div>
-  <?=$this->mobileMenu()->footer()?>
-</div>
diff --git a/themes/jquerymobile/templates/record/ajaxtab.phtml b/themes/jquerymobile/templates/record/ajaxtab.phtml
deleted file mode 100644
index 6f7d520981ebef08a220bd6ef46f1afaf76ecd02..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/record/ajaxtab.phtml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?
-foreach ($this->tabs as $tab => $obj) {
-    if (strtolower($this->activeTab) == strtolower($tab)) {
-        echo $this->record($this->driver)->getTab($obj);
-    }
-}
-?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/record/cite.phtml b/themes/jquerymobile/templates/record/cite.phtml
deleted file mode 100644
index adceff58dab0ecf09a343032e1062c16ecd2fa52..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/record/cite.phtml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?
-    // Set page title.
-    $this->headTitle($this->translate('Record Citations'));
-
-    // Collect citation data:
-    $helper = $this->citation($this->driver);
-    $citations = array();
-    foreach ($this->driver->getCitationFormats() as $format) {
-        $citations[$format . ' Citation'] = $helper->getCitation($format);
-    }
-?>
-<div data-role="page" id="Record-view">
-  <?=$this->mobileMenu()->header()?>
-  <div class="record" data-role="content" data-record-id="<?=$this->escapeHtmlAttr($this->driver->getUniqueId())?>">
-    <? if (count($citations) == 0): ?>
-      <?=$this->transEsc('No citations are available for this record')?>
-    <? else: ?>
-      <? foreach ($citations as $caption => $citation): ?>
-        <strong><?=$this->transEsc($caption)?></strong>
-        <p class="citationText">
-          <?=$citation?>
-        </p>
-      <? endforeach; ?>
-      <div class="note"><?=$this->transEsc('Warning: These citations may not always be 100% accurate')?>.</div>
-    <? endif; ?>
-  </div>
-  <?=$this->mobileMenu()->footer()?>
-</div>
diff --git a/themes/jquerymobile/templates/record/comments-list.phtml b/themes/jquerymobile/templates/record/comments-list.phtml
deleted file mode 100644
index dd57c17b7e3ed9adefce9b924cfcd25e76de46fe..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/record/comments-list.phtml
+++ /dev/null
@@ -1,17 +0,0 @@
-<? $comments = $this->driver->getComments(); if (empty($comments) || count($comments) == 0): ?>
-  <li><p><?=$this->transEsc('Be the first to leave a comment')?>!</p></li>
-<? endif; ?>
-<? foreach ($comments as $comment): ?>
-  <li>
-    <a href="#">
-      <p><?=$this->escapeHtml($comment->comment)?></p>
-      <p class="posted-by"><?=$this->transEsc('Posted by')?> <strong><?=$this->escapeHtml(trim($comment->firstname . ' ' . $comment->lastname))?></strong></p>
-      <span class="ui-li-aside"><?=$this->escapeHtml(array_shift(explode(' ', $comment->created)))?></span>
-    </a>
-    <? if (($user = $this->auth()->isLoggedIn()) && $comment->user_id == $user->id): ?>
-      <a rel="external" href="<?=$this->recordLink()->getActionUrl($this->driver, 'DeleteComment')?>?delete=<?=urlencode($comment->id)?>" data-comment-id="<?=$this->escapeHtmlAttr($comment->id)?>" class="deleteRecordComment">
-        <?=$this->transEsc('Delete')?>
-      </a>
-    <? endif; ?>
-  </li>
-<? endforeach; ?>
diff --git a/themes/jquerymobile/templates/record/cover.phtml b/themes/jquerymobile/templates/record/cover.phtml
deleted file mode 100644
index 52b6c86fa1183517f62a0963597521477704d9d3..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/record/cover.phtml
+++ /dev/null
@@ -1,8 +0,0 @@
-<? /* Display thumbnail if appropriate: */ ?>
-<? if ($cover): ?>
-  <? if ($this->link): ?><a rel="external" href="<?=$this->escapeHtmlAttr($this->link)?>"><? endif; ?>
-  <div class="recordcover">
-    <img alt="<?=$this->transEsc('Cover Image')?>" class="recordcover" src="<?=$this->escapeHtmlAttr($cover); ?>"/>
-  </div>
-  <? if ($this->link): ?></a><? endif; ?>
-<? endif; ?>
diff --git a/themes/jquerymobile/templates/record/email.phtml b/themes/jquerymobile/templates/record/email.phtml
deleted file mode 100644
index 0ecec92f9dda6b4fcdd2a305224a36439147e262..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/record/email.phtml
+++ /dev/null
@@ -1,16 +0,0 @@
-<?
-    // Set page title.
-    $this->headTitle($this->translate('Email Record'));
-?>
-<div data-role="page" id="Record-view">
-  <?=$this->mobileMenu()->header()?>
-  <div data-role="content">
-    <?=$this->flashmessages()?>
-    <form method="post" name="emailRecord" data-ajax="false">
-      <input type="hidden" name="id" value="<?=$this->escapeHtmlAttr($this->driver->getUniqueId())?>" />
-      <input type="hidden" name="source" value="<?=$this->escapeHtmlAttr($this->driver->getSourceIdentifier())?>" />
-      <?=$this->render('Helpers/email-form-fields.phtml')?>
-    </form>
-  </div>
-  <?=$this->mobileMenu()->footer()?>
-</div>
diff --git a/themes/jquerymobile/templates/record/export-menu.phtml b/themes/jquerymobile/templates/record/export-menu.phtml
deleted file mode 100644
index 3668c1beafb69a7c551879c7de182ae8cd1e8f5e..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/record/export-menu.phtml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?
-    // Set page title.
-    $this->headTitle($this->translate('Export Record'));
-?>
-<div data-role="page" id="Record-view">
-  <?=$this->mobileMenu()->header()?>
-  <div data-role="content">
-    <?=$this->flashmessages()?>
-    <? $exportFormats = $this->export()->getFormatsForRecord($this->driver); if (count($exportFormats) > 0): ?>
-      <?=$this->transEsc('export_choose_format')?>
-      <ul>
-      <? foreach ($exportFormats as $exportFormat): ?>
-        <li><a rel="external" href="<?=$this->recordLink()->getActionUrl($this->driver, 'Export')?>?style=<?=$this->escapeHtml($exportFormat)?>"><?=$this->transEsc('Export to')?> <?=$this->transEsc($this->export()->getLabelForFormat($exportFormat))?></a></li>
-      <? endforeach; ?>
-      </ul>
-    <? else: ?>
-      <?=$this->transEsc('export_no_formats')?>
-    <? endif; ?>
-  </div>
-  <?=$this->mobileMenu()->footer()?>
-</div>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/record/header-navbar.phtml b/themes/jquerymobile/templates/record/header-navbar.phtml
deleted file mode 100644
index 9e0f0463b259129aa84918417d53b1b3015ba23d..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/record/header-navbar.phtml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?
-    // Disable "staff view" in mobile UI (we copy $this->tabs because unset doesn't
-    // work correctly when run directly against the view model):
-    $tabs = $this->tabs;
-    unset($tabs['Details']);
-?>
-<? if (!empty($tabs)): ?>
-  <div data-role="navbar">
-    <ul>
-      <? foreach ($tabs as $tab => $obj): ?>
-        <?
-          /* Initially invisible tabs are not supported in this theme; just skip them! */
-          if (!$obj->isVisible()) continue;
-        ?>
-        <li>
-          <a rel="external"<?=(strtolower(isset($this->activeTab) ? $this->activeTab : '') == strtolower($tab)) ? ' class="ui-btn-active"' : ''?> href="<?=$this->recordLink()->getTabUrl($this->driver, $tab)?>"><?=$this->transEsc($obj->getDescription())?></a>
-        </li>
-      <? endforeach; ?>
-    </ul>
-  </div>
-<? endif; ?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/record/hold.phtml b/themes/jquerymobile/templates/record/hold.phtml
deleted file mode 100644
index 53c98eb2736cc4e064eee6233384eb33fda59c87..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/record/hold.phtml
+++ /dev/null
@@ -1,114 +0,0 @@
-<?
-    // Set up hold script:
-    $this->headScript()->appendFile("hold.js");
-
-    // Set page title.
-    $this->headTitle($this->translate('request_place_text') . ': ' . $this->driver->getBreadcrumb());
-?>
-<div data-role="page" id="Record-view">
-  <?=$this->mobileMenu()->header()?>
-  <div data-role="content">
-    <h2><?=$this->transEsc('request_place_text')?></h2>
-    <? if ($this->helpText): ?>
-    <p class="helptext"><?=$this->helpText?></p>
-    <? endif; ?>
-    <?=$this->flashmessages()?>
-    <div class="hold-form">
-
-      <form method="post" data-ajax="false">
-
-        <? if (in_array("comments", $this->extraHoldFields)): ?>
-          <div class="hold-comment">
-          <strong><?=$this->transEsc("Comments")?>:</strong><br/>
-          <textarea rows="3" cols="20" name="gatheredDetails[comment]"><?=isset($this->gatheredDetails['comment']) ? $this->escapeHtml($this->gatheredDetails['comment']) : ''?></textarea>
-          </div>
-        <? endif; ?>
-
-        <? if (in_array("requiredByDate", $this->extraHoldFields)): ?>
-          <div class="hold-required-by">
-          <strong><?=$this->transEsc("hold_required_by")?>: </strong>
-          <div id="requiredByHolder"><input id="requiredByDate" type="text" name="gatheredDetails[requiredBy]" value="<?=(isset($this->gatheredDetails['requiredBy']) && !empty($this->gatheredDetails['requiredBy'])) ? $this->escapeHtml($this->gatheredDetails['requiredBy']) : $this->escapeHtml($this->defaultRequiredDate)?>" size="8" /> <strong>(<?=$this->dateTime()->getDisplayDateFormat()?>)</strong></div>
-          </div>
-        <? endif; ?>
-
-        <? if ($this->requestGroupNeeded): ?>
-          <div class="hold-request-group">
-            <?
-              if (isset($this->gatheredDetails['requestGroupId']) && $this->gatheredDetails['requestGroupId'] !== "") {
-                  $selected = $this->gatheredDetails['requestGroupId'];
-              } else {
-                  $selected = $this->defaultRequestGroup;
-              }
-           ?>
-            <strong><?=$this->transEsc("hold_request_group")?>:</strong>
-            <select id="requestGroupId" name="gatheredDetails[requestGroupId]">
-            <? if ($selected === false): ?>
-              <option value="" selected="selected">
-                <?=$this->transEsc('select_request_group')?>
-              </option>
-            <? endif; ?>
-            <? foreach ($this->requestGroups as $group): ?>
-              <option value="<?=$this->escapeHtmlAttr($group['id'])?>"<?=($selected == $group['id']) ? ' selected="selected"' : ''?>>
-                <?=$this->transEsc('request_group_' . $group['name'], null, $group['name'])?>
-              </option>
-            <? endforeach; ?>
-            </select>
-          </div>
-        <? endif; ?>
-
-        <? if (in_array("pickUpLocation", $this->extraHoldFields)): ?>
-          <?
-            if (isset($this->gatheredDetails['pickUpLocation']) && $this->gatheredDetails['pickUpLocation'] !== "") {
-                $selected = $this->gatheredDetails['pickUpLocation'];
-            } elseif (isset($this->homeLibrary) && $this->homeLibrary !== "") {
-                $selected = $this->homeLibrary;
-            } else {
-                $selected = $this->defaultPickup;
-            }
-          ?>
-          <div class="hold-pickup-location">
-          <? if ($this->requestGroupNeeded): ?>
-            <span id="pickUpLocationLabel"><strong><?=$this->transEsc("pick_up_location")?>:
-              <noscript> (<?=$this->transEsc("Please enable JavaScript.")?>)</noscript>
-            </strong></span>
-            <select id="pickUpLocation" name="gatheredDetails[pickUpLocation]" data-default="<?=$this->escapeHtmlAttr($selected)?>">
-              <? if ($selected === false): ?>
-              <option value="" selected="selected">
-                <?=$this->transEsc('select_pickup_location')?>
-              </option>
-              <? endif; ?>
-            </select>
-          <? elseif ($this->pickup): ?>
-            <strong><?=$this->transEsc("pick_up_location")?>:</strong><br/>
-            <select name="gatheredDetails[pickUpLocation]">
-            <? if ($selected === false && count($this->pickup) > 1): ?>
-              <option value="" selected="selected">
-                <?=$this->transEsc('select_pickup_location')?>
-              </option>
-            <? endif; ?>
-            <? foreach ($this->pickup as $lib): ?>
-              <option value="<?=$this->escapeHtmlAttr($lib['locationID'])?>"<?=($selected == $lib['locationID']) ? ' selected="selected"' : ''?>>
-                <?=$this->transEsc('location_' . $lib['locationDisplay'], null, $lib['locationDisplay'])?>
-              </option>
-            <? endforeach; ?>
-            </select>
-          <? else: ?>
-            <input type="hidden" name="gatheredDetails[pickUpLocation]" value="<?=$this->escapeHtmlAttr($this->defaultPickup)?>" />
-          <? endif; ?>
-          </div>
-        <? endif; ?>
-
-        <input type="submit" name="placeHold" value="<?=$this->transEsc('request_submit_text')?>"/>
-
-      </form>
-
-    </div>
-  </div>
-  <?=$this->mobileMenu()->footer()?>
-</div>
-
-<script type="text/javascript">
-$(document).ready(function(){
-    setUpHoldRequestForm('<?=$this->escapeHtml($this->driver->getUniqueId()) ?>');
-});
-</script>
diff --git a/themes/jquerymobile/templates/record/save.phtml b/themes/jquerymobile/templates/record/save.phtml
deleted file mode 100644
index 149feb4c13ab9842722739d6161349f2b39a773c..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/record/save.phtml
+++ /dev/null
@@ -1,57 +0,0 @@
-<?
-    // Set page title.
-    $this->headTitle($this->translate('Save'));
-?>
-<div data-role="page" id="Record-view">
-  <?=$this->mobileMenu()->header()?>
-  <div data-role="content">
-    <h3><?=$this->transEsc("add_favorite_prefix") ?> <?=$this->escapeHtml($this->driver->getBreadcrumb())?> <?=$this->transEsc("add_favorite_suffix") ?></h3>
-    <form method="post" name="saveRecord" data-ajax="false">
-      <input type="hidden" name="submit" value="1" />
-      <input type="hidden" name="id" value="<?=$this->escapeHtmlAttr($this->driver->getUniqueId()) ?>" />
-      <input type="hidden" name="source" value="<?=$this->escapeHtmlAttr($this->driver->getSourceIdentifier())?>" />
-      <? if (!empty($this->containingLists)): ?>
-        <ul data-role="listview" data-dividertheme="e" data-inset="true">
-          <li data-role="list-divider"><?=$this->transEsc('This item is already part of the following list/lists') ?>:</li>
-          <? foreach ($this->containingLists as $list): ?>
-            <li><a rel="external" href="<?=$this->url('userList', array('id' => $list['id'])) ?>"><?=$this->escapeHtml($list['title'])?></a></li>
-          <? endforeach; ?>
-        </ul>
-      <? endif; ?>
-
-      <?/* Only display the list drop-down if the user has lists that do not contain
-      this item OR if they have no lists at all and need to create a default list */?>
-      <? $showLists = (!empty($this->nonContainingLists) || (empty($this->containingLists) && empty($this->nonContainingLists))); ?>
-
-      <div data-role="fieldcontain">
-        <? if ($showLists): ?>
-          <label class="displayBlock" for="save_list"><?=$this->transEsc('Choose a List') ?></label>
-          <select id="save_list" name="list">
-            <? if ($this->nonContainingLists): ?>
-              <? foreach ($this->nonContainingLists as $list): ?>
-                <option value="<?=$list['id'] ?>"<? if ($list['id']==$this->userList()->lastUsed()): ?> selected="selected"<? endif; ?>><?=$this->escapeHtml($list['title'])?></option>
-              <? endforeach; ?>
-            <? else: ?>
-              <option value=""><?=$this->transEsc('My Favorites') ?></option>
-            <? endif; ?>
-          </select>
-        <? endif; ?>
-
-        <a rel="external" data-role="button" data-rel="dialog" href="<?=$this->url('editList', array('id' => 'NEW')) ?>?recordId=<?=urlencode($this->driver->getUniqueId())?>&amp;recordSource=<?=urlencode($this->driver->getSourceIdentifier())?>" class="listEdit" title="<?=$this->transEsc('Create a List') ?>"><? if ($showLists) echo $this->transEsc('or create a new list'); else echo $this->transEsc('Create a List'); ?></a>
-
-        <? if ($showLists): ?>
-          <? if ($this->usertags()->getMode() !== 'disabled'): ?>
-            <label class="displayBlock" for="add_mytags"><?=$this->transEsc('Add Tags') ?></label>
-            <input class="mainFocus" id="add_mytags" type="text" name="mytags" value="" size="50"/>
-            <p><?=$this->transEsc("add_tag_note") ?></p>
-          <? endif; ?>
-          <label class="displayBlock" for="add_notes"><?=$this->transEsc('Add a Note') ?></label>
-          <textarea id="add_notes" name="notes"></textarea>
-          </div><div data-role="fieldcontain">
-          <input class="button" type="submit" value="<?=$this->transEsc('Save') ?>"/>
-        <? endif; ?>
-      </div>
-    </form>
-  </div>
-  <?=$this->mobileMenu()->footer()?>
-</div>
diff --git a/themes/jquerymobile/templates/record/sms.phtml b/themes/jquerymobile/templates/record/sms.phtml
deleted file mode 100644
index b81c0acac3b71714994ee91d018055ca8c7610ec..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/record/sms.phtml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?
-    // Set page title.
-    $this->headTitle($this->translate('Text this'));
-?>
-<div data-role="page" id="Record-view">
-  <?=$this->mobileMenu()->header()?>
-  <div data-role="content">
-    <?=$this->flashmessages()?>
-    <form method="post" name="smsRecord" data-ajax="false">
-      <input type="hidden" name="id" value="<?=$this->escapeHtmlAttr($this->driver->getUniqueId())?>" />
-      <input type="hidden" name="source" value="<?=$this->escapeHtmlAttr($this->driver->getSourceIdentifier())?>" />
-      <div data-role="fieldcontain">
-        <label for="sms_to"><?=$this->transEsc('Number')?>:</label>
-        <input id="sms_to" type="text" name="to" value="<?=isset($this->to) ? $this->to : ''?>" />
-        <? if (is_array($this->carriers) && count($this->carriers) > 1): ?>
-          <label for="sms_provider"><?=$this->transEsc('Provider')?>:</label>
-          <select id="sms_provider" name="provider" class="<?=$this->jqueryValidation(array('required'=>'This field is required'))?>">
-            <option selected="selected" value=""><?=$this->transEsc('Select your carrier')?></option>
-            <? foreach ($this->carriers as $val => $details): ?>
-              <option<?=(isset($this->provider) && $val == $this->provider) ? ' selected="selected"' : ''?> value="<?=$this->escapeHtmlAttr($val)?>"><?=$this->escapeHtml($details['name'])?></option>
-            <? endforeach; ?>
-          </select>
-        <? else: ?>
-          <? $keys = is_array($this->carriers) ? array_keys($this->carriers) : array(); ?>
-          <input type="hidden" name="provider" value="<?=isset($keys[0]) ? $keys[0] : ''?>" />
-        <? endif; ?>
-      </div>
-      <?=$this->recaptcha()->html($this->useRecaptcha) ?>
-      <div data-role="fieldcontain">
-        <input class="button" type="submit" name="submit" value="<?=$this->transEsc('Send')?>"/>
-      </div>
-    </form>
-  </div>
-  <?=$this->mobileMenu()->footer()?>
-</div>
diff --git a/themes/jquerymobile/templates/record/view.phtml b/themes/jquerymobile/templates/record/view.phtml
deleted file mode 100644
index 91373a0842339f84d8d109c690a471a946b7c055..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/record/view.phtml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?
-    // Grab tab contents up front -- this will set the page title, which we need to
-    // do before we display the page header below.
-    $activeTab = false;
-    foreach ($this->tabs as $tab => $obj) {
-        if (strtolower($tab) == strtolower($this->activeTab)) {
-            $activeTab = $tab;
-        }
-    }
-    $tab = $activeTab ? $this->record($this->driver)->getTab($this->tabs[$activeTab]) : '';
-?>
-<div data-role="page" id="Record-view">
-  <?=$this->mobileMenu()->header(array('searchLink' => $this->searchOptions($this->searchClassId)->getSearchHomeAction()))?>
-  <div class="record" data-role="content" data-record-id="<?=$this->escapeHtmlAttr($this->driver->getUniqueId())?>">
-    <?=$this->flashmessages()?>
-    <? if ($this->activeTab == $this->defaultTab): ?>
-      <?=$this->record($this->driver)->getCoreMetadata()?>
-    <? else: ?>
-      <h3><?=$this->escapeHtml($this->driver->getBreadcrumb())?></h3>
-    <? endif; ?>
-    <?=$tab?>
-    <?=$this->record($this->driver)->getToolbar()?>
-  </div>
-  <?=$this->mobileMenu()->footer()?>
-</div>
diff --git a/themes/jquerymobile/templates/records/home.phtml b/themes/jquerymobile/templates/records/home.phtml
deleted file mode 100644
index 395239f8074ee1e4ea3e46316af96d65f3939cd3..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/records/home.phtml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?
-    $this->overrideTitle = $this->translate('View Records');
-    $this->overrideSearchHeading = '';
-
-    // Load standard settings from the default search results screen:
-    echo $this->render('search/results.phtml');
-?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/search/advanced.phtml b/themes/jquerymobile/templates/search/advanced.phtml
deleted file mode 100644
index cb394dec92d564e2c1915b4150132ff9b86f499f..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/search/advanced.phtml
+++ /dev/null
@@ -1,72 +0,0 @@
-<?
-  // Set page title.
-  $this->headTitle($this->translate('Advanced Search'));
-  // Set default value if necessary:
-  if (!isset($this->searchClassId)) {
-    $this->searchClassId = 'Solr';
-  }
-  // Load search actions and settings (if any):
-  $options = $this->searchOptions($this->searchClassId);
-  $basicSearch = $options->getSearchAction();
-  $searchHome = $basicSearch;
-  $searchHome['action'] = 'Home';
-  $lastSort = $this->searchMemory()->getLastSort($options->getSearchClassId());
-  $lastLimit = $this->searchMemory()->getLastLimit($options->getSearchClassId());
-  if (isset($this->saved) && is_object($this->saved)) {
-    $hiddenFilters = $this->saved->getParams()->getHiddenFilters();
-  } else {
-    $hiddenFilters = $this->searchtabs()->getHiddenFilters($this->searchClassId, true);
-  }
-?>
-<div data-role="page" id="Search-home">
-  <?=$this->mobileMenu()->header(array('hideSearchLink' => true))?>
-  <div data-role="content">
-    <!-- SEARCH BOXES -->
-    <form method="get" action="<?=$this->url($basicSearch)?>" data-ajax="false">
-      <input type="hidden" name="join" value="AND" />
-      <fieldset class="ui-grid-a">
-      <? for ($i = 0; $i < 3; $i++): ?>
-        <div class="ui-block-a">
-          <label class="offscreen" for="searchForm_lookfor">
-            <?=$this->transEsc("Search")?>
-          </label>
-          <input id="search_lookfor0" type="text" name="lookfor0[]" style="margin-top:.5em;height:28px"/>
-        </div>
-        <div class="ui-block-b">
-          <select id="searchForm_type" name="type0[]" data-mini="true">
-            <? foreach ($options->getBasicHandlers() as $searchVal => $searchDesc): ?>
-              <option value="<?=$this->escapeHtmlAttr($searchVal)?>"<?=$this->searchIndex == $searchVal ? ' selected="selected"' : ''?>><?=$this->transEsc($searchDesc)?></option>
-            <? endforeach; ?>
-          </select>
-        </div>
-      <? endfor; ?>
-        <div class="ui-block-a"><hr/></div><div class="ui-block-b"><hr/></div>
-        <div class="ui-block-a">
-          <select id="search_bool0" name="bool0[]">
-            <option value="AND"><?=$this->transEsc("search_match")?>: <?=$this->transEsc('search_AND') ?></option>
-            <option value="OR" ><?=$this->transEsc("search_match")?>: <?=$this->transEsc('search_OR')  ?></option>
-            <option value="NOT"><?=$this->transEsc("search_match")?>: <?=$this->transEsc('search_NOT') ?></option>
-          </select>
-        </div>
-        <div class="ui-block-b">
-          <input type="submit" name="submit" value="<?=$this->transEsc("Find")?>" data-role="button" data-theme="b"/>
-        </div>
-      </fieldset>
-      <?
-        /* Load hidden limit preference from Session */
-        if (!empty($lastLimit)) {
-          echo '<input type="hidden" name="limit" value="' . $this->escapeHtmlAttr($lastLimit) . '" />';
-        }
-        if (!empty($lastSort)) {
-          echo '<input type="hidden" name="sort" value="' . $this->escapeHtmlAttr($lastSort) . '" />';
-        }
-      ?>
-      <? foreach ($hiddenFilters as $key => $filter): ?>
-        <? foreach ($filter as $value): ?>
-          <input type="hidden" name="hiddenFilters[]" value="<?=$this->escapeHtmlAttr($key) . ':' . $this->escapeHtmlAttr($value)?>" />
-        <? endforeach; ?>
-      <? endforeach; ?>
-    </form>
-  </div>
-  <?=$this->mobileMenu()->footer()?>
-</div>
diff --git a/themes/jquerymobile/templates/search/email.phtml b/themes/jquerymobile/templates/search/email.phtml
deleted file mode 100644
index 6b879aee1625753083f5e1b7c7827422bc7056ab..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/search/email.phtml
+++ /dev/null
@@ -1,15 +0,0 @@
-<?
-    // Set page title.
-    $this->headTitle($this->translate('Email this Search'));
-?>
-<div data-role="page">
-  <?=$this->mobileMenu()->header()?>
-  <div data-role="content">
-    <?=$this->flashmessages()?>
-    <form method="post" name="emailSearch" data-ajax="false">
-      <input type="hidden" name="url" value="<?=$this->escapeHtmlAttr($this->url)?>" />
-      <?=$this->render('Helpers/email-form-fields.phtml')?>
-    </form>
-  </div>
-  <?=$this->mobileMenu()->footer()?>
-</div>
diff --git a/themes/jquerymobile/templates/search/footer-navbar.phtml b/themes/jquerymobile/templates/search/footer-navbar.phtml
deleted file mode 100644
index 3a8366aa1bab4f48e1abb3360f0b2ace9f4b830e..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/search/footer-navbar.phtml
+++ /dev/null
@@ -1,5 +0,0 @@
-<? if ($this->layout()->templateName == 'history'): // use myresearch navbar for Search/history ?>
-  <?=$this->render('myresearch/footer-navbar.phtml')?>
-<? else:                            // use default navbar for everything else ?>
-  <?=$this->render('default-footer-navbar.phtml');?>
-<? endif; ?>
diff --git a/themes/jquerymobile/templates/search/header-navbar.phtml b/themes/jquerymobile/templates/search/header-navbar.phtml
deleted file mode 100644
index 6bb71b162e2d3a2078a283ea10b23f5ec95614a6..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/search/header-navbar.phtml
+++ /dev/null
@@ -1,20 +0,0 @@
-<? if ($this->layout()->templateName == 'history'): // use myresearch navbar for Search/history ?>
-  <?=$this->render('myresearch/header-navbar.phtml')?>
-<? elseif (isset($this->results) && is_object($this->results) && $this->results->getResultTotal() > 0): ?>
-  <div data-role="navbar">
-    <ul>
-      <li><a href="#Search-narrow" data-rel="dialog" data-transition="flip"><?=$this->transEsc('Narrow Search')?></a></li>
-      <? if ($this->accountCapabilities()->getSavedSearchSetting() === 'enabled'): ?>
-        <li>
-          <? if (isset($this->results) && is_numeric($this->results->getSearchId())): ?>
-            <? if ($this->results->isSavedSearch()): ?>
-              <a rel="external" href="<?=$this->url('myresearch-savesearch')?>?delete=<?=urlencode($this->results->getSearchId())?>"><?=$this->transEsc('save_search_remove')?></a>
-            <? else: ?>
-              <a rel="external" href="<?=$this->url('myresearch-savesearch')?>?save=<?=urlencode($this->results->getSearchId())?>"><?=$this->transEsc('save_search')?></a>
-            <? endif; ?>
-          <? endif; ?>
-        </li>
-      <? endif; ?>
-    </ul>
-  </div>
-<? endif; ?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/search/history-table.phtml b/themes/jquerymobile/templates/search/history-table.phtml
deleted file mode 100644
index 480d6d22f14953df79e1c0bcebf2e83b177a2e4a..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/search/history-table.phtml
+++ /dev/null
@@ -1,33 +0,0 @@
-<? $saveSupported = $this->accountCapabilities()->getSavedSearchSetting() === 'enabled'; ?>
-<? foreach (($this->showSaved ? array_reverse($this->saved) : array_reverse($this->unsaved)) as $iteration => $info): ?>
-  <li>
-    <a rel="external" href="<?=$this->url($info->getOptions()->getSearchAction()) . $info->getUrlQuery()->getParams()?>">
-    <div class="result">
-    <h3><?
-      echo $this->historylabel($info->getParams()->getSearchClassId()) . ' ';
-      $desc = $info->getParams()->getDisplayQuery();
-      echo empty($desc) ? $this->transEsc("history_empty_search") : $this->escapeHtml($desc);
-    ?></h3>
-    <span class="ui-li-count"><?=$this->escapeHtml($this->localizedNumber($info->getResultTotal()))?></span>
-    <p><strong><?=$this->transEsc("history_time")?></strong>: <?=$this->escapeHtml($this->dateTime()->convertToDisplayDateAndTime("U", $info->getStartTime()))?></p>
-    <? $info->getParams()->activateAllFacets(); foreach ($info->getParams()->getFilterList(true) as $field => $filters): ?>
-      <? foreach ($filters as $i => $filter): ?>
-        <p><? if ($filter['operator'] == 'NOT') echo $this->transEsc('NOT') . ' '; if ($filter['operator'] == 'OR' && $i > 0) echo $this->transEsc('OR') . ' '; ?><strong><?=$this->transEsc($field)?></strong>: <?=$this->escapeHtml($filter['displayText'])?></p>
-      <? endforeach; ?>
-    <? endforeach; ?>
-    <? foreach($info->getParams()->getCheckboxFacets() as $facet): ?>
-      <? if ($facet['selected']): ?>
-        <p><strong><?=$this->transEsc($facet['desc'])?></strong></p>
-      <? endif; ?>
-    <? endforeach; ?>
-    </div>
-    </a>
-    <? if ($saveSupported): ?>
-      <? if ($this->showSaved): ?>
-        <a rel="external" href="<?=$this->url('myresearch-savesearch')?>?delete=<?=urlencode($info->getSearchId())?>&amp;mode=history" class="delete"><?=$this->transEsc("history_delete_link")?></a>
-      <? else: ?>
-        <a rel="external" href="<?=$this->url('myresearch-savesearch')?>?save=<?=urlencode($info->getSearchId())?>&amp;mode=history" class="add"><?=$this->transEsc("history_save_link")?></a>
-      <? endif; ?>
-    <? endif; ?>
-  </li>
-<? endforeach; ?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/search/history.phtml b/themes/jquerymobile/templates/search/history.phtml
deleted file mode 100644
index 73c5bd52f517f3545d91a02da4a4720e9d8345fd..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/search/history.phtml
+++ /dev/null
@@ -1,34 +0,0 @@
-<?
-    // Set page title.
-    $this->headTitle($this->translate('Search History'));
-
-    $saveSupported = $this->accountCapabilities()->getSavedSearchSetting() === 'enabled';
-    if (!$saveSupported) {
-        $this->saved = [];
-    }
-?>
-<div data-role="page" id="Search-history">
-  <?=$this->mobileMenu()->header()?>
-  <div data-role="content">
-    <?=$this->flashmessages()?>
-    <? if (!empty($this->saved) || !empty($this->unsaved)): ?>
-      <? if (!empty($this->saved)): ?>
-        <ul class="results history" data-role="listview" data-dividertheme="e" data-split-icon="minus" data-split-theme="c" data-inset="true">
-          <li data-role="list-divider"><?=$this->transEsc("history_saved_searches")?></li>
-          <?=$this->context()->renderInContext('search/history-table.phtml', array('showSaved' => true));?>
-        </ul>
-      <? endif; ?>
-
-      <? if (!empty($this->unsaved)): ?>
-        <ul class="results history" data-role="listview" data-dividertheme="e" data-split-icon="plus" data-split-theme="c" data-inset="true">
-          <li data-role="list-divider"><?=$this->transEsc("history_recent_searches")?></li>
-          <?=$this->context()->renderInContext('search/history-table.phtml', array('showSaved' => false));?>
-        </ul>
-        <a rel="external" href="?purge=true" data-role="button"><?=$this->transEsc("history_purge")?></a>
-      <? endif; ?>
-    <? else: ?>
-      <p><?=$this->transEsc("history_no_searches")?></p>
-    <? endif; ?>
-  </div>
-  <?=$this->mobileMenu()->footer()?>
-</div>
diff --git a/themes/jquerymobile/templates/search/home.phtml b/themes/jquerymobile/templates/search/home.phtml
deleted file mode 100644
index 8ceb6c2a766cd38b5005258880848daa125db3c5..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/search/home.phtml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?
-    // Set page title.
-    $this->headTitle($this->translate('Search Home'));
-?>
-<div data-role="page" id="Search-home">
-  <?=$this->mobileMenu()->header(array('searchLink' => false, 'results' => null))?>
-  <div data-role="content">
-    <? if ($this->ils()->getOfflineMode() == "ils-offline"): ?>
-      <div class="sysInfo">
-        <h2><?=$this->transEsc('ils_offline_title')?></h2>
-        <p><strong><?=$this->transEsc('ils_offline_status')?></strong></p>
-        <p><?=$this->transEsc('ils_offline_home_message')?></p>
-        <? $supportEmail = $this->escapeHtmlAttr($this->systemEmail()); ?>
-        <p><a href="mailto:<?=$supportEmail?>"><?=$supportEmail?></a></p>
-      </div>
-    <? endif; ?>
-    <?=$this->render("search/searchbox.phtml")?>
-    <? if (isset($this->overrideHomeOptions)): // allow other templates to override the normal options here ?>
-      <?=$this->overrideHomeOptions?>
-    <? else: ?>
-      <ul data-role="listview" data-inset="true" data-dividertheme="b">
-        <li data-role="list-divider"><?=$this->transEsc('Find More')?></li>
-        <li><a data-ajax="false" href="<?=$this->url('search-advanced')?>"><?=$this->transEsc('Advanced Search')?></a></li>
-        <li><a data-ajax="false" href="<?=$this->url('browse-home')?>"><?=$this->transEsc('Browse the Catalog')?></a></li>
-        <li><a data-ajax="false" href="<?=$this->url('alphabrowse-home')?>"><?=$this->transEsc('Browse Alphabetically')?></a></li>
-        <li><a data-ajax="false" href="<?=$this->url('search-reserves')?>"><?=$this->transEsc('Course Reserves')?></a></li>
-        <li><a data-ajax="false" href="<?=$this->url('search-newitem')?>"><?=$this->transEsc('New Items')?></a></li>
-      </ul>
-    <? endif; ?>
-  </div>
-  <?=$this->mobileMenu()->footer()?>
-</div>
diff --git a/themes/jquerymobile/templates/search/list-authorfacets.phtml b/themes/jquerymobile/templates/search/list-authorfacets.phtml
deleted file mode 100644
index 62a746b6d73a956345415f056cc2a28cf76cb516..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/search/list-authorfacets.phtml
+++ /dev/null
@@ -1,13 +0,0 @@
-<ul class="results" data-role="listview" data-split-icon="plus" data-split-theme="c">
-  <? foreach ($this->results->getResults() as $record): ?>
-    <li>
-      <a rel="external" href="<?=$this->url('author-home')?>?author=<?=urlencode($record['value'])?>">
-        <div class="result">
-          <h3><?=$this->escapeHtml($record['value'])?></h3>
-          
-        </div>
-      </a>
-      <span class="ui-li-count"><?=$this->escapeHtml($record['count'])?></span>
-    </li>
-  <? endforeach; ?>
-</ul>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/search/list-grid.phtml b/themes/jquerymobile/templates/search/list-grid.phtml
deleted file mode 100644
index 7ed9212a004aedd3eb161e73778d4e481b1f4d29..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/search/list-grid.phtml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?
-    /* Grid view is not currently supported in the mobile theme. This file loads the
-       list view as a sub-template in case a user follows a link which contains the
-       view=grid parameter in the URL.
-     */
-    echo $this->render('search/list-list.phtml');
-?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/search/list-list.phtml b/themes/jquerymobile/templates/search/list-list.phtml
deleted file mode 100644
index 863c5f52933aff337e6a1cf666c63d34cb1e8e60..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/search/list-list.phtml
+++ /dev/null
@@ -1,5 +0,0 @@
-<ul class="results" data-role="listview" data-split-icon="plus" data-split-theme="c">
-  <? foreach ($this->results->getResults() as $current): ?>
-    <li><?=$this->record($current)->getSearchResult('list')?></li>
-  <? endforeach; ?>
-</ul>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/search/newitem.phtml b/themes/jquerymobile/templates/search/newitem.phtml
deleted file mode 100644
index 8a05ea56f2627d599af3c1211d8a555e2656e39e..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/search/newitem.phtml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?
-    // Set up page title:
-    $this->headTitle($this->translate('New Item Search'));
-
-    // Set up breadcrumbs:
-    $this->layout()->breadcrumbs = '<em>' . $this->transEsc('New Items') . '</em>';
-?>
-<div data-role="page">
-  <?=$this->mobileMenu()->header()?>
-  <div data-role="content">
-    <h3><?=$this->transEsc('Find New Items')?></h3>
-    <form method="get" data-ajax="false">
-      <div data-role="fieldcontain">
-        <fieldset data-role="controlgroup">
-          <legend><?=$this->transEsc('Range')?>:</legend>
-          <? foreach ($this->ranges as $key => $range): ?>
-            <input id="newitem_range_<?=$this->escapeHtmlAttr($key)?>" type="radio" name="range" value="<?=$this->escapeHtmlAttr($range)?>"<?= ($key == 0) ? ' checked="checked"' : ''?>/>
-            <label for="newitem_range_<?=$this->escapeHtmlAttr($key)?>">
-              <?=($range == 1) ? $this->transEsc('Yesterday') : $this->transEsc('Past') . ' ' . $this->escapeHtml($range) . ' ' . $this->transEsc('Days')?>
-            </label>
-          <? endforeach; ?>
-        </fieldset>
-      </div>
-      <? if (is_array($this->fundList) && !empty($this->fundList)): ?>
-        <div data-role="fieldcontain">
-          <label for="newitem_department"><?=$this->transEsc('Department')?>:</label>
-          <select id="newitem_department" name="department">
-          <? foreach ($this->fundList as $fundId => $fund): ?>
-            <option value="<?=$this->escapeHtmlAttr($fundId)?>"><?=$this->escapeHtml($fund)?></option>
-          <? endforeach; ?>
-          </select>
-        </div>
-      <? endif; ?>
-      <div data-role="fieldcontain">
-        <input type="submit" name="submit" value="<?=$this->transEsc('Find')?>"/>
-      </div>
-    </form>
-  </div>
-  <?=$this->mobileMenu()->footer()?>
-</div>
diff --git a/themes/jquerymobile/templates/search/newitemresults.phtml b/themes/jquerymobile/templates/search/newitemresults.phtml
deleted file mode 100644
index 1153f29b3ba88a2e282fbec5b39e8d8634cab478..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/search/newitemresults.phtml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?
-    // Set some overrides, then call the standard search results action:
-    $this->overrideTitle = $this->translate('New Items');
-    $this->overrideSearchHeading = $this->transEsc('New Items');
-    $this->overrideEmptyMessage = $this->transEsc('No new item information is currently available.');
-    echo $this->render('search/results.phtml');
-?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/search/pagination.phtml b/themes/jquerymobile/templates/search/pagination.phtml
deleted file mode 100644
index bea0cafa4c0b28b9d34944dd56079212af7715b7..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/search/pagination.phtml
+++ /dev/null
@@ -1,11 +0,0 @@
-<div data-role="controlgroup" data-type="horizontal" align="center">
-  <? if ($this->pageCount): ?>
-    <? if (isset($this->previous)): ?>
-      <a rel="external" data-role="button" data-rel="back" href="<?=$this->currentPath() . $this->results->getUrlQuery()->setPage($this->previous)?>">&laquo; <?=$this->transEsc('Prev')?></a>
-    <? endif; ?>
-
-    <? if (isset($this->next)): ?>
-      <a rel="external" data-role="button" href="<?=$this->currentPath() . $this->results->getUrlQuery()->setPage($this->next)?>"><?=$this->transEsc('Next');?> &raquo;</a>
-    <? endif; ?>
-  <? endif; ?>
-</div>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/search/reserves.phtml b/themes/jquerymobile/templates/search/reserves.phtml
deleted file mode 100644
index e8ab8320c25339cf67d09f91e27d1858bf65ba1c..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/search/reserves.phtml
+++ /dev/null
@@ -1,61 +0,0 @@
-<?
-    // Set up page title:
-    $this->headTitle($this->translate('Reserves Search'));
-?>
-<div data-role="page">
-  <?=$this->mobileMenu()->header()?>
-  <div data-role="content">
-    <h3><?=$this->transEsc('Search For Items on Reserve')?></h3>
-    <? if (is_array($this->courseList)): ?>
-      <form method="get" name="searchForm" class="search" data-ajax="false">
-        <div data-role="fieldcontain">
-          <label for="reserves_by_course"><?=$this->transEsc('By Course')?>:</label>
-          <select name="course" id="reserves_by_course">
-            <option></option>
-            <? foreach ($this->courseList as $courseId => $courseName): ?>
-              <option value="<?=$this->escapeHtmlAttr($courseId)?>"><?=$this->escapeHtml($courseName)?></option>
-            <? endforeach; ?>
-          </select>
-        </div>
-        <div data-role="fieldcontain">
-          <input type="submit" name="submit" value="<?=$this->transEsc('Find')?>"/>
-        </div>
-      </form>
-    <? endif; ?>
-
-    <? if (is_array($this->instList)): ?>
-      <form method="get" name="searchForm" class="search" data-ajax="false">
-        <div data-role="fieldcontain">
-          <label for="reserves_by_inst"><?=$this->transEsc('By Instructor')?>:</label>
-          <select name="inst" id="reserves_by_inst">
-            <option></option>
-            <? foreach ($this->instList as $instId => $instName): ?>
-              <option value="<?=$this->escapeHtmlAttr($instId)?>"><?=$this->escapeHtml($instName)?></option>
-            <? endforeach; ?>
-          </select>
-        </div>
-        <div data-role="fieldcontain">
-          <input type="submit" name="submit" value="<?=$this->transEsc('Find')?>"/>
-        </div>
-      </form>
-    <? endif; ?>
-
-    <? if (is_array($this->deptList)): ?>
-      <form method="get" name="searchForm" class="search" data-ajax="false">
-        <div data-role="fieldcontain">
-          <label for="reserves_by_dept"><?=$this->transEsc('By Department')?>:</label>
-          <select name="dept" id="reserves_by_dept">
-            <option></option>
-            <? foreach ($this->deptList as $deptId => $deptName): ?>
-              <option value="<?=$this->escapeHtmlAttr($deptId)?>"><?=$this->escapeHtml($deptName)?></option>
-            <? endforeach; ?>
-          </select>
-        </div>
-        <div data-role="fieldcontain">
-          <input type="submit" name="submit" value="<?=$this->transEsc('Find')?>"/>
-        </div>
-      </form>
-    <? endif; ?>
-  </div>
-  <?=$this->mobileMenu()->footer()?>
-</div>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/search/reservesresults.phtml b/themes/jquerymobile/templates/search/reservesresults.phtml
deleted file mode 100644
index 55c40b494cf556c50471fae560a8ad3079d36a65..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/search/reservesresults.phtml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?
-    // Set some overrides, then call the standard search results action:
-    $this->overrideTitle = $this->translate('Reserves Search Results');
-    $this->overrideSearchHeading = $this->transEsc('Reserves');
-    if (isset($this->instructor) || isset($this->course)) {
-        $this->overrideSearchHeading .= ' (';
-        if (isset($this->instructor)) {
-            $this->overrideSearchHeading .= $this->transEsc('Instructor') . ': <strong>' . $this->escapeHtml($this->instructor) . '</strong>';
-            if (isset($this->course)) {
-                $this->overrideSearchHeading .= ', ';
-            }
-        }
-        if (isset($this->course)) {
-            $this->overrideSearchHeading .= $this->transEsc('Course') . ': <strong>' . $this->escapeHtml($this->course) . '</strong>';
-        }
-        $this->overrideSearchHeading .= ')';
-    }
-    $this->overrideEmptyMessage = $this->transEsc('course_reserves_empty_list');
-    echo $this->render('search/results.phtml');
-?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/search/reservessearch.phtml b/themes/jquerymobile/templates/search/reservessearch.phtml
deleted file mode 100644
index 678c5d8e2bfdd369e628fdae9e3650647bc09ba6..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/search/reservessearch.phtml
+++ /dev/null
@@ -1,51 +0,0 @@
-<?
-    // Set up page title:
-    $this->headTitle($this->translate('Reserves Search'));
-
-    // Convenience variables:
-    $reservesLookfor = $this->params->getDisplayQuery();
-?>
-
-<div data-role="page">
-  <?=$this->mobileMenu()->header()?>
-  <div data-role="content">
-    <h3><?=$this->transEsc('Search For Items on Reserve')?></h3>
-    <form method="get" name="reservesSearchForm" class="search" data-ajax="false">
-      <div data-role="fieldcontain">
-        <label for="reservesSearchForm_lookfor" class="offscreen"><?=$this->transEsc("Your search terms")?></label>
-        <input id="reservesSearchForm_lookfor" type="text" name="lookfor" size="40" value="<?=$this->escapeHtmlAttr($reservesLookfor)?>" <?=$this->searchOptions('SolrReserves')->autocompleteEnabled() ? ' class="autocomplete searcher:SolrReserves type:Reserves"' : ''?> />
-      </div>
-      <div data-role="fieldcontain">
-        <input type="submit" name="submit" value="<?=$this->transEsc("Find")?>"/>
-      </div>
-    </form>
-
-    <? foreach ($this->results->getRecommendations('side') as $current): ?>
-      <?=$this->recommend($current)?>
-    <? endforeach; ?>
-
-    <? if ($this->results->getResultTotal() < 1): ?>
-      <p class="error"><?=$this->transEsc('nohit_prefix')?> - <strong><?=$this->escapeHtml($reservesLookfor)?></strong> - <?=$this->transEsc('nohit_suffix')?></p>
-      <? if (isset($this->parseError)): ?>
-        <p class="error"><?=$this->transEsc('nohit_parse_error')?></p>
-      <? endif; ?>
-    <? else: ?>
-      <ul class="results" data-role="listview" data-split-icon="plus" data-split-theme="c">
-        <? foreach ($this->results->getResults() as $record): ?>
-          <?
-              $url = $this->currentPath() . $this->escapeHtmlAttr(
-                  '?inst=' . urlencode($record->getInstructorId())
-                  . '&course=' . urlencode($record->getCourseId())
-                  . '&dept=' . urlencode($record->getDepartmentId())
-              );
-          ?>
-          <li>
-            <a rel="external" href="<?=$url?>"><?=$this->escapeHtml($record->getDepartment())?> <?=$this->escapeHtml($record->getCourse())?> <?=$this->escapeHtml($record->getInstructor())?> <span class="ui-li-count"><?=$this->localizedNumber($record->getItemCount())?></span></a>
-          </li>
-        <? endforeach; ?>
-      </ul>
-      <?=$this->paginationControl($this->results->getPaginator(), 'Sliding', 'search/pagination.phtml', array('results' => $this->results))?>
-    <? endif; ?>
-  </div>
-  <?=$this->mobileMenu()->footer()?>
-</div>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/search/results.phtml b/themes/jquerymobile/templates/search/results.phtml
deleted file mode 100644
index e76ffbbdfa53147b1937085bf749c1e90d6c791a..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/search/results.phtml
+++ /dev/null
@@ -1,59 +0,0 @@
-<?
-    // Set up page title:
-    $lookfor = $this->results->getUrlQuery()->isQuerySuppressed() ? '' : $this->params->getDisplayQuery();
-    if (isset($this->overrideTitle)) {
-        $this->headTitle($this->overrideTitle);
-    } else {
-        $this->headTitle($this->translate('Search Results') . (empty($lookfor) ? '' : " - {$lookfor}"));
-    }
-
-    // Load Javascript dependencies into header:
-    $this->headScript()->appendFile("check_item_statuses.js");
-?>
-<div data-role="page" id="Search-list" class="results-page">
-  <?=$this->mobileMenu()->header()?>
-  <div data-role="content">
-    <?=$this->flashmessages()?>
-    <? if (($recordTotal = $this->results->getResultTotal()) > 0): ?>
-      <p>
-        <?=$this->transEsc("Showing")?>
-        <strong><?=$this->localizedNumber($this->results->getStartRecord())?></strong> - <strong><?=$this->localizedNumber($this->results->getEndRecord())?></strong>
-        <? if (!isset($this->skipTotalCount)): ?>
-          <?=$this->transEsc('of')?> <strong><?=$this->localizedNumber($recordTotal)?></strong>
-        <? endif; ?>
-        <? if (isset($this->overrideSearchHeading)): ?>
-          <?=$this->overrideSearchHeading?>
-        <? elseif ($this->params->getSearchType() == 'basic'): ?>
-          <?=$this->transEsc('for search')?>: <strong>'<?=$this->escapeHtml($lookfor)?>'</strong>
-        <? endif; ?>
-      </p>
-    <? endif; ?>
-
-    <? foreach ($this->results->getRecommendations('side') as $current): ?>
-      <?=$this->recommend($current)?>
-    <? endforeach; ?>
-
-    <? if ($recordTotal < 1): ?>
-      <p class="error">
-        <? if (isset($this->overrideEmptyMessage)): ?>
-          <?=$this->overrideEmptyMessage?>
-        <? else: ?>
-          <?=$this->transEsc('nohit_prefix')?> - <strong><?=$this->escapeHtml($lookfor)?></strong> - <?=$this->transEsc('nohit_suffix')?>
-        <? endif; ?>
-      </p>
-      <? if (isset($this->parseError)): ?>
-        <p class="error"><?=$this->transEsc('nohit_parse_error')?></p>
-      <? endif; ?>
-      <? foreach ($this->results->getRecommendations('noresults') as $current): ?>
-        <?=$this->recommend($current)?>
-      <? endforeach; ?>
-    <? else: ?>
-      <?=$this->render('search/list-' . $this->params->getView() . '.phtml')?>
-      <?=$this->paginationControl($this->results->getPaginator(), 'Sliding', 'search/pagination.phtml', array('results' => $this->results))?>
-      <div data-role="controlgroup">
-        <a href="<?=$this->url('search-email')?>" data-role="button" rel="external"><?=$this->transEsc("Email this Search")?></a>
-      </div>
-    <? endif; ?>
-  </div>
-  <?=$this->mobileMenu()->footer()?>
-</div>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/search/searchbox.phtml b/themes/jquerymobile/templates/search/searchbox.phtml
deleted file mode 100644
index df31eca5c68114dd3b106019b38082ef1de27d93..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/search/searchbox.phtml
+++ /dev/null
@@ -1,50 +0,0 @@
-<?
-  // Set default value if necessary:
-  if (!isset($this->searchClassId)) {
-      $this->searchClassId = 'Solr';
-  }
-
-  // Load search actions and settings (if any):
-  $options = $this->searchOptions($this->searchClassId);
-  $handlers = $this->searchbox()->getHandlers(
-      $this->searchClassId,
-      isset($this->searchIndex) ? $this->searchIndex : null
-  );
-  $handlerCount = count($handlers);
-  $basicSearch = $this->searchbox()->combinedHandlersActive() ? 'combined-searchbox' : $options->getSearchAction();
-  $lastSort = $this->searchMemory()->getLastSort($options->getSearchClassId());
-  $lastLimit = $this->searchMemory()->getLastLimit($options->getSearchClassId());
-?>
-<form method="get" action="<?=$this->url($basicSearch)?>" data-ajax="false">
-  <label class="offscreen" for="searchForm_lookfor">
-    <?=$this->transEsc("Search")?>
-  </label>
-  <input type="search" placeholder="<?=$this->transEsc("Search")?>" name="lookfor" id="searchForm_lookfor" value="<?=$this->escapeHtmlAttr($this->lookfor)?>"/>
-  
-  <label class="offscreen" for="searchForm_type"><?=$this->transEsc("Search Type")?></label>
-  <? if ($handlerCount > 1): ?>
-    <select id="searchForm_type" name="type" data-native-menu="false">
-      <? foreach ($handlers as $handler): ?>
-        <option value="<?=$this->escapeHtmlAttr($handler['value'])?>"<?=$handler['selected'] ? ' selected="selected"' : ''?>><?=$handler['indent'] ? '-- ' : ''?><?=$this->transEsc($handler['label'])?></option>
-      <? endforeach; ?>
-    </select>
-  <? elseif ($handlerCount == 1): ?>
-    <input type="hidden" name="type" value="<?=$this->escapeHtmlAttr($handlers[0]['value'])?>" />
-  <? endif; ?>
-  <div data-role="fieldcontain">
-    <input type="submit" data-theme="b" name="submit" value="<?=$this->transEsc("Find")?>"/>
-  </div>
-  <?
-    /* Show hidden field for active search class when in combined handler mode. */
-    if ($this->searchbox()->combinedHandlersActive()) {
-      echo '<input type="hidden" name="activeSearchClassId" value="' . $this->escapeHtmlAttr($this->searchClassId) . '" />';
-    }
-    /* Load hidden limit preference from Session */
-    if (!empty($lastLimit)) {
-      echo '<input type="hidden" name="limit" value="' . $this->escapeHtmlAttr($lastLimit) . '" />';
-    }
-    if (!empty($lastSort)) {
-      echo '<input type="hidden" name="sort" value="' . $this->escapeHtmlAttr($lastSort) . '" />';
-    }
-  ?>
-</form>
diff --git a/themes/jquerymobile/templates/summon/advanced.phtml b/themes/jquerymobile/templates/summon/advanced.phtml
deleted file mode 100644
index 7f4698c9308267d24006520626d71c86ff82fe9b..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/summon/advanced.phtml
+++ /dev/null
@@ -1,3 +0,0 @@
-<?
-  echo $this->render('search/advanced.phtml');
-?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/summon/header-navbar.phtml b/themes/jquerymobile/templates/summon/header-navbar.phtml
deleted file mode 100644
index eb264af2bc4e0495ba3d2928a7d77724e764a09f..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/summon/header-navbar.phtml
+++ /dev/null
@@ -1 +0,0 @@
-<?=$this->render('search/header-navbar.phtml')?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/summon/home.phtml b/themes/jquerymobile/templates/summon/home.phtml
deleted file mode 100644
index 881bf39a2f68368ad5874c06cb393530cc3140f8..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/summon/home.phtml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?
-    $this->overrideHomeOptions = '';  // turn off extra options
-    echo $this->render('search/home.phtml');
-?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/summon/search.phtml b/themes/jquerymobile/templates/summon/search.phtml
deleted file mode 100644
index 979f6b18acd22c648c5a06f3b070532734c8ba6a..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/summon/search.phtml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?
-    // Override top search link:
-    $this->searchLink = 'summon-home';
-
-    // Load standard settings from the default search results screen:
-    echo $this->render('search/results.phtml');
-?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/tag/home.phtml b/themes/jquerymobile/templates/tag/home.phtml
deleted file mode 100644
index c1797c1cd4a1ebb2ccad84718b1e225e51cac6a8..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/tag/home.phtml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?
-    // Load standard settings from the default search results screen:
-    echo $this->render('search/results.phtml');
-?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/web/home.phtml b/themes/jquerymobile/templates/web/home.phtml
deleted file mode 100644
index 881bf39a2f68368ad5874c06cb393530cc3140f8..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/web/home.phtml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?
-    $this->overrideHomeOptions = '';  // turn off extra options
-    echo $this->render('search/home.phtml');
-?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/web/results.phtml b/themes/jquerymobile/templates/web/results.phtml
deleted file mode 100644
index 9c5b81545ee3bf2c77986993d378c10a61cf7055..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/web/results.phtml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?
-    // Override top search link:
-    $this->searchLink = 'web-home';
-
-    // Load standard settings from the default search results screen:
-    echo $this->render('search/results.phtml');
-?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/worldcat/advanced.phtml b/themes/jquerymobile/templates/worldcat/advanced.phtml
deleted file mode 100644
index 7f4698c9308267d24006520626d71c86ff82fe9b..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/worldcat/advanced.phtml
+++ /dev/null
@@ -1,3 +0,0 @@
-<?
-  echo $this->render('search/advanced.phtml');
-?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/worldcat/home.phtml b/themes/jquerymobile/templates/worldcat/home.phtml
deleted file mode 100644
index 881bf39a2f68368ad5874c06cb393530cc3140f8..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/worldcat/home.phtml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?
-    $this->overrideHomeOptions = '';  // turn off extra options
-    echo $this->render('search/home.phtml');
-?>
\ No newline at end of file
diff --git a/themes/jquerymobile/templates/worldcat/search.phtml b/themes/jquerymobile/templates/worldcat/search.phtml
deleted file mode 100644
index 40bae653821125aa11a038b1abc49b53ad0754be..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/templates/worldcat/search.phtml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?
-    // Override top search link:
-    $this->searchLink = 'worldcat-home';
-
-    // Load standard settings from the default search results screen:
-    echo $this->render('search/results.phtml');
-?>
\ No newline at end of file
diff --git a/themes/jquerymobile/theme.config.php b/themes/jquerymobile/theme.config.php
deleted file mode 100644
index 5fef818eb67a8cec29465e0c324746f2dc915569..0000000000000000000000000000000000000000
--- a/themes/jquerymobile/theme.config.php
+++ /dev/null
@@ -1,22 +0,0 @@
-<?php
-return array(
-    'extends' => 'root',
-    'css' => array(
-        'jquery.mobile-1.0rc2.min.css',
-        'styles.css',
-        'formats.css',
-    ),
-    'js' => array(
-        'jquery-1.6.4.min.js',
-        'common.js',
-        'jquery.mobile-1.0rc2.min.js',
-        'jquery.cookie.js',
-        'scripts.js',
-    ),
-    'favicon' => 'vufind-favicon.ico',
-    'helpers' => array(
-        'invokables' => array(
-            'mobilemenu' => 'VuFind\View\Helper\jQueryMobile\MobileMenu'
-        )
-    ),
-);
\ No newline at end of file
diff --git a/themes/root/templates/Citation/apa-article.phtml b/themes/root/templates/Citation/apa-article.phtml
index 1cf039095907af347d1fce6c29912089dee58062..35f08a280ed2862feb9099ca3ca3e7c37a520fbb 100644
--- a/themes/root/templates/Citation/apa-article.phtml
+++ b/themes/root/templates/Citation/apa-article.phtml
@@ -5,4 +5,4 @@
 <? if (!empty($this->volume)): ?><?=$this->escapeHtml($this->volume)?><? endif; ?></span><? if (!empty($this->issue)): ?>(<?=$this->escapeHtml($this->issue)?>)<? endif; ?>
 <? if (!empty($this->volume) || !empty($this->issue)): ?>, <? endif; ?>
 <? if (!empty($this->pageRange)) echo strstr($this->pageRange, '-') ? 'pp. ' : 'p. '; ?>
-<?=$this->escapeHtml($this->pageRange)?>. <? if (isset($this->doi)): ?>doi:<?=$this->escapeHtml($this->doi)?><? endif; ?>
\ No newline at end of file
+<?=$this->escapeHtml($this->pageRange)?>. <? if (isset($this->doi)): ?>doi:<?=$this->escapeHtml($this->doi)?><? endif; ?>
diff --git a/themes/root/templates/Citation/apa.phtml b/themes/root/templates/Citation/apa.phtml
index 678928feea34d0f538b09fb03cb286af53c3ccb7..5c5170205782b670df3667eeecdb1ee5e8be91cf 100644
--- a/themes/root/templates/Citation/apa.phtml
+++ b/themes/root/templates/Citation/apa.phtml
@@ -2,4 +2,4 @@
 <? if (!empty($this->year)): ?>(<?=$this->escapeHtml($this->year)?>). <? endif; ?>
 <span style="font-style:italic;"><?=$this->escapeHtml($this->title)?></span><? if ($this->periodAfterTitle): ?>.<? endif ?> 
 <? if (!empty($this->edition)): ?>(<?=$this->escapeHtml($this->edition)?>). <? endif; ?>
-<? if (!empty($this->publisher)): ?><?=$this->escapeHtml($this->publisher)?>.<? endif; ?>
\ No newline at end of file
+<? if (!empty($this->publisher)): ?><?=$this->escapeHtml($this->publisher)?>.<? endif; ?>
diff --git a/themes/root/templates/Citation/mla.phtml b/themes/root/templates/Citation/mla.phtml
index 71f27deec5e2a11a5011bf122bffc702efa3ed1d..d10656a7b9f7a4f8314a84292629569cb4ae026f 100644
--- a/themes/root/templates/Citation/mla.phtml
+++ b/themes/root/templates/Citation/mla.phtml
@@ -2,4 +2,4 @@
 <span style="font-style:italic;"><?=$this->escapeHtml($this->title)?></span><? if ($this->periodAfterTitle): ?>.<? endif ?> 
 <? if (!empty($this->edition)): ?><?=$this->escapeHtml($this->edition)?> <? endif; ?>
 <? if (!empty($this->publisher)): ?><?=$this->escapeHtml($this->publisher)?><? endif; ?>
-<? if (!empty($this->year)): ?><? if (!empty($this->publisher)): ?>, <? endif; ?><?=$this->escapeHtml($this->year)?><? endif; ?><? if (!empty($this->year) || !empty($this->publisher)): ?>.<? endif; ?>
\ No newline at end of file
+<? if (!empty($this->year)): ?><? if (!empty($this->publisher)): ?>, <? endif; ?><?=$this->escapeHtml($this->year)?><? endif; ?><? if (!empty($this->year) || !empty($this->publisher)): ?>.<? endif; ?>
diff --git a/themes/root/templates/Email/record-sms.phtml b/themes/root/templates/Email/record-sms.phtml
index 722515247dcd5150b968fdbc7adba592ee75368f..a456ea481233ae2764efd637e54aceb573b72e1c 100644
--- a/themes/root/templates/Email/record-sms.phtml
+++ b/themes/root/templates/Email/record-sms.phtml
@@ -15,7 +15,7 @@
         // the last location encountered.
         $callno = $location = $backupLocation = false;
         $useBackupLocation = true;
-        foreach ($holdings as $details) {
+        foreach ($holdings['holdings'] as $details) {
             $location = $details['location'];
             foreach ($details['items'] as $item) {
                 $callno = isset($item['callnumber']) ? $item['callnumber'] : false;
diff --git a/themes/root/templates/Email/recover-password.phtml b/themes/root/templates/Email/recover-password.phtml
index 6037d640e280c061414c309da769eb7cddef0989..dd84e2ecc3c1e7f5f5871027673aeaf56742b2ec 100644
--- a/themes/root/templates/Email/recover-password.phtml
+++ b/themes/root/templates/Email/recover-password.phtml
@@ -1,3 +1,3 @@
 <?=$this->translate('recovery_email_notification', array('%%library%%' => $this->library)) ?>
 
-<?=$this->translate('recovery_email_url_pretext', array('%%url%%' => $this->url)) ?>
\ No newline at end of file
+<?=$this->translate('recovery_email_url_pretext', array('%%url%%' => $this->url)) ?>
diff --git a/themes/root/templates/HelpTranslations/de/advsearch.phtml b/themes/root/templates/HelpTranslations/de/advsearch.phtml
index eeae7847eb155ffe60400692152edcb877eee077..270ad37cc7a7586b986f9a30512abb672ee8ddd5 100644
--- a/themes/root/templates/HelpTranslations/de/advsearch.phtml
+++ b/themes/root/templates/HelpTranslations/de/advsearch.phtml
@@ -18,16 +18,16 @@
     <p>Mit der Einstellung "Suchbedingung" können Sie die Relation zwischen den
        einzelnen Feldern innerhalb einer Suchgruppe festlegen.</p>
     <ul>
-      <li>"Mit ALLEN Wörtern" - Gibt nur die Treffer zurück, die alle Wörtern
+      <li>"Mit ALLEN Wörtern" - Gibt nur die Treffer zurück, die alle Wörter
           bzw. Phrasen enthalten (entspricht dem boolschen UND).</li>
-      <li>"Mit IRGENDEINEM der Wörter" - Gibt die Treffer zurück, die mit mindestens
+      <li>"Mit IRGENDEINEM der Wörter" - Gibt die Treffer zurück, die mindestens
           eines der Wörter oder Phrasen enthalten (entspricht dem boolschen ODER).</li>
       <li>"OHNE die Wörter" - Gibt alle Treffer zurück, die nicht die
-          angegebenen Wörtern oder Phrasen enthalten (entspricht dem boolschen NICHT ODER).
+          angegebenen Wörter oder Phrasen enthalten (entspricht dem boolschen NICHT).
       </li>
     </ul>
     <p>Mit der Schaltfläche "Suchfeld hinzufügen" können weitere Suchfelder
-       hinzugefügt werden und mit den Kreuzchen können sie wieder entfernt werden..</p>
+       hinzugefügt werden und mit den Kreuzchen können sie wieder entfernt werden.</p>
   </dd>
   
   <dt><a name="Search Groups"></a>Suchgruppen</dt>
@@ -47,11 +47,11 @@
        oder "Mit IRGENDEINER Wortgruppe" können Sie steuern, ob für die Suche alle
        Gruppen oder nur mindestens eine berücksichtigt werden sollen.
     </p>
-    <p>Für das weiter oben beschriebene Beispiel, können Sie die Suche mit den
+    <p>Für das weiter oben beschriebene Beispiel können Sie die Suche mit den
        Suchkriterien folgendermaßen lösen:</p>
     <ul>
       <li>Fügen Sie in die Eingabefelder der ersten Suchgruppe den Begriff "Indien" und "China"
-          ein und setzen Sie "Suchbedingung" auf "Mit IRGENEINEM der Wörter".</li> 
+          ein und setzen Sie "Suchbedingung" auf "Mit IRGENDEINEM der Wörter".</li>
       <li>Fügen Sie eine weitere Suchgruppe hinzu und geben Sie dort "Geschichte"
           ein.</li>
       <li>Setzen Sie die Suchbedingung auf "Mit ALLEN Wörtern".</li>
diff --git a/themes/root/templates/HelpTranslations/de/tag.phtml b/themes/root/templates/HelpTranslations/de/tag.phtml
index fe05946fa5ac3087ada4ad9e7497d5c50720e892..8fb15bfbadf0f0c3cb11d5b3b51b61cad48cb285 100644
--- a/themes/root/templates/HelpTranslations/de/tag.phtml
+++ b/themes/root/templates/HelpTranslations/de/tag.phtml
@@ -20,4 +20,4 @@
     anderen Objekten, welche das selbe Schlagwort teilen, oder zu einer
     Liste von weiteren <em>Tags</em>. Damit können mit dem Navigtor die Objekte
     auf einfache Art besucht werden.
-</p>
\ No newline at end of file
+</p>
diff --git a/themes/root/templates/HelpTranslations/el/search.phtml b/themes/root/templates/HelpTranslations/el/search.phtml
index adedb3d8b95e49ed2322a6e92265dc39d637abda..728d5d2095fb9175c26fbe057887760064f2308a 100644
--- a/themes/root/templates/HelpTranslations/el/search.phtml
+++ b/themes/root/templates/HelpTranslations/el/search.phtml
@@ -1 +1,120 @@
-<h1>Χρήσιμες συμβουλές για να κάνετε Αναζήτηση</h1>

<ul class="HelpMenu">
  <li><a href="#Wildcard Searches">Αναζητήση με χαρακτήρες μπαλαντέρ</a></li>
  <li><a href="#Fuzzy Searches">Αναζήτηση ασαφούς όρου - Fuzzy Search</a></li>
  <li><a href="#Proximity Searches">Αναζήτηση συγγενών όρων - Proximity Search</a></li>
  <li><a href="#Range Searches">Αναζήτηση σε Εύρος - Range Search</a></li>
  <li><a href="#Boosting a Term">Ενίσχυση Βαρύτητας Όρου</a></li>
  <li><a href="#Boolean operators">Λογικοί Τελεστές - Boolean Operators</a>
    <ul>
      <li><a href="#AND">AND</a></li>
      <li><a href="#+">+</a></li>
      <li><a href="#OR">OR</a></li>
      <li><a href="#NOT">NOT</a></li>
      <li><a href="#-">-</a></li>
    </ul>
  </li>
</ul>

<dl class="Content">
  <dt><a name="Wildcard Searches"></a>Αναζητήση με χαρακτήρες μπαλαντέρ</dt>
  <dd>
    <p>Για να κάνετε αναζήτηση με μόνο ένα χαρακτήρα ως μπαλαντέρ χρησιμοποιείστε το σύμβολο <strong>?</strong> .</p>
    <p>Για παράδειγμα, για να αναζητήσετε την λέξη "text" ή "test" μπορείτε να χρησιμοποιήσετε τον όρο:</p>
    <pre class="code">te?t</pre>
    <p>Για να χρησιμοποιήσετε πολλαπλούς χαρακτήρες, 0 ή και περισσότερους, ως μπαλαντέρ χρησιμοποιήστε το σύμβολο<strong>*</strong> .</p>
    <p>Για παράδειγμα, για να αναζητήσετε τις λέξεις test, tests ή tester, μπορείτε να χρησιμοποιήσετε τον όρο: </p>
    <pre class="code">test*</pre>
    <p>Μπορείτε επίσης, να χρησιμοποιήσετε τους χαρακτήρες μπαλαντέρ και μέσα στη λέξη.</p>
    <pre class="code">te*t</pre>
    <p>Σημείωση: Δεν μπορείτε να χρησιμοποιήσετε τα σύμβολα * και ? σαν πρώτους χαρακτήρες μίας λέξης.</p>
  </dd>

  <dt><a name="Fuzzy Searches"></a>Αναζήτηση ασαφούς όρου - Fuzzy Search</dt>
  <dd>
    <p>Χρησιμοποιήστε το σύμβολο <strong>~</strong> στο τέλος όρου αναζήτησης <strong>μιας μόνο </strong> λέξης. Για παράδειγμα για να αναζητήσετε ένα όρο του οποίου η ορθογραφία μοιάζει με την λέξη "roam" χρησιμοποιήστε την αναζήτηση ασαφούς όρου: </p>
    <pre class="code">roam~</pre>
    <p>Αυτή η αναζήτηση θα βρεί όρους όπως foam και roams.</p>
    <p>Εάν εισάγετε μια επιπλέον παράμετρο μπορείτε να ορίσετε και την επιθυμητή εγγύτητα Η τιμή είναι μεταξύ 0 και 1. Χρησιμοποιώντας τιμή πλησιέστερη στο 1, θα ταυτιστούν μόνο όροι με υψηλότερη εγγύτητα. Για παράδειγμα:</p>
    <pre class="code">roam~0.8</pre>
    <p>Η προεπιλεγμένη τιμή που χρησιμοποιείται στην περίπτωση που δεν δηλωθεί η παράμετρος είναι 0.5.</p>
  </dd>
  
  <dt><a name="Proximity Searches"></a>Αναζήτηση συγγενών όρων - Proximity Search</dt>
  <dd>
    <p>
      Χρησιμοποιήστε το σύμβολο  <strong>~</strong> στο τέλος όρου <strong> Πολλαπλών </strong> λέξεων.
      Για παράδειγμα, για να αναζήτησετε τις λέξεις economics και keynes που έχουν απόσταση 10 λέξεων μεταξύ τους, χρησιμοποιήστε: 
    </p>
    <pre class="code">"economics Keynes"~10</pre>
  </dd>
  
  <dt><a name="Range Searches"></a>Αναζήτηση σε Εύρος - Range Search</dt>
  <dd>
    <p>
      Για να πραγματοποιήσετε μια αναζήτηση σε εύρος μπορείτε να χρησιμοποιήσετε τους χαρακτήρες  <strong>{ }</strong> .
       Για παράδειγμα, για να αναζητήσετε τον όρο που ξεκινά με το γράμμα A, B, ή C χρησιμοποιήστε: 
    </p>
    <pre class="code">{A TO C}</pre>
    <p>
      Το ίδιο μπορεί να χρησιμοποιηθεί και με πεδία που έχουν αριθμούς, όπως για παράδειγμα το Έτος: 
    </p>
    <pre class="code">[2002 TO 2003]</pre>
  </dd>
  
  <dt><a name="Boosting a Term"></a>Ενίσχυση Βαρύτητας Όρου</dt>
  <dd>
    <p>
      Για να εφαρμόσετε περισσότερη βαρύτητα σε ένα όρο, μπορείτε να χρησιμοποιήσετε τον χαρακτήρα <strong>^</strong> .
       Για παράδειγμα μπορείτε να δοκιμάσετε την παρακάτω αναζήτηση: 
    </p>
    <pre class="code">economics Keynes^5</pre>
    <p>Το οποίο θα δώσει μεγαλύτερη βαρύτητα στον όρο "Keynes"</p>
  </dd>

  <dt><a name="Boolean operators"></a>Λογικοί Τελεστές - Boolean Operators</dt>
  <dd>
    <p>
      Οι Λογικοί Τελεστές μας επιτρέπουν να συνδυάσουμε όρους.
       Οι τελεστές που επιτρέπονται είναι οι εξής: <strong>AND</strong>, <strong>+</strong>, <strong>OR</strong>, <strong>NOT</strong> και <strong>-</strong>. 
    </p>
    <p>Σημείωση: Οι Λογικοί Τελεστές πρέπει να εισάγονται πάντα με ΚΕΦΑΛΑΙΟΥΣ ΧΑΡΑΚΤΗΡΕΣ.</p>
    <dl>      
      <dt><a name="AND"></a>AND</dt>
      <dd>
        <p>Ο Τελεστής <strong>AND</strong> είναι ο προεπιλεγμένος τελεστής σύνδεσης. Αυτό σημαίνει πως εάν δεν οριστεί Λογικός Τελεστής μεταξύ των δύο όρων, χρησιμοποιείται ο Τελεστής AND. Ο Τελεστής AND αντιστοιχίζει εγγραφές όπου και οι δυο όροι αναζήτησης περιέχονται σε οποιοδήποτε πεδίο της εγγραφής. </p>
        <p>Για να αναζητήσετε τις εγγραφές που περιέχουν τον όρο "economics" και τον όρο "Keynes" χρησιμοποιήστε το ερώτημα: </p>
        <pre class="code">economics Keynes</pre>
        <p>ή</p>
        <pre class="code">economics AND Keynes</pre>		
      </dd>
      <dt><a name="+"></a>+</dt>
      <dd>
        <p>Ο Τελεστής "+" απαιτεί από τον όρο που εισάγεται μετά το σύμβολο "+" να υπάρχει σε κάποιο από τα πεδία της εγγραφής.</p>
        <p>Για να αναζητήσετε εγγραφές που πρέπει να περιέχουν τον όρο"economics" και μπορεί να περιέχουν τον όρο "Keynes" χρησιμοποιήστε το ερώτημα:</p>
        <pre class="code">+economics Keynes</pre>
      </dd>
      <dt><a name="OR"></a>OR</dt>
      <dd>
        <p>Ο Τελεστής <strong>OR</strong> συνδέει δύο όρους και βρίσκει μια εγγραφή που περιέχει οποιονδήποτε από τους όρους αυτούς.</p>
        <p>Για να αναζητήσετε έγγραφα που περιέχουν τους όρους "economics Keynes" ή μόνο τον όρο "Keynes" χρησιμοποιήστε το ερώτημα:</p>
        <pre class="code">"economics Keynes" OR Keynes</pre>
      </dd>
      <dt><a name="NOT"></a>NOT</dt>
      <dd>
        <p>Ο Τελεστής NOT αποκλείει εγγραφές που περιέχουν τον όρο που εισάγεται μετά την λέξη NOT.</p>
        <p>Για να αναζητήσετε έγγραφα που περιέχουν τον όρο "economics" αλλά όχι τον όρο "Keynes" χρησιμοποιήστε το ερώτημα: </p>
        <pre class="code">"economics" NOT "Keynes"</pre>
        <p>Σημείωση: Ο Τελεστής NOT δεν μπορεί να χρησιμοποιηθεί μόνο με ένα όρο. Για παράδειγμα, η ακόλουθη αναζήτηση δεν θα επιστρέψει κανένα αποτέλεσμα: </p>
        <pre class="code">NOT economics</pre>
      </dd>
      <dt><a name="-"></a>-</dt>
      <dd>
        <p>Ο Τελεστής "<Strong>-</strong>" αποκλείει εγγραφές που περιέχουν τον όρο που εισάγεται μετά το σύμβολο "-" .</p>
        <p>Για να αναζητήσετε έγγραφα που περιέχουν τον όρο "economics" αλλά όχι τον όρο "Keynes" χρησιμοποιήστε το ερώτημα: </p>
        <pre class="code">economics -Keynes</pre>
      </dd>
    </dl>
  </dd>
</dl>
\ No newline at end of file
+<h1>Χρήσιμες συμβουλές για να κάνετε Αναζήτηση</h1>
+
+<ul class="HelpMenu">
+  <li><a href="#Wildcard Searches">Αναζητήση με χαρακτήρες μπαλαντέρ</a></li>
+  <li><a href="#Fuzzy Searches">Αναζήτηση ασαφούς όρου - Fuzzy Search</a></li>
+  <li><a href="#Proximity Searches">Αναζήτηση συγγενών όρων - Proximity Search</a></li>
+  <li><a href="#Range Searches">Αναζήτηση σε Εύρος - Range Search</a></li>
+  <li><a href="#Boosting a Term">Ενίσχυση Βαρύτητας Όρου</a></li>
+  <li><a href="#Boolean operators">Λογικοί Τελεστές - Boolean Operators</a>
+    <ul>
+      <li><a href="#AND">AND</a></li>
+      <li><a href="#+">+</a></li>
+      <li><a href="#OR">OR</a></li>
+      <li><a href="#NOT">NOT</a></li>
+      <li><a href="#-">-</a></li>
+    </ul>
+  </li>
+</ul>
+
+<dl class="Content">
+  <dt><a name="Wildcard Searches"></a>Αναζητήση με χαρακτήρες μπαλαντέρ</dt>
+  <dd>
+    <p>Για να κάνετε αναζήτηση με μόνο ένα χαρακτήρα ως μπαλαντέρ χρησιμοποιείστε το σύμβολο <strong>?</strong> .</p>
+    <p>Για παράδειγμα, για να αναζητήσετε την λέξη "text" ή "test" μπορείτε να χρησιμοποιήσετε τον όρο:</p>
+    <pre class="code">te?t</pre>
+    <p>Για να χρησιμοποιήσετε πολλαπλούς χαρακτήρες, 0 ή και περισσότερους, ως μπαλαντέρ χρησιμοποιήστε το σύμβολο<strong>*</strong> .</p>
+    <p>Για παράδειγμα, για να αναζητήσετε τις λέξεις test, tests ή tester, μπορείτε να χρησιμοποιήσετε τον όρο: </p>
+    <pre class="code">test*</pre>
+    <p>Μπορείτε επίσης, να χρησιμοποιήσετε τους χαρακτήρες μπαλαντέρ και μέσα στη λέξη.</p>
+    <pre class="code">te*t</pre>
+    <p>Σημείωση: Δεν μπορείτε να χρησιμοποιήσετε τα σύμβολα * και ? σαν πρώτους χαρακτήρες μίας λέξης.</p>
+  </dd>
+
+  <dt><a name="Fuzzy Searches"></a>Αναζήτηση ασαφούς όρου - Fuzzy Search</dt>
+  <dd>
+    <p>Χρησιμοποιήστε το σύμβολο <strong>~</strong> στο τέλος όρου αναζήτησης <strong>μιας μόνο </strong> λέξης. Για παράδειγμα για να αναζητήσετε ένα όρο του οποίου η ορθογραφία μοιάζει με την λέξη "roam" χρησιμοποιήστε την αναζήτηση ασαφούς όρου: </p>
+    <pre class="code">roam~</pre>
+    <p>Αυτή η αναζήτηση θα βρεί όρους όπως foam και roams.</p>
+    <p>Εάν εισάγετε μια επιπλέον παράμετρο μπορείτε να ορίσετε και την επιθυμητή εγγύτητα Η τιμή είναι μεταξύ 0 και 1. Χρησιμοποιώντας τιμή πλησιέστερη στο 1, θα ταυτιστούν μόνο όροι με υψηλότερη εγγύτητα. Για παράδειγμα:</p>
+    <pre class="code">roam~0.8</pre>
+    <p>Η προεπιλεγμένη τιμή που χρησιμοποιείται στην περίπτωση που δεν δηλωθεί η παράμετρος είναι 0.5.</p>
+  </dd>
+
+  <dt><a name="Proximity Searches"></a>Αναζήτηση συγγενών όρων - Proximity Search</dt>
+  <dd>
+    <p>
+      Χρησιμοποιήστε το σύμβολο  <strong>~</strong> στο τέλος όρου <strong> Πολλαπλών </strong> λέξεων.
+      Για παράδειγμα, για να αναζήτησετε τις λέξεις economics και keynes που έχουν απόσταση 10 λέξεων μεταξύ τους, χρησιμοποιήστε:
+    </p>
+    <pre class="code">"economics Keynes"~10</pre>
+  </dd>
+
+  <dt><a name="Range Searches"></a>Αναζήτηση σε Εύρος - Range Search</dt>
+  <dd>
+    <p>
+      Για να πραγματοποιήσετε μια αναζήτηση σε εύρος μπορείτε να χρησιμοποιήσετε τους χαρακτήρες  <strong>{ }</strong> .
+       Για παράδειγμα, για να αναζητήσετε τον όρο που ξεκινά με το γράμμα A, B, ή C χρησιμοποιήστε:
+    </p>
+    <pre class="code">{A TO C}</pre>
+    <p>
+      Το ίδιο μπορεί να χρησιμοποιηθεί και με πεδία που έχουν αριθμούς, όπως για παράδειγμα το Έτος:
+    </p>
+    <pre class="code">[2002 TO 2003]</pre>
+  </dd>
+
+  <dt><a name="Boosting a Term"></a>Ενίσχυση Βαρύτητας Όρου</dt>
+  <dd>
+    <p>
+      Για να εφαρμόσετε περισσότερη βαρύτητα σε ένα όρο, μπορείτε να χρησιμοποιήσετε τον χαρακτήρα <strong>^</strong> .
+       Για παράδειγμα μπορείτε να δοκιμάσετε την παρακάτω αναζήτηση:
+    </p>
+    <pre class="code">economics Keynes^5</pre>
+    <p>Το οποίο θα δώσει μεγαλύτερη βαρύτητα στον όρο "Keynes"</p>
+  </dd>
+
+  <dt><a name="Boolean operators"></a>Λογικοί Τελεστές - Boolean Operators</dt>
+  <dd>
+    <p>
+      Οι Λογικοί Τελεστές μας επιτρέπουν να συνδυάσουμε όρους.
+       Οι τελεστές που επιτρέπονται είναι οι εξής: <strong>AND</strong>, <strong>+</strong>, <strong>OR</strong>, <strong>NOT</strong> και <strong>-</strong>.
+    </p>
+    <p>Σημείωση: Οι Λογικοί Τελεστές πρέπει να εισάγονται πάντα με ΚΕΦΑΛΑΙΟΥΣ ΧΑΡΑΚΤΗΡΕΣ.</p>
+    <dl>
+      <dt><a name="AND"></a>AND</dt>
+      <dd>
+        <p>Ο Τελεστής <strong>AND</strong> είναι ο προεπιλεγμένος τελεστής σύνδεσης. Αυτό σημαίνει πως εάν δεν οριστεί Λογικός Τελεστής μεταξύ των δύο όρων, χρησιμοποιείται ο Τελεστής AND. Ο Τελεστής AND αντιστοιχίζει εγγραφές όπου και οι δυο όροι αναζήτησης περιέχονται σε οποιοδήποτε πεδίο της εγγραφής. </p>
+        <p>Για να αναζητήσετε τις εγγραφές που περιέχουν τον όρο "economics" και τον όρο "Keynes" χρησιμοποιήστε το ερώτημα: </p>
+        <pre class="code">economics Keynes</pre>
+        <p>ή</p>
+        <pre class="code">economics AND Keynes</pre>
+      </dd>
+      <dt><a name="+"></a>+</dt>
+      <dd>
+        <p>Ο Τελεστής "+" απαιτεί από τον όρο που εισάγεται μετά το σύμβολο "+" να υπάρχει σε κάποιο από τα πεδία της εγγραφής.</p>
+        <p>Για να αναζητήσετε εγγραφές που πρέπει να περιέχουν τον όρο"economics" και μπορεί να περιέχουν τον όρο "Keynes" χρησιμοποιήστε το ερώτημα:</p>
+        <pre class="code">+economics Keynes</pre>
+      </dd>
+      <dt><a name="OR"></a>OR</dt>
+      <dd>
+        <p>Ο Τελεστής <strong>OR</strong> συνδέει δύο όρους και βρίσκει μια εγγραφή που περιέχει οποιονδήποτε από τους όρους αυτούς.</p>
+        <p>Για να αναζητήσετε έγγραφα που περιέχουν τους όρους "economics Keynes" ή μόνο τον όρο "Keynes" χρησιμοποιήστε το ερώτημα:</p>
+        <pre class="code">"economics Keynes" OR Keynes</pre>
+      </dd>
+      <dt><a name="NOT"></a>NOT</dt>
+      <dd>
+        <p>Ο Τελεστής NOT αποκλείει εγγραφές που περιέχουν τον όρο που εισάγεται μετά την λέξη NOT.</p>
+        <p>Για να αναζητήσετε έγγραφα που περιέχουν τον όρο "economics" αλλά όχι τον όρο "Keynes" χρησιμοποιήστε το ερώτημα: </p>
+        <pre class="code">"economics" NOT "Keynes"</pre>
+        <p>Σημείωση: Ο Τελεστής NOT δεν μπορεί να χρησιμοποιηθεί μόνο με ένα όρο. Για παράδειγμα, η ακόλουθη αναζήτηση δεν θα επιστρέψει κανένα αποτέλεσμα: </p>
+        <pre class="code">NOT economics</pre>
+      </dd>
+      <dt><a name="-"></a>-</dt>
+      <dd>
+        <p>Ο Τελεστής "<Strong>-</strong>" αποκλείει εγγραφές που περιέχουν τον όρο που εισάγεται μετά το σύμβολο "-" .</p>
+        <p>Για να αναζητήσετε έγγραφα που περιέχουν τον όρο "economics" αλλά όχι τον όρο "Keynes" χρησιμοποιήστε το ερώτημα: </p>
+        <pre class="code">economics -Keynes</pre>
+      </dd>
+    </dl>
+  </dd>
+</dl>
diff --git a/themes/root/templates/HelpTranslations/el/tag.phtml b/themes/root/templates/HelpTranslations/el/tag.phtml
index 26d6a823f4c1c054fb5f1abf98464e0c696c4934..6c3f71d1937f598b3e4ab7ca4b00c00bfe72ad77 100644
--- a/themes/root/templates/HelpTranslations/el/tag.phtml
+++ b/themes/root/templates/HelpTranslations/el/tag.phtml
@@ -14,4 +14,4 @@
 μεταβάλλει ο διαχειρηστής της συλλογής με ελάχιστο κόπο και προγραμματισμό ).
 </p>
 
-<a href="http://en.wikipedia.org/wiki/Tag_%28metadata%29">Παρέχεται από Wikipedia</a>
\ No newline at end of file
+<a href="http://en.wikipedia.org/wiki/Tag_%28metadata%29">Παρέχεται από Wikipedia</a>
diff --git a/themes/root/templates/HelpTranslations/en/tag.phtml b/themes/root/templates/HelpTranslations/en/tag.phtml
index 35e3d02b4f00cf65d890450071309e3e47e59e47..de39d6dc79fd158d398f6f22900418eb5bbae9df 100644
--- a/themes/root/templates/HelpTranslations/en/tag.phtml
+++ b/themes/root/templates/HelpTranslations/en/tag.phtml
@@ -12,4 +12,4 @@ Tags are usually chosen informally and personally by the author/creator of the i
 Typically, an item will have one or more &quot;tags&quot; associated with it, as part of some classification software or system. The software will provide links to other items that share that keyword tag, or even to specified collections of tags. This allows for multiple &quot;browse-able paths&quot; through the items which can quickly and easily be altered by the collection's administrator, with minimal effort and planning.
 </p>
 
-<a href="http://en.wikipedia.org/wiki/Tag_%28metadata%29">From Wikipedia</a>
\ No newline at end of file
+<a href="http://en.wikipedia.org/wiki/Tag_%28metadata%29">From Wikipedia</a>
diff --git a/themes/root/templates/HelpTranslations/es/advsearch.phtml b/themes/root/templates/HelpTranslations/es/advsearch.phtml
index d90ce8e98aeec2384911c6e93aa0a212bad0f50a..740a4231050b0f18857304792fe14d8ac1ca4a21 100644
--- a/themes/root/templates/HelpTranslations/es/advsearch.phtml
+++ b/themes/root/templates/HelpTranslations/es/advsearch.phtml
@@ -49,4 +49,4 @@
       <li>Seleccione el parámetro "TODOS los términos"</li>
     </ul>
   </dd>
-</dl>
\ No newline at end of file
+</dl>
diff --git a/themes/root/templates/HelpTranslations/es/search.phtml b/themes/root/templates/HelpTranslations/es/search.phtml
index 7cb681f26eea85645877c94c0642708a15e90a89..cf3e47bebbb30d6f42d2b2e67aee27454e088ce4 100644
--- a/themes/root/templates/HelpTranslations/es/search.phtml
+++ b/themes/root/templates/HelpTranslations/es/search.phtml
@@ -153,4 +153,4 @@
       </dd>
     </dl>
   </dd>
-</dl>
\ No newline at end of file
+</dl>
diff --git a/themes/root/templates/HelpTranslations/fr/tag.phtml b/themes/root/templates/HelpTranslations/fr/tag.phtml
index 2b29fa28ba14208c46362373816b5b63041ca6f1..9944e8a5679543dd32ce96db0df8d3c8537c9b3c 100644
--- a/themes/root/templates/HelpTranslations/fr/tag.phtml
+++ b/themes/root/templates/HelpTranslations/fr/tag.phtml
@@ -23,4 +23,4 @@ En pratique, un objet informatique peut avoir un ou plusieurs tags qui lui
 sont associés.
 </p>
 
-<a href="http://fr.wikipedia.org/wiki/Tag_(métadonnée)">Wikipédia</a>
\ No newline at end of file
+<a href="http://fr.wikipedia.org/wiki/Tag_(métadonnée)">Wikipédia</a>
diff --git a/themes/root/templates/HelpTranslations/ga/advsearch.phtml b/themes/root/templates/HelpTranslations/ga/advsearch.phtml
index cdc5bc7160f1227a31c211a4573c0ea7032f895b..4d6ff5e1d7e8151a132f9452b5fa224f6ddfb85f 100644
--- a/themes/root/templates/HelpTranslations/ga/advsearch.phtml
+++ b/themes/root/templates/HelpTranslations/ga/advsearch.phtml
@@ -31,4 +31,4 @@
       <li>Déan deimhin de go bhfuil “GACH Grúpa” mar shocrú meaitseála agat ag ceanntásc na nGrúpaí Cuardaigh.</li>
     </ul>
   </dd>
-</dl>
\ No newline at end of file
+</dl>
diff --git a/themes/root/templates/HelpTranslations/ga/tag.phtml b/themes/root/templates/HelpTranslations/ga/tag.phtml
index 58956a0877edfacfc5bd0ac3a535e9d4bc34b949..6f675a19f1e7fab4981b54f8e1b2c496d1537fe0 100644
--- a/themes/root/templates/HelpTranslations/ga/tag.phtml
+++ b/themes/root/templates/HelpTranslations/ga/tag.phtml
@@ -13,4 +13,4 @@ Is é an t-údar nó cruthaitheoir na míre a roghnaíonn an chlib go neamhfhoir
 Is iondúil go mbíonn clib amháin nó níos mó ag baint le mír mar chuid de bhogearra rangaithe nó de chóras rangaithe.  Soláthróidh an bogearra naisc le míreanna a bhfuil clib an eochairfhocail sin leo, nó fiú le bailiúcháin sainithe chlibeanna.  Ciallaíonn sé seo gur féidir a lán cosán brabhsála a bheith ann idir na míreanna agus gur féidir le riarthóir an bhailiúcháin iad a athrú go tapa, gan stró ar bith agus gan mórán pleanála a dhéanamh. 
 </p>
 
-<a href="http://en.wikipedia.org/wiki/Tag_%28metadata%29">Ó Wikipedia</a>
\ No newline at end of file
+<a href="http://en.wikipedia.org/wiki/Tag_%28metadata%29">Ó Wikipedia</a>
diff --git a/themes/root/templates/HelpTranslations/it/search.phtml b/themes/root/templates/HelpTranslations/it/search.phtml
index ce41b5d7c5cdec673def36e94c0f7a4dd7616ef6..4bd53e48883e2c97ddafe24e364eed27d914fc52 100644
--- a/themes/root/templates/HelpTranslations/it/search.phtml
+++ b/themes/root/templates/HelpTranslations/it/search.phtml
@@ -116,4 +116,4 @@
       </dd>
     </dl>
   </dd>
-</dl>
\ No newline at end of file
+</dl>
diff --git a/themes/root/templates/HelpTranslations/it/tag.phtml b/themes/root/templates/HelpTranslations/it/tag.phtml
index 4cad8d1fc07a15897f890c302fef5471fa1b540f..9af2daa5375d860a89ef76b9c7151edb4b7d9181 100644
--- a/themes/root/templates/HelpTranslations/it/tag.phtml
+++ b/themes/root/templates/HelpTranslations/it/tag.phtml
@@ -9,6 +9,6 @@ I tag sono generalmente scelti in modo informale e personalmente dall'autore/cre
 </p>
 
 <p>
-In genere, un elemento avrà una o più & quot; tags & quot; ad esso associati, come parte di alcuni software o del sistema di classificazione. Il software fornisce collegamenti ad altri elementi che condividono quel tag parola chiave, o anche a collezioni di tag specifici. Ciò permette percorsi &quot; multi-navigabili&quot; attraverso gli elementi che possono rapidamente e facilmente essere modificati dall'amministratore della collezione, con il minimo sforzo.</p>
+In genere, un elemento avrà una o più &quot; tags &quot; ad esso associati, come parte di alcuni software o del sistema di classificazione. Il software fornisce collegamenti ad altri elementi che condividono quel tag parola chiave, o anche a collezioni di tag specifici. Ciò permette percorsi &quot; multi-navigabili&quot; attraverso gli elementi che possono rapidamente e facilmente essere modificati dall'amministratore della collezione, con il minimo sforzo.</p>
 
-<a href="http://en.wikipedia.org/wiki/Tag_%28metadata%29">da Wikipedia</a>
\ No newline at end of file
+<a href="http://en.wikipedia.org/wiki/Tag_%28metadata%29">da Wikipedia</a>
diff --git a/themes/root/templates/HelpTranslations/ja/tag.phtml b/themes/root/templates/HelpTranslations/ja/tag.phtml
index 59863be94731d30d2616c3ae5aa487a10ba16bda..6071c5e3afbdebb1796dc9f04a5ab7cb604aac98 100644
--- a/themes/root/templates/HelpTranslations/ja/tag.phtml
+++ b/themes/root/templates/HelpTranslations/ja/tag.phtml
@@ -12,4 +12,4 @@
 一般に、資料は何らかの分類ソフトウェアやシステムにより1つ以上の &quot;tags&quot; が付与されることになります。これらのソフトウェアは同じキーワードタグを持つ他の資料や特定のタグコレクションへのリンクを提供します。これにより、コレクション管理者による変更が簡単ですぐにできるアイテムを通じて、最小限の努力と計画だけで、ブラウズ可能な複数のパスが可能になります。
 </p>
 
-<a href="http://en.wikipedia.org/wiki/Tag_%28metadata%29">Wikipediaによる</a>
\ No newline at end of file
+<a href="http://en.wikipedia.org/wiki/Tag_%28metadata%29">Wikipediaによる</a>
diff --git a/themes/root/templates/HelpTranslations/pt-br/tag.phtml b/themes/root/templates/HelpTranslations/pt-br/tag.phtml
index b134ade83da4a8786a954a18b2c705a990e40cac..3e98a06f0266b2df209ad71ccdb4cd7273d9629b 100644
--- a/themes/root/templates/HelpTranslations/pt-br/tag.phtml
+++ b/themes/root/templates/HelpTranslations/pt-br/tag.phtml
@@ -12,4 +12,4 @@ Tags ou etiquetas são, usualmente, escolhidas informalmente e como escolha pess
 Tipicamente, um item terá uma ou mais &quot;tags&quot; associadas, como parte de sistemas ou software de  classificação. Os softwares ofertarão links para outros itens que compartilham as tags ou coleções de tags específicas. Isso permite que os multiplos quot;Paths&quot; de um item possa ser facilmente  e rapidamente  alterado pelo administrador da coleção com o mpinimo de esforço e planejamento.
 </p>
 
-<a href="http://pt.wikipedia.org/wiki/Tag_(metadata)">Fonte: Wikipedia, com complementação</a>
\ No newline at end of file
+<a href="http://pt.wikipedia.org/wiki/Tag_(metadata)">Fonte: Wikipedia, com complementação</a>
diff --git a/themes/root/templates/RecordDriver/AbstractBase/export-endnote.phtml b/themes/root/templates/RecordDriver/AbstractBase/export-endnote.phtml
index e5d4695ac01df8966cb062545102e3edf9ba5068..d0838ee50cf2e1f97fc89130b5f22a51dbe8c500 100644
--- a/themes/root/templates/RecordDriver/AbstractBase/export-endnote.phtml
+++ b/themes/root/templates/RecordDriver/AbstractBase/export-endnote.phtml
@@ -116,4 +116,4 @@ if (!empty($summary)) {
 
 // Record separator:
 echo "\n";
-?>
\ No newline at end of file
+?>
diff --git a/themes/root/templates/RecordDriver/AbstractBase/export-marc.phtml b/themes/root/templates/RecordDriver/AbstractBase/export-marc.phtml
index c71d7db438e9c6e7b2f54cd0862e52b762dabc16..82306a143ad08d8cd4d1b175aadef4062dd8d5a2 100644
--- a/themes/root/templates/RecordDriver/AbstractBase/export-marc.phtml
+++ b/themes/root/templates/RecordDriver/AbstractBase/export-marc.phtml
@@ -1 +1 @@
-<?=$this->driver->getMarcRecord()->toRaw()?>
\ No newline at end of file
+<?=$this->driver->getMarcRecord()->toRaw()?>
diff --git a/themes/root/templates/RecordDriver/AbstractBase/export-marcxml.phtml b/themes/root/templates/RecordDriver/AbstractBase/export-marcxml.phtml
index d40440f422bea9b30acb27716d183a2b15ae076b..5b2bbe9ccf53aad38959c3d40ea4465cbb84b4ef 100644
--- a/themes/root/templates/RecordDriver/AbstractBase/export-marcxml.phtml
+++ b/themes/root/templates/RecordDriver/AbstractBase/export-marcxml.phtml
@@ -1 +1 @@
-<?=$this->driver->getMarcRecord()->toXML()?>
\ No newline at end of file
+<?=$this->driver->getMarcRecord()->toXML()?>
diff --git a/themes/root/templates/RecordDriver/AbstractBase/export-rdf.phtml b/themes/root/templates/RecordDriver/AbstractBase/export-rdf.phtml
index 1b201ed8aa5f94a29d302472cc62eccafe757c9c..6d35443ff7f84d5301fce64351cd0e7b5e47fad9 100644
--- a/themes/root/templates/RecordDriver/AbstractBase/export-rdf.phtml
+++ b/themes/root/templates/RecordDriver/AbstractBase/export-rdf.phtml
@@ -1 +1 @@
-<?=$this->driver->getRDFXML()?>
\ No newline at end of file
+<?=$this->driver->getRDFXML()?>
diff --git a/themes/root/templates/RecordDriver/AbstractBase/export-refworks.phtml b/themes/root/templates/RecordDriver/AbstractBase/export-refworks.phtml
index 8ffa52b01af5e9ed1ca7780a109e88f82e23b3e7..223d7a8dce7b421be4f6b5bf98d5b459d3e7fe81 100644
--- a/themes/root/templates/RecordDriver/AbstractBase/export-refworks.phtml
+++ b/themes/root/templates/RecordDriver/AbstractBase/export-refworks.phtml
@@ -141,4 +141,4 @@ if ($doi = $this->driver->tryMethod('getCleanDOI')) {
 
 // Record separator:
 echo "\n";
-?>
\ No newline at end of file
+?>
diff --git a/themes/root/templates/RecordDriver/Summon/export-endnote.phtml b/themes/root/templates/RecordDriver/Summon/export-endnote.phtml
index 11b49399f999d5aed186865308c4fbe653d29f12..fba5898a7320dc50b0327fed14cd683efdc5a729 100644
--- a/themes/root/templates/RecordDriver/Summon/export-endnote.phtml
+++ b/themes/root/templates/RecordDriver/Summon/export-endnote.phtml
@@ -8,4 +8,4 @@ foreach ($formats as $i => $format) {
 // Use the default template, but override the formats:
 $this->overrideFormats = $formats;
 echo $this->render('RecordDriver/AbstractBase/export-endnote.phtml');
-?>
\ No newline at end of file
+?>
diff --git a/themes/root/templates/RecordDriver/Summon/export-refworks.phtml b/themes/root/templates/RecordDriver/Summon/export-refworks.phtml
index 621f324cf5768bfb46d2526d00f4ef4d426eaeeb..09781ee3ec658c036f37863d8dee957de99f62b5 100644
--- a/themes/root/templates/RecordDriver/Summon/export-refworks.phtml
+++ b/themes/root/templates/RecordDriver/Summon/export-refworks.phtml
@@ -8,4 +8,4 @@ foreach ($formats as $i => $format) {
 // Use the default template, but override the formats:
 $this->overrideFormats = $formats;
 echo $this->render('RecordDriver/AbstractBase/export-refworks.phtml');
-?>
\ No newline at end of file
+?>
diff --git a/themes/root/templates/api/swagger.phtml b/themes/root/templates/api/swagger.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..d136d4667de0f0c9bd2ad8b2ceeedd32d7cf8a76
--- /dev/null
+++ b/themes/root/templates/api/swagger.phtml
@@ -0,0 +1,14 @@
+<? // This template is a JSON Swagger specification ?>
+<? $basePath = rtrim($this->url('home'), '/') . '/api/v1'; ?>
+{
+    "swagger": "2.0",
+    "info": {
+        "title": "<?=$this->config->Site->title ?>",
+        "version": "<?=$this->version ?>"
+    },
+    "basePath": "<?=$basePath ?>",
+    "produces": [
+        "application/json"
+    ],
+    <?=$this->specs ?>
+}
diff --git a/themes/root/templates/help/home.phtml b/themes/root/templates/help/home.phtml
index bbea276caf237c836675adca17f7aecb0623e571..6752e0d66216cb61dca40ed218f7aa968a9aae4e 100644
--- a/themes/root/templates/help/home.phtml
+++ b/themes/root/templates/help/home.phtml
@@ -6,4 +6,4 @@
   <?=$help?>
 <? else: ?>
   <p class="warning"><?=$this->transEsc('help_page_missing')?></p>
-<? endif; ?>
\ No newline at end of file
+<? endif; ?>
diff --git a/themes/root/templates/layout/help.phtml b/themes/root/templates/layout/help.phtml
index b1d249faae4e509a74d40be569c30b8a8f83a482..8a5cc8ac2314454a63b39d74f57f9772538b4a43 100644
--- a/themes/root/templates/layout/help.phtml
+++ b/themes/root/templates/layout/help.phtml
@@ -9,4 +9,4 @@
   <body>
     <?=$this->layout()->content?>
   </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/themes/root/templates/search/opensearch-error.phtml b/themes/root/templates/search/opensearch-error.phtml
index b7eb61ba52cdd0868a0f5747f4dc81e0ef023bb7..8c96f966b1957cc170e3e10c300dd2cb85cb5e7b 100644
--- a/themes/root/templates/search/opensearch-error.phtml
+++ b/themes/root/templates/search/opensearch-error.phtml
@@ -1,2 +1,2 @@
 <?='<'?>?xml version="1.0"?<?='>'?>
-<Error>Invalid Method. Only "describe" is supported</Error>
\ No newline at end of file
+<Error>Invalid Method. Only "describe" is supported</Error>
diff --git a/themes/root/templates/searchapi/swagger.phtml b/themes/root/templates/searchapi/swagger.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..b50c6c49cf36b81c1c3a8b059b62a3dff86ab8e9
--- /dev/null
+++ b/themes/root/templates/searchapi/swagger.phtml
@@ -0,0 +1,374 @@
+<? // This template is a JSON fragment of a complete Swagger specification ?>
+<? ob_start(); ?>
+                    {
+                        "name": "field[]",
+                        "in": "query",
+                        "description": "Fields to return.<? if ($this->defaultFields): ?> If not specified, a set of default fields is returned.\n\nThe default fields are:\n- <?=implode('\n- ', array_map('addslashes', $this->defaultFields)) ?><? endif; ?>",
+                        "type": "array",
+                        "collectionFormat": "multi",
+                        "items": {
+                            "type": "string"
+                        }
+                    }
+<? $field = ob_get_contents(); ?>
+<? ob_end_clean(); ?>
+<? ob_start(); ?>
+                    {
+                        "name": "prettyPrint",
+                        "in": "query",
+                        "description": "Whether to pretty-print the response. Useful for observing the results in a browser.",
+                        "type": "boolean",
+                        "default": false
+                    },
+                    {
+                        "name": "lng",
+                        "in": "query",
+                        "description": "Language for returned translated strings.",
+                        "type": "string",
+                        "enum": [<?=implode(', ', array_map(function ($v) { return '"' . addslashes($v) . '"'; }, array_keys($this->config->Languages->toArray()))) ?>],
+                        "default": "<?=addslashes($this->config->Site->language) ?>"
+                    },
+                    {
+                        "name": "callback",
+                        "in": "query",
+                        "description": "A callback that can be used for JSONP.",
+                        "type": "string"
+                    }
+<? $commonFields = ob_get_contents(); ?>
+<? ob_end_clean(); ?>
+{
+    "paths": {
+        "/record": {
+            "get": {
+                "summary": "Fetch records",
+                "description": "Return a single record or multiple records. POST method may also be used if sending a long request.",
+                "parameters": [
+                    {
+                        "name": "id",
+                        "in": "query",
+                        "description": "A single record ID",
+                        "required": false,
+                        "type": "string"
+                    },
+                    {
+                        "name": "id[]",
+                        "in": "query",
+                        "description": "Multiple record IDs",
+                        "required": false,
+                        "type": "array",
+                        "collectionFormat": "multi",
+                        "items": {
+                            "type": "string"
+                        }
+                    },
+<?=$field ?>,
+<?=$commonFields ?>
+                ],
+                "tags": [
+                    "Record"
+                ],
+                "responses": {
+                    "200": {
+                        "description": "Response containing result count and records",
+                        "schema": {
+                            "$ref": "#/definitions/SearchResponse"
+                        }
+                    },
+                    "default": {
+                        "description": "Error",
+                        "schema": {
+                            "$ref": "#/definitions/Error"
+                        }
+                    }
+                }
+            }
+        },
+        "/search": {
+            "get": {
+                "summary": "Search the index",
+                "description": "Search the index with given terms and filters. POST method may also be used if sending a long request.\n\nThe URL syntax here is the as the one used in VuFind user interface. It is possible to make a search in VuFind and copy the query parameters here to make the same search via the API.",
+                "parameters": [
+                    {
+                        "name": "lookfor",
+                        "in": "query",
+                        "description": "Search terms. May be a single term, multiple words or a complex query containing boolean operators (AND, OR, NOT), quotes etc. Terms may also be prefixed with a field name (e.g. author:smith) to target only that field (see also type parameter).",
+                        "required": false,
+                        "type": "string"
+                    },
+                    {
+                        "name": "type",
+                        "in": "query",
+                        "description": "Search type. The following search types are available:\n- <?=implode('\n- ', array_map('addslashes', array_keys($this->searchTypes))) ?>",
+                        "required": false,
+                        "type": "string",
+                        "default": "<?=addslashes($this->defaultSearchType) ?>"
+                    },
+<?=$field ?>,
+                    {
+                        "name": "filter[]",
+                        "in": "query",
+                        "description": "Filter queries. Repeat for every filter.\nThe format for a filter is field:value.\n\n'AND' filtering is used by default. 'OR' or 'NOT' filtering can be used by prepending the field with '~' (OR) or '-' (NOT).",
+                        "type": "array",
+                        "collectionFormat": "multi",
+                        "items": {
+                            "type": "string"
+                        }
+                    },
+                    {
+                        "name": "facet[]",
+                        "in": "query",
+                        "description": "Fields to facet on. Repeat for every field. <? if ($this->facetConfig): ?>At least the following fields are available for faceting (there may be additional facetable index fields not published here):\n- <?=implode('\n- ', array_map('addslashes', array_keys($this->facetConfig))) ?><? endif; ?>",
+                        "type": "array",
+                        "collectionFormat": "multi",
+                        "items": {
+                            "type": "string"
+                        }
+                    },
+                    {
+                        "name": "facetFilter[]",
+                        "in": "query",
+                        "description": "Faceting result filters. Contains regular expressions that the facet must match for it to be returned. The result will include the matched facet items and for hierarchical facets any ancestor values.\nFormat for a facet filter is field:regexp, e.g. `author_facet:Sm.*th`.\n\n**N.B.**The filtered facet needs to be present in the list of returned facets (facet[] parameter).",
+                        "type": "array",
+                        "collectionFormat": "multi",
+                        "items": {
+                            "type": "string"
+                        }
+                    },
+                    {
+                        "name": "sort",
+                        "in": "query",
+                        "description": "Sort method.",
+                        "type": "string",
+                        "enum": [<?=implode(', ', array_map(function ($v) { return '"' . addslashes($v) . '"'; }, array_keys($this->sortOptions))) ?>],
+                        "default": "<?=addslashes($this->defaultSort) ?>"
+                    },
+                    {
+                        "name": "page",
+                        "in": "query",
+                        "description": "Record page (first page is 1).",
+                        "type": "integer",
+                        "minimum": 1,
+                        "default": 1
+                    },
+                    {
+                        "name": "limit",
+                        "in": "query",
+                        "description": "Records to return per page. Set to 0 to return no records.",
+                        "type": "integer",
+                        "minimum": 0,
+                        "maximum": 100,
+                        "default": 20
+                    },
+<?=$commonFields ?>
+                ],
+                "tags": [
+                    "Search"
+                ],
+                "responses": {
+                    "200": {
+                        "description": "Response containing result count, records and/or facets.",
+                        "schema": {
+                            "$ref": "#/definitions/SearchResponse"
+                        }
+                    },
+                    "default": {
+                        "description": "Error",
+                        "schema": {
+                            "$ref": "#/definitions/Error"
+                        }
+                    }
+                }
+            }
+        }
+    },
+    "definitions": {
+        "Authors": {
+            "type": "object",
+            "properties": {
+                "main": {
+                    "description": "Main authors",
+                    "type": "array",
+                    "items": {
+                      "$ref": "#/definitions/AuthorWithRoles"
+                    }
+                },
+                "secondary": {
+                    "description": "Secondary authors",
+                    "type": "array",
+                    "items": {
+                      "$ref": "#/definitions/AuthorWithRoles"
+                    }
+                },
+                "corporate": {
+                    "description": "Corporate authors",
+                    "type": "array",
+                    "items": {
+                      "$ref": "#/definitions/AuthorWithRoles"
+                    }
+                }
+            }
+        },
+        "AuthorWithRoles": {
+            "type": "object",
+            "properties": {
+                "Author name": {
+                    "type": "array",
+                    "description": "Author's roles",
+                    "items": {
+                        "type": "string"
+                    }
+                }
+            }
+        },
+        "Error": {
+            "type": "object",
+            "properties": {
+                "status": {
+                    "description": "Status code",
+                    "type": "string",
+                    "enum": ["ERROR"]
+                },
+                "statusMessage": {
+                    "description": "A descriptive error message",
+                    "type": "string"
+                }
+            },
+            "required": ["status", "statusMessage"]
+        },
+        "Facet": {
+            "type": "object",
+            "properties": {
+                "value": {
+                    "description": "Facet value",
+                    "type": "string"
+                },
+                "translated": {
+                    "description": "Translated facet value",
+                    "type": "string"
+                },
+                "count": {
+                    "description": "Count of records that can be found if the facet is added to the search as a filter",
+                    "type": "integer"
+                },
+                "href": {
+                    "description": "The current search with the facet added as a filter",
+                    "type": "string"
+                },
+                "isApplied": {
+                    "description": "True if if the facet is in use in the filter parameter of the query",
+                    "type": "boolean"
+                },
+                "children": {
+                    "description": "For hierarchical facets, any child facets",
+                    "type": "array",
+                    "items": {
+                        "$ref": "#/definitions/Facet"
+                    }
+                }
+            }
+        },
+        "Link": {
+            "type": "object",
+            "properties": {
+                "type": {
+                    "description": "Link type (e.g. id, isn or title)",
+                    "type": "string"
+                },
+                "value": {
+                    "description": "Link value (e.g. record ID, ISBN or title)",
+                    "type": "string"
+                },
+                "exclude": {
+                    "description": "Record IDs that need to be excluded from the results",
+                    "type": "array",
+                    "items": {
+                        "type": "string"
+                    }
+                }
+            }
+        },
+        "Record": {
+            "type": "object",
+            "properties": <?=json_encode($this->recordFields) ?>
+        },
+        "RecordLink": {
+            "type": "object",
+            "properties": {
+                "title": {
+                    "description": "Link title",
+                    "type": "string"
+                },
+                "value": {
+                    "description": "Link value",
+                    "type": "string"
+                },
+                "link": {
+                    "$ref": "#/definitions/Link"
+                }
+            }
+        },
+        "SearchResponse": {
+            "type": "object",
+            "properties": {
+                "resultCount": {
+                    "description": "Number of results",
+                    "type": "integer"
+                },
+                "records": {
+                    "description": "Records",
+                    "type": "array",
+                    "items": {
+                        "$ref": "#/definitions/Record"
+                    }
+                },
+                "facets": {
+                    "description": "Facets",
+                    "type": "array",
+                    "items": {
+                        "$ref": "#/definitions/Facet"
+                    }
+                },
+                "status": {
+                    "description": "Status code",
+                    "type": "string",
+                    "enum": ["OK"]
+                }
+            },
+            "required": ["resultCount", "status"]
+        },
+        "Subject": {
+            "type": "object",
+            "properties": {
+                "heading": {
+                    "description": "Subject heading parts as an array from the least specific to the most specific",
+                    "type": "array",
+                    "items": {
+                        "type": "string"
+                    }
+                },
+                "type": {
+                    "description": "Subject type",
+                    "type": "string",
+                    "enum": ["", "personal name", "corporate name", "meeting name", "uniform title", "chronological", "topic", "geographic", "genre\/form", "occupation", "keyword"]
+                },
+                "source": {
+                    "description": "Subject source/thesaurus (e.g. lcsh, mesh)",
+                    "type": "string"
+                }
+            }
+        },
+        "Url": {
+            "type": "object",
+            "properties": {
+                "url": {
+                    "description": "URL",
+                    "type": "string"
+                },
+                "desc": {
+                    "description": "URL Description",
+                    "type": "string"
+                }
+            }
+        }
+    }
+}
diff --git a/themes/root/theme.config.php b/themes/root/theme.config.php
index 0de80f7ed5c50f93f94d52b7fd234a447944be53..a6d343b351705aac9412ac604cc5115818434769 100644
--- a/themes/root/theme.config.php
+++ b/themes/root/theme.config.php
@@ -27,6 +27,7 @@ return array(
             'piwik' => 'VuFind\View\Helper\Root\Factory::getPiwik',
             'recaptcha' => 'VuFind\View\Helper\Root\Factory::getRecaptcha',
             'record' => 'VuFind\View\Helper\Root\Factory::getRecord',
+            'recorddataformatter' => 'VuFind\View\Helper\Root\RecordDataFormatterFactory',
             'recordlink' => 'VuFind\View\Helper\Root\Factory::getRecordLink',
             'related' => 'VuFind\View\Helper\Root\Factory::getRelated',
             'safemoneyformat' => 'VuFind\View\Helper\Root\Factory::getSafeMoneyFormat',
diff --git a/themes/sandal/css/compiled.css b/themes/sandal/css/compiled.css
new file mode 100644
index 0000000000000000000000000000000000000000..1bb67f413382e5f830a9955788e8f9f0bac33a45
--- /dev/null
+++ b/themes/sandal/css/compiled.css
@@ -0,0 +1,8 @@
+/*!
+ * Bootstrap v3.3.7 (http://getbootstrap.com)
+ * Copyright 2011-2016 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ *//*! 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,.channel .channel-record.is-selected{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}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:-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:default}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}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:bold}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{*,*:before,*:after{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="#"]:after,a[href^="javascript:"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000 !important}.label,.result .format,.sidebar .format{border:1px solid #000}.table{border-collapse:collapse !important}.table td,.table th{background-color:#fff !important}.table-bordered th,.table-bordered td{border:1px solid #ddd !important}}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}*:before,*:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}input,button,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#1565c0;text-decoration:none}a:hover,a:focus,.channel .channel-record.is-selected{color:#0d417b;text-decoration:underline}a:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.img-responsive,.thumbnail>img,.thumbnail a>img,.carousel-inner>.item>img,.carousel-inner>.item>a>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:0}.img-thumbnail{padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out;display:inline-block;max-width:100%;height:auto}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}[role="button"]{cursor:pointer}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small,.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 .small,h2 .small,h3 .small,h4 .small,h5 .small,h6 .small,.h1 .small,.h2 .small,.h3 .small,.h4 .small,.h5 .small,.h6 .small{font-weight:normal;line-height:1;color:#777}h1,.h1,h2,.h2,h3,.h3{margin-top:20px;margin-bottom:10px}h1 small,.h1 small,h2 small,.h2 small,h3 small,.h3 small,h1 .small,.h1 .small,h2 .small,.h2 .small,h3 .small,.h3 .small{font-size:65%}h4,.h4,h5,.h5,h6,.h6{margin-top:10px;margin-bottom:10px}h4 small,.h4 small,h5 small,.h5 small,h6 small,.h6 small,h4 .small,.h4 .small,h5 .small,.h5 .small,h6 .small,.h6 .small{font-size:75%}h1,.h1{font-size:36px}h2,.h2{font-size:30px}h3,.h3{font-size:24px}h4,.h4{font-size:18px}h5,.h5{font-size:14px}h6,.h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}small,.small{font-size:85%}mark,.mark{background-color:#fcf8e3;padding:.2em}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#1976d2}a.text-primary:hover,a.text-primary:focus{color:#145ca4}.text-success{color:#3c763d}a.text-success:hover,a.text-success:focus{color:#2b542c}.text-info{color:#31708f}a.text-info:hover,a.text-info:focus{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:hover,a.text-warning:focus{color:#66512c}.text-danger{color:#a94442}a.text-danger:hover,a.text-danger:focus{color:#843534}.bg-primary{color:#fff;background-color:#1976d2}a.bg-primary:hover,a.bg-primary:focus{background-color:#145ca4}.bg-success{background-color:#dff0d8}a.bg-success:hover,a.bg-success:focus{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:hover,a.bg-info:focus{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:hover,a.bg-warning:focus{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:hover,a.bg-danger:focus{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ul,ol{margin-top:0;margin-bottom:10px}ul ul,ol ul,ul ol,ol ol{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none;margin:0;margin-left:-5px}.list-inline>li{display:inline-block;padding-left:5px;padding-right:5px}dl{margin-top:0;margin-bottom:20px}dt,dd{line-height:1.42857143}dt{font-weight:bold}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #777}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote p:last-child,blockquote ul:last-child,blockquote ol:last-child{margin-bottom:0}blockquote footer,blockquote small,blockquote .small{display:block;font-size:80%;line-height:1.42857143;color:#777}blockquote footer:before,blockquote small:before,blockquote .small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0;text-align:right}.blockquote-reverse footer:before,blockquote.pull-right footer:before,.blockquote-reverse small:before,blockquote.pull-right small:before,.blockquote-reverse .small:before,blockquote.pull-right .small:before{content:''}.blockquote-reverse footer:after,blockquote.pull-right footer:after,.blockquote-reverse small:after,blockquote.pull-right small:after,.blockquote-reverse .small:after,blockquote.pull-right .small:after{content:'\00A0 \2014'}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;box-shadow:inset 0 -1px 0 rgba(0,0,0,0.25)}kbd kbd{padding:0;font-size:100%;font-weight:bold;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;word-break:break-all;word-wrap:break-word;color:#333;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container,footer{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}@media (min-width:768px){.container,footer{width:750px}}@media (min-width:992px){.container,footer{width:970px}}@media (min-width:1200px){.container,footer{width:1170px}}.container-fluid{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}.row{margin-left:-15px;margin-right:-15px}.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12{position:relative;min-height:1px;padding-left:15px;padding-right:15px}.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{background-color:transparent}caption{padding-top:8px;padding-bottom:8px;color:#777;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>thead>tr>th,.table>tbody>tr>th,.table>tfoot>tr>th,.table>thead>tr>td,.table>tbody>tr>td,.table>tfoot>tr>td{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>th,.table>caption+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>td,.table>thead:first-child>tr:first-child>td{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>thead>tr>th,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>tbody>tr>td,.table-condensed>tfoot>tr>td{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>tbody>tr>td,.table-bordered>tfoot>tr>td{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>thead>tr>td{border-bottom-width:2px}.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#cfd8dc}table col[class*="col-"]{position:static;float:none;display:table-column}table td[class*="col-"],table th[class*="col-"]{position:static;float:none;display:table-cell}.table>thead>tr>td.active,.table>tbody>tr>td.active,.table>tfoot>tr>td.active,.table>thead>tr>th.active,.table>tbody>tr>th.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>tbody>tr.active>td,.table>tfoot>tr.active>td,.table>thead>tr.active>th,.table>tbody>tr.active>th,.table>tfoot>tr.active>th{background-color:#cfd8dc}.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover,.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr.active:hover>th{background-color:#c0ccd1}.table>thead>tr>td.success,.table>tbody>tr>td.success,.table>tfoot>tr>td.success,.table>thead>tr>th.success,.table>tbody>tr>th.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>tbody>tr.success>td,.table>tfoot>tr.success>td,.table>thead>tr.success>th,.table>tbody>tr.success>th,.table>tfoot>tr.success>th{background-color:#dff0d8}.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover,.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr.success:hover>th{background-color:#d0e9c6}.table>thead>tr>td.info,.table>tbody>tr>td.info,.table>tfoot>tr>td.info,.table>thead>tr>th.info,.table>tbody>tr>th.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>tbody>tr.info>td,.table>tfoot>tr.info>td,.table>thead>tr.info>th,.table>tbody>tr.info>th,.table>tfoot>tr.info>th{background-color:#d9edf7}.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover,.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr.info:hover>th{background-color:#c4e3f3}.table>thead>tr>td.warning,.table>tbody>tr>td.warning,.table>tfoot>tr>td.warning,.table>thead>tr>th.warning,.table>tbody>tr>th.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>tbody>tr.warning>td,.table>tfoot>tr.warning>td,.table>thead>tr.warning>th,.table>tbody>tr.warning>th,.table>tfoot>tr.warning>th{background-color:#fcf8e3}.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover,.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr.warning:hover>th{background-color:#faf2cc}.table>thead>tr>td.danger,.table>tbody>tr>td.danger,.table>tfoot>tr>td.danger,.table>thead>tr>th.danger,.table>tbody>tr>th.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>tbody>tr.danger>td,.table>tfoot>tr.danger>td,.table>thead>tr.danger>th,.table>tbody>tr.danger>th,.table>tfoot>tr.danger>th{background-color:#f2dede}.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover,.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr.danger:hover>th{background-color:#ebcccc}.table-responsive{overflow-x:auto;min-height:.01%}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>thead>tr>th,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tfoot>tr>td{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>thead>tr>th:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.table-responsive>.table-bordered>thead>tr>th:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>th,.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}}fieldset{padding:0;margin:0;border:0;min-width:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:bold}input[type="search"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type="radio"],input[type="checkbox"]{margin:4px 0 0;margin-top:1px \9;line-height:normal}input[type="file"]{display:block}input[type="range"]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#333}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff;background-image:none;border:1px solid #aaa;border-radius:.25rem;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border-color ease-in-out .15s, box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s, box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s, box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control::-ms-expand{border:0;background-color:transparent}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{background-color:#eee;opacity:1}.form-control[disabled],fieldset[disabled] .form-control{cursor:not-allowed}textarea.form-control{height:auto}input[type="search"]{-webkit-appearance:none}@media screen and (-webkit-min-device-pixel-ratio:0){input[type="date"].form-control,input[type="time"].form-control,input[type="datetime-local"].form-control,input[type="month"].form-control{line-height:34px}input[type="date"].input-sm,input[type="time"].input-sm,input[type="datetime-local"].input-sm,input[type="month"].input-sm,.input-group-sm input[type="date"],.input-group-sm input[type="time"],.input-group-sm input[type="datetime-local"],.input-group-sm input[type="month"]{line-height:30px}input[type="date"].input-lg,input[type="time"].input-lg,input[type="datetime-local"].input-lg,input[type="month"].input-lg,.input-group-lg input[type="date"],.input-group-lg input[type="time"],.input-group-lg input[type="datetime-local"],.input-group-lg input[type="month"]{line-height:46px}}.form-group{margin-bottom:15px}.radio,.checkbox{position:relative;display:block;margin-top:10px;margin-bottom:10px}.radio label,.checkbox label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:normal;cursor:pointer}.radio input[type="radio"],.radio-inline input[type="radio"],.checkbox input[type="checkbox"],.checkbox-inline input[type="checkbox"]{position:absolute;margin-left:-20px;margin-top:4px \9}.radio+.radio,.checkbox+.checkbox{margin-top:-5px}.radio-inline,.checkbox-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;vertical-align:middle;font-weight:normal;cursor:pointer}.radio-inline+.radio-inline,.checkbox-inline+.checkbox-inline{margin-top:0;margin-left:10px}input[type="radio"][disabled],input[type="checkbox"][disabled],input[type="radio"].disabled,input[type="checkbox"].disabled,fieldset[disabled] input[type="radio"],fieldset[disabled] input[type="checkbox"]{cursor:not-allowed}.radio-inline.disabled,.checkbox-inline.disabled,fieldset[disabled] .radio-inline,fieldset[disabled] .checkbox-inline{cursor:not-allowed}.radio.disabled label,.checkbox.disabled label,fieldset[disabled] .radio label,fieldset[disabled] .checkbox label{cursor:not-allowed}.form-control-static{padding-top:7px;padding-bottom:7px;margin-bottom:0;min-height:34px}.form-control-static.input-lg,.form-control-static.input-sm{padding-left:0;padding-right:0}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}textarea.input-sm,select[multiple].input-sm{height:auto}.form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.form-group-sm select.form-control{height:30px;line-height:30px}.form-group-sm textarea.form-control,.form-group-sm select[multiple].form-control{height:auto}.form-group-sm .form-control-static{height:30px;min-height:32px;padding:6px 10px;font-size:12px;line-height:1.5}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:0}select.input-lg{height:46px;line-height:46px}textarea.input-lg,select[multiple].input-lg{height:auto}.form-group-lg .form-control{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:0}.form-group-lg select.form-control{height:46px;line-height:46px}.form-group-lg textarea.form-control,.form-group-lg select[multiple].form-control{height:auto}.form-group-lg .form-control-static{height:46px;min-height:38px;padding:11px 16px;font-size:18px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center;pointer-events:none}.input-lg+.form-control-feedback,.input-group-lg+.form-control-feedback,.form-group-lg .form-control+.form-control-feedback{width:46px;height:46px;line-height:46px}.input-sm+.form-control-feedback,.input-group-sm+.form-control-feedback,.form-group-sm .form-control+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .help-block,.has-success .control-label,.has-success .radio,.has-success .checkbox,.has-success .radio-inline,.has-success .checkbox-inline,.has-success.radio label,.has-success.checkbox label,.has-success.radio-inline label,.has-success.checkbox-inline label{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;border-color:#3c763d;background-color:#dff0d8}.has-success .form-control-feedback{color:#3c763d}.has-warning .help-block,.has-warning .control-label,.has-warning .radio,.has-warning .checkbox,.has-warning .radio-inline,.has-warning .checkbox-inline,.has-warning.radio label,.has-warning.checkbox label,.has-warning.radio-inline label,.has-warning.checkbox-inline label{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;border-color:#8a6d3b;background-color:#fcf8e3}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .help-block,.has-error .control-label,.has-error .radio,.has-error .checkbox,.has-error .radio-inline,.has-error .checkbox-inline,.has-error.radio label,.has-error.checkbox label,.has-error.radio-inline label,.has-error.checkbox-inline label{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;border-color:#a94442;background-color:#f2dede}.has-error .form-control-feedback{color:#a94442}.has-feedback label~.form-control-feedback{top:25px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn,.form-inline .input-group .form-control{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .radio,.form-inline .checkbox{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .radio label,.form-inline .checkbox label{padding-left:0}.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{margin-top:0;margin-bottom:0;padding-top:7px}.form-horizontal .radio,.form-horizontal .checkbox{min-height:27px}.form-horizontal .form-group{margin-left:-15px;margin-right:-15px}@media (min-width:768px){.form-horizontal .control-label{text-align:right;margin-bottom:0;padding-top:7px}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:11px;font-size:18px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px;font-size:12px}}.btn{display:inline-block;margin-bottom:0;font-weight:normal;text-align:center;vertical-align:middle;touch-action:manipulation;cursor:pointer;background-image:none;border:1px solid transparent;white-space:nowrap;padding:6px 12px;font-size:14px;line-height:1.42857143;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.btn:focus,.btn:active:focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn.active.focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn:hover,.btn:focus,.btn.focus{color:#111;text-decoration:none}.btn:active,.btn.active{outline:0;background-image:none;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-default{color:#111;background-color:#eee;border-color:#ccc}.btn-default:focus,.btn-default.focus{color:#111;background-color:#d5d5d5;border-color:#8c8c8c}.btn-default:hover{color:#111;background-color:#d5d5d5;border-color:#adadad}.btn-default:active,.btn-default.active,.open>.dropdown-toggle.btn-default{color:#111;background-color:#d5d5d5;border-color:#adadad}.btn-default:active:hover,.btn-default.active:hover,.open>.dropdown-toggle.btn-default:hover,.btn-default:active:focus,.btn-default.active:focus,.open>.dropdown-toggle.btn-default:focus,.btn-default:active.focus,.btn-default.active.focus,.open>.dropdown-toggle.btn-default.focus{color:#111;background-color:#c3c3c3;border-color:#8c8c8c}.btn-default:active,.btn-default.active,.open>.dropdown-toggle.btn-default{background-image:none}.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled.focus,.btn-default[disabled].focus,fieldset[disabled] .btn-default.focus{background-color:#eee;border-color:#ccc}.btn-default .badge{color:#eee;background-color:#111}.btn-default:hover,.btn-default:focus,.btn-default:active,.btn-default.active,.open .btn-default.dropdown-toggle{color:#eee;background-color:#111;border-color:#adadad}.btn-primary{color:#fff;background-color:#1976d2;border-color:#fff}.btn-primary:focus,.btn-primary.focus{color:#fff;background-color:#145ca4;border-color:#bfbfbf}.btn-primary:hover{color:#fff;background-color:#145ca4;border-color:#e0e0e0}.btn-primary:active,.btn-primary.active,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#145ca4;border-color:#e0e0e0}.btn-primary:active:hover,.btn-primary.active:hover,.open>.dropdown-toggle.btn-primary:hover,.btn-primary:active:focus,.btn-primary.active:focus,.open>.dropdown-toggle.btn-primary:focus,.btn-primary:active.focus,.btn-primary.active.focus,.open>.dropdown-toggle.btn-primary.focus{color:#fff;background-color:#104a85;border-color:#bfbfbf}.btn-primary:active,.btn-primary.active,.open>.dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled:hover,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary:hover,.btn-primary.disabled:focus,.btn-primary[disabled]:focus,fieldset[disabled] .btn-primary:focus,.btn-primary.disabled.focus,.btn-primary[disabled].focus,fieldset[disabled] .btn-primary.focus{background-color:#1976d2;border-color:#fff}.btn-primary .badge{color:#1976d2;background-color:#fff}.btn-primary:hover,.btn-primary:focus,.btn-primary:active,.btn-primary.active,.open .btn-primary.dropdown-toggle{color:#1976d2;background-color:#fff;border-color:#e0e0e0}.btn-success{color:#fff;background-color:#028302;border-color:#fff}.btn-success:focus,.btn-success.focus{color:#fff;background-color:#015101;border-color:#bfbfbf}.btn-success:hover{color:#fff;background-color:#015101;border-color:#e0e0e0}.btn-success:active,.btn-success.active,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#015101;border-color:#e0e0e0}.btn-success:active:hover,.btn-success.active:hover,.open>.dropdown-toggle.btn-success:hover,.btn-success:active:focus,.btn-success.active:focus,.open>.dropdown-toggle.btn-success:focus,.btn-success:active.focus,.btn-success.active.focus,.open>.dropdown-toggle.btn-success.focus{color:#fff;background-color:#012e01;border-color:#bfbfbf}.btn-success:active,.btn-success.active,.open>.dropdown-toggle.btn-success{background-image:none}.btn-success.disabled:hover,.btn-success[disabled]:hover,fieldset[disabled] .btn-success:hover,.btn-success.disabled:focus,.btn-success[disabled]:focus,fieldset[disabled] .btn-success:focus,.btn-success.disabled.focus,.btn-success[disabled].focus,fieldset[disabled] .btn-success.focus{background-color:#028302;border-color:#fff}.btn-success .badge{color:#028302;background-color:#fff}.btn-success:hover,.btn-success:focus,.btn-success:active,.btn-success.active,.open .btn-success.dropdown-toggle{color:#028302;background-color:#fff;border-color:#e0e0e0}.btn-info{color:#fff;background-color:#1C5F74;border-color:#fff}.btn-info:focus,.btn-info.focus{color:#fff;background-color:#123d4b;border-color:#bfbfbf}.btn-info:hover{color:#fff;background-color:#123d4b;border-color:#e0e0e0}.btn-info:active,.btn-info.active,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#123d4b;border-color:#e0e0e0}.btn-info:active:hover,.btn-info.active:hover,.open>.dropdown-toggle.btn-info:hover,.btn-info:active:focus,.btn-info.active:focus,.open>.dropdown-toggle.btn-info:focus,.btn-info:active.focus,.btn-info.active.focus,.open>.dropdown-toggle.btn-info.focus{color:#fff;background-color:#0b262e;border-color:#bfbfbf}.btn-info:active,.btn-info.active,.open>.dropdown-toggle.btn-info{background-image:none}.btn-info.disabled:hover,.btn-info[disabled]:hover,fieldset[disabled] .btn-info:hover,.btn-info.disabled:focus,.btn-info[disabled]:focus,fieldset[disabled] .btn-info:focus,.btn-info.disabled.focus,.btn-info[disabled].focus,fieldset[disabled] .btn-info.focus{background-color:#1C5F74;border-color:#fff}.btn-info .badge{color:#1C5F74;background-color:#fff}.btn-info:hover,.btn-info:focus,.btn-info:active,.btn-info.active,.open .btn-info.dropdown-toggle{color:#1C5F74;background-color:#fff;border-color:#e0e0e0}.btn-warning{color:#fff;background-color:#A56100;border-color:#fff}.btn-warning:focus,.btn-warning.focus{color:#fff;background-color:#724300;border-color:#bfbfbf}.btn-warning:hover{color:#fff;background-color:#724300;border-color:#e0e0e0}.btn-warning:active,.btn-warning.active,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#724300;border-color:#e0e0e0}.btn-warning:active:hover,.btn-warning.active:hover,.open>.dropdown-toggle.btn-warning:hover,.btn-warning:active:focus,.btn-warning.active:focus,.open>.dropdown-toggle.btn-warning:focus,.btn-warning:active.focus,.btn-warning.active.focus,.open>.dropdown-toggle.btn-warning.focus{color:#fff;background-color:#4e2e00;border-color:#bfbfbf}.btn-warning:active,.btn-warning.active,.open>.dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled:hover,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning:hover,.btn-warning.disabled:focus,.btn-warning[disabled]:focus,fieldset[disabled] .btn-warning:focus,.btn-warning.disabled.focus,.btn-warning[disabled].focus,fieldset[disabled] .btn-warning.focus{background-color:#A56100;border-color:#fff}.btn-warning .badge{color:#A56100;background-color:#fff}.btn-warning:hover,.btn-warning:focus,.btn-warning:active,.btn-warning.active,.open .btn-warning.dropdown-toggle{color:#A56100;background-color:#fff;border-color:#e0e0e0}.btn-danger{color:#fff;background-color:#A41915;border-color:#fff}.btn-danger:focus,.btn-danger.focus{color:#fff;background-color:#77120f;border-color:#bfbfbf}.btn-danger:hover{color:#fff;background-color:#77120f;border-color:#e0e0e0}.btn-danger:active,.btn-danger.active,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#77120f;border-color:#e0e0e0}.btn-danger:active:hover,.btn-danger.active:hover,.open>.dropdown-toggle.btn-danger:hover,.btn-danger:active:focus,.btn-danger.active:focus,.open>.dropdown-toggle.btn-danger:focus,.btn-danger:active.focus,.btn-danger.active.focus,.open>.dropdown-toggle.btn-danger.focus{color:#fff;background-color:#570d0b;border-color:#bfbfbf}.btn-danger:active,.btn-danger.active,.open>.dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled:hover,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger:hover,.btn-danger.disabled:focus,.btn-danger[disabled]:focus,fieldset[disabled] .btn-danger:focus,.btn-danger.disabled.focus,.btn-danger[disabled].focus,fieldset[disabled] .btn-danger.focus{background-color:#A41915;border-color:#fff}.btn-danger .badge{color:#A41915;background-color:#fff}.btn-danger:hover,.btn-danger:focus,.btn-danger:active,.btn-danger.active,.open .btn-danger.dropdown-toggle{color:#A41915;background-color:#fff;border-color:#e0e0e0}.btn-link{color:#1565c0;font-weight:normal;border-radius:0}.btn-link,.btn-link:active,.btn-link.active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:hover,.btn-link:focus,.btn-link:active{border-color:transparent}.btn-link:hover,.btn-link:focus{color:#0d417b;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,fieldset[disabled] .btn-link:hover,.btn-link[disabled]:focus,fieldset[disabled] .btn-link:focus{color:#777;text-decoration:none}.btn-lg,.btn-group-lg>.btn{padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:0}.btn-sm,.btn-group-sm>.btn{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-xs,.btn-group-xs>.btn{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-property:height, visibility;transition-property:height, visibility;-webkit-transition-duration:.35s;transition-duration:.35s;-webkit-transition-timing-function:ease;transition-timing-function:ease}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px dashed;border-top:4px solid \9;border-right:4px solid transparent;border-left:4px solid transparent}.dropup,.dropdown{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;list-style:none;font-size:14px;text-align:left;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,0.175);box-shadow:0 6px 12px rgba(0,0,0,0.175);background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:normal;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{text-decoration:none;color:#000;background-color:#cfd8dc}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{color:#fff;text-decoration:none;outline:0;background-color:#1976d2}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{color:#777}.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{text-decoration:none;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);cursor:not-allowed}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{left:auto;right:0}.dropdown-menu-left{left:0;right:auto}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;left:0;right:0;bottom:0;top:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px dashed;border-bottom:4px solid \9;content:""}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media (min-width:768px){.navbar-right .dropdown-menu{left:auto;right:0}.navbar-right .dropdown-menu-left{left:0;right:auto}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;float:left}.btn-group>.btn:hover,.btn-group-vertical>.btn:hover,.btn-group>.btn:focus,.btn-group-vertical>.btn:focus,.btn-group>.btn:active,.btn-group-vertical>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn.active{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn,.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-bottom-left-radius:0;border-top-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-left:8px;padding-right:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-left:12px;padding-right:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:4px;border-top-left-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-right-radius:0;border-top-left-radius:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-right-radius:0;border-top-left-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{float:none;display:table-cell;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle="buttons"]>.btn input[type="radio"],[data-toggle="buttons"]>.btn-group>.btn input[type="radio"],[data-toggle="buttons"]>.btn input[type="checkbox"],[data-toggle="buttons"]>.btn-group>.btn input[type="checkbox"]{position:absolute;clip:rect(0, 0, 0, 0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*="col-"]{float:none;padding-left:0;padding-right:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group .form-control:focus{z-index:3}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:0}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn,select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn,select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn{height:auto}.input-group-addon,.input-group-btn,.input-group .form-control{display:table-cell}.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child),.input-group .form-control:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:normal;line-height:1;color:#333;text-align:center;background-color:#eee;border:1px solid #aaa;border-radius:.25rem}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:0}.input-group-addon input[type="radio"],.input-group-addon input[type="checkbox"]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group-btn:last-child>.btn-group:not(:last-child)>.btn{border-bottom-right-radius:0;border-top-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:first-child>.btn-group:not(:first-child)>.btn{border-bottom-left-radius:0;border-top-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:hover,.input-group-btn>.btn:focus,.input-group-btn>.btn:active{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{z-index:2;margin-left:-1px}.nav{margin-bottom:0;padding-left:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:hover,.nav>li.disabled>a:focus{color:#777;text-decoration:none;background-color:transparent;cursor:not-allowed}.nav .open>a,.nav .open>a:hover,.nav .open>a:focus{background-color:#eee;border-color:#1565c0}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{color:#777;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent;cursor:default}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{text-align:center;margin-bottom:5px}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:hover,.nav-pills>li.active>a:focus{color:#fff;background-color:#1976d2}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{text-align:center;margin-bottom:5px}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-right-radius:0;border-top-left-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{overflow-x:visible;padding-right:15px;padding-left:15px;border-top:1px solid transparent;box-shadow:inset 0 1px 0 rgba(255,255,255,0.1);-webkit-overflow-scrolling:touch}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;box-shadow:none}.navbar-collapse.collapse{display:block !important;height:auto !important;padding-bottom:0;overflow:visible !important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{padding-left:0;padding-right:0}}.navbar-fixed-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{max-height:340px}@media (max-device-width:480px) and (orientation:landscape){.navbar-fixed-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{max-height:200px}}.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;padding:15px 15px;font-size:18px;line-height:20px;height:50px}.navbar-brand:hover,.navbar-brand:focus{text-decoration:none}.navbar-brand>img{display:block}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;margin-right:15px;padding:9px 10px;margin-top:8px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;box-shadow:none}.navbar-nav .open .dropdown-menu>li>a,.navbar-nav .open .dropdown-menu .dropdown-header{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:hover,.navbar-nav .open .dropdown-menu>li>a:focus{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}.navbar-form{margin-left:-15px;margin-right:-15px;padding:10px 15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);margin-top:8px;margin-bottom:8px}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn,.navbar-form .input-group .form-control{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .radio,.navbar-form .checkbox{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .radio label,.navbar-form .checkbox label{padding-left:0}.navbar-form .radio input[type="radio"],.navbar-form .checkbox input[type="checkbox"]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media (min-width:768px){.navbar-form{width:auto;border:0;margin-left:0;margin-right:0;padding-top:0;padding-bottom:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-right-radius:0;border-top-left-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{margin-bottom:0;border-top-right-radius:4px;border-top-left-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-left:15px;margin-right:15px}}@media (min-width:768px){.navbar-left{float:left !important;float:left}.navbar-right{float:right !important;float:right;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#132531;border-color:#0a1319}.navbar-default .navbar-brand{color:#fff}.navbar-default .navbar-brand:hover,.navbar-default .navbar-brand:focus{color:#068139;background-color:transparent}.navbar-default .navbar-text{color:#fff}.navbar-default .navbar-nav>li>a{color:#fff}.navbar-default .navbar-nav>li>a:hover,.navbar-default .navbar-nav>li>a:focus{color:#132531;background-color:#fff}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:hover,.navbar-default .navbar-nav>.active>a:focus{color:#132531;background-color:#fff}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:hover,.navbar-default .navbar-nav>.disabled>a:focus{color:#fff;background-color:#068139}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:hover,.navbar-default .navbar-toggle:focus{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#0a1319}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:hover,.navbar-default .navbar-nav>.open>a:focus{background-color:#fff;color:#132531}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#fff}.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus{color:#132531;background-color:#fff}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus{color:#132531;background-color:#fff}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#fff;background-color:#068139}}.navbar-default .navbar-link{color:#fff}.navbar-default .navbar-link:hover{color:#132531}.navbar-default .btn-link{color:#fff}.navbar-default .btn-link:hover,.navbar-default .btn-link:focus{color:#132531}.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:hover,.navbar-default .btn-link[disabled]:focus,fieldset[disabled] .navbar-default .btn-link:focus{color:#fff}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#9d9d9d}.navbar-inverse .navbar-brand:hover,.navbar-inverse .navbar-brand:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a:hover,.navbar-inverse .navbar-nav>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:hover,.navbar-inverse .navbar-nav>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:hover,.navbar-inverse .navbar-nav>.disabled>a:focus{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:hover,.navbar-inverse .navbar-toggle:focus{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:hover,.navbar-inverse .navbar-nav>.open>a:focus{background-color:#080808;color:#fff}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#9d9d9d}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .btn-link{color:#9d9d9d}.navbar-inverse .btn-link:hover,.navbar-inverse .btn-link:focus{color:#fff}.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:hover,.navbar-inverse .btn-link[disabled]:focus,fieldset[disabled] .navbar-inverse .btn-link:focus{color:#444}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{content:"/\00a0";padding:0 5px;color:#ccc}.breadcrumb>.active{color:#777}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;line-height:1.42857143;text-decoration:none;color:#607d8b;background-color:#fff;border:1px solid transparent;margin-left:-1px}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-bottom-left-radius:4px;border-top-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-bottom-right-radius:4px;border-top-right-radius:4px}.pagination>li>a:hover,.pagination>li>span:hover,.pagination>li>a:focus,.pagination>li>span:focus{z-index:2;color:#0d417b;background-color:#eee;border-color:transparent}.pagination>.active>a,.pagination>.active>span,.pagination>.active>a:hover,.pagination>.active>span:hover,.pagination>.active>a:focus,.pagination>.active>span:focus{z-index:3;color:#fff;background-color:#1976d2;border-color:#1976d2;cursor:default}.pagination>.disabled>span,.pagination>.disabled>span:hover,.pagination>.disabled>span:focus,.pagination>.disabled>a,.pagination>.disabled>a:hover,.pagination>.disabled>a:focus{color:#777;background-color:#fff;border-color:#ddd;cursor:not-allowed}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px;line-height:1.3333333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-bottom-left-radius:0;border-top-left-radius:0}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-bottom-right-radius:0;border-top-right-radius:0}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-bottom-left-radius:3px;border-top-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-bottom-right-radius:3px;border-top-right-radius:3px}.pager{padding-left:0;margin:20px 0;list-style:none;text-align:center}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid transparent;border-radius:15px}.pager li>a:hover,.pager li>a:focus{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:hover,.pager .disabled>a:focus,.pager .disabled>span{color:#777;background-color:#fff;cursor:not-allowed}.label,.result .format,.sidebar .format{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:bold;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:hover,a.label:focus{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#777}.label-default[href]:hover,.label-default[href]:focus{background-color:#5e5e5e}.label-primary{background-color:#1976d2}.label-primary[href]:hover,.label-primary[href]:focus{background-color:#145ca4}.label-success{background-color:#028302}.label-success[href]:hover,.label-success[href]:focus{background-color:#015101}.label-info,.result .format,.sidebar .format{background-color:#1C5F74}.label-info[href]:hover,.label-info[href]:focus{background-color:#123d4b}.label-warning{background-color:#A56100}.label-warning[href]:hover,.label-warning[href]:focus{background-color:#724300}.label-danger{background-color:#A41915}.label-danger[href]:hover,.label-danger[href]:focus{background-color:#77120f}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:bold;color:#fff;line-height:1;vertical-align:middle;white-space:nowrap;text-align:center;background-color:#777;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-xs .badge,.btn-group-xs>.btn .badge{top:0;padding:1px 5px}a.badge:hover,a.badge:focus{color:#fff;text-decoration:none;cursor:pointer}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#1565c0;background-color:#fff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding-top:30px;padding-bottom:30px;margin-bottom:30px;color:inherit;background-color:#eee}.jumbotron h1,.jumbotron .h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.jumbotron>hr{border-top-color:#d5d5d5}.container .jumbotron,.container-fluid .jumbotron{border-radius:0;padding-left:15px;padding-right:15px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron,.container-fluid .jumbotron{padding-left:60px;padding-right:60px}.jumbotron h1,.jumbotron .h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:border .2s ease-in-out;-o-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail>img,.thumbnail a>img{margin-left:auto;margin-right:auto}a.thumbnail:hover,a.thumbnail:focus,a.thumbnail.active{border-color:#1565c0}.thumbnail .caption{padding:9px;color:#333}.alert,.savedLists{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:bold}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{background-color:#dff0d8;border-color:#d6e9c6;color:#3c763d}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info,.savedLists{background-color:#d9edf7;border-color:#bce8f1;color:#31708f}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{background-color:#fcf8e3;border-color:#faebcc;color:#8a6d3b}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{background-color:#f2dede;border-color:#ebccd1;color:#a94442}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{overflow:hidden;height:20px;margin-bottom:20px;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1)}.progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#1976d2;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress-striped .progress-bar,.progress-bar-striped{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-size:40px 40px}.progress.active .progress-bar,.progress-bar.active{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#028302}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.progress-bar-info{background-color:#1C5F74}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.progress-bar-warning{background-color:#A56100}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.progress-bar-danger{background-color:#A41915}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)}.media{margin-top:15px}.media:first-child{margin-top:0}.media,.media-body{zoom:1;overflow:hidden}.media-body{width:10000px}.media-object{display:block}.media-object.img-thumbnail{max-width:none}.media-right,.media>.pull-right{padding-left:10px}.media-left,.media>.pull-left{padding-right:10px}.media-left,.media-right,.media-body{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{margin-bottom:20px;padding-left:0}.list-group-item,.result.embedded .getFull.expanded,.result.embedded .loading{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-right-radius:0;border-top-left-radius:0}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:0;border-bottom-left-radius:0}a.list-group-item,button.list-group-item{color:#555}a.list-group-item .list-group-item-heading,button.list-group-item .list-group-item-heading{color:#333}a.list-group-item:hover,button.list-group-item:hover,a.list-group-item:focus,button.list-group-item:focus{text-decoration:none;color:#555;background-color:#f5f5f5}button.list-group-item{width:100%;text-align:left}.list-group-item.disabled,.list-group-item.disabled:hover,.list-group-item.disabled:focus{background-color:#eee;color:#777;cursor:not-allowed}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text{color:#777}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{z-index:2;color:#fff;background-color:#1976d2;border-color:#1976d2}.list-group-item.active .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>.small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:hover .list-group-item-text,.list-group-item.active:focus .list-group-item-text{color:#c0dcf7}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success,button.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading,button.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:hover,button.list-group-item-success:hover,a.list-group-item-success:focus,button.list-group-item-success:focus{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,button.list-group-item-success.active,a.list-group-item-success.active:hover,button.list-group-item-success.active:hover,a.list-group-item-success.active:focus,button.list-group-item-success.active:focus{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info,button.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading,button.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:hover,button.list-group-item-info:hover,a.list-group-item-info:focus,button.list-group-item-info:focus{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,button.list-group-item-info.active,a.list-group-item-info.active:hover,button.list-group-item-info.active:hover,a.list-group-item-info.active:focus,button.list-group-item-info.active:focus{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning,button.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading,button.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:hover,button.list-group-item-warning:hover,a.list-group-item-warning:focus,button.list-group-item-warning:focus{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,button.list-group-item-warning.active,a.list-group-item-warning.active:hover,button.list-group-item-warning.active:hover,a.list-group-item-warning.active:focus,button.list-group-item-warning.active:focus{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger,button.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading,button.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:hover,button.list-group-item-danger:hover,a.list-group-item-danger:focus,button.list-group-item-danger:focus{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,button.list-group-item-danger.active,a.list-group-item-danger.active:hover,button.list-group-item-danger.active:hover,a.list-group-item-danger.active:focus,button.list-group-item-danger.active:focus{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,0.05);box-shadow:0 1px 1px rgba(0,0,0,0.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-right-radius:3px;border-top-left-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>a,.panel-title>small,.panel-title>.small,.panel-title>small>a,.panel-title>.small>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-right-radius:3px;border-top-left-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.panel-heading+.panel-collapse>.list-group .list-group-item:first-child{border-top-right-radius:0;border-top-left-radius:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.table,.panel>.table-responsive>.table,.panel>.panel-collapse>.table{margin-bottom:0}.panel>.table caption,.panel>.table-responsive>.table caption,.panel>.panel-collapse>.table caption{padding-left:15px;padding-right:15px}.panel>.table:first-child,.panel>.table-responsive:first-child>.table:first-child{border-top-right-radius:3px;border-top-left-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table:last-child,.panel>.table-responsive:last-child>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-left-radius:3px;border-bottom-right-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child th,.panel>.table>tbody:first-child>tr:first-child td{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{border:0;margin-bottom:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.panel-body,.panel-group .panel-heading+.panel-collapse>.list-group{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#1976d2}.panel-primary>.panel-heading{color:#fff;background-color:#1976d2;border-color:#1976d2}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#1976d2}.panel-primary>.panel-heading .badge{color:#1976d2;background-color:#fff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#1976d2}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#3c763d}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading .badge{color:#d9edf7;background-color:#31708f}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading .badge{color:#f2dede;background-color:#a94442}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive iframe,.embed-responsive embed,.embed-responsive object,.embed-responsive video{position:absolute;top:0;left:0;bottom:0;height:100%;width:100%;border:0}.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);box-shadow:inset 0 1px 1px rgba(0,0,0,0.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,0.15)}.well-lg{padding:24px;border-radius:0}.well-sm{padding:9px;border-radius:3px}.close,.adv-term-remove{float:right;font-size:21px;font-weight:bold;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.close:hover,.close:focus{color:#000;text-decoration:none;cursor:pointer;opacity:.5;filter:alpha(opacity=50)}button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none}.modal-open{overflow:hidden}.modal{display:none;overflow:hidden;position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transform:translate(0, -25%);-ms-transform:translate(0, -25%);-o-transform:translate(0, -25%);transform:translate(0, -25%);-webkit-transition:-webkit-transform 0.3s ease-out;-moz-transition:-moz-transform 0.3s ease-out;-o-transition:-o-transform 0.3s ease-out;transition:transform 0.3s ease-out}.modal.in .modal-dialog{-webkit-transform:translate(0, 0);-ms-transform:translate(0, 0);-o-transform:translate(0, 0);transform:translate(0, 0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,0.2);border-radius:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,0.5);box-shadow:0 3px 9px rgba(0,0,0,0.5);background-clip:padding-box;outline:0}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{opacity:0;filter:alpha(opacity=0)}.modal-backdrop.in{opacity:.5;filter:alpha(opacity=50)}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-left:5px;margin-bottom:0}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,0.5);box-shadow:0 5px 15px rgba(0,0,0,0.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-style:normal;font-weight:normal;letter-spacing:normal;line-break:auto;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;white-space:normal;word-break:normal;word-spacing:normal;word-wrap:normal;font-size:12px;opacity:0;filter:alpha(opacity=0)}.tooltip.in{opacity:.9;filter:alpha(opacity=90)}.tooltip.top{margin-top:-3px;padding:5px 0}.tooltip.right{margin-left:3px;padding:0 5px}.tooltip.bottom{margin-top:3px;padding:5px 0}.tooltip.left{margin-left:-3px;padding:0 5px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{bottom:0;right:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;left:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-style:normal;font-weight:normal;letter-spacing:normal;line-break:auto;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;white-space:normal;word-break:normal;word-spacing:normal;word-wrap:normal;font-size:14px;background-color:#fff;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);border-radius:0;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2)}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{margin:0;padding:8px 14px;font-size:14px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:-1 -1 0 0}.popover-content{padding:9px 14px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow{border-width:11px}.popover>.arrow:after{border-width:10px;content:""}.popover.top>.arrow{left:50%;margin-left:-11px;border-bottom-width:0;border-top-color:#999;border-top-color:rgba(0,0,0,0.25);bottom:-11px}.popover.top>.arrow:after{content:" ";bottom:1px;margin-left:-10px;border-bottom-width:0;border-top-color:#fff}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-left-width:0;border-right-color:#999;border-right-color:rgba(0,0,0,0.25)}.popover.right>.arrow:after{content:" ";left:1px;bottom:-10px;border-left-width:0;border-right-color:#fff}.popover.bottom>.arrow{left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,0.25);top:-11px}.popover.bottom>.arrow:after{content:" ";top:1px;margin-left:-10px;border-top-width:0;border-bottom-color:#fff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,0.25)}.popover.left>.arrow:after{content:" ";right:1px;border-right-width:0;border-left-color:#fff;bottom:-10px}.carousel{position:relative}.carousel-inner{position:relative;overflow:hidden;width:100%}.carousel-inner>.item{display:none;position:relative;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>img,.carousel-inner>.item>a>img{line-height:1}@media all and (transform-3d),(-webkit-transform-3d){.carousel-inner>.item{-webkit-transition:-webkit-transform 0.6s ease-in-out;-moz-transition:-moz-transform 0.6s ease-in-out;-o-transition:-o-transform 0.6s ease-in-out;transition:transform 0.6s ease-in-out;-webkit-backface-visibility:hidden;-moz-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;-moz-perspective:1000px;perspective:1000px}.carousel-inner>.item.next,.carousel-inner>.item.active.right{-webkit-transform:translate3d(100%, 0, 0);transform:translate3d(100%, 0, 0);left:0}.carousel-inner>.item.prev,.carousel-inner>.item.active.left{-webkit-transform:translate3d(-100%, 0, 0);transform:translate3d(-100%, 0, 0);left:0}.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right,.carousel-inner>.item.active{-webkit-transform:translate3d(0, 0, 0);transform:translate3d(0, 0, 0);left:0}}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;left:0;bottom:0;width:15%;opacity:.5;filter:alpha(opacity=50);font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,0.6);background-color:rgba(0,0,0,0)}.carousel-control.left{background-image:-webkit-linear-gradient(left, rgba(0,0,0,0.5) 0, rgba(0,0,0,0.0001) 100%);background-image:-o-linear-gradient(left, rgba(0,0,0,0.5) 0, rgba(0,0,0,0.0001) 100%);background-image:linear-gradient(to right, rgba(0,0,0,0.5) 0, rgba(0,0,0,0.0001) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1)}.carousel-control.right{left:auto;right:0;background-image:-webkit-linear-gradient(left, rgba(0,0,0,0.0001) 0, rgba(0,0,0,0.5) 100%);background-image:-o-linear-gradient(left, rgba(0,0,0,0.0001) 0, rgba(0,0,0,0.5) 100%);background-image:linear-gradient(to right, rgba(0,0,0,0.0001) 0, rgba(0,0,0,0.5) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1)}.carousel-control:hover,.carousel-control:focus{outline:0;color:#fff;text-decoration:none;opacity:.9;filter:alpha(opacity=90)}.carousel-control .icon-prev,.carousel-control .icon-next,.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right{position:absolute;top:50%;margin-top:-10px;z-index:5;display:inline-block}.carousel-control .icon-prev,.carousel-control .glyphicon-chevron-left{left:50%;margin-left:-10px}.carousel-control .icon-next,.carousel-control .glyphicon-chevron-right{right:50%;margin-right:-10px}.carousel-control .icon-prev,.carousel-control .icon-next{width:20px;height:20px;line-height:1;font-family:serif}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;margin-left:-30%;padding-left:0;list-style:none;text-align:center}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;border:1px solid #fff;border-radius:10px;cursor:pointer;background-color:#000 \9;background-color:rgba(0,0,0,0)}.carousel-indicators .active{margin:0;width:12px;height:12px;background-color:#fff}.carousel-caption{position:absolute;left:15%;right:15%;bottom:20px;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,0.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-prev,.carousel-control .icon-next{width:30px;height:30px;margin-top:-10px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-10px}.carousel-caption{left:20%;right:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.clearfix:before,.clearfix:after,.dl-horizontal dd:before,.dl-horizontal dd:after,.container:before,.container:after,.container-fluid:before,.container-fluid:after,.row:before,.row:after,.form-horizontal .form-group:before,.form-horizontal .form-group:after,.btn-toolbar:before,.btn-toolbar:after,.btn-group-vertical>.btn-group:before,.btn-group-vertical>.btn-group:after,.nav:before,.nav:after,.navbar:before,.navbar:after,.navbar-header:before,.navbar-header:after,.navbar-collapse:before,.navbar-collapse:after,.pager:before,.pager:after,.panel-body:before,.panel-body:after,.modal-header:before,.modal-header:after,.modal-footer:before,.modal-footer:after,footer:before,footer:after{content:" ";display:table}.clearfix:after,.dl-horizontal dd:after,.container:after,.container-fluid:after,.row:after,.form-horizontal .form-group:after,.btn-toolbar:after,.btn-group-vertical>.btn-group:after,.nav:after,.navbar:after,.navbar-header:after,.navbar-collapse:after,.pager:after,.panel-body:after,.modal-header:after,.modal-footer:after,footer:after{clear:both}.center-block{display:block;margin-left:auto;margin-right:auto}.pull-right{float:right !important}.pull-left{float:left !important}.hide{display:none !important}.show{display:block !important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none !important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-xs,.visible-sm,.visible-md,.visible-lg{display:none !important}.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block{display:none !important}@media (max-width:767px){.visible-xs{display:block !important}table.visible-xs{display:table !important}tr.visible-xs{display:table-row !important}th.visible-xs,td.visible-xs{display:table-cell !important}}@media (max-width:767px){.visible-xs-block{display:block !important}}@media (max-width:767px){.visible-xs-inline{display:inline !important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block !important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block !important}table.visible-sm{display:table !important}tr.visible-sm{display:table-row !important}th.visible-sm,td.visible-sm{display:table-cell !important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block !important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline !important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block !important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block !important}table.visible-md{display:table !important}tr.visible-md{display:table-row !important}th.visible-md,td.visible-md{display:table-cell !important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block !important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline !important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block !important}}@media (min-width:1200px){.visible-lg{display:block !important}table.visible-lg{display:table !important}tr.visible-lg{display:table-row !important}th.visible-lg,td.visible-lg{display:table-cell !important}}@media (min-width:1200px){.visible-lg-block{display:block !important}}@media (min-width:1200px){.visible-lg-inline{display:inline !important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block !important}}@media (max-width:767px){.hidden-xs{display:none !important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none !important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none !important}}@media (min-width:1200px){.hidden-lg{display:none !important}}.visible-print{display:none !important}@media print{.visible-print{display:block !important}table.visible-print{display:table !important}tr.visible-print{display:table-row !important}th.visible-print,td.visible-print{display:table-cell !important}}.visible-print-block{display:none !important}@media print{.visible-print-block{display:block !important}}.visible-print-inline{display:none !important}@media print{.visible-print-inline{display:inline !important}}.visible-print-inline-block{display:none !important}@media print{.visible-print-inline-block{display:inline-block !important}}@media print{.hidden-print{display:none !important}}/*!
+ *  Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome
+ *  License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)
+ */@font-face{font-family:'FontAwesome';src:url('../../bootstrap3/css/fonts/fontawesome-webfont.eot?v=4.7.0');src:url('../../bootstrap3/css/fonts/fontawesome-webfont.eot?#iefix&v=4.7.0') format('embedded-opentype'),url('../../bootstrap3/css/fonts/fontawesome-webfont.woff2?v=4.7.0') format('woff2'),url('../../bootstrap3/css/fonts/fontawesome-webfont.woff?v=4.7.0') format('woff'),url('../../bootstrap3/css/fonts/fontawesome-webfont.ttf?v=4.7.0') format('truetype'),url('../../bootstrap3/css/fonts/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-remove:before,.fa-close:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook-f:before,.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-feed:before,.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before,.fa-gratipay:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-resistance:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-y-combinator-square:before,.fa-yc-square:before,.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"}.fa-buysellads:before{content:"\f20d"}.fa-connectdevelop:before{content:"\f20e"}.fa-dashcube:before{content:"\f210"}.fa-forumbee:before{content:"\f211"}.fa-leanpub:before{content:"\f212"}.fa-sellsy:before{content:"\f213"}.fa-shirtsinbulk:before{content:"\f214"}.fa-simplybuilt:before{content:"\f215"}.fa-skyatlas:before{content:"\f216"}.fa-cart-plus:before{content:"\f217"}.fa-cart-arrow-down:before{content:"\f218"}.fa-diamond:before{content:"\f219"}.fa-ship:before{content:"\f21a"}.fa-user-secret:before{content:"\f21b"}.fa-motorcycle:before{content:"\f21c"}.fa-street-view:before{content:"\f21d"}.fa-heartbeat:before{content:"\f21e"}.fa-venus:before{content:"\f221"}.fa-mars:before{content:"\f222"}.fa-mercury:before{content:"\f223"}.fa-intersex:before,.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-venus-double:before{content:"\f226"}.fa-mars-double:before{content:"\f227"}.fa-venus-mars:before{content:"\f228"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-neuter:before{content:"\f22c"}.fa-genderless:before{content:"\f22d"}.fa-facebook-official:before{content:"\f230"}.fa-pinterest-p:before{content:"\f231"}.fa-whatsapp:before{content:"\f232"}.fa-server:before{content:"\f233"}.fa-user-plus:before{content:"\f234"}.fa-user-times:before{content:"\f235"}.fa-hotel:before,.fa-bed:before{content:"\f236"}.fa-viacoin:before{content:"\f237"}.fa-train:before{content:"\f238"}.fa-subway:before{content:"\f239"}.fa-medium:before{content:"\f23a"}.fa-yc:before,.fa-y-combinator:before{content:"\f23b"}.fa-optin-monster:before{content:"\f23c"}.fa-opencart:before{content:"\f23d"}.fa-expeditedssl:before{content:"\f23e"}.fa-battery-4:before,.fa-battery:before,.fa-battery-full:before{content:"\f240"}.fa-battery-3:before,.fa-battery-three-quarters:before{content:"\f241"}.fa-battery-2:before,.fa-battery-half:before{content:"\f242"}.fa-battery-1:before,.fa-battery-quarter:before{content:"\f243"}.fa-battery-0:before,.fa-battery-empty:before{content:"\f244"}.fa-mouse-pointer:before{content:"\f245"}.fa-i-cursor:before{content:"\f246"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-sticky-note:before{content:"\f249"}.fa-sticky-note-o:before{content:"\f24a"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-diners-club:before{content:"\f24c"}.fa-clone:before{content:"\f24d"}.fa-balance-scale:before{content:"\f24e"}.fa-hourglass-o:before{content:"\f250"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\f251"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\f253"}.fa-hourglass:before{content:"\f254"}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:"\f255"}.fa-hand-stop-o:before,.fa-hand-paper-o:before{content:"\f256"}.fa-hand-scissors-o:before{content:"\f257"}.fa-hand-lizard-o:before{content:"\f258"}.fa-hand-spock-o:before{content:"\f259"}.fa-hand-pointer-o:before{content:"\f25a"}.fa-hand-peace-o:before{content:"\f25b"}.fa-trademark:before{content:"\f25c"}.fa-registered:before{content:"\f25d"}.fa-creative-commons:before{content:"\f25e"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-tripadvisor:before{content:"\f262"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-get-pocket:before{content:"\f265"}.fa-wikipedia-w:before{content:"\f266"}.fa-safari:before{content:"\f267"}.fa-chrome:before{content:"\f268"}.fa-firefox:before{content:"\f269"}.fa-opera:before{content:"\f26a"}.fa-internet-explorer:before{content:"\f26b"}.fa-tv:before,.fa-television:before{content:"\f26c"}.fa-contao:before{content:"\f26d"}.fa-500px:before{content:"\f26e"}.fa-amazon:before{content:"\f270"}.fa-calendar-plus-o:before{content:"\f271"}.fa-calendar-minus-o:before{content:"\f272"}.fa-calendar-times-o:before{content:"\f273"}.fa-calendar-check-o:before{content:"\f274"}.fa-industry:before{content:"\f275"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-map-o:before{content:"\f278"}.fa-map:before{content:"\f279"}.fa-commenting:before{content:"\f27a"}.fa-commenting-o:before{content:"\f27b"}.fa-houzz:before{content:"\f27c"}.fa-vimeo:before{content:"\f27d"}.fa-black-tie:before{content:"\f27e"}.fa-fonticons:before{content:"\f280"}.fa-reddit-alien:before{content:"\f281"}.fa-edge:before{content:"\f282"}.fa-credit-card-alt:before{content:"\f283"}.fa-codiepie:before{content:"\f284"}.fa-modx:before{content:"\f285"}.fa-fort-awesome:before{content:"\f286"}.fa-usb:before{content:"\f287"}.fa-product-hunt:before{content:"\f288"}.fa-mixcloud:before{content:"\f289"}.fa-scribd:before{content:"\f28a"}.fa-pause-circle:before{content:"\f28b"}.fa-pause-circle-o:before{content:"\f28c"}.fa-stop-circle:before{content:"\f28d"}.fa-stop-circle-o:before{content:"\f28e"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-hashtag:before{content:"\f292"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-percent:before{content:"\f295"}.fa-gitlab:before{content:"\f296"}.fa-wpbeginner:before{content:"\f297"}.fa-wpforms:before{content:"\f298"}.fa-envira:before{content:"\f299"}.fa-universal-access:before{content:"\f29a"}.fa-wheelchair-alt:before{content:"\f29b"}.fa-question-circle-o:before{content:"\f29c"}.fa-blind:before{content:"\f29d"}.fa-audio-description:before{content:"\f29e"}.fa-volume-control-phone:before{content:"\f2a0"}.fa-braille:before{content:"\f2a1"}.fa-assistive-listening-systems:before{content:"\f2a2"}.fa-asl-interpreting:before,.fa-american-sign-language-interpreting:before{content:"\f2a3"}.fa-deafness:before,.fa-hard-of-hearing:before,.fa-deaf:before{content:"\f2a4"}.fa-glide:before{content:"\f2a5"}.fa-glide-g:before{content:"\f2a6"}.fa-signing:before,.fa-sign-language:before{content:"\f2a7"}.fa-low-vision:before{content:"\f2a8"}.fa-viadeo:before{content:"\f2a9"}.fa-viadeo-square:before{content:"\f2aa"}.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-ghost:before{content:"\f2ac"}.fa-snapchat-square:before{content:"\f2ad"}.fa-pied-piper:before{content:"\f2ae"}.fa-first-order:before{content:"\f2b0"}.fa-yoast:before{content:"\f2b1"}.fa-themeisle:before{content:"\f2b2"}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:"\f2b3"}.fa-fa:before,.fa-font-awesome:before{content:"\f2b4"}.fa-handshake-o:before{content:"\f2b5"}.fa-envelope-open:before{content:"\f2b6"}.fa-envelope-open-o:before{content:"\f2b7"}.fa-linode:before{content:"\f2b8"}.fa-address-book:before{content:"\f2b9"}.fa-address-book-o:before{content:"\f2ba"}.fa-vcard:before,.fa-address-card:before{content:"\f2bb"}.fa-vcard-o:before,.fa-address-card-o:before{content:"\f2bc"}.fa-user-circle:before{content:"\f2bd"}.fa-user-circle-o:before{content:"\f2be"}.fa-user-o:before{content:"\f2c0"}.fa-id-badge:before{content:"\f2c1"}.fa-drivers-license:before,.fa-id-card:before{content:"\f2c2"}.fa-drivers-license-o:before,.fa-id-card-o:before{content:"\f2c3"}.fa-quora:before{content:"\f2c4"}.fa-free-code-camp:before{content:"\f2c5"}.fa-telegram:before{content:"\f2c6"}.fa-thermometer-4:before,.fa-thermometer:before,.fa-thermometer-full:before{content:"\f2c7"}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:"\f2c8"}.fa-thermometer-2:before,.fa-thermometer-half:before{content:"\f2c9"}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:"\f2ca"}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:"\f2cb"}.fa-shower:before{content:"\f2cc"}.fa-bathtub:before,.fa-s15:before,.fa-bath:before{content:"\f2cd"}.fa-podcast:before{content:"\f2ce"}.fa-window-maximize:before{content:"\f2d0"}.fa-window-minimize:before{content:"\f2d1"}.fa-window-restore:before{content:"\f2d2"}.fa-times-rectangle:before,.fa-window-close:before{content:"\f2d3"}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:"\f2d4"}.fa-bandcamp:before{content:"\f2d5"}.fa-grav:before{content:"\f2d6"}.fa-etsy:before{content:"\f2d7"}.fa-imdb:before{content:"\f2d8"}.fa-ravelry:before{content:"\f2d9"}.fa-eercast:before{content:"\f2da"}.fa-microchip:before{content:"\f2db"}.fa-snowflake-o:before{content:"\f2dc"}.fa-superpowers:before{content:"\f2dd"}.fa-wpexplorer:before{content:"\f2de"}.fa-meetup:before{content:"\f2e0"}.sr-only{width:1px;height:1px;margin:-1px;clip:rect(0, 0, 0, 0);clip:rect(1px, 1px, 1px, 1px);position:absolute;width:auto;height:auto;margin:0;padding:0;overflow:hidden;border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}.btn:focus{outline:dotted 2px #000}div.active:focus{outline:dotted 1px #000}a:focus{outline:dotted 1px #000}.close:hover,.close:focus{outline:dotted 1px #000}.nav>li>a:hover,.nav>li>a:focus{outline:dotted 1px #000}.carousel-indicators li,.carousel-indicators li.active{height:18px;width:18px;border-width:2px;position:relative;box-shadow:0 0 0 1px #808080}.carousel-indicators.active li{background-color:rgba(100,149,253,0.6)}.carousel-indicators.active li.active{background-color:white}.carousel-tablist-highlight{display:block;position:absolute;outline:2px solid transparent;background-color:transparent;box-shadow:0 0 0 1px transparent}.carousel-tablist-highlight.focus{outline:2px solid #6495ED;background-color:rgba(0,0,0,0.4)}a.carousel-control:focus{outline:2px solid #6495ED;background-image:linear-gradient(to right, transparent 0, rgba(0,0,0,0.5) 100%);box-shadow:0 0 0 1px #000000}.carousel-pause-button{position:absolute;top:-30em;left:-300em;display:block}.carousel-pause-button.focus{top:.5em;left:.5em}.carousel:hover .carousel-caption,.carousel.contrast .carousel-caption{background-color:rgba(0,0,0,0.5);z-index:10}.alert-success{color:#2d4821}.alert-info,.savedLists{color:#214c62}.alert-warning{color:#6c4a00;background-color:#ffd700}.alert-danger{color:#ff4136}.alert-danger:hover{color:#ff1103}input::-webkit-input-placeholder,textarea::-webkit-input-placeholder,input:-ms-input-placeholder,textarea:-ms-input-placeholder,input::-ms-input-placeholder,textarea::-ms-input-placeholder,input::placeholder,textarea::placeholder{color:#888}.sr-only{clip:rect(1px, 1px, 1px, 1px);position:absolute;width:auto;height:auto;margin:0;padding:0;overflow:hidden;border:0}.sr-only:focus{background-color:#fff;border-radius:4px;clip:auto;color:#132531;display:block;font-size:14px;height:50px;line-height:20px;padding:15px 15px;position:absolute;left:5px;top:5px;text-decoration:none;text-transform:none;width:auto;z-index:100000}.navbar-brand{font-size:20px}.adv-group{position:relative;margin-bottom:.5rem;padding:1rem;border:1px solid #ddd;border-radius:4px}.adv-group:before,.adv-group:after{content:" ";display:table}.adv-group:after{clear:both}.adv-group:before,.adv-group:after{content:" ";display:table}.adv-group:after{clear:both}.adv-group~.adv-group{margin-top:1rem}.adv-group .add_search_link{display:inline-block;margin-top:4px}.add_search_link,.adv-group-close{display:inline-block;padding-top:.25rem;padding-bottom:.25rem}.adv-group-close{color:#a94442}.adv-search,.adv-search .input-group{width:100%}.adv-search{margin-bottom:1.5rem}.adv-search:before,.adv-search:after{content:" ";display:table}.adv-search:after{clear:both}.adv-search:before,.adv-search:after{content:" ";display:table}.adv-search:after{clear:both}.adv-term-input{margin-bottom:.5rem}.adv-term-type{float:left;max-width:80%}.adv-term-remove{float:left;width:20%;height:30px;line-height:1.7;text-align:center;opacity:.4}.adv-submit:before,.adv-submit:after{content:" ";display:table}.adv-submit:after{clear:both}.adv-submit:before,.adv-submit:after{content:" ";display:table}.adv-submit:after{clear:both}.adv-submit .clear-btn{float:right}@media (min-width:768px){.adv-group-terms{float:left;width:75%;padding-right:1rem}.adv-group-match{float:right;width:25%}.adv-group-close{position:absolute;right:1rem;bottom:1rem;min-width:calc(24%)}.adv-search{margin-bottom:0}.adv-search .adv-term-input,.adv-search .adv-term-type{float:left}.adv-search .adv-term-input{width:60%;margin-right:2%}.adv-search .adv-term-type{max-width:30%}.adv-search .adv-term-remove{width:8%}}#groupPlaceHolder{display:block;padding:1rem}@media (min-width:768px){fieldset,.fieldset{float:left;width:33%;padding-right:1rem;padding-bottom:1rem}.solr-facets,.summon-facets{float:none;width:auto;margin-top:1rem}.summon-facets .facet-fieldset{float:left;width:50%;padding-right:1rem}}.adv-term-input,.adv-term-op{margin-bottom:.25rem}.adv-search:first-of-type .adv-term-op{display:none}@media (min-width:768px){.eds-adv .adv-term-op{float:left;width:16%;margin-right:1%}body.rtl .eds-adv .adv-term-op{float:right;margin-left:0;margin-right:1%}.eds-adv .adv-search:first-of-type .adv-term-input{margin-left:17%}.eds-adv .adv-term-input{width:39%;margin-right:0}.eds-adv .help-block{float:left;width:6%;text-align:center}}.primo-adv-search .search{margin-bottom:.5rem}.primo-adv-search .search-container{width:100%}.primo-adv-label{line-height:34px;padding-right:1rem}@media (min-width:768px){.primo.adv-group,.primo-adv-search .search{display:flex}.primo.adv-group select,.primo-adv-search .search select{flex-shrink:2;margin-right:.5rem}.primo.adv-group .primo-adv-input,.primo-adv-search .search .primo-adv-input{flex-grow:1}.primo-adv-label{flex-shrink:0}}@media (min-width:768px){.solr-facet-container{display:flex;flex-wrap:wrap}.solr-adv-facet{flex:1 25%}}body.rtl fieldset,body.rtl .fieldset,body.rtl .adv-search .adv-term-input,body.rtl .adv-search .adv-term-type,body.rtl .eds-adv .help-block,body.rtl .summon-facets .facet-fieldset{float:right}body.rtl .adv-submit .clear-btn,body.rtl .adv-group-match{float:left}body.rtl .adv-search .adv-term-input{margin-left:2%;margin-right:0}body.rtl .date-from{padding-left:.25rem;padding-right:0}body.rtl .date-to{padding-left:0;padding-right:.25rem}.alphabrowse{border-collapse:separate}.alphabrowse .lcc{width:20%}.alphabrowse .titles{width:10%;text-align:center}.alphabrowse tr.browse-match td{border-top:.2rem solid #1976d2;border-bottom:.2rem solid #1976d2}.alphabrowse tr.browse-match td:first-child{border-left:.2em solid #1976d2}.alphabrowse tr.browse-match td:last-child{border-right:.2em solid #1976d2}.autocomplete-results{position:absolute;display:table;max-width:500px;margin:0;margin-top:2px;padding:0;border:1px solid lightgray;background-color:#fff;overflow:hidden;z-index:50}.autocomplete-results .ac-item{display:block;margin:0;padding:.5rem;border-bottom:1px solid lightgray;cursor:pointer}.autocomplete-results .ac-item:last-child{border:0}.autocomplete-results .ac-item:hover{background-color:#cfd8dc}.autocomplete-results .ac-item.loading{background-color:#fff}.autocomplete-results .ac-item.selected{background-color:#1976d2;color:#fff}.autocomplete-results .ac-item small{display:block;color:darkgray}.autocomplete-results .ac-section-header{float:right;display:block;margin-top:-1.75rem;padding:0 .5rem;color:lightgray;background-color:#fff}.autocomplete-results .ac-section-divider{margin:1rem .5rem;border:0;border-top:2px solid lightgray}.channel{position:relative;width:100%;height:300px;border:1px solid #ccc;border-radius:4px}.channel .slider-menu{border-top-color:#ccc;border-radius:0 0 4px 4px}.channel .slider-menu .channel-links .btn{margin-left:4px}.channel .channel-record.slide{display:inline-block;min-width:100px;max-height:240px;padding:0 .5rem;text-align:center;text-overflow:ellipsis;overflow:hidden}.channel .channel-record .thumb{height:200px;background-position:center center;background-repeat:no-repeat;background-size:contain}.channel .popover{width:500px;max-width:none}.channel-title a:hover{text-decoration:none}.channel-title i.fa-fw{width:1.4em;padding-top:.5em;font-size:.6em;text-align:center;vertical-align:top}.channel-title .placeholder{width:25px}.fa-printer:before{content:"\f02f"}.fa-grid:before{content:"\f00a"}.fa-visual:before{content:"\f008"}.fa-x:before{content:"\f0f6"}.fa-atlas:before{content:"\f14e"}.fa-book:before{content:"\f02d"}.fa-braille:before{content:"\f0a6"}.fa-cdrom:before{content:"\f109"}.fa-chart:before{content:"\f012"}.fa-chipcartridge:before{content:"\f109"}.fa-collage:before{content:"\f03e"}.fa-disccartridge:before{content:"\f109"}.fa-drawing:before{content:"\f03e"}.fa-ebook:before{content:"\f0f6"}.fa-electronic:before{content:"\f1c6"}.fa-filmstrip:before{content:"\f008"}.fa-flashcard:before{content:"\f0e7"}.fa-floppydisk:before{content:"\f0c7"}.fa-globe:before{content:"\f0ac"}.fa-journal:before{content:"\f0f6"}.fa-kit:before{content:"\f0b1"}.fa-manuscript:before{content:"\f0f6"}.fa-map:before{content:"\f14e"}.fa-microfilm:before{content:"\f008"}.fa-motionpicture:before{content:"\f03d"}.fa-musicalscore:before{content:"\f001"}.fa-musicrecording:before{content:"\f001"}.fa-newspaper:before{content:"\f0f6"}.fa-online:before{content:"\f109"}.fa-painting:before{content:"\f03e"}.fa-photo:before{content:"\f03e"}.fa-photonegative:before{content:"\f03e"}.fa-physicalobject:before{content:"\f187"}.fa-print:before{content:"\f03e"}.fa-sensorimage:before{content:"\f03e"}.fa-serial:before{content:"\f0f6"}.fa-slide:before{content:"\f008"}.fa-software:before{content:"\f109"}.fa-soundcassette:before{content:"\f025"}.fa-sounddisc:before{content:"\f109"}.fa-soundrecording:before{content:"\f025"}.fa-tapecartridge:before{content:"\f109"}.fa-tapecassette:before{content:"\f025"}.fa-tapereel:before{content:"\f008"}.fa-transparency:before{content:"\f008"}.fa-unknown:before{content:"\f128"}.fa-video:before{content:"\f03d"}.fa-videocartridge:before{content:"\f03d"}.fa-videocassette:before{content:"\f03d"}.fa-videodisc:before{content:"\f109"}.fa-videoreel:before{content:"\f03d"}.hierarchy-tree .jstree-ocl:before,.jstree-facet .jstree-ocl:before{float:left;width:10px;padding:0;margin-left:-10px;font-family:'FontAwesome';font-style:normal;font-weight:normal;cursor:pointer;text-decoration:inherit;speak:none}.hierarchy-tree .jstree-open>.jstree-ocl:before,.jstree-facet .jstree-open>.jstree-ocl:before{content:"\f0d7"}.hierarchy-tree .jstree-closed>.jstree-ocl:before,.jstree-facet .jstree-closed>.jstree-ocl:before{content:"\f0da"}.hierarchy-tree .jstree-leaf>.jstree-ocl:before,.jstree-facet .jstree-leaf>.jstree-ocl:before{content:" "}.hierarchy-tree .jstree-icon,.jstree-facet .jstree-icon{width:16px;color:#000}.hierarchy-tree .jstree-anchor,.jstree-facet .jstree-anchor{padding-left:5px;white-space:nowrap}.hierarchy-tree .jstree-container-ul,.jstree-facet .jstree-container-ul,.hierarchy-tree .jstree-children,.jstree-facet .jstree-children{padding-left:16px}.hierarchy-tree .jstree-initial-node,.jstree-facet .jstree-initial-node{display:none}.hierarchy-tree .jstree-clicked,.jstree-facet .jstree-clicked{color:#fff;background-color:#1976d2}.hierarchy-tree .jstree-clicked .jstree-icon,.jstree-facet .jstree-clicked .jstree-icon{color:#fff}.hierarchy-tree .jstree-search a,.jstree-facet .jstree-search a{font-style:italic;color:#8b0000;font-weight:bold}.jstree-node.list-group-item{margin-bottom:0;border:0;border-bottom:1px solid #ddd;border-radius:0}#hierarchyTreeHolder{overflow-x:hidden;border-right:1px solid #eee}#hierarchyTree .currentHierarchy>a,#hierarchyTree .currentRecord a{font-weight:bold;color:#000}.facet .jstree-ocl:before{float:left;width:10px;padding:0;margin-left:-10px;font-family:'FontAwesome';font-weight:normal;font-style:normal;text-decoration:inherit;cursor:pointer;speak:none}.facet .jstree-default .jstree-open>.jstree-ocl:before{content:"\f0d7"}.facet .jstree-default .jstree-closed>.jstree-ocl:before{content:"\f0da"}.facet .jstree-default .jstree-leaf>.jstree-ocl:before{content:" "}.jstree-facet li span.main{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.jstree-facet .main.applied .fa-check{margin-top:2px;margin-right:4px}.jstree-facet .jstree-container-ul{padding:0}.jstree-facet .jstree-container-ul>li.active,.jstree-facet .jstree-container-ul>li.active a.jstree-anchor{background-color:#265680;color:#fff}li.jstree-facet,li.jstree-node{list-style:none}li.jstree-facet .badge{cursor:text}li.jstree-facet ul{padding-left:20px}.facet .jstree-node.list-group-item{padding-left:19px}.facet .jstree-icon::before{margin-left:-12px}.facet .jstree-facet li span.main{padding:1px}#modal{background-color:rgba(0,0,0,0.2)}#modal .modal-content>.close{position:absolute;right:-50px;top:0;z-index:2;font-size:32pt;color:#fff;opacity:.7}body.rtl #modal .modal-content>.close{left:-50px;right:auto}#modal .modal-content>.close:hover{opacity:1}#modal .modal-body h1,#modal .modal-body h2{margin-top:.3rem;margin-bottom:1.3rem}#modal .cart-controls .btn{margin-bottom:4px}#modal .cart-controls .checkbox{padding-bottom:1rem}#modal .cart-controls~hr{margin-top:0}.lightbox-scroll{overflow-y:auto}.modal-loading{float:right}body.rtl .modal-loading{float:left}.lightbox-only{display:none}#modal .lightbox-only{display:initial}.offcanvas-overlay,.offcanvas-toggle{display:none}@media screen and (max-width:767px){body.offcanvas{overflow-x:hidden}body.offcanvas .sidebar{position:fixed;height:100%;top:0;width:75vw;padding-left:0;padding-right:0;overflow-y:auto}body.offcanvas .sidebar h4{padding-left:12px}body.offcanvas .sidebar .checkbox{margin-left:32px}body.offcanvas .sidebar .list-group,body.offcanvas .sidebar .list-group-item{border-left:0;border-right:0;border-radius:0 !important}body.offcanvas.active{overflow-y:hidden}body.offcanvas.offcanvas-left{padding-left:15px}body.offcanvas.offcanvas-left .main{background:#FFF}body.offcanvas.offcanvas-left.active{margin-left:75vw;margin-right:-75vw}body.offcanvas.offcanvas-left.active .sidebar{left:0}body.offcanvas.offcanvas-left.active .offcanvas-overlay{right:-75vw}body.offcanvas.offcanvas-left.active .offcanvas-toggle{left:75vw}body.offcanvas.offcanvas-left .sidebar{left:-75vw}body.offcanvas.offcanvas-left .offcanvas-overlay{right:-100%}body.offcanvas.offcanvas-left .offcanvas-toggle{left:0}body.offcanvas.offcanvas-right{padding-right:15px}body.offcanvas.offcanvas-right .main>.container{background:#FFF}body.offcanvas.offcanvas-right.active{margin-left:-75vw;margin-right:75vw}body.offcanvas.offcanvas-right.active .sidebar{right:0}body.offcanvas.offcanvas-right.active .offcanvas-overlay{left:-75vw}body.offcanvas.offcanvas-right.active .offcanvas-toggle{right:75vw}body.offcanvas.offcanvas-right .sidebar{right:-75vw}body.offcanvas.offcanvas-right .offcanvas-overlay{left:-100%}body.offcanvas.offcanvas-right .offcanvas-toggle{right:0}body.offcanvas .offcanvas-overlay{display:block;position:fixed;top:0;width:100%;height:100%;background-color:rgba(0,0,0,0.3);z-index:3}body.offcanvas .offcanvas-toggle{display:block;position:fixed;top:0;width:calc(25px);height:100%;border-left:1px solid #eee;border-right:1px solid #eee;line-height:90vh;text-align:center;background-color:#fff;z-index:5}body.offcanvas .offcanvas-overlay,body.offcanvas .offcanvas-toggle,body.offcanvas .offcanvas-toggle *{cursor:pointer}body.offcanvas,body.offcanvas .sidebar,body.offcanvas .offcanvas-overlay,body.offcanvas .offcanvas-toggle{-webkit-transition:all .25s ease-out;-o-transition:all .25s ease-out;transition:all .25s ease-out}}.record .media-body h3{margin-top:0}.recordcover{max-height:300px}@media (max-width:767px){.record .media-left,.record .media-right{display:block}.record .media-body{display:block;width:auto;margin-top:1rem}}.result .record .format::after,.record .format:last-child::after{content:""}.record .format::after{content:", "}.record-previews{margin-top:.5rem}.record-nav.nav{margin-bottom:1rem}.record-nav>li,.btn-bookbag-toggle{width:100%}.record-nav>li>a{padding:.5rem}.record-nav>li>a,.btn-bookbag-toggle{text-align:center}@media (min-width:768px){.record-nav>li,.btn-bookbag-toggle{width:auto}.record-nav>li>a{padding:10px 15px}.record-nav>li>a,.btn-bookbag-toggle{text-align:left}}.comment-label,.comment-name{font-style:italic}.comment{margin-bottom:1rem}.comment-name .delete{color:#a94442}@media (min-width:768px){.comment-form,.comment{display:flex;margin-bottom:0}.comment-label,.comment-name{min-width:25%;font-style:unset}.comment-form .text-form{width:100%}.comment-form>label{flex:0 0 auto}.comment-form textarea{display:block;width:100%}}.tagList button{margin-top:0;padding-top:0;padding-bottom:4px;font-size:95%;vertical-align:initial}.tagList .tag .badge{margin:0;padding:3px 7px;font-weight:normal}.tagList button .fa-close{margin-top:3px}.tagList .tag{display:inline-block;margin:0 1px 1px;padding:6px 6px;font-size:14px;line-height:1.42857143;border-radius:4px}.tagList .tag.selected{background-color:#1976d2}.tagList .tag.selected a{color:#fff}.tagList .tag.selected .badge{color:#222;background-color:#fff}.tagList .tag.selected .badge:hover{color:#a94442}.tagList .tag .badge .fa{width:12px}.tagList button{border:0}.tagList .tag-form{display:inline}.tagList.loggedin .tag:not(.selected) .badge:hover{background-color:#028302}.citation .pace-car th,.citation .pace-car td{border:0;padding:0}.citation th{text-align:right}.item-notes ul{padding-left:2rem}.subject-line:hover{color:#999}.subject-line:hover a{color:#0d417b}.subject-line a:hover~a{color:#999;text-decoration:none}.marc-row-LEADER,.marc-row-006,.marc-row-007,.marc-row-008{white-space:pre-wrap}@media (max-width:767px){.bulkActionButtons,#datevispublishDatexWrapper,.result .checkbox{display:none}}.searchHomeContent:before,.searchHomeContent:after{content:" ";display:table}.searchHomeContent:after{clear:both}.searchHomeContent:before,.searchHomeContent:after{content:" ";display:table}.searchHomeContent:after{clear:both}.home-facet-list{padding-left:0;padding-right:1rem;list-style:none}@media (min-width:768px){.search-home-facets,.home-facet-container{display:flex}.home-facet{flex:1 1 100%;flex-basis:auto}.home-facet-list{flex:0 1 100%}}.searchForm{margin:0;padding:0}header .container.navbar{margin-bottom:0}.search-sort{display:flex}.search-sort label{line-height:34px;padding-right:.5rem}.search-stats{display:block;padding-top:1rem;padding-bottom:1rem}@media (min-width:768px){.search-header{display:flex}.search-stats{flex-grow:1}.search-controls{text-align:right}}.bulk-checkbox,.bulkActionButtons label{display:inline-block}.bulkActionButtons label input{margin-top:2px}.bulkActionButtons:before,.bulkActionButtons:after{content:" ";display:table}.bulkActionButtons:after{clear:both}.bulkActionButtons:before,.bulkActionButtons:after{content:" ";display:table}.bulkActionButtons:after{clear:both}@media (max-width:767px){.grid{min-height:250px}}.result{display:flex;padding-top:1rem}.result .record-checkbox,.result .record-number{display:none}.result .title{font-weight:bold}.result .list-tab-content.record .img-col{display:none}.result .list-tab-content.record .info-col{width:100%}.result .checkbox-select-item{float:left}@media (max-width:767px){.result a{max-width:100%;text-decoration:underline}}@media (min-width:768px){.result .record-checkbox{display:block;flex:0;cursor:pointer}.result .record-number{display:block;flex:0 2rem;text-align:center}}.record .media,.result .media{flex:1;margin:0}.record .media-left,.result .media-left,.record .media-right,.result .media-right{text-align:center}.record .media-left img,.result .media-left img,.record .media-right img,.result .media-right img{max-width:100%;max-height:300px}.record .media-left.small img,.result .media-left.small img,.record .media-right.small img,.result .media-right.small img,.record .media-left.medium img,.result .media-left.medium img,.record .media-right.medium img,.result .media-right.medium img,.record .media-left.large img,.result .media-left.large img,.record .media-right.large img,.result .media-right.large img{display:inline-block;width:60px;max-width:none}@media (min-width:768px){.record .media-left,.result .media-left,.record .media-right,.result .media-right{max-width:25%;padding-right:10px;padding-left:10px}.record .media-left a,.result .media-left a,.record .media-right a,.result .media-right a{display:inline-block;max-width:100%;text-align:center;white-space:nowrap;text-decoration:underline}.record .media-left.small img,.result .media-left.small img,.record .media-right.small img,.result .media-right.small img,.record .media-left.medium img,.result .media-left.medium img,.record .media-right.medium img,.result .media-right.medium img,.record .media-left.large img,.result .media-left.large img,.record .media-right.large img,.result .media-right.large img{width:auto;max-width:100%}.record .media-left.small>a,.result .media-left.small>a,.record .media-right.small>a,.result .media-right.small>a,.record .media-left.small>img,.result .media-left.small>img,.record .media-right.small>img,.result .media-right.small>img{width:60px}.record .media-left.medium>a,.result .media-left.medium>a,.record .media-right.medium>a,.result .media-right.medium>a,.record .media-left.medium>img,.result .media-left.medium>img,.record .media-right.medium>img,.result .media-right.medium>img{width:100px}.record .media-left.large>a,.result .media-left.large>a,.record .media-right.large>a,.result .media-right.large>a,.record .media-left.large>img,.result .media-left.large>img,.record .media-right.large>img,.result .media-right.large>img{width:160px}}.record .media-left.small img,.record .media-right.small img,.record .media-left.medium img,.record .media-right.medium img,.record .media-left.large img,.record .media-right.large img{width:auto}.result-body{padding:0;padding-bottom:.25rem}.result-links .alert{margin:0}.result-formats{margin-bottom:.5rem}.btn-bookbag-toggle form{display:inline}.cart-link-icon.fa{margin-right:.3rem}.result .cart-link-icon{color:#333;width:1.28571429em;text-align:center}.savedLists{display:none}@media (min-width:768px){.result-body{float:left;width:75%}.result-links{float:left;width:25%;padding:0}.savedLists.loaded{display:block}}body.rtl .result .btn-bookbag-toggle .fa{margin-left:.3rem;margin-right:0}@media (min-width:768px){body.rtl .result-body,body.rtl .result-links{float:right}}.result.embedded .getFull{display:block;margin-left:-0.5rem;padding-left:.5rem;border-left:1px solid transparent}.result.embedded .getFull.expanded{margin-top:-11px;padding-left:.5rem;border-top-left-radius:4px;border-top-right-radius:4px}.result.embedded .getFull.expanded::before{content:'\25BC';position:absolute;right:1rem;color:#777}.result.embedded .loading{margin-left:.75rem;padding:1rem;background:#fff}.result.embedded .long-view{margin-left:-0.5rem;padding:.5rem;border:1px solid #ddd;background-color:#fff;border-bottom-left-radius:4px;border-bottom-right-radius:4px}.result.embedded .long-view .tab-content{padding:0}.result.embedded .list-tabs{margin-bottom:0}.result.embedded .list-tab-toggle{cursor:pointer}.result.embedded .list-tab-content{padding:1rem}.search-grid::after{display:table;clear:both;content:''}.grid-result{display:flex;float:left;width:50%}.grid-result .grid-body{flex:1}.grid-result .grid-checkbox{flex:0 0 30px;min-width:0}.grid-result .title{font-weight:bold}.grid-result .label,.grid-result .format{display:inline-block;white-space:normal}.grid-large-break,.grid-small-break{clear:both}@media (min-width:992px){.grid-result{width:25%}.grid-small-break{display:none}}.searchtools a{padding:0 .5rem;white-space:nowrap}.template-dir-combined.template-name-results.offcanvas{margin:0;padding:0}@media (min-width:768px){.combined-search-container{display:flex}.combined-search-container .result{margin-left:0}.combined-search-container .result-body{float:none;width:auto}.combined-search-container .result-links{display:none}.combined-column{flex:0 1 100%;padding-left:1rem}.combined-column:last-child{padding-right:1rem}}.wikipedia img{margin-right:1rem}.geoItem{font-size:.9em;margin:0 0 10px}.title-in-heading{font-size:inherit;font-style:italic}.facet-group{display:block;margin-bottom:1rem}.facet-group .facet,.facet-group .title{display:block;padding:8px 15px;line-height:1.5rem}.facet-group .facet .badge,.facet-group .title .badge,.facet-group .facet .status,.facet-group .title .status{float:right}body.rtl .facet-group .facet .badge,body.rtl .facet-group .title .badge,body.rtl .facet-group .facet .status,body.rtl .facet-group .title .status{float:left}.facet-group .facet .badge,.facet-group .title .badge{max-height:19px;line-height:1.1rem}.facet-group .facet{border-bottom:1px solid #ddd}.facet-group .title{padding-right:8px;border:1px solid #ddd;font-weight:bold}.facet-group [data-toggle="collapse"]{cursor:pointer}.facet-group [data-toggle="collapse"]::after{content:'\25B2';float:right}body.rtl .facet-group [data-toggle="collapse"]::after{float:left}.facet-group .collapsed::after{content:'\25BC'}.facet-group .collapse,.facet-group .collapsing,.facet-group>.facet{border-left:1px solid #ddd;border-right:1px solid #ddd}.facet-group>.facet:first-child{border-top:1px solid #ddd}.facet-group .facetOR .text{display:inline-block;padding-left:.5rem;text-indent:-0.5rem}.facet-group .excludable{display:flex;flex-direction:row-reverse;padding-right:0}.facet-group .excludable .badge{flex-shrink:0}.facet-group .excludable .text{flex-grow:1}.facet-group .excludable .exclude{flex-basis:2rem;flex-shrink:0;text-align:center}body.rtl .facet-group .excludable{padding-left:0;padding-right:15px}.checkbox-filter{display:block;padding-bottom:1rem;font-weight:bold;color:#333}.facet-group>.checkbox,.sidebar .facet.checkbox{margin:0;padding-left:2rem}.active-filters .facet,.facet-group .active{padding-right:.65rem;background-color:#1976d2;color:#fff}.active-filters .facet a,.facet-group .active a{color:#fff}.facet.active .badge,.jstree-node.active .badge,.jstree-node.active .badge .fa{background-color:#fff;color:#1976d2}.narrow-toggle{text-align:center}.top-row .applied{font-weight:bold}.top-row .applied:hover{color:#a94442}.top-row .applied:hover .fa.fa-check:before{content:"\f00d"}.full-facet-list{margin-top:1rem}.full-facet-list .active .fa{float:right;margin-top:.25rem;margin-right:.5rem;margin-left:.5rem}body.rtl .full-facet-list .active .fa{float:left}#similar-items-carousel .carousel-indicators{bottom:0}#similar-items-carousel .carousel-indicators li{width:8px;height:8px;margin:2px;margin-bottom:4px;background-color:#fff;border:1px solid #222;box-shadow:none;transition-duration:.4s;transition-property:width,height,margin}#similar-items-carousel .carousel-indicators li.active{width:16px;height:16px;margin-bottom:0}#similar-items-carousel .hover-overlay{position:relative;display:block;min-width:150px;min-height:200px;margin:auto;text-align:center}#similar-items-carousel .hover-overlay img{max-width:100%;margin:10px 0}#similar-items-carousel .hover-overlay .content{position:absolute;top:0;left:0;display:none;width:100%;height:100%;padding:.5em .5em 0;color:#fff;background-color:rgba(0,0,0,0.5)}#similar-items-carousel .hover-overlay:hover .content{display:block}#similar-items-carousel .item{padding:0 4em}#similar-items-carousel .item.prev,#similar-items-carousel .item.active,#similar-items-carousel .item.next{display:flex}#similar-items-carousel .carousel-item{flex-basis:25%}.slider-container{padding:4px 10px;text-align:center}.slider-container .slider.slider-horizontal{width:100%}.slider-container .slider-track{background:#777;box-shadow:inset 0 1px 0 rgba(0,0,0,0.4)}.slider-container .slider-handle{background:#1976d2;background-image:none;border:1px solid #1976d2;box-shadow:none;opacity:.9}.slider-container .slider-handle:hover,.slider-container .slider-handle:active,.slider-container .slider-handle:focus{opacity:1;background:#FFF;border-color:#777}.slider-container .slider-handle:active,.slider-container .slider-handle:focus{border-color:#1976d2}.slider-container .slider-selection{background:#CCC;box-shadow:inset 0 -1px 0 rgba(0,0,0,0.3)}.slider-container input{display:none}html{font-size:14px}a,label{cursor:pointer}.alert.alert-info a{text-decoration:underline}.btn.disabled:active,.btn.disabled:focus,.btn.disabled:hover{color:#000}.list-unstyled{margin:0}.icon-bar{background-color:#888}.highlight,mark{background:#ff6;padding:.1em .2em}img{max-width:100%}.breadcrumb{margin-top:.5rem;margin-bottom:.5rem}.label,.result .format,.sidebar .format{display:inline-block}.popover{width:250px}.resulthead:before,.resulthead:after{content:" ";display:table}.resulthead:after{clear:both}.resulthead:before,.resulthead:after{content:" ";display:table}.resulthead:after{clear:both}.sub-breadcrumb{padding:5px 10px;white-space:nowrap}.sub-breadcrumb li{display:inline-block}.sub-breadcrumb li+li:before{padding-left:5px;padding-right:5px;color:#ccc;content:"/\00a0"}.tab-content{padding:4px}h2{font-size:20px}h3{font-size:16px}@media (min-width:768px){h2{font-size:23px;font-weight:normal}h3{font-size:20px;font-weight:normal}.form-control{max-width:400px}#modal .form-control{max-width:none}}footer{padding:1rem}@media (min-width:768px){.footer-container{display:flex;width:100%}.footer-column{flex:0 1 100%}.mainbody{width:75%}.sidebar{width:25%}.mainbody.left,.sidebar.left{float:left;padding-right:1rem}.mainbody.right,.sidebar.right{float:right;padding-left:1rem}}.has-error,.sms-error{margin-bottom:0}.help-block.with-errors{margin:0;padding-top:6px;padding-bottom:6px}.help-block.with-errors:empty{padding:0}.form-admin-maintenance .form-control{display:inline-block;width:100px}.badge a{color:#fff}@media (min-width:768px){.browse-container{display:flex}.browse-list{flex-basis:25%;padding-right:1rem}.browse-list:last-child{padding-right:0}}.browse-item{position:relative;display:block;padding:.5rem 1rem;border:1px solid #ddd;border-bottom:0;word-wrap:break-word}.browse-item.active{background-color:#1976d2;color:#fff}.browse-item.active .badge{background-color:#fff;color:#222}.browse-item:hover{background-color:#eee}.browse-item:last-child{border-bottom:1px solid #ddd}.browse-item.with-badge{padding-right:3rem}.browse-item.with-badge .badge{position:absolute;top:.5rem;right:.25rem}.browse-item.view-record{padding:2px 4px;font-size:85%;text-align:right;border-top:0}.cart-controls .checkbox{line-height:2.5rem;padding-right:1rem}.nav .btn-bookbag-toggle{float:left}.nav .btn-bookbag-toggle a{display:block;padding:10px 15px;text-decoration:none}.nav .btn-bookbag-toggle a:hover,.nav .btn-bookbag-toggle a:focus{outline:dotted 1px #000;text-decoration:none;background-color:#eee}@media (min-width:768px){.collection-hierarchytree{display:flex}.collection-hierarchytree .tree-panel,#tree-preview{flex-basis:50%;padding:1rem}}.translation-output{width:100%;max-width:none;font-family:Menlo,Monaco,Consolas,"Courier New",monospace;font-size:12px;white-space:pre}.date-fields{display:flex}.date-fields .date-from{padding-right:.25rem}.date-fields .date-to{padding-left:.25rem}.top-facets{margin-left:-0.5rem;margin-right:-0.5rem}.top-facets .facet,.top-facets .narrow-toggle,.top-facets>strong{display:inline-block;padding:.25rem .5rem;white-space:nowrap}.top-facets .narrow-toggle{text-decoration:underline}@media (min-width:768px){.author-facets{display:flex}.author-list{flex:0 1 100%}}.form-login .btn-link~.btn-link{padding-left:0}.myresearch-menu a{display:block;padding:10px 15px}.myresearch-menu a:hover,.myresearch-menu a:focus{background-color:#eee}.myresearch-menu a .badge{float:right}.myresearch-menu a.active{background-color:#1976d2;color:#fff}.myresearch-menu a.active .badge{background-color:#fff;color:#222}.list-edit-container:before,.list-edit-container:after{content:" ";display:table}.list-edit-container:after{clear:both}.list-edit-container:before,.list-edit-container:after{content:" ";display:table}.list-edit-container:after{clear:both}#dateVisColorSettings{background-color:#fff;fill:#eee;outline-color:#c38835;stroke:#1976d2}.table{table-layout:fixed;word-wrap:break-word}.node{position:absolute;box-sizing:content-box;margin:-1px;overflow:hidden;font:10px sans-serif;line-height:12px;border:1px solid #fff}.node div{margin-top:0}.toplevel{border:2px solid #000}.node .label{position:absolute;bottom:0;left:0;min-height:1px;padding:2px 4px;font-size:85%;background-color:rgba(0,0,0,0.5);border-radius:0;text-shadow:none}.notalabel{color:#000}#viz-instructions{padding-top:600px}span[class^="services-"],span[class*=" services-"] span::before{content:", "}span[class^="services-"],span[class*=" services-"] span:first-of-type::before{content:""}h1,h2,h3,h4{margin:0;margin-bottom:1rem}.help-block h1,.help-block h2,.help-block h3,.help-block h4{margin:0}.highlight,mark{background-color:#ff6}table{font-size:14px}.badge{margin-bottom:1px;font-size:10px}.btn{height:34px;border-radius:.25rem;border-color:#999}.btn-default:hover,.btn-default:focus{color:#fff;border-color:transparent}.btn-link,.btn-primary{border-color:transparent}.btn-primary:hover{background-color:#fff;color:#1976d2;border-color:#1976d2}.btn-link{color:#1976d2}.form-control{box-shadow:none}.form-control:hover,.form-control:focus{border-color:#1976d2}.form-control:focus{padding-bottom:4px;border-bottom:3px solid #ff6d00;box-shadow:none}select.form-control{padding-bottom:6px;border:1px solid #aaa}.breadcrumb a{color:#333}.breadcrumb .active{color:#111}.nav>li>a{color:#1976d2}.navbar-collapse,.navbar-form{box-shadow:none}.alert,.savedLists{margin-top:1rem;margin-bottom:1rem;border:0;color:#000}.alert .btn{color:#555;background-color:#fff;border-color:#777}.alert .btn-primary{color:#1976d2;background-color:#fff;border-color:#1976d2}.alert-info,.alert-info:hover,.savedLists{color:#001b44;background-color:#cdecff}.alert-info a,.alert-info:hover a{color:#357edd}.alert-success,.alert-success:hover{color:#137752;background-color:#9eebcf}.alert-success a,.alert-success:hover a{color:#fff}.alert-danger,.alert-danger:hover{color:#fff;background-color:#ff4136}.alert-danger a,.alert-danger:hover a{color:#ffdfdf}.label,.result .format,.sidebar .format{font-weight:400}.pagination{display:table;margin-left:auto;margin-right:auto;border-radius:0}.pagination:before,.pagination:after{content:" ";display:table}.pagination:after{clear:both}.pagination:before,.pagination:after{content:" ";display:table}.pagination:after{clear:both}.pagination>li>a,.pagination>li>span{padding-left:1rem;padding-right:1rem;font-size:13px;font-weight:500;line-height:1rem}.pagination>li>a.page-prev,.pagination>li>span.page-prev,.pagination>li>a.page-next,.pagination>li>span.page-next{font-size:1rem;font-weight:bold;color:#1976d2}.pagination>.active>a,.pagination>.active>span{border-radius:4px}.search{padding-left:1rem;padding-right:1rem}.list-group-item.title{color:#333}.bulkActionButtons label{font-weight:500;color:#555}.search-header.search-header{padding-top:0}.search-stats>h2{margin:0}.author-facets{font-size:14px}.result{margin-left:-1rem;margin-right:-1rem;padding-top:1rem;padding-left:1rem;padding-bottom:1rem;border-bottom:1px solid #ccc;font-size:14px}.result .media-left{padding-left:0}.result .media-right{padding-right:0}.result .record-cover img{border:1px solid #eee}.result .record-number{font-size:14px;font-weight:bold;color:#777}.result .title{font-size:1rem}.result .callnumAndLocation{margin-top:.25rem;margin-bottom:.25rem;font-size:12px}.result .format,.result .label{display:inline-block;padding:4px .75rem;font-size:11px}.result .savedLists{margin-bottom:0;white-space:nowrap}.result .savedLists>ol,.result .savedLists>ul{padding-left:1rem}@media (min-width:768px){.result{margin-left:0;margin-right:0;padding-left:0}}.grid-result{padding-bottom:1rem;padding-right:1rem;text-align:center}.grid-result .title{font-size:14px}.result.checked,.grid-result.checked{color:#fff;background-color:#1976d2;border-color:#fff}.result.checked a,.grid-result.checked a{color:#fff;text-decoration:underline}.result.checked .format,.grid-result.checked .format,.result.checked .label,.grid-result.checked .label{color:#1976d2;background-color:#fff}.result.checked .record-number,.grid-result.checked .record-number{color:#fff}.result.checked .alert,.grid-result.checked .alert{background-color:#fff}.result.checked .alert a,.grid-result.checked .alert a{color:#fff}.result-body,.result-links{float:left;margin:0;padding:0}.result-body{width:85%}.result-links{width:15%;text-align:center}@media (max-width:767px){.result-link-icon,.result .cart-link-icon{width:100%;margin:0;padding-top:.5rem;padding-bottom:.5rem;font-size:1.5rem;color:#333}.result-link-label,.result .cart-link-label{display:none}}.grid-result .grid-checkbox label{width:100%}@media (min-width:768px){.result{padding-right:1rem}.result-body{width:75%}.result-links{width:25%;text-align:left}.result-link-icon,.result .cart-link-icon{margin-right:.2rem;padding:0;font-size:inherit;color:#222}.result-link-icon{margin-right:0}.result-link-label,.result .cart-link-label{display:inline}}.top-facets,.search-header{font-size:14px}.search-header{padding-top:1rem;padding-bottom:1rem}#searchForm{font-size:14px}#searchForm_lookfor,#searchForm_type{margin-bottom:4px}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{border-color:#ff6d00;background-color:#ff6d00}.searchHomeContent{margin-right:calc(50% - 50vw + .5rem);margin-left:calc(50% - 50vw + .5rem);position:relative;padding:6rem 3rem;padding-left:calc(50vw - 50%);background-color:#607d8b;background-image:url('https://source.unsplash.com/collection/803311/1000x300');background-repeat:no-repeat;background-size:cover;background-position:center top;box-shadow:0 .5rem 2rem rgba(0,0,0,0.1)}.searchHomeContent:before,.searchHomeContent:after{content:" ";display:table}.searchHomeContent:after{clear:both}.searchHomeContent:before,.searchHomeContent:after{content:" ";display:table}.searchHomeContent:after{clear:both}.searchHomeContent .btn-link,.searchHomeContent .nav-tabs a{color:#fff;text-shadow:0 1px 0 #000}.searchHomeContent::before{position:absolute;top:0;left:0;background-color:rgba(255,255,255,0.5)}.template-dir-search.template-name-home .breadcrumbs{border:0}.search{border:0}#searchForm{padding-top:.5rem;padding-bottom:calc(3.5rem)}.nav.searchbox,#searchForm{position:relative;width:100%}.nav.searchbox .nav-tabs,#searchForm .nav-tabs{position:absolute;bottom:0;border:0}.nav.searchbox .nav-tabs a,#searchForm .nav-tabs a,.nav.searchbox .nav-tabs a:hover,#searchForm .nav-tabs a:hover{border:0;border-bottom:3px solid transparent}.nav.searchbox .nav-tabs a,#searchForm .nav-tabs a{height:calc(2.5rem);line-height:calc(2.5rem);padding:0 1rem;border-radius:0;background-color:transparent}.nav.searchbox .nav-tabs a:hover,#searchForm .nav-tabs a:hover{border-color:rgba(255,255,255,0.5);color:#cfd8dc;background-color:transparent}.nav.searchbox .nav-tabs .active a,#searchForm .nav-tabs .active a{color:#fff;border-color:#fff}@media (min-width:768px){#searchForm_lookfor,#searchForm_type{margin-bottom:0}#searchForm{padding-bottom:2rem}.nav.searchbox .nav-tabs a,#searchForm .nav-tabs a{height:2rem;padding-bottom:3px;line-height:2rem}}.solr-adv-facet{padding-right:1rem}.solr-adv-facet:last-child{padding-right:0}.adv_search_links{margin-bottom:0}.adv_search_links a{text-decoration:underline}.tab-content .adv_search_links{margin-bottom:1.5rem}#content>[name="bulkActionForm"] .bulkActionButtons{padding-top:1rem;padding-bottom:1rem}.combined-search-container{margin-right:calc(50% - 50vw + .5rem);margin-left:calc(50% - 50vw + .5rem)}.combined-search-container .result{margin-right:0}body.rtl .result .media-body{padding-left:0;padding-right:.5rem}body.rtl .result .result-body,body.rtl .result .result-links{float:right;text-align:right}html{font-size:16px;overflow-x:hidden}body{font-size:1rem;font-family:-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;color:#111}.main .container{background-color:#fff}.mainbody{padding-top:1rem}.navbar{border-radius:0}.banner{width:auto;color:#fff}.banner a{color:#fff}.banner .navbar-right{margin-top:calc(-5px)}.banner .navbar-brand{width:104.61538462px;height:40px}@media (min-width:768px){.banner .navbar-right{margin-top:calc(5px)}.banner .navbar-brand{width:156.92307692px;height:60px}}header{background-color:#607d8b;font-size:14px;font-weight:500;color:#fff}header .navbar-nav{margin-top:0}header a,header .nav a,header .btn-link{color:#fff}header a:hover,header .nav a:hover,header .btn-link:hover{color:#cfd8dc}header .btn-primary{color:#000;background-color:#cfd8dc}header .btn-primary:hover{color:#000;background-color:#cfd8dc;border-color:#000}header .nav>li>a:hover,header .nav>li>a:focus{color:#000;background-color:#cfd8dc}header .navbar-toggle{margin:.5rem;padding-left:1rem;padding-right:1rem;font-size:14px}header .dropdown-menu a{color:#000}header .dropdown-menu a:hover{background-color:#cfd8dc;color:#000}header .dropdown-menu .active a,header .dropdown-menu .active a:hover{background-color:#607d8b}header .form-control{border:0}header .form-control:focus{padding-bottom:3px;border-bottom:3px solid #ffb700}header .navbar-brand{width:200px;height:100%;margin-top:5px;background-image:url("../../sandal/images/vufind_logo_dark.png");background-position:center center;background-repeat:no-repeat;background-size:contain}header .navbar-brand,header .navbar-brand:active,header .navbar-brand:hover,header .navbar-brand:focus{color:transparent}header .navbar-brand.lang-ar{background-image:url("../../sandal/images/vufind_logo_ar_dark.png")}.breadcrumbs{border-bottom:1px solid #cfd8dc;background-color:#cfd8dc}.breadcrumb{margin:0;padding-left:0;padding-right:0;font-size:14px;color:#777;background-color:transparent;border-radius:0}.breadcrumb a{color:#1565c0}.breadcrumb .active{color:#000}.breadcrumb .active a{color:#37474F}.breadcrumb .active a:hover{color:#0d47a1}.breadcrumb>li+li::before{font-weight:900;color:#fff}#cartSummary strong{font-weight:inherit}.channel-title{margin-top:1rem}.channel,.channel-title.no-results{margin-bottom:2rem}.myresearch-menu a:hover{background-color:#fff}.record-nav{display:table;margin-left:auto;margin-top:1rem;margin-right:auto}.info-col{font-size:14px}.info-col h3{margin-top:0;font-weight:500}.record .sidebar{margin-top:1rem}.comment-list{margin-top:.5rem}.comment{margin-bottom:.5rem}.comment .delete{font-size:14px}.comment-form .btn-primary{margin-top:.25rem}.tagList{line-height:2rem}.tagList .tag .fa-close{margin:0}.sidebar{padding-top:1rem;font-size:14px;background-color:#eee}.sidebar .facet-group{margin-left:1rem;margin-right:1rem}.sidebar .facet-group .title{background-color:#fff;color:#111}.sidebar .facet-group .title::after{width:1rem;font-family:"FontAwesome";text-align:center;color:#777;content:'\f106'}.sidebar .facet-group .title.collapsed::after{content:'\f107'}.sidebar .active-filters .title::after,#advSearchForm .sidebar .title:after{content:none}.sidebar .facet{background-color:#fff;color:#000}.sidebar a.facet:hover,.sidebar .facet.checkbox:hover{background-color:#cdecff}.sidebar .facet.active,.sidebar .facet.active:hover,.sidebar .active-filters .facet,.sidebar .active-filters .facet:hover,.sidebar .jstree-facet .jstree-container-ul>.active{border-color:#ff6d00;background-color:#ff6d00;color:#fff}.sidebar .facet.active .badge,.sidebar .facet.active:hover .badge,.sidebar .active-filters .facet .badge,.sidebar .active-filters .facet:hover .badge,.sidebar .jstree-facet .jstree-container-ul>.active .badge{color:#ff6d00;background-color:#fff}.sidebar .facet .badge{max-height:15px;margin-top:5px;line-height:.8;background-color:#777}.sidebar.left,.sidebar.right{padding-left:0;padding-right:0}.sidebar .checkbox-filter,.sidebar>h4{margin-left:1rem}.jstree-facet .main .fa-check{margin-top:3px}@media (min-width:768px) and (max-width:991px){.sidebar .facet{flex-flow:wrap}.sidebar .facet .text{width:100%}.sidebar .facet .badge{flex-grow:1;order:1}.sidebar .facet .exclude{order:2}}
\ No newline at end of file
diff --git a/themes/sandal/images/vufind_logo_ar_dark.png b/themes/sandal/images/vufind_logo_ar_dark.png
new file mode 100644
index 0000000000000000000000000000000000000000..cecf8e7434e1e703356fd9e625d5f4b403fdbc3a
Binary files /dev/null and b/themes/sandal/images/vufind_logo_ar_dark.png differ
diff --git a/themes/sandal/images/vufind_logo_dark.png b/themes/sandal/images/vufind_logo_dark.png
new file mode 100644
index 0000000000000000000000000000000000000000..f8d25be9545f521141457ed52bffbdb8853f8e89
Binary files /dev/null and b/themes/sandal/images/vufind_logo_dark.png differ
diff --git a/themes/sandal/less/colors.less b/themes/sandal/less/colors.less
new file mode 100644
index 0000000000000000000000000000000000000000..c655c557456b8836c3cb3b28c7777f24ff96be6d
--- /dev/null
+++ b/themes/sandal/less/colors.less
@@ -0,0 +1,49 @@
+@import "vendor/tachyons-colors.less"; // Import colors from the tachyons library
+
+/* Material Colors can be found here: https://material.io/guidelines/style/color.html */
+@brand-primary: #1976d2; /* Material Blue 700 */
+@brand-secondary: #ff6d00; /* Material Orange A700 */
+
+@header-bg: #607d8b; /* Material Blue Grey 500 */
+@header-light: #cfd8dc; /* Material Blue Grey 100 */
+
+@action-color: @brand-primary;
+@action-hover-bg: @white;
+@action-hover-color: @black;
+@passive-icon-color: @gray;
+@highlighter-color: lighten(#FF0, 20%);
+
+@search-row-bg: @white;
+@search-row-bg-alt: @light-gray;
+@search-row-bg-hover: @lightest-blue;
+@search-row-selected-bg: @brand-primary;
+@search-row-selected-color: @white;
+
+@sidebar-title-bg: @white;
+@sidebar-title-color: @near-black;
+@sidebar-title-icon-color: @gray-light;
+@sidebar-item-bg: @white;
+@sidebar-item-color: @black;
+@sidebar-item-hover-bg: @lightest-blue;
+@sidebar-item-badge: @gray;
+@sidebar-active-bg: @brand-secondary;
+@sidebar-active-color: @white;
+
+/* Bootstrap variable changes */
+
+@link-color: #1565c0; /* Material Blue 800 */
+@link-color-hover: #0d47a1; /* Material Blue 900 */
+
+@input-border:              @light-silver;
+@input-color:               @dark-gray;
+@btn-default-bg:            @light-gray;
+@btn-default-color:         @near-black;
+@btn-primary-bg:            @action-color;
+
+@input-border-radius:         .25rem;
+
+@autocomplete-hover-bg:     @header-light;
+@dropdown-link-hover-bg:    @header-light;
+@dropdown-link-hover-color: @black;
+@table-bg-hover:            @header-light;
+@pagination-color:          @header-bg;
diff --git a/themes/sandal/less/common.less b/themes/sandal/less/common.less
new file mode 100644
index 0000000000000000000000000000000000000000..0989391bb57428570ccf07d80bb33bcb0cf1586d
--- /dev/null
+++ b/themes/sandal/less/common.less
@@ -0,0 +1,123 @@
+/* ------ Border radius changes ------ */
+@list-group-border-radius: 0;
+@border-radius-large: 0; // modal
+
+/* ------ Common element changes ------ */
+h1, h2, h3, h4 {
+  margin: 0;
+  margin-bottom: 1rem;
+
+  .help-block & { margin: 0; }
+}
+.highlight,
+mark { background-color: @highlighter-color; }
+table { font-size: @reduced-font-size; }
+
+/* ------ Bootstrap class overrides ------ */
+.badge {
+  margin-bottom: 1px;
+  font-size: 10px;
+}
+.btn {
+  height: 34px;
+  border-radius: .25rem;
+  border-color: @silver;
+}
+.btn-default:hover,
+.btn-default:focus {
+  color: @white;
+  border-color: transparent;
+}
+.btn-link,
+.btn-primary { border-color: transparent; }
+.btn-primary:hover {
+  background-color: @action-hover-bg;
+  color: @action-color;
+  border-color: @brand-primary;
+}
+.btn-link { color: @brand-primary; }
+
+.form-control { box-shadow: none; }
+.form-control:hover,
+.form-control:focus { border-color: @brand-primary; }
+.form-control:focus {
+  padding-bottom: 4px; // Prevent jumping
+  border-bottom: 3px solid @brand-secondary;
+  box-shadow: none;
+}
+select.form-control {
+  padding-bottom: @padding-base-vertical;
+  border: 1px solid @light-silver;
+}
+
+.breadcrumb a { color: @dark-gray; }
+.breadcrumb .active { color: @near-black; }
+
+.nav > li > a { color: @brand-primary; }
+.navbar-collapse,
+.navbar-form { box-shadow: none; }
+
+.alert {
+  margin-top: 1rem;
+  margin-bottom: 1rem;
+  border: 0;
+  color: @black;
+
+  .btn {
+    color: @mid-gray;
+    background-color: @white;
+    border-color: @gray;
+  }
+  .btn-primary {
+    color: @action-color;
+    background-color: @white;
+    border-color: @action-color;
+  }
+}
+.alert-info,
+.alert-info:hover {
+  color: @navy;
+  background-color: @lightest-blue;
+  a { color: @blue; }
+}
+.alert-success,
+.alert-success:hover {
+  color: @dark-green;
+  background-color: @light-green;
+  a { color: @white; }
+}
+.alert-danger,
+.alert-danger:hover {
+  color: @white;
+  background-color: @red;
+  a { color: @washed-red; }
+}
+
+.label { font-weight: 400; }
+
+@pagination-border: transparent;
+@pagination-hover-border: transparent;
+.pagination {
+  .clearfix();
+  display: table;
+  margin-left: auto;
+  margin-right: auto;
+  border-radius: 0;
+}
+.pagination > li > a,
+.pagination > li > span {
+  padding-left: 1rem;
+  padding-right: 1rem;
+  font-size: 13px;
+  font-weight: 500;
+  line-height: 1rem;
+
+  &.page-prev,
+  &.page-next {
+    font-size: 1rem;
+    font-weight: bold;
+    color: @brand-primary;
+  }
+}
+.pagination > .active > a,
+.pagination > .active > span { border-radius: @border-radius-base; }
\ No newline at end of file
diff --git a/themes/sandal/less/compiled.less b/themes/sandal/less/compiled.less
new file mode 100644
index 0000000000000000000000000000000000000000..7a85ff748b6d71042036a18b2e7c073ae459bc73
--- /dev/null
+++ b/themes/sandal/less/compiled.less
@@ -0,0 +1 @@
+@import "sandal";
diff --git a/themes/sandal/less/rtl.less b/themes/sandal/less/rtl.less
new file mode 100644
index 0000000000000000000000000000000000000000..8f008f0e106f35b0e7d888030afdf70564bcb7ea
--- /dev/null
+++ b/themes/sandal/less/rtl.less
@@ -0,0 +1,14 @@
+body.rtl {
+  .result {
+    .media-body {
+      padding-left: 0;
+      padding-right: .5rem;
+    }
+
+    .result-body,
+    .result-links {
+      float: right;
+      text-align: right;
+    }
+  }
+}
diff --git a/themes/sandal/less/sandal.less b/themes/sandal/less/sandal.less
new file mode 100644
index 0000000000000000000000000000000000000000..4ac1371125203905382222288598da3b800877e1
--- /dev/null
+++ b/themes/sandal/less/sandal.less
@@ -0,0 +1,234 @@
+@import "bootstrap";
+@import "colors";
+@import "variables";
+@import "common";
+@import "search";
+@import "rtl";
+
+html {
+  font-size: 16px;
+  overflow-x: hidden;
+}
+body {
+  font-size: 1rem;
+  font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; // native font stack
+  color: @near-black;
+}
+
+/* -- Layout --- */
+.main .container { background-color: @white; }
+.mainbody { padding-top: 1rem; }
+
+/* --- Header --- */
+.navbar { border-radius: 0; }
+.banner {
+  width: auto;
+  color: #fff;
+
+  a { color: #fff; }
+}
+.banner .navbar-right { margin-top: calc((@banner-height-sm - 50px) / 2); } // Put right nav in the middle
+.banner .navbar-brand {
+  width: (170 / 65) * @banner-height-sm;
+  height: @banner-height-sm;
+}
+@media (min-width: 768px) {
+  .banner .navbar-right { margin-top: calc((@banner-height - 50px) / 2); }
+  .banner .navbar-brand {
+    width: (170 / 65) * @banner-height;
+    height: @banner-height;
+  }
+}
+
+header {
+  background-color: @header-bg;
+  font-size: @reduced-font-size;
+  font-weight: 500;
+  color: @white;
+
+  .navbar-nav { margin-top: 0; }
+  a,
+  .nav a,
+  .btn-link {
+    color: @white;
+    &:hover { color: @header-light; }
+  }
+  .btn-primary {
+    color: @black;
+    background-color: @header-light;
+  }
+  .btn-primary:hover {
+    color: @black;
+    background-color: @header-light;
+    border-color: @black;
+  }
+  .nav>li>a:hover,
+  .nav>li>a:focus {
+    color: @black;
+    background-color: @header-light;
+  }
+  .navbar-toggle {
+    margin: .5rem;
+    padding-left: 1rem;
+    padding-right: 1rem;
+    font-size: @reduced-font-size;
+  }
+  .dropdown-menu a { color: @black; }
+  .dropdown-menu a:hover {
+    background-color: @header-light;
+    color: @black;
+  }
+  .dropdown-menu .active a,
+  .dropdown-menu .active a:hover { background-color: @header-bg; }
+
+  .form-control { border: 0; }
+  .form-control:focus {
+    padding-bottom: 3px; // Smaller font-size means smaller jump
+    border-bottom: 3px solid @gold;
+  }
+
+  .navbar-brand {
+    width: 200px;
+    height: 100%;
+    margin-top: 5px;
+    .background-image('vufind_logo_dark.png');
+    background-position: center center;
+    background-repeat: no-repeat;
+    background-size: contain;
+    &,
+    &:active,
+    &:hover,
+    &:focus { color: transparent; }
+    &.lang-ar { .background-image('vufind_logo_ar_dark.png'); }
+  }
+}
+
+.breadcrumbs {
+  border-bottom: 1px solid @header-light;
+  background-color: @header-light;
+}
+.breadcrumb {
+  margin: 0;
+  padding-left: 0;
+  padding-right: 0;
+  font-size: @reduced-font-size;
+  color: @gray;
+  background-color: transparent;
+  border-radius: 0;
+}
+.breadcrumb a { color: @link-color; }
+.breadcrumb .active { color: @black; }
+.breadcrumb .active a { color: #37474F; } /* Material Blue Grey 800 */
+.breadcrumb .active a:hover { color: @link-color-hover; } /* Material Blue Grey 900 */
+.breadcrumb > li+li::before {
+  font-weight: 900;
+  color: #fff;
+}
+
+/* --- Cart --- */
+#cartSummary strong { font-weight: inherit; }
+
+/* --- Channels --- */
+.channel-title { margin-top: 1rem; }
+.channel,
+.channel-title.no-results { margin-bottom: 2rem; }
+
+/* --- MyResearch --- */
+.myresearch-menu a:hover { background-color: @white; }
+
+/* --- Record --- */
+.record-nav {
+  display: table;
+  margin-left: auto;
+  margin-top: 1rem;
+  margin-right: auto;
+}
+.info-col { font-size: @reduced-font-size; }
+.info-col h3 {
+  margin-top: 0;
+  font-weight: 500;
+}
+.record .sidebar { margin-top: 1rem; }
+.comment-list { margin-top: .5rem; }
+.comment { margin-bottom: .5rem; }
+.comment .delete { font-size: @reduced-font-size; }
+.comment-form .btn-primary { margin-top: .25rem; }
+.tagList { line-height: 2rem; }
+.tagList .tag .fa-close { margin: 0; }
+
+/* --- Sidebar --- */
+.sidebar {
+  padding-top: 1rem;
+  font-size: @reduced-font-size;
+  background-color: @light-gray;
+
+  .facet-group {
+    margin-left: 1rem;
+    margin-right: 1rem;
+  }
+  /* Collapsed arrows */
+  .facet-group .title {
+    background-color: @sidebar-title-bg;
+    color: @sidebar-title-color;
+    &::after {
+      width: 1rem;
+      font-family: "FontAwesome";
+      text-align: center;
+      color: @sidebar-title-icon-color;
+      content: '\f106';
+    }
+  }
+  .facet-group .title.collapsed::after { content: '\f107'; }
+  .active-filters .title::after,
+  #advSearchForm & .title:after { content: none; } // No arrow on active filter title
+
+  .facet {
+    background-color: @sidebar-item-bg;
+    color: @sidebar-item-color;
+  }
+  a.facet:hover,
+  .facet.checkbox:hover { background-color: @sidebar-item-hover-bg; }
+
+  .facet.active,
+  .facet.active:hover,
+  .active-filters .facet,
+  .active-filters .facet:hover,
+  .jstree-facet .jstree-container-ul > .active {
+    border-color: @sidebar-active-bg;
+    background-color: @sidebar-active-bg;
+    color: @sidebar-active-color;
+
+    .badge {
+      color: @sidebar-active-bg;
+      background-color: @white;
+    }
+  }
+
+  .facet .badge {
+    max-height: 15px;
+    margin-top: 5px;
+    line-height: .8;
+    background-color: @sidebar-item-badge;
+  }
+}
+.sidebar.left,
+.sidebar.right {
+  padding-left: 0;
+  padding-right: 0;
+}
+.sidebar .checkbox-filter,
+.sidebar > h4 { margin-left: 1rem; }
+
+.jstree-facet .main .fa-check { margin-top: 3px; }
+@media (min-width: 768px) and (max-width: 991px) {
+  .sidebar .facet {
+    flex-flow: wrap;
+
+    .text { width: 100%; }
+    .badge {
+      flex-grow: 1;
+      order: 1;
+    }
+    .exclude { order: 2; }
+  }
+}
diff --git a/themes/sandal/less/search.less b/themes/sandal/less/search.less
new file mode 100644
index 0000000000000000000000000000000000000000..58f4b880145f8134b0910972c2aea802dafc4aef
--- /dev/null
+++ b/themes/sandal/less/search.less
@@ -0,0 +1,241 @@
+.search {
+  padding-left: 1rem;
+  padding-right: 1rem;
+}
+.list-group-item.title { color: @dark-gray; }
+.bulkActionButtons {
+  label {
+    font-weight: 500;
+    color: @mid-gray;
+  }
+}
+.search-header.search-header { padding-top: 0; } // Duplicate to increase specificity
+.search-stats > h2 { margin: 0; } // No results padding
+
+.author-facets { font-size: @reduced-font-size; }
+
+.result {
+  margin-left: -1rem;
+  margin-right: -1rem;
+  padding-top: 1rem;
+  padding-left: 1rem;
+  padding-bottom: 1rem;
+  border-bottom: 1px solid @moon-gray;
+  font-size: @reduced-font-size;
+
+  .media-left { padding-left: 0; }
+  .media-right { padding-right: 0; }
+  .record-cover img { border: 1px solid @gray-lighter; }
+  .record-number {
+    font-size: @reduced-font-size;
+    font-weight: bold;
+    color: @gray;
+  }
+
+  .title { font-size: 1rem; }
+  .callnumAndLocation {
+    margin-top: .25rem;
+    margin-bottom: .25rem;
+    font-size: 12px;
+  }
+  .format,
+  .label {
+    display: inline-block;
+    padding: 4px .75rem;
+    font-size: 11px;
+  }
+  .savedLists {
+    margin-bottom: 0;
+    white-space: nowrap;
+  }
+  .savedLists > ol,
+  .savedLists > ul { padding-left: 1rem; }
+}
+@media (min-width: 768px) {
+  .result {
+    margin-left: 0;
+    margin-right: 0;
+    padding-left: 0;
+  }
+}
+
+.grid-result {
+  padding-bottom: 1rem;
+  padding-right: 1rem;
+  text-align: center;
+
+  .title { font-size: @reduced-font-size; }
+}
+
+.result.checked,
+.grid-result.checked {
+  color: @search-row-selected-color;
+  background-color: @search-row-selected-bg;
+  border-color: @white;
+  a {
+    color: @search-row-selected-color;
+    text-decoration: underline;
+  }
+  .format,
+  .label {
+    color: @brand-primary;
+    background-color: #fff;
+  }
+  .record-number { color: @search-row-selected-color; }
+  .alert { background-color: @search-row-selected-color; }
+  .alert a { color: @search-row-selected-color; }
+}
+.result-body,
+.result-links {
+  float: left;
+  margin: 0;
+  padding: 0;
+}
+.result-body { width: 85%; }
+.result-links {
+  width: 15%;
+  text-align: center;
+}
+@media (max-width: 767px) {
+  .result-link-icon,
+  .result .cart-link-icon {
+    width: 100%;
+    margin: 0;
+    padding-top: .5rem;
+    padding-bottom: .5rem;
+    font-size: @result-sm-icon-size;
+    color: @dark-gray;
+  }
+  .result-link-label,
+  .result .cart-link-label { display: none; }
+}
+
+.grid-result .grid-checkbox label { width: 100%; }
+@media (min-width: 768px) {
+  .result { padding-right: 1rem; }
+  .result-body { width: 75%; }
+  .result-links {
+    width: 25%;
+    text-align: left;
+  }
+  .result-link-icon,
+  .result .cart-link-icon {
+    margin-right: .2rem;
+    padding: 0;
+    font-size: inherit;
+    color: @gray-darker;
+  }
+  .result-link-icon { margin-right: 0; }
+  .result-link-label,
+  .result .cart-link-label { display: inline; }
+}
+
+.top-facets,
+.search-header { font-size: @reduced-font-size; }
+.search-header {
+  padding-top: 1rem;
+  padding-bottom: 1rem;
+}
+#searchForm { font-size: @reduced-font-size; }
+#searchForm_lookfor,
+#searchForm_type { margin-bottom: 4px; }
+
+.list-group-item.active,
+.list-group-item.active:hover,
+.list-group-item.active:focus {
+  border-color: @sidebar-active-bg;
+  background-color: @sidebar-active-bg;
+}
+
+.searchHomeContent {
+  .full-width();
+  .clearfix();
+  position: relative;
+  padding: 6rem 3rem;
+  padding-left: ~"calc(50vw - 50%)"; // Align searchbox with container
+  background-color: @header-bg;
+  background-image: url('https://source.unsplash.com/collection/803311/1000x300');
+  background-repeat: no-repeat;
+  background-size: cover;
+  background-position: center top;
+  box-shadow: 0 .5rem 2rem rgba(0,0,0,.1);
+  .btn-link,
+  .nav-tabs a {
+    color: @white;
+    text-shadow: 0 1px 0 @black;
+  }
+}
+.searchHomeContent::before {
+  position: absolute;
+  top: 0;
+  left: 0;
+  background-color: rgba(255,255,255,.5);
+}
+.template-dir-search.template-name-home .breadcrumbs { border: 0; }
+
+.search { border: 0; }
+#searchForm {
+  padding-top: .5rem;
+  padding-bottom: calc(@search-tab-height + 1.5rem);
+}
+.nav.searchbox,
+#searchForm {
+  position: relative;
+  width: 100%;
+
+  .nav-tabs {
+    position: absolute;
+    bottom: 0;
+    border: 0;
+  }
+  .nav-tabs a,
+  .nav-tabs a:hover {
+    border: 0;
+    border-bottom: 3px solid transparent;
+  }
+  .nav-tabs a {
+    height: calc(@search-tab-height + .5rem);
+    line-height: calc(@search-tab-height + .5rem);
+    padding: 0 1rem;
+    border-radius: 0;
+    background-color: transparent;
+  }
+  .nav-tabs a:hover {
+    border-color: @white-50;
+    color: @header-light;
+    background-color: transparent;
+  }
+  .nav-tabs .active a {
+    color: #fff;
+    border-color: @white;
+  }
+}
+@media (min-width: 768px) {
+  #searchForm_lookfor,
+  #searchForm_type { margin-bottom: 0; }
+  #searchForm { padding-bottom: @search-tab-height; }
+  .nav.searchbox .nav-tabs a,
+  #searchForm .nav-tabs a {
+    height: @search-tab-height;
+    padding-bottom: 3px;
+    line-height: @search-tab-height;
+  }
+}
+
+/* ------ Advanced ------ */
+.solr-adv-facet { padding-right: 1rem; }
+.solr-adv-facet:last-child { padding-right: 0; }
+.adv_search_links { margin-bottom: 0; }
+.adv_search_links a { text-decoration: underline; }
+.tab-content .adv_search_links { margin-bottom: 1.5rem; } // Advanced links with search tabs
+
+/* ------ Combined ------ */
+#content > [name="bulkActionForm"] .bulkActionButtons {
+  padding-top: 1rem;
+  padding-bottom: 1rem;
+}
+.combined-search-container {
+  .full-width();
+
+  .result { margin-right: 0; }
+}
diff --git a/themes/sandal/less/variables.less b/themes/sandal/less/variables.less
new file mode 100644
index 0000000000000000000000000000000000000000..3cdc11be796986c14f50ad07bfbe2c5469159cca
--- /dev/null
+++ b/themes/sandal/less/variables.less
@@ -0,0 +1,19 @@
+@reduced-font-size: 14px;
+@img-path: "../../sandal/images/";
+
+@banner-height: 60px;
+@banner-height-sm: 40px;
+@search-tab-height: 2rem;
+
+@result-checkbox-width: 28px;
+@result-checkbox-height: 80px;
+@result-sm-icon-size: 1.5rem;
+
+/* ------ Mixins ------ */
+.full-width() { // Break out of the container
+  margin-right: ~"calc(50% - 50vw + .5rem)"; // .5rem seems to be the margin of error in Chrome
+  margin-left: ~"calc(50% - 50vw + .5rem)";
+}
+.background-image(@file) {
+  background-image: url("@{img-path}@{file}");
+}
diff --git a/themes/sandal/less/vendor/tachyons-colors.less b/themes/sandal/less/vendor/tachyons-colors.less
new file mode 100644
index 0000000000000000000000000000000000000000..69c1392d5e583f0ca2394c853ad826330dc15601
--- /dev/null
+++ b/themes/sandal/less/vendor/tachyons-colors.less
@@ -0,0 +1,72 @@
+/*
+
+   Tachyons
+   COLOR VARIABLES
+
+   Grayscale
+   - Solids
+   - Transparencies
+   Colors
+
+*/
+@black: #000;
+@near-black: #111;
+@dark-gray: #333;
+@mid-gray: #555;
+@gray: #777;
+@silver: #999;
+@light-silver: #aaa;
+@moon-gray: #ccc;
+@light-gray: #eee;
+@near-white: #f4f4f4;
+@white: #fff;
+@transparent: transparent;
+@black-90: rgba(0,0,0,.9);
+@black-80: rgba(0,0,0,.8);
+@black-70: rgba(0,0,0,.7);
+@black-60: rgba(0,0,0,.6);
+@black-50: rgba(0,0,0,.5);
+@black-40: rgba(0,0,0,.4);
+@black-30: rgba(0,0,0,.3);
+@black-20: rgba(0,0,0,.2);
+@black-10: rgba(0,0,0,.1);
+@black-05: rgba(0,0,0,.05);
+@black-025: rgba(0,0,0,.025);
+@black-0125: rgba(0,0,0,.0125);
+@white-90: rgba(255,255,255,.9);
+@white-80: rgba(255,255,255,.8);
+@white-70: rgba(255,255,255,.7);
+@white-60: rgba(255,255,255,.6);
+@white-50: rgba(255,255,255,.5);
+@white-40: rgba(255,255,255,.4);
+@white-30: rgba(255,255,255,.3);
+@white-20: rgba(255,255,255,.2);
+@white-10: rgba(255,255,255,.1);
+@white-05: rgba(255,255,255,.05);
+@white-025: rgba(255,255,255,.025);
+@white-0125: rgba(255,255,255,.0125);
+@dark-red: #e7040f;
+@red: #ff4136;
+@light-red: #ff725c;
+@orange: #ff6300;
+@gold: #ffb700;
+@yellow: #ffd700;
+@light-yellow: #fbf1a9;
+@purple: #5e2ca5;
+@light-purple: #a463f2;
+@dark-pink: #d5008f;
+@hot-pink: #ff41b4;
+@pink: #ff80cc;
+@light-pink: #ffa3d7;
+@dark-green: #137752;
+@green: #19a974;
+@light-green: #9eebcf;
+@navy: #001b44;
+@dark-blue: #00449e;
+@blue: #357edd;
+@light-blue: #96ccff;
+@lightest-blue: #cdecff;
+@washed-blue: #f6fffe;
+@washed-green: #e8fdf5;
+@washed-yellow: #fffceb;
+@washed-red: #ffdfdf;
diff --git a/themes/sandal/scss/colors.scss b/themes/sandal/scss/colors.scss
new file mode 100644
index 0000000000000000000000000000000000000000..d942e58b6bda013b2455c0a901592e93fd175383
--- /dev/null
+++ b/themes/sandal/scss/colors.scss
@@ -0,0 +1,49 @@
+@import 'vendor/tachyons-colors'; // Import colors from the tachyons library
+
+/* Material Colors can be found here: https://material.io/guidelines/style/color.html */
+$brand-primary: #1976d2 !default; /* Material Blue 700 */
+$brand-secondary: #ff6d00 !default; /* Material Orange A700 */
+
+$header-bg: #607d8b !default; /* Material Blue Grey 500 */
+$header-light: #cfd8dc !default; /* Material Blue Grey 100 */
+
+$action-color: $brand-primary !default;
+$action-hover-bg: $white !default;
+$action-hover-color: $black !default;
+$passive-icon-color: $gray !default;
+$highlighter-color: lighten(#FF0, 20%) !default;
+
+$search-row-bg: $white !default;
+$search-row-bg-alt: $light-gray !default;
+$search-row-bg-hover: $lightest-blue !default;
+$search-row-selected-bg: $brand-primary !default;
+$search-row-selected-color: $white !default;
+
+$sidebar-title-bg: $white !default;
+$sidebar-title-color: $near-black !default;
+$sidebar-title-icon-color: $gray-light !default;
+$sidebar-item-bg: $white !default;
+$sidebar-item-color: $black !default;
+$sidebar-item-hover-bg: $lightest-blue !default;
+$sidebar-item-badge: $gray !default;
+$sidebar-active-bg: $brand-secondary !default;
+$sidebar-active-color: $white !default;
+
+/* Bootstrap variable changes */
+
+$link-color: #1565c0 !default; /* Material Blue 800 */
+$link-color-hover: #0d47a1 !default; /* Material Blue 900 */
+
+$input-border:              $light-silver !default;
+$input-color:               $dark-gray !default;
+$btn-default-bg:            $light-gray !default;
+$btn-default-color:         $near-black !default;
+$btn-primary-bg:            $action-color !default;
+
+$input-border-radius:         .25rem !default;
+
+$autocomplete-hover-bg:     $header-light !default;
+$dropdown-link-hover-bg:    $header-light !default;
+$dropdown-link-hover-color: $black !default;
+$table-bg-hover:            $header-light !default;
+$pagination-color:          $header-bg !default;
diff --git a/themes/sandal/scss/common.scss b/themes/sandal/scss/common.scss
new file mode 100644
index 0000000000000000000000000000000000000000..3b81087eca65addd58c73787f5070b8b4503a906
--- /dev/null
+++ b/themes/sandal/scss/common.scss
@@ -0,0 +1,123 @@
+/* ------ Border radius changes ------ */
+$list-group-border-radius: 0 !default;
+$border-radius-large: 0 !default; // modal
+
+/* ------ Common element changes ------ */
+h1, h2, h3, h4 {
+  margin: 0;
+  margin-bottom: 1rem;
+
+  .help-block & { margin: 0; }
+}
+.highlight,
+mark { background-color: $highlighter-color; }
+table { font-size: $reduced-font-size; }
+
+/* ------ Bootstrap class overrides ------ */
+.badge {
+  margin-bottom: 1px;
+  font-size: 10px;
+}
+.btn {
+  height: 34px;
+  border-radius: .25rem;
+  border-color: $silver;
+}
+.btn-default:hover,
+.btn-default:focus {
+  color: $white;
+  border-color: transparent;
+}
+.btn-link,
+.btn-primary { border-color: transparent; }
+.btn-primary:hover {
+  background-color: $action-hover-bg;
+  color: $action-color;
+  border-color: $brand-primary;
+}
+.btn-link { color: $brand-primary; }
+
+.form-control { box-shadow: none; }
+.form-control:hover,
+.form-control:focus { border-color: $brand-primary; }
+.form-control:focus {
+  padding-bottom: 4px; // Prevent jumping
+  border-bottom: 3px solid $brand-secondary;
+  box-shadow: none;
+}
+select.form-control {
+  padding-bottom: $padding-base-vertical;
+  border: 1px solid $light-silver;
+}
+
+.breadcrumb a { color: $dark-gray; }
+.breadcrumb .active { color: $near-black; }
+
+.nav > li > a { color: $brand-primary; }
+.navbar-collapse,
+.navbar-form { box-shadow: none; }
+
+.alert {
+  margin-top: 1rem;
+  margin-bottom: 1rem;
+  border: 0;
+  color: $black;
+
+  .btn {
+    color: $mid-gray;
+    background-color: $white;
+    border-color: $gray;
+  }
+  .btn-primary {
+    color: $action-color;
+    background-color: $white;
+    border-color: $action-color;
+  }
+}
+.alert-info,
+.alert-info:hover {
+  color: $navy;
+  background-color: $lightest-blue;
+  a { color: $blue; }
+}
+.alert-success,
+.alert-success:hover {
+  color: $dark-green;
+  background-color: $light-green;
+  a { color: $white; }
+}
+.alert-danger,
+.alert-danger:hover {
+  color: $white;
+  background-color: $red;
+  a { color: $washed-red; }
+}
+
+.label { font-weight: 400; }
+
+$pagination-border: transparent !default;
+$pagination-hover-border: transparent !default;
+.pagination {
+  @include clearfix();
+  display: table;
+  margin-left: auto;
+  margin-right: auto;
+  border-radius: 0;
+}
+.pagination > li > a,
+.pagination > li > span {
+  padding-left: 1rem;
+  padding-right: 1rem;
+  font-size: 13px;
+  font-weight: 500;
+  line-height: 1rem;
+
+  &.page-prev,
+  &.page-next {
+    font-size: 1rem;
+    font-weight: bold;
+    color: $brand-primary;
+  }
+}
+.pagination > .active > a,
+.pagination > .active > span { border-radius: $border-radius-base; }
\ No newline at end of file
diff --git a/themes/sandal/scss/compiled.scss b/themes/sandal/scss/compiled.scss
new file mode 100644
index 0000000000000000000000000000000000000000..7a85ff748b6d71042036a18b2e7c073ae459bc73
--- /dev/null
+++ b/themes/sandal/scss/compiled.scss
@@ -0,0 +1 @@
+@import "sandal";
diff --git a/themes/sandal/scss/rtl.scss b/themes/sandal/scss/rtl.scss
new file mode 100644
index 0000000000000000000000000000000000000000..8f008f0e106f35b0e7d888030afdf70564bcb7ea
--- /dev/null
+++ b/themes/sandal/scss/rtl.scss
@@ -0,0 +1,14 @@
+body.rtl {
+  .result {
+    .media-body {
+      padding-left: 0;
+      padding-right: .5rem;
+    }
+
+    .result-body,
+    .result-links {
+      float: right;
+      text-align: right;
+    }
+  }
+}
diff --git a/themes/sandal/scss/sandal.scss b/themes/sandal/scss/sandal.scss
new file mode 100644
index 0000000000000000000000000000000000000000..4e20993909fac1a1a1a0a21603d46fe1536dd2e0
--- /dev/null
+++ b/themes/sandal/scss/sandal.scss
@@ -0,0 +1,229 @@
+@import "bootstrap";
+@import "colors";
+@import "variables";
+@import "common";
+@import "search";
+@import "rtl";
+
+html {
+  font-size: 16px;
+  overflow-x: hidden;
+}
+body {
+  font-size: 1rem;
+  font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; // native font stack
+  color: $near-black;
+}
+
+/* -- Layout --- */
+.main .container { background-color: $white; }
+.mainbody { padding-top: 1rem; }
+
+/* --- Header --- */
+.navbar { border-radius: 0; }
+.banner {
+  width: auto;
+  color: #fff;
+
+  a { color: #fff; }
+}
+.banner .navbar-right { margin-top: calc(($banner-height-sm - 50px) / 2); } // Put right nav in the middle
+.banner .navbar-brand {
+  width: (170 / 65) * $banner-height-sm;
+  height: $banner-height-sm;
+}
+@media (min-width: 768px) {
+  .banner .navbar-right { margin-top: calc(($banner-height - 50px) / 2); }
+  .banner .navbar-brand {
+    width: (170 / 65) * $banner-height;
+    height: $banner-height;
+  }
+}
+
+header {
+  background-color: $header-bg;
+  font-size: $reduced-font-size;
+  font-weight: 500;
+  color: $white;
+
+  .navbar-nav { margin-top: 0; }
+  a,
+  .nav a,
+  .btn-link {
+    color: $white;
+    &:hover { color: $header-light; }
+  }
+  .btn-primary {
+    color: $black;
+    background-color: $header-light;
+  }
+  .btn-primary:hover {
+    color: $black;
+    background-color: $header-light;
+    border-color: $black;
+  }
+  .nav>li>a:hover,
+  .nav>li>a:focus {
+    color: $black;
+    background-color: $header-light;
+  }
+  .navbar-toggle {
+    margin: .5rem;
+    padding-left: 1rem;
+    padding-right: 1rem;
+    font-size: $reduced-font-size;
+  }
+  .dropdown-menu a { color: $black; }
+  .dropdown-menu a:hover {
+    background-color: $header-light;
+    color: $black;
+  }
+  .dropdown-menu .active a,
+  .dropdown-menu .active a:hover { background-color: $header-bg; }
+
+  .form-control { border: 0; }
+  .form-control:focus {
+    padding-bottom: 3px; // Smaller font-size means smaller jump
+    border-bottom: 3px solid $gold;
+  }
+
+  .navbar-brand {
+    width: 200px;
+    height: 100%;
+    margin-top: 5px;
+    @include background-image('vufind_logo_dark.png');
+    background-position: center center;
+    background-repeat: no-repeat;
+    background-size: contain;
+    &,
+    &:active,
+    &:hover,
+    &:focus { color: transparent; }
+    &.lang-ar { @include background-image('vufind_logo_ar_dark.png'); }
+  }
+}
+
+.breadcrumbs {
+  border-bottom: 1px solid $header-light;
+  background-color: $header-light;
+}
+.breadcrumb {
+  margin: 0;
+  padding-left: 0;
+  padding-right: 0;
+  font-size: $reduced-font-size;
+  color: $gray;
+  background-color: transparent;
+  border-radius: 0;
+}
+.breadcrumb a { color: $link-color; }
+.breadcrumb .active { color: $black; }
+.breadcrumb .active a { color: #37474F; } /* Material Blue Grey 800 */
+.breadcrumb .active a:hover { color: $link-color-hover; } /* Material Blue Grey 900 */
+.breadcrumb > li+li::before {
+  font-weight: 900;
+  color: #fff;
+}
+
+/* --- Cart --- */
+#cartSummary strong { font-weight: inherit; }
+
+/* --- MyResearch --- */
+.myresearch-menu a:hover { background-color: $white; }
+
+/* --- Record --- */
+.record-nav {
+  display: table;
+  margin-left: auto;
+  margin-top: 1rem;
+  margin-right: auto;
+}
+.info-col { font-size: $reduced-font-size; }
+.info-col h3 {
+  margin-top: 0;
+  font-weight: 500;
+}
+.record .sidebar { margin-top: 1rem; }
+.comment-list { margin-top: .5rem; }
+.comment { margin-bottom: .5rem; }
+.comment .delete { font-size: $reduced-font-size; }
+.comment-form .btn-primary { margin-top: .25rem; }
+.tagList { line-height: 2rem; }
+.tagList .tag .fa-close { margin: 0; }
+
+/* --- Sidebar --- */
+.sidebar {
+  padding-top: 1rem;
+  font-size: $reduced-font-size;
+  background-color: $light-gray;
+
+  .facet-group {
+    margin-left: 1rem;
+    margin-right: 1rem;
+  }
+  /* Collapsed arrows */
+  .facet-group .title {
+    background-color: $sidebar-title-bg;
+    color: $sidebar-title-color;
+    &::after {
+      width: 1rem;
+      font-family: "FontAwesome";
+      text-align: center;
+      color: $sidebar-title-icon-color;
+      content: '\f106';
+    }
+  }
+  .facet-group .title.collapsed::after { content: '\f107'; }
+  .active-filters .title::after,
+  #advSearchForm & .title:after { content: none; } // No arrow on active filter title
+
+  .facet {
+    background-color: $sidebar-item-bg;
+    color: $sidebar-item-color;
+  }
+  a.facet:hover,
+  .facet.checkbox:hover { background-color: $sidebar-item-hover-bg; }
+
+  .facet.active,
+  .facet.active:hover,
+  .active-filters .facet,
+  .active-filters .facet:hover,
+  .jstree-facet .jstree-container-ul > .active {
+    border-color: $sidebar-active-bg;
+    background-color: $sidebar-active-bg;
+    color: $sidebar-active-color;
+
+    .badge {
+      color: $sidebar-active-bg;
+      background-color: $white;
+    }
+  }
+
+  .facet .badge {
+    max-height: 15px;
+    margin-top: 5px;
+    line-height: .8;
+    background-color: $sidebar-item-badge;
+  }
+}
+.sidebar.left,
+.sidebar.right {
+  padding-left: 0;
+  padding-right: 0;
+}
+.sidebar .checkbox-filter,
+.sidebar > h4 { margin-left: 1rem; }
+
+.jstree-facet .main .fa-check { margin-top: 3px; }
+@media (min-width: 768px) and (max-width: 991px) {
+  .sidebar .facet {
+    flex-flow: wrap;
+
+    .text { width: 100%; }
+    .badge {
+      flex-grow: 1;
+      order: 1;
+    }
+    .exclude { order: 2; }
+  }
+}
diff --git a/themes/sandal/scss/search.scss b/themes/sandal/scss/search.scss
new file mode 100644
index 0000000000000000000000000000000000000000..c3cb6bdc261748cd459fea8006f3285252704fbe
--- /dev/null
+++ b/themes/sandal/scss/search.scss
@@ -0,0 +1,241 @@
+.search {
+  padding-left: 1rem;
+  padding-right: 1rem;
+}
+.list-group-item.title { color: $dark-gray; }
+.bulkActionButtons {
+  label {
+    font-weight: 500;
+    color: $mid-gray;
+  }
+}
+.search-header.search-header { padding-top: 0; } // Duplicate to increase specificity
+.search-stats > h2 { margin: 0; } // No results padding
+
+.author-facets { font-size: $reduced-font-size; }
+
+.result {
+  margin-left: -1rem;
+  margin-right: -1rem;
+  padding-top: 1rem;
+  padding-left: 1rem;
+  padding-bottom: 1rem;
+  border-bottom: 1px solid $moon-gray;
+  font-size: $reduced-font-size;
+
+  .media-left { padding-left: 0; }
+  .media-right { padding-right: 0; }
+  .record-cover img { border: 1px solid $gray-lighter; }
+  .record-number {
+    font-size: $reduced-font-size;
+    font-weight: bold;
+    color: $gray;
+  }
+
+  .title { font-size: 1rem; }
+  .callnumAndLocation {
+    margin-top: .25rem;
+    margin-bottom: .25rem;
+    font-size: 12px;
+  }
+  .format,
+  .label {
+    display: inline-block;
+    padding: 4px .75rem;
+    font-size: 11px;
+  }
+  .savedLists {
+    margin-bottom: 0;
+    white-space: nowrap;
+  }
+  .savedLists > ol,
+  .savedLists > ul { padding-left: 1rem; }
+}
+@media (min-width: 768px) {
+  .result {
+    margin-left: 0;
+    margin-right: 0;
+    padding-left: 0;
+  }
+}
+
+.grid-result {
+  padding-bottom: 1rem;
+  padding-right: 1rem;
+  text-align: center;
+
+  .title { font-size: $reduced-font-size; }
+}
+
+.result.checked,
+.grid-result.checked {
+  color: $search-row-selected-color;
+  background-color: $search-row-selected-bg;
+  border-color: $white;
+  a {
+    color: $search-row-selected-color;
+    text-decoration: underline;
+  }
+  .format,
+  .label {
+    color: $brand-primary;
+    background-color: #fff;
+  }
+  .record-number { color: $search-row-selected-color; }
+  .alert { background-color: $search-row-selected-color; }
+  .alert a { color: $search-row-selected-color; }
+}
+.result-body,
+.result-links {
+  float: left;
+  margin: 0;
+  padding: 0;
+}
+.result-body { width: 85%; }
+.result-links {
+  width: 15%;
+  text-align: center;
+}
+@media (max-width: 767px) {
+  .result-link-icon,
+  .result .cart-link-icon {
+    width: 100%;
+    margin: 0;
+    padding-top: .5rem;
+    padding-bottom: .5rem;
+    font-size: $result-sm-icon-size;
+    color: $dark-gray;
+  }
+  .result-link-label,
+  .result .cart-link-label { display: none; }
+}
+
+.grid-result .grid-checkbox label { width: 100%; }
+@media (min-width: 768px) {
+  .result { padding-right: 1rem; }
+  .result-body { width: 75%; }
+  .result-links {
+    width: 25%;
+    text-align: left;
+  }
+  .result-link-icon,
+  .result .cart-link-icon {
+    margin-right: .2rem;
+    padding: 0;
+    font-size: inherit;
+    color: $gray-darker;
+  }
+  .result-link-icon { margin-right: 0; }
+  .result-link-label,
+  .result .cart-link-label { display: inline; }
+}
+
+.top-facets,
+.search-header { font-size: $reduced-font-size; }
+.search-header {
+  padding-top: 1rem;
+  padding-bottom: 1rem;
+}
+#searchForm { font-size: $reduced-font-size; }
+#searchForm_lookfor,
+#searchForm_type { margin-bottom: 4px; }
+
+.list-group-item.active,
+.list-group-item.active:hover,
+.list-group-item.active:focus {
+  border-color: $sidebar-active-bg;
+  background-color: $sidebar-active-bg;
+}
+
+.searchHomeContent {
+  @include full-width();
+  @include clearfix();
+  position: relative;
+  padding: 6rem 3rem;
+  padding-left: calc(50vw - 50%); // Align searchbox with container
+  background-color: $header-bg;
+  background-image: url('https://source.unsplash.com/collection/803311/1000x300');
+  background-repeat: no-repeat;
+  background-size: cover;
+  background-position: center top;
+  box-shadow: 0 .5rem 2rem rgba(0,0,0,.1);
+  .btn-link,
+  .nav-tabs a {
+    color: $white;
+    text-shadow: 0 1px 0 $black;
+  }
+}
+.searchHomeContent::before {
+  position: absolute;
+  top: 0;
+  left: 0;
+  background-color: rgba(255,255,255,.5);
+}
+.template-dir-search.template-name-home .breadcrumbs { border: 0; }
+
+.search { border: 0; }
+#searchForm {
+  padding-top: .5rem;
+  padding-bottom: calc($search-tab-height + 1.5rem);
+}
+.nav.searchbox,
+#searchForm {
+  position: relative;
+  width: 100%;
+
+  .nav-tabs {
+    position: absolute;
+    bottom: 0;
+    border: 0;
+  }
+  .nav-tabs a,
+  .nav-tabs a:hover {
+    border: 0;
+    border-bottom: 3px solid transparent;
+  }
+  .nav-tabs a {
+    height: calc($search-tab-height + .5rem);
+    line-height: calc($search-tab-height + .5rem);
+    padding: 0 1rem;
+    border-radius: 0;
+    background-color: transparent;
+  }
+  .nav-tabs a:hover {
+    border-color: $white-50;
+    color: $header-light;
+    background-color: transparent;
+  }
+  .nav-tabs .active a {
+    color: #fff;
+    border-color: $white;
+  }
+}
+@media (min-width: 768px) {
+  #searchForm_lookfor,
+  #searchForm_type { margin-bottom: 0; }
+  #searchForm { padding-bottom: $search-tab-height; }
+  .nav.searchbox .nav-tabs a,
+  #searchForm .nav-tabs a {
+    height: $search-tab-height;
+    padding-bottom: 3px;
+    line-height: $search-tab-height;
+  }
+}
+
+/* ------ Advanced ------ */
+.solr-adv-facet { padding-right: 1rem; }
+.solr-adv-facet:last-child { padding-right: 0; }
+.adv_search_links { margin-bottom: 0; }
+.adv_search_links a { text-decoration: underline; }
+.tab-content .adv_search_links { margin-bottom: 1.5rem; } // Advanced links with search tabs
+
+/* ------ Combined ------ */
+#content > [name="bulkActionForm"] .bulkActionButtons {
+  padding-top: 1rem;
+  padding-bottom: 1rem;
+}
+.combined-search-container {
+  @include full-width();
+
+  .result { margin-right: 0; }
+}
diff --git a/themes/sandal/scss/variables.scss b/themes/sandal/scss/variables.scss
new file mode 100644
index 0000000000000000000000000000000000000000..228134c356b6aa42fec64b2021fc885d4be76f3c
--- /dev/null
+++ b/themes/sandal/scss/variables.scss
@@ -0,0 +1,19 @@
+$reduced-font-size: 14px !default;
+$img-path: "../../sandal/images/" !default;
+
+$banner-height: 60px !default;
+$banner-height-sm: 40px !default;
+$search-tab-height: 2rem !default;
+
+$result-checkbox-width: 28px !default;
+$result-checkbox-height: 80px !default;
+$result-sm-icon-size: 1.5rem !default;
+
+/* ------ Mixins ------ */
+@mixin full-width(){ // Break out of the container
+  margin-right: calc(50% - 50vw + .5rem); // .5rem seems to be the margin of error in Chrome
+  margin-left: calc(50% - 50vw + .5rem);
+}
+@mixin background-image($file){
+  background-image: url("#{$img-path}#{$file}");
+}
diff --git a/themes/sandal/scss/vendor/tachyons-colors.scss b/themes/sandal/scss/vendor/tachyons-colors.scss
new file mode 100644
index 0000000000000000000000000000000000000000..d84bbd13248c0ef7eff3ee52a4dc51f6e90e6520
--- /dev/null
+++ b/themes/sandal/scss/vendor/tachyons-colors.scss
@@ -0,0 +1,72 @@
+/*
+
+   Tachyons
+   COLOR VARIABLES
+
+   Grayscale
+   - Solids
+   - Transparencies
+   Colors
+
+*/
+$black: #000;
+$near-black: #111;
+$dark-gray: #333;
+$mid-gray: #555;
+$gray: #777;
+$silver: #999;
+$light-silver: #aaa;
+$moon-gray: #ccc;
+$light-gray: #eee;
+$near-white: #f4f4f4;
+$white: #fff;
+$transparent: transparent;
+$black-90: rgba(0,0,0,.9);
+$black-80: rgba(0,0,0,.8);
+$black-70: rgba(0,0,0,.7);
+$black-60: rgba(0,0,0,.6);
+$black-50: rgba(0,0,0,.5);
+$black-40: rgba(0,0,0,.4);
+$black-30: rgba(0,0,0,.3);
+$black-20: rgba(0,0,0,.2);
+$black-10: rgba(0,0,0,.1);
+$black-05: rgba(0,0,0,.05);
+$black-025: rgba(0,0,0,.025);
+$black-0125: rgba(0,0,0,.0125);
+$white-90: rgba(255,255,255,.9);
+$white-80: rgba(255,255,255,.8);
+$white-70: rgba(255,255,255,.7);
+$white-60: rgba(255,255,255,.6);
+$white-50: rgba(255,255,255,.5);
+$white-40: rgba(255,255,255,.4);
+$white-30: rgba(255,255,255,.3);
+$white-20: rgba(255,255,255,.2);
+$white-10: rgba(255,255,255,.1);
+$white-05: rgba(255,255,255,.05);
+$white-025: rgba(255,255,255,.025);
+$white-0125: rgba(255,255,255,.0125);
+$dark-red: #e7040f;
+$red: #ff4136;
+$light-red: #ff725c;
+$orange: #ff6300;
+$gold: #ffb700;
+$yellow: #ffd700;
+$light-yellow: #fbf1a9;
+$purple: #5e2ca5;
+$light-purple: #a463f2;
+$dark-pink: #d5008f;
+$hot-pink: #ff41b4;
+$pink: #ff80cc;
+$light-pink: #ffa3d7;
+$dark-green: #137752;
+$green: #19a974;
+$light-green: #9eebcf;
+$navy: #001b44;
+$dark-blue: #00449e;
+$blue: #357edd;
+$light-blue: #96ccff;
+$lightest-blue: #cdecff;
+$washed-blue: #f6fffe;
+$washed-green: #e8fdf5;
+$washed-yellow: #fffceb;
+$washed-red: #ffdfdf;
diff --git a/themes/sandal/theme.config.php b/themes/sandal/theme.config.php
new file mode 100644
index 0000000000000000000000000000000000000000..2bb286a457e59310d49c43b0861688cc8eada802
--- /dev/null
+++ b/themes/sandal/theme.config.php
@@ -0,0 +1,4 @@
+<?php
+return array(
+    'extends' => 'bootstrap3',
+);
diff --git a/util/commit.php b/util/commit.php
index deb839887bceb3f90e9d9f53c352e01313a2ffad..c5ff187b38b09a82cd0b7f7f5c19d26c4b97181f 100644
--- a/util/commit.php
+++ b/util/commit.php
@@ -26,7 +26,7 @@
  * @link     https://vufind.org/wiki/performance#index_optimization Wiki
  */
 
-// Load the Zend framework -- this will automatically trigger the appropriate
-// controller action based on directory and file names
-define('CLI_DIR', __DIR__);     // save directory name of current script
+// Manipulate command line to load correct route, then load Zend Framework:
+array_unshift($_SERVER['argv'], array_shift($_SERVER['argv']), 'util', 'commit');
+$_SERVER['argc'] += 2;
 require_once __DIR__ . '/../public/index.php';
diff --git a/util/createHierarchyTrees.php b/util/createHierarchyTrees.php
index 7b134cb725d33fc83d7f0c869702113cd4b23419..a9fdb0596ccc6478cb5a23b49339dd9eaca691c3 100644
--- a/util/createHierarchyTrees.php
+++ b/util/createHierarchyTrees.php
@@ -32,7 +32,7 @@
  * @link     https://vufind.org/wiki Wiki
  */
 
-// Load the Zend framework -- this will automatically trigger the appropriate
-// controller action based on directory and file names
-define('CLI_DIR', __DIR__);     // save directory name of current script
+// Manipulate command line to load correct route, then load Zend Framework:
+array_unshift($_SERVER['argv'], array_shift($_SERVER['argv']), 'util', 'createHierarchyTrees');
+$_SERVER['argc'] += 2;
 require_once __DIR__ . '/../public/index.php';
diff --git a/util/cssBuilder.php b/util/cssBuilder.php
index 1189659189102a1404607ed31d51b2637505ea22..b2e0e26a2d2e1d887191dc903cd38a7187461b53 100644
--- a/util/cssBuilder.php
+++ b/util/cssBuilder.php
@@ -26,7 +26,7 @@
  * @link     https://vufind.org/wiki Wiki
  */
 
-// Load the Zend framework -- this will automatically trigger the appropriate
-// controller action based on directory and file names
-define('CLI_DIR', __DIR__);     // save directory name of current script
+// Manipulate command line to load correct route, then load Zend Framework:
+array_unshift($_SERVER['argv'], array_shift($_SERVER['argv']), 'util', 'cssBuilder');
+$_SERVER['argc'] += 2;
 require_once __DIR__ . '/../public/index.php';
diff --git a/util/deletes.php b/util/deletes.php
index fd13511b0e1562029f92b02e04b76d1910f4bf58..9b68a09479ad43caf66796714c2613cf805a8389 100644
--- a/util/deletes.php
+++ b/util/deletes.php
@@ -27,7 +27,7 @@
  * @link     https://vufind.org/wiki/automation Wiki
  */
 
-// Load the Zend framework -- this will automatically trigger the appropriate
-// controller action based on directory and file names
-define('CLI_DIR', __DIR__);     // save directory name of current script
+// Manipulate command line to load correct route, then load Zend Framework:
+array_unshift($_SERVER['argv'], array_shift($_SERVER['argv']), 'util', 'deletes');
+$_SERVER['argc'] += 2;
 require_once __DIR__ . '/../public/index.php';
diff --git a/util/expire_searches.php b/util/expire_searches.php
index 098a169e0d17111ad35f280ead34a6b329c9b355..c1275ff59cb4189c43190c9a774544ab02e3c293 100644
--- a/util/expire_searches.php
+++ b/util/expire_searches.php
@@ -26,7 +26,7 @@
  * @link     https://vufind.org/jira/browse/VUFIND-235 JIRA Ticket
  */
 
-// Load the Zend framework -- this will automatically trigger the appropriate
-// controller action based on directory and file names
-define('CLI_DIR', __DIR__);     // save directory name of current script
+// Manipulate command line to load correct route, then load Zend Framework:
+array_unshift($_SERVER['argv'], array_shift($_SERVER['argv']), 'util', 'expire_searches');
+$_SERVER['argc'] += 2;
 require_once __DIR__ . '/../public/index.php';
diff --git a/util/expire_sessions.php b/util/expire_sessions.php
index 06db2c4c6d43f9710788b524254c8868bb079401..92a46f27a81fa43296846c3edf8d557c60c70d23 100644
--- a/util/expire_sessions.php
+++ b/util/expire_sessions.php
@@ -26,7 +26,7 @@
  * @link     https://vufind.org/jira/browse/VUFIND-235 JIRA Ticket
  */
 
-// Load the Zend framework -- this will automatically trigger the appropriate
-// controller action based on directory and file names
-define('CLI_DIR', __DIR__);     // save directory name of current script
+// Manipulate command line to load correct route, then load Zend Framework:
+array_unshift($_SERVER['argv'], array_shift($_SERVER['argv']), 'util', 'expire_sessions');
+$_SERVER['argc'] += 2;
 require_once __DIR__ . '/../public/index.php';
diff --git a/util/index_reserves.php b/util/index_reserves.php
index 02dcea582ec54b30061c4c150e0facf03688a240..546ad8c5f0704b74ec5ee3085b11f4f1f657e5d4 100644
--- a/util/index_reserves.php
+++ b/util/index_reserves.php
@@ -26,7 +26,7 @@
  * @link     https://vufind.org/wiki Wiki
  */
 
-// Load the Zend framework -- this will automatically trigger the appropriate
-// controller action based on directory and file names
-define('CLI_DIR', __DIR__);     // save directory name of current script
+// Manipulate command line to load correct route, then load Zend Framework:
+array_unshift($_SERVER['argv'], array_shift($_SERVER['argv']), 'util', 'index_reserves');
+$_SERVER['argc'] += 2;
 require_once __DIR__ . '/../public/index.php';
diff --git a/util/optimize.php b/util/optimize.php
index 5e8cef74d0abdcfee27fb30794c56e5278a689cb..3436f6d263f307492494d3f37bdc4ee0aaa8f7f1 100644
--- a/util/optimize.php
+++ b/util/optimize.php
@@ -26,7 +26,7 @@
  * @link     https://vufind.org/wiki/performance#index_optimization Wiki
  */
 
-// Load the Zend framework -- this will automatically trigger the appropriate
-// controller action based on directory and file names
-define('CLI_DIR', __DIR__);     // save directory name of current script
+// Manipulate command line to load correct route, then load Zend Framework:
+array_unshift($_SERVER['argv'], array_shift($_SERVER['argv']), 'util', 'optimize');
+$_SERVER['argc'] += 2;
 require_once __DIR__ . '/../public/index.php';
diff --git a/util/sitemap.php b/util/sitemap.php
index d54eeaebd594e4be6753749b7bc6c4c438596b70..756192e965ebee93b82b0fa13abf9131418d3ad1 100644
--- a/util/sitemap.php
+++ b/util/sitemap.php
@@ -26,7 +26,7 @@
  * @link     https://vufind.org/wiki/search_engine_optimization Wiki
  */
  
-// Load the Zend framework -- this will automatically trigger the appropriate
-// controller action based on directory and file names
-define('CLI_DIR', __DIR__);     // save directory name of current script
+// Manipulate command line to load correct route, then load Zend Framework:
+array_unshift($_SERVER['argv'], array_shift($_SERVER['argv']), 'util', 'sitemap');
+$_SERVER['argc'] += 2;
 require_once __DIR__ . '/../public/index.php';
diff --git a/util/suppressed.php b/util/suppressed.php
index 5ca75afcf16d05cd97f013910cc1811914d020db..65239ad84a75e1eb24c48b0ec3f31010f72cbac4 100644
--- a/util/suppressed.php
+++ b/util/suppressed.php
@@ -27,7 +27,7 @@
  * @link     https://vufind.org/wiki/automation Wiki
  */
 
-// Load the Zend framework -- this will automatically trigger the appropriate
-// controller action based on directory and file names
-define('CLI_DIR', __DIR__);     // save directory name of current script
+// Manipulate command line to load correct route, then load Zend Framework:
+array_unshift($_SERVER['argv'], array_shift($_SERVER['argv']), 'util', 'suppressed');
+$_SERVER['argc'] += 2;
 require_once __DIR__ . '/../public/index.php';
diff --git a/vendor/jasig/phpcas/LICENSE b/vendor/jasig/phpcas/LICENSE
deleted file mode 100644
index 261eeb9e9f8b2b4b0d119366dda99c6fd7d35c64..0000000000000000000000000000000000000000
--- a/vendor/jasig/phpcas/LICENSE
+++ /dev/null
@@ -1,201 +0,0 @@
-                                 Apache License
-                           Version 2.0, January 2004
-                        http://www.apache.org/licenses/
-
-   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-   1. Definitions.
-
-      "License" shall mean the terms and conditions for use, reproduction,
-      and distribution as defined by Sections 1 through 9 of this document.
-
-      "Licensor" shall mean the copyright owner or entity authorized by
-      the copyright owner that is granting the License.
-
-      "Legal Entity" shall mean the union of the acting entity and all
-      other entities that control, are controlled by, or are under common
-      control with that entity. For the purposes of this definition,
-      "control" means (i) the power, direct or indirect, to cause the
-      direction or management of such entity, whether by contract or
-      otherwise, or (ii) ownership of fifty percent (50%) or more of the
-      outstanding shares, or (iii) beneficial ownership of such entity.
-
-      "You" (or "Your") shall mean an individual or Legal Entity
-      exercising permissions granted by this License.
-
-      "Source" form shall mean the preferred form for making modifications,
-      including but not limited to software source code, documentation
-      source, and configuration files.
-
-      "Object" form shall mean any form resulting from mechanical
-      transformation or translation of a Source form, including but
-      not limited to compiled object code, generated documentation,
-      and conversions to other media types.
-
-      "Work" shall mean the work of authorship, whether in Source or
-      Object form, made available under the License, as indicated by a
-      copyright notice that is included in or attached to the work
-      (an example is provided in the Appendix below).
-
-      "Derivative Works" shall mean any work, whether in Source or Object
-      form, that is based on (or derived from) the Work and for which the
-      editorial revisions, annotations, elaborations, or other modifications
-      represent, as a whole, an original work of authorship. For the purposes
-      of this License, Derivative Works shall not include works that remain
-      separable from, or merely link (or bind by name) to the interfaces of,
-      the Work and Derivative Works thereof.
-
-      "Contribution" shall mean any work of authorship, including
-      the original version of the Work and any modifications or additions
-      to that Work or Derivative Works thereof, that is intentionally
-      submitted to Licensor for inclusion in the Work by the copyright owner
-      or by an individual or Legal Entity authorized to submit on behalf of
-      the copyright owner. For the purposes of this definition, "submitted"
-      means any form of electronic, verbal, or written communication sent
-      to the Licensor or its representatives, including but not limited to
-      communication on electronic mailing lists, source code control systems,
-      and issue tracking systems that are managed by, or on behalf of, the
-      Licensor for the purpose of discussing and improving the Work, but
-      excluding communication that is conspicuously marked or otherwise
-      designated in writing by the copyright owner as "Not a Contribution."
-
-      "Contributor" shall mean Licensor and any individual or Legal Entity
-      on behalf of whom a Contribution has been received by Licensor and
-      subsequently incorporated within the Work.
-
-   2. Grant of Copyright License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      copyright license to reproduce, prepare Derivative Works of,
-      publicly display, publicly perform, sublicense, and distribute the
-      Work and such Derivative Works in Source or Object form.
-
-   3. Grant of Patent License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      (except as stated in this section) patent license to make, have made,
-      use, offer to sell, sell, import, and otherwise transfer the Work,
-      where such license applies only to those patent claims licensable
-      by such Contributor that are necessarily infringed by their
-      Contribution(s) alone or by combination of their Contribution(s)
-      with the Work to which such Contribution(s) was submitted. If You
-      institute patent litigation against any entity (including a
-      cross-claim or counterclaim in a lawsuit) alleging that the Work
-      or a Contribution incorporated within the Work constitutes direct
-      or contributory patent infringement, then any patent licenses
-      granted to You under this License for that Work shall terminate
-      as of the date such litigation is filed.
-
-   4. Redistribution. You may reproduce and distribute copies of the
-      Work or Derivative Works thereof in any medium, with or without
-      modifications, and in Source or Object form, provided that You
-      meet the following conditions:
-
-      (a) You must give any other recipients of the Work or
-          Derivative Works a copy of this License; and
-
-      (b) You must cause any modified files to carry prominent notices
-          stating that You changed the files; and
-
-      (c) You must retain, in the Source form of any Derivative Works
-          that You distribute, all copyright, patent, trademark, and
-          attribution notices from the Source form of the Work,
-          excluding those notices that do not pertain to any part of
-          the Derivative Works; and
-
-      (d) If the Work includes a "NOTICE" text file as part of its
-          distribution, then any Derivative Works that You distribute must
-          include a readable copy of the attribution notices contained
-          within such NOTICE file, excluding those notices that do not
-          pertain to any part of the Derivative Works, in at least one
-          of the following places: within a NOTICE text file distributed
-          as part of the Derivative Works; within the Source form or
-          documentation, if provided along with the Derivative Works; or,
-          within a display generated by the Derivative Works, if and
-          wherever such third-party notices normally appear. The contents
-          of the NOTICE file are for informational purposes only and
-          do not modify the License. You may add Your own attribution
-          notices within Derivative Works that You distribute, alongside
-          or as an addendum to the NOTICE text from the Work, provided
-          that such additional attribution notices cannot be construed
-          as modifying the License.
-
-      You may add Your own copyright statement to Your modifications and
-      may provide additional or different license terms and conditions
-      for use, reproduction, or distribution of Your modifications, or
-      for any such Derivative Works as a whole, provided Your use,
-      reproduction, and distribution of the Work otherwise complies with
-      the conditions stated in this License.
-
-   5. Submission of Contributions. Unless You explicitly state otherwise,
-      any Contribution intentionally submitted for inclusion in the Work
-      by You to the Licensor shall be under the terms and conditions of
-      this License, without any additional terms or conditions.
-      Notwithstanding the above, nothing herein shall supersede or modify
-      the terms of any separate license agreement you may have executed
-      with Licensor regarding such Contributions.
-
-   6. Trademarks. This License does not grant permission to use the trade
-      names, trademarks, service marks, or product names of the Licensor,
-      except as required for reasonable and customary use in describing the
-      origin of the Work and reproducing the content of the NOTICE file.
-
-   7. Disclaimer of Warranty. Unless required by applicable law or
-      agreed to in writing, Licensor provides the Work (and each
-      Contributor provides its Contributions) on an "AS IS" BASIS,
-      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-      implied, including, without limitation, any warranties or conditions
-      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-      PARTICULAR PURPOSE. You are solely responsible for determining the
-      appropriateness of using or redistributing the Work and assume any
-      risks associated with Your exercise of permissions under this License.
-
-   8. Limitation of Liability. In no event and under no legal theory,
-      whether in tort (including negligence), contract, or otherwise,
-      unless required by applicable law (such as deliberate and grossly
-      negligent acts) or agreed to in writing, shall any Contributor be
-      liable to You for damages, including any direct, indirect, special,
-      incidental, or consequential damages of any character arising as a
-      result of this License or out of the use or inability to use the
-      Work (including but not limited to damages for loss of goodwill,
-      work stoppage, computer failure or malfunction, or any and all
-      other commercial damages or losses), even if such Contributor
-      has been advised of the possibility of such damages.
-
-   9. Accepting Warranty or Additional Liability. While redistributing
-      the Work or Derivative Works thereof, You may choose to offer,
-      and charge a fee for, acceptance of support, warranty, indemnity,
-      or other liability obligations and/or rights consistent with this
-      License. However, in accepting such obligations, You may act only
-      on Your own behalf and on Your sole responsibility, not on behalf
-      of any other Contributor, and only if You agree to indemnify,
-      defend, and hold each Contributor harmless for any liability
-      incurred by, or claims asserted against, such Contributor by reason
-      of your accepting any such warranty or additional liability.
-
-   END OF TERMS AND CONDITIONS
-
-   APPENDIX: How to apply the Apache License to your work.
-
-      To apply the Apache License to your work, attach the following
-      boilerplate notice, with the fields enclosed by brackets "[]"
-      replaced with your own identifying information. (Don't include
-      the brackets!)  The text should be enclosed in the appropriate
-      comment syntax for the file format. We also recommend that a
-      file or class name and description of purpose be included on the
-      same "printed page" as the copyright notice for easier
-      identification within third-party archives.
-
-   Copyright [yyyy] [name of copyright owner]
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
diff --git a/vendor/symfony/dependency-injection/Tests/Fixtures/yaml/services1.yml b/vendor/symfony/dependency-injection/Tests/Fixtures/yaml/services1.yml
deleted file mode 100644
index 8b137891791fe96927ad78e64b0aad7bded08bdc..0000000000000000000000000000000000000000
--- a/vendor/symfony/dependency-injection/Tests/Fixtures/yaml/services1.yml
+++ /dev/null
@@ -1 +0,0 @@
-